From 64c48cdf55a756d5263cf8ebfa308258b68a47b5 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Sun, 23 Apr 2023 16:01:00 +0200 Subject: [PATCH] feat: categorize tabs --- packages/devtools-kit/src/_types/common.ts | 5 ++ .../devtools-kit/src/_types/custom-tabs.ts | 10 ++- packages/devtools-kit/src/_types/index.ts | 1 + .../devtools/client/components/SideNav.vue | 29 ++++---- .../client/components/SideNavItem.vue | 3 - packages/devtools/client/composables/state.ts | 71 ++++++++++++------- .../devtools/client/composables/storage.ts | 1 + packages/devtools/client/meta.d.ts | 5 ++ .../client/pages/modules/custom-[name].vue | 4 +- .../devtools/client/pages/modules/hooks.vue | 1 + .../devtools/client/pages/modules/pages.vue | 2 +- .../devtools/client/pages/modules/payload.vue | 3 +- .../devtools/client/pages/modules/plugins.vue | 1 + .../client/pages/modules/runtime-configs.vue | 3 +- .../client/pages/modules/server-routes.vue | 1 + .../devtools/client/pages/modules/storage.vue | 1 + .../client/pages/modules/terminals.vue | 3 + .../client/pages/modules/virtual-files.vue | 1 + packages/devtools/client/pages/settings.vue | 47 +++++++++--- .../devtools/src/integrations/vite-inspect.ts | 1 + packages/devtools/src/integrations/vscode.ts | 1 + .../devtools/src/server-rpc/custom-tabs.ts | 5 +- packages/devtools/src/types/ui-state.ts | 1 + 23 files changed, 137 insertions(+), 63 deletions(-) create mode 100644 packages/devtools-kit/src/_types/common.ts diff --git a/packages/devtools-kit/src/_types/common.ts b/packages/devtools-kit/src/_types/common.ts new file mode 100644 index 000000000..4c665e5b4 --- /dev/null +++ b/packages/devtools-kit/src/_types/common.ts @@ -0,0 +1,5 @@ +export type TabCategory = + | 'app' + | 'analyze' + | 'server' + | 'modules' diff --git a/packages/devtools-kit/src/_types/custom-tabs.ts b/packages/devtools-kit/src/_types/custom-tabs.ts index d7e8577af..bed6cfc3d 100644 --- a/packages/devtools-kit/src/_types/custom-tabs.ts +++ b/packages/devtools-kit/src/_types/custom-tabs.ts @@ -1,4 +1,5 @@ import type { VNode } from 'vue' +import type { TabCategory } from './common' export interface ModuleCustomTab { /** @@ -17,6 +18,11 @@ export interface ModuleCustomTab { * Main view of the tab */ view: ModuleView + /** + * Category of the tab + * @default 'app' + */ + category?: TabCategory /** * Insert static vnode to the tab entry * @@ -105,8 +111,8 @@ export interface ModuleBuiltinTab { icon?: string title?: string path?: string - requireClient?: boolean - shouldShow?: () => boolean + category?: TabCategory + shouldShow?: () => any } export type ModuleTabInfo = ModuleCustomTab | ModuleBuiltinTab diff --git a/packages/devtools-kit/src/_types/index.ts b/packages/devtools-kit/src/_types/index.ts index 86b5c56ee..e436be981 100644 --- a/packages/devtools-kit/src/_types/index.ts +++ b/packages/devtools-kit/src/_types/index.ts @@ -8,3 +8,4 @@ export * from './wizard' export * from './rpc' export * from './server-ctx' export * from './module-options' +export * from './common' diff --git a/packages/devtools/client/components/SideNav.vue b/packages/devtools/client/components/SideNav.vue index 36a1eeb3c..9d1cb7560 100644 --- a/packages/devtools/client/components/SideNav.vue +++ b/packages/devtools/client/components/SideNav.vue @@ -1,6 +1,6 @@ - -
- - diff --git a/packages/devtools/client/components/SideNavItem.vue b/packages/devtools/client/components/SideNavItem.vue index 156c2cae1..c15cfeb14 100644 --- a/packages/devtools/client/components/SideNavItem.vue +++ b/packages/devtools/client/components/SideNavItem.vue @@ -6,13 +6,10 @@ const props = defineProps<{ }>() const settings = useDevToolsSettings() -const client = useClient() const isEnabled = computed(() => { const _tab = props.tab as ModuleBuiltinTab if (_tab.shouldShow && !_tab.shouldShow()) return false - if (_tab.requireClient && !client.value) - return false if (settings.hiddenTabs.value.includes(_tab.name)) return false return true diff --git a/packages/devtools/client/composables/state.ts b/packages/devtools/client/composables/state.ts index f7aa951d4..dccc22937 100644 --- a/packages/devtools/client/composables/state.ts +++ b/packages/devtools/client/composables/state.ts @@ -2,7 +2,7 @@ import type { Component } from 'nuxt/schema' import { $fetch } from 'ofetch' import type { Ref } from 'vue' import { objectPick } from '@antfu/utils' -import type { HookInfo, ModuleBuiltinTab, ModuleMetric, RouteInfo } from '../../src/types' +import type { HookInfo, ModuleBuiltinTab, ModuleCustomTab, ModuleMetric, RouteInfo, TabCategory } from '../../src/types' let modules: ModuleMetric[] | undefined @@ -79,13 +79,13 @@ export function useTerminals() { return useAsyncState('getTerminals', () => rpc.getTerminals()) } -export function useTabs() { - const router = useRouter() +export function useAllTabs() { const customTabs = useCustomTabs() const settings = useDevToolsSettings() + const router = useRouter() - const builtin = computed(() => { - return router.getRoutes() + const builtin = computed(() => [ + ...router.getRoutes() .filter(route => route.path.startsWith('/modules/') && route.meta.title && !route.meta.wip) .filter(route => !route.meta.experimental || (route.meta.experimental && settings.showExperimentalFeatures.value)) .sort((a, b) => (a.meta.order || 100) - (b.meta.order || 100)) @@ -95,33 +95,54 @@ export function useTabs() { path: i.path, ...i.meta, } - }) - }) + }), + ...(customTabs.value || []).filter(i => i.name.startsWith('builtin-')), + ]) + + const custom = computed(() => (customTabs.value || []) + .filter(i => !i.name.startsWith('builtin-'))) + + return computed(() => [ + ...builtin.value, + ...custom.value, + ]) +} + +export function useCategorizedTabs(enabledOnly = true) { + const tabs = enabledOnly + ? useEnabledTabs() + : useAllTabs() - const builtInCustom = computed(() => (customTabs.value || []).filter(i => i.name.startsWith('builtin-'))) - const customCustom = computed(() => (customTabs.value || []).filter(i => !i.name.startsWith('builtin-'))) + const settings = useDevToolsSettings() - return { - custom: customCustom, - builtin: computed(() => [ - ...builtin.value, - ...builtInCustom.value, - ]), - all: computed(() => [ - ...builtin.value, - ...builtInCustom.value, - ...customCustom.value, - ]), - } + return computed(() => { + const categories: Record = { + app: [], + analyze: [], + server: [], + modules: [], + } + + for (const tab of tabs.value) { + const category = tab.category || 'app' + if (enabledOnly && settings.hiddenTabCategories.value.includes(category)) + continue + if (!categories[category]) + console.warn(`Unknown tab category: ${category}`) + else + categories[category].push(tab) + } + + return Object.entries(categories) + }) } export function useEnabledTabs() { - const client = useClient() - const tabs = useTabs() + const tabs = useAllTabs() - return computed(() => tabs.all.value.filter((tab) => { + return computed(() => tabs.value.filter((tab) => { const _tab = tab as ModuleBuiltinTab - if (_tab.requireClient && !client.value) + if (_tab.shouldShow && !_tab.shouldShow()) return false return true })) diff --git a/packages/devtools/client/composables/storage.ts b/packages/devtools/client/composables/storage.ts index 5c647c966..21a705cbf 100644 --- a/packages/devtools/client/composables/storage.ts +++ b/packages/devtools/client/composables/storage.ts @@ -13,6 +13,7 @@ const devToolsSettings = useLocalStorage('nuxt-devtools-sett showExperimentalFeatures: false, scale: 1, hiddenTabs: [], + hiddenTabCategories: [], }, { mergeDefaults: true }) const devToolsSettingsRefs = toRefs(devToolsSettings) diff --git a/packages/devtools/client/meta.d.ts b/packages/devtools/client/meta.d.ts index af48249b0..fd07851b0 100644 --- a/packages/devtools/client/meta.d.ts +++ b/packages/devtools/client/meta.d.ts @@ -1,8 +1,13 @@ +import { TabCategory } from "../src/types" + declare module '#app' { interface PageMeta { icon?: string title?: string order?: number + category?: TabCategory + shouldShow?: () => any + badge?: () => string | number | undefined } } diff --git a/packages/devtools/client/pages/modules/custom-[name].vue b/packages/devtools/client/pages/modules/custom-[name].vue index b7fec201d..dda2f5dbc 100644 --- a/packages/devtools/client/pages/modules/custom-[name].vue +++ b/packages/devtools/client/pages/modules/custom-[name].vue @@ -8,8 +8,8 @@ definePageMeta({ const route = useRoute() const router = useRouter() const name = computed(() => route.params.name) -const tabs = useTabs() -const tab = computed(() => tabs.all.value.find(i => i.name === name.value) as ModuleCustomTab) +const tabs = useAllTabs() +const tab = computed(() => tabs.value.find(i => i.name === name.value) as ModuleCustomTab) onMounted(() => { // if the tab is not found and passed a certain timeout, redirect to the overview page diff --git a/packages/devtools/client/pages/modules/hooks.vue b/packages/devtools/client/pages/modules/hooks.vue index 4cf4b514d..acd66fc65 100644 --- a/packages/devtools/client/pages/modules/hooks.vue +++ b/packages/devtools/client/pages/modules/hooks.vue @@ -2,6 +2,7 @@ definePageMeta({ icon: 'carbon-ibm-cloud-direct-link-2-connect', title: 'Hooks', + category: 'analyze', }) const serverHooks = useServerHooks() diff --git a/packages/devtools/client/pages/modules/pages.vue b/packages/devtools/client/pages/modules/pages.vue index 35dca5ed0..b2f8bab57 100644 --- a/packages/devtools/client/pages/modules/pages.vue +++ b/packages/devtools/client/pages/modules/pages.vue @@ -6,7 +6,7 @@ import type { RouteInfo } from '~~/../src/types' definePageMeta({ icon: 'carbon-tree-view-alt', title: 'Pages', - requireClient: true, + shouldShow: () => !!useClient().value, order: 1, }) diff --git a/packages/devtools/client/pages/modules/payload.vue b/packages/devtools/client/pages/modules/payload.vue index 432ea2163..d087bdc0c 100644 --- a/packages/devtools/client/pages/modules/payload.vue +++ b/packages/devtools/client/pages/modules/payload.vue @@ -2,7 +2,8 @@ definePageMeta({ icon: 'carbon-data-set', title: 'Payload', - requireClient: true, + category: 'analyze', + shouldShow: () => !!useClient().value, order: 7, }) diff --git a/packages/devtools/client/pages/modules/plugins.vue b/packages/devtools/client/pages/modules/plugins.vue index 37e8926f9..3a085b5e6 100644 --- a/packages/devtools/client/pages/modules/plugins.vue +++ b/packages/devtools/client/pages/modules/plugins.vue @@ -5,6 +5,7 @@ definePageMeta({ icon: 'carbon-plug', title: 'Plugins', order: 5, + category: 'analyze', }) const config = useServerConfig() diff --git a/packages/devtools/client/pages/modules/runtime-configs.vue b/packages/devtools/client/pages/modules/runtime-configs.vue index 2adedc1b3..8b719a40f 100644 --- a/packages/devtools/client/pages/modules/runtime-configs.vue +++ b/packages/devtools/client/pages/modules/runtime-configs.vue @@ -2,7 +2,8 @@ definePageMeta({ icon: 'carbon-settings-services', title: 'Runtime Configs', - requireClient: true, + category: 'analyze', + shouldShow: () => !!useClient().value, order: 6, }) diff --git a/packages/devtools/client/pages/modules/server-routes.vue b/packages/devtools/client/pages/modules/server-routes.vue index 332f41857..686cc99a6 100644 --- a/packages/devtools/client/pages/modules/server-routes.vue +++ b/packages/devtools/client/pages/modules/server-routes.vue @@ -6,6 +6,7 @@ definePageMeta({ title: 'Server Routes', layout: 'full', experimental: true, + category: 'server', shouldShow() { return useServerRoutes().value?.length }, diff --git a/packages/devtools/client/pages/modules/storage.vue b/packages/devtools/client/pages/modules/storage.vue index 4a11adda3..9b54aea72 100644 --- a/packages/devtools/client/pages/modules/storage.vue +++ b/packages/devtools/client/pages/modules/storage.vue @@ -6,6 +6,7 @@ definePageMeta({ title: 'Storage', experimental: true, layout: 'full', + category: 'server', }) const nuxtApp = useNuxtApp() diff --git a/packages/devtools/client/pages/modules/terminals.vue b/packages/devtools/client/pages/modules/terminals.vue index 725539302..9e16f7478 100644 --- a/packages/devtools/client/pages/modules/terminals.vue +++ b/packages/devtools/client/pages/modules/terminals.vue @@ -4,6 +4,9 @@ definePageMeta({ title: 'Terminals', layout: 'full', shouldShow() { + return !!useTerminals().value?.length + }, + badge() { return useTerminals().value?.length }, }) diff --git a/packages/devtools/client/pages/modules/virtual-files.vue b/packages/devtools/client/pages/modules/virtual-files.vue index 3b07f3025..288453465 100644 --- a/packages/devtools/client/pages/modules/virtual-files.vue +++ b/packages/devtools/client/pages/modules/virtual-files.vue @@ -5,6 +5,7 @@ definePageMeta({ icon: 'i-carbon-border-none', title: 'Virtual Files', layout: 'full', + category: 'analyze', }) interface VfsData { diff --git a/packages/devtools/client/pages/settings.vue b/packages/devtools/client/pages/settings.vue index 77503a04c..f5b23dcb0 100644 --- a/packages/devtools/client/pages/settings.vue +++ b/packages/devtools/client/pages/settings.vue @@ -4,6 +4,7 @@ const { showExperimentalFeatures, scale, hiddenTabs, + hiddenTabCategories, } = useDevToolsSettings() const scaleOptions = [ @@ -14,7 +15,7 @@ const scaleOptions = [ ['Huge', 18 / 15], ] -const allTabs = useTabs() +const categories = useCategorizedTabs(false) function toggleTab(name: string, v: boolean) { if (v) @@ -22,6 +23,13 @@ function toggleTab(name: string, v: boolean) { else hiddenTabs.value.push(name) } + +function toggleTabCategory(name: string, v: boolean) { + if (v) + hiddenTabCategories.value = hiddenTabCategories.value.filter(i => i !== name) + else + hiddenTabCategories.value.push(name) +}