diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 2bd7dda..4f9b8cd 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -17,6 +17,9 @@ jobs: - name: Install dependencies run: npm ci + - name: Build + run: npx @kinvolk/headlamp-plugin build + - name: Lint run: npx eslint --ext .ts,.tsx src/ diff --git a/.gitignore b/.gitignore index 70def5f..5df0edb 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules/ dist/ .headlamp-plugin/ .mcp.json +*.tar.gz diff --git a/package-lock.json b/package-lock.json index 5a20917..75e4df1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "polaris-headlamp-plugin", - "version": "0.0.3", + "version": "0.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "polaris-headlamp-plugin", - "version": "0.0.3", + "version": "0.0.5", "devDependencies": { "@kinvolk/headlamp-plugin": "^0.13.0" } diff --git a/src/api/polaris.ts b/src/api/polaris.ts index 808b3d8..f40d5d5 100644 --- a/src/api/polaris.ts +++ b/src/api/polaris.ts @@ -93,6 +93,13 @@ export function countResults(data: AuditData): ResultCounts { // --- Settings --- +export const INTERVAL_OPTIONS = [ + { label: '1 minute', value: 60 }, + { label: '5 minutes', value: 300 }, + { label: '10 minutes', value: 600 }, + { label: '30 minutes', value: 1800 }, +]; + const STORAGE_KEY = 'polaris-plugin-refresh-interval'; const DEFAULT_INTERVAL_SECONDS = 300; // 5 minutes diff --git a/src/components/PolarisSettings.tsx b/src/components/PolarisSettings.tsx new file mode 100644 index 0000000..be80a22 --- /dev/null +++ b/src/components/PolarisSettings.tsx @@ -0,0 +1,40 @@ +import { NameValueTable, SectionBox } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; +import React from 'react'; +import { getRefreshInterval, INTERVAL_OPTIONS, setRefreshInterval } from '../api/polaris'; + +interface PluginSettingsProps { + data?: { [key: string]: string | number | boolean }; + onDataChange?: (data: { [key: string]: string | number | boolean }) => void; +} + +export default function PolarisSettings(props: PluginSettingsProps) { + const { data, onDataChange } = props; + const currentInterval = (data?.refreshInterval as number) ?? getRefreshInterval(); + + function handleChange(e: React.ChangeEvent) { + const seconds = Number(e.target.value); + setRefreshInterval(seconds); + onDataChange?.({ ...data, refreshInterval: seconds }); + } + + return ( + + + {INTERVAL_OPTIONS.map(opt => ( + + ))} + + ), + }, + ]} + /> + + ); +} diff --git a/src/components/PolarisView.tsx b/src/components/PolarisView.tsx index 7a7313f..c7b79ff 100644 --- a/src/components/PolarisView.tsx +++ b/src/components/PolarisView.tsx @@ -1,4 +1,10 @@ -import { Loader, SectionBox, SectionHeader } from '@kinvolk/headlamp-plugin/lib/CommonComponents'; +import { + Loader, + NameValueTable, + SectionBox, + SectionHeader, + StatusLabel, +} from '@kinvolk/headlamp-plugin/lib/CommonComponents'; import React from 'react'; import { AuditData, @@ -6,118 +12,66 @@ import { countResults, getRefreshInterval, ResultCounts, - setRefreshInterval, usePolarisData, } from '../api/polaris'; -const INTERVAL_OPTIONS = [ - { label: '1 minute', value: 60 }, - { label: '5 minutes', value: 300 }, - { label: '10 minutes', value: 600 }, - { label: '30 minutes', value: 1800 }, -]; - -function RefreshSettings(props: { interval: number; onChange: (seconds: number) => void }) { - return ( -
- - -
- ); -} - -function StatCard(props: { label: string; value: number; color?: string }) { - return ( -
-
- {props.value} -
-
{props.label}
-
- ); -} - -function ScoreBadge(props: { score: number }) { - const color = props.score >= 80 ? '#4caf50' : props.score >= 50 ? '#ff9800' : '#f44336'; - return ( -
-
{props.score}%
-
Cluster Score
-
- ); +function scoreStatus(score: number): 'success' | 'warning' | 'error' { + if (score >= 80) return 'success'; + if (score >= 50) return 'warning'; + return 'error'; } function OverviewSection(props: { data: AuditData; counts: ResultCounts }) { const score = computeScore(props.counts); + const status = scoreStatus(score); + return ( <> - + {score}%, + }, + ]} + /> -
- - - - -
+ {props.counts.pass}, + }, + { + name: 'Warning', + value: {props.counts.warning}, + }, + { + name: 'Danger', + value: {props.counts.danger}, + }, + ]} + />
-
- - - - -
+
); } export default function PolarisView() { - const [interval, setInterval] = React.useState(getRefreshInterval); - - function handleIntervalChange(seconds: number) { - setInterval(seconds); - setRefreshInterval(seconds); - } - + const interval = getRefreshInterval(); const { data, loading, error } = usePolarisData(interval); if (loading) { @@ -128,16 +82,18 @@ export default function PolarisView() { return ( <> - , - ]} - /> + {error && ( -
{error}
+ {error}, + }, + ]} + />
)} @@ -145,7 +101,14 @@ export default function PolarisView() { {!data && !error && ( -
No Polaris audit results found.
+
)} diff --git a/src/index.tsx b/src/index.tsx index 3b30f3f..fdce70e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,5 +1,10 @@ -import { registerRoute, registerSidebarEntry } from '@kinvolk/headlamp-plugin/lib'; +import { + registerPluginSettings, + registerRoute, + registerSidebarEntry, +} from '@kinvolk/headlamp-plugin/lib'; import React from 'react'; +import PolarisSettings from './components/PolarisSettings'; import PolarisView from './components/PolarisView'; registerSidebarEntry({ @@ -17,3 +22,5 @@ registerRoute({ exact: true, component: () => , }); + +registerPluginSettings('polaris-headlamp-plugin', PolarisSettings, true);