import type { RouteLocationRaw } from 'vue-router'; import { ref, type Ref, watchEffect } from 'vue'; export enum PanelHeirarchyType { LEAF = 'leaf', FOLDER = 'folder', } export type PanelHeirarchyLeaf = { name: string; to: RouteLocationRaw; type: PanelHeirarchyType.LEAF; }; export type PanelHeirarchyFolder = { name: string; children: PanelHeirarchyChildren; type: PanelHeirarchyType.FOLDER; }; export type PanelHeirarchyChildren = ( | PanelHeirarchyFolder | PanelHeirarchyLeaf )[]; export function usePanelHeirarchy(): Ref { const internal: PanelHeirarchyFolder = { name: 'Internal', children: [ { name: 'Graph Test', to: { name: 'graph' }, type: PanelHeirarchyType.LEAF, }, { name: 'Telemetry Elements', to: { name: 'tlm' }, type: PanelHeirarchyType.LEAF, }, { name: 'Commands', to: { name: 'cmd' }, type: PanelHeirarchyType.LEAF, }, { name: 'Chart', to: { name: 'chart' }, type: PanelHeirarchyType.LEAF, }, { name: 'Panel Editor', to: { name: 'panel_editor' }, type: PanelHeirarchyType.LEAF, }, ], type: PanelHeirarchyType.FOLDER, }; const result: Ref = ref([internal]); watchEffect(async () => { try { const res = await fetch(`/api/panel`); const data = await res.json(); const server_panels: PanelHeirarchyFolder = { name: 'Server Panels', children: [], type: PanelHeirarchyType.FOLDER, }; for (const entry of data) { server_panels.children.push({ name: entry['name'], to: { name: 'panel', params: { id: entry['id'] } }, type: PanelHeirarchyType.LEAF, }); } result.value = [internal, server_panels]; } catch {} }); return result; } export function filterHeirarchy( heirarchy: PanelHeirarchyChildren, predicate: (leaf: PanelHeirarchyLeaf) => boolean, ): PanelHeirarchyChildren { const result: PanelHeirarchyChildren = []; for (const element of heirarchy) { switch (element.type) { case PanelHeirarchyType.LEAF: if (predicate(element)) { result.push(element); } break; case PanelHeirarchyType.FOLDER: const folder_contents = filterHeirarchy( element.children, predicate, ); if (folder_contents.length > 0) { result.push({ name: element.name, children: folder_contents, type: PanelHeirarchyType.FOLDER, }); } break; } } return result; } export function getFirstLeaf( heirarchy: PanelHeirarchyChildren, ): PanelHeirarchyLeaf | null { for (const element of heirarchy) { switch (element.type) { case PanelHeirarchyType.LEAF: return element; case PanelHeirarchyType.FOLDER: const leaf = getFirstLeaf(element.children); if (leaf != null) { return leaf; } break; } } return null; }