diff --git a/src/components/DynamicSidebarRegistrar.tsx b/src/components/DynamicSidebarRegistrar.tsx deleted file mode 100644 index 7cf8bdf..0000000 --- a/src/components/DynamicSidebarRegistrar.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { registerSidebarEntry } from '@kinvolk/headlamp-plugin/lib'; -import React from 'react'; -import { getNamespaces } from '../api/polaris'; -import { usePolarisDataContext } from '../api/PolarisDataContext'; - -const registeredNamespaces = new Set(); - -export default function DynamicSidebarRegistrar() { - const { data } = usePolarisDataContext(); - - React.useEffect(() => { - if (!data) return; - - const namespaces = getNamespaces(data); - for (const ns of namespaces) { - if (registeredNamespaces.has(ns)) continue; - registeredNamespaces.add(ns); - registerSidebarEntry({ - parent: 'polaris-namespaces', - name: `polaris-ns-${ns}`, - label: ns, - url: `/polaris/ns/${ns}`, - icon: 'mdi:folder-outline', - }); - } - }, [data]); - - return null; -} diff --git a/src/components/NamespacesListView.tsx b/src/components/NamespacesListView.tsx new file mode 100644 index 0000000..a580940 --- /dev/null +++ b/src/components/NamespacesListView.tsx @@ -0,0 +1,126 @@ +import { + Loader, + NameValueTable, + SectionBox, + SectionHeader, + SimpleTable, + StatusLabel, +} from '@kinvolk/headlamp-plugin/lib/CommonComponents'; +import React from 'react'; +import { Link } from 'react-router-dom'; +import { + computeScore, + countResultsForItems, + filterResultsByNamespace, + getNamespaces, +} from '../api/polaris'; +import { usePolarisDataContext } from '../api/PolarisDataContext'; + +function scoreStatus(score: number): 'success' | 'warning' | 'error' { + if (score >= 80) return 'success'; + if (score >= 50) return 'warning'; + return 'error'; +} + +interface NamespaceRow { + namespace: string; + score: number; + pass: number; + warning: number; + danger: number; +} + +export default function NamespacesListView() { + const { data, loading, error } = usePolarisDataContext(); + + if (loading) { + return ; + } + + if (error) { + return ( + <> + + + {error}, + }, + ]} + /> + + + ); + } + + if (!data) { + return ( + <> + + + + + + ); + } + + const namespaces = getNamespaces(data); + const rows: NamespaceRow[] = namespaces.map(ns => { + const results = filterResultsByNamespace(data, ns); + const counts = countResultsForItems(results); + const score = computeScore(counts); + return { + namespace: ns, + score, + pass: counts.pass, + warning: counts.warning, + danger: counts.danger, + }; + }); + + return ( + <> + + + ( + {row.namespace} + ), + }, + { + label: 'Score', + getter: (row: NamespaceRow) => ( + {row.score}% + ), + }, + { + label: 'Pass', + getter: (row: NamespaceRow) => ( + {row.pass} + ), + }, + { + label: 'Warning', + getter: (row: NamespaceRow) => ( + {row.warning} + ), + }, + { + label: 'Danger', + getter: (row: NamespaceRow) => ( + {row.danger} + ), + }, + ]} + data={rows} + emptyMessage="No namespaces found in Polaris audit data." + /> + + + ); +} diff --git a/src/index.tsx b/src/index.tsx index 074df7c..db49107 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -6,8 +6,8 @@ import { import React from 'react'; import { PolarisDataProvider } from './api/PolarisDataContext'; import DashboardView from './components/DashboardView'; -import DynamicSidebarRegistrar from './components/DynamicSidebarRegistrar'; import NamespaceDetailView from './components/NamespaceDetailView'; +import NamespacesListView from './components/NamespacesListView'; import PolarisSettings from './components/PolarisSettings'; // --- Sidebar entries --- @@ -40,7 +40,7 @@ registerSidebarEntry({ parent: 'polaris', name: 'polaris-namespaces', label: 'Namespaces', - url: '/polaris', + url: '/polaris/namespaces', icon: 'mdi:dns', }); @@ -48,12 +48,11 @@ registerSidebarEntry({ registerRoute({ path: '/polaris', - sidebar: 'polaris', + sidebar: 'polaris-overview', name: 'polaris', exact: true, component: () => ( - ), @@ -66,20 +65,30 @@ registerRoute({ exact: true, component: () => ( - ), }); +registerRoute({ + path: '/polaris/namespaces', + sidebar: 'polaris-namespaces', + name: 'polaris-namespaces', + exact: true, + component: () => ( + + + + ), +}); + registerRoute({ path: '/polaris/ns/:namespace', - sidebar: 'polaris', + sidebar: 'polaris-namespaces', name: 'polaris-namespace', exact: true, component: () => ( - ),