From 52f16beb92f8c84c5ce5572e9bb6bb9b79a227ad Mon Sep 17 00:00:00 2001 From: Mike Burgess Date: Tue, 17 Dec 2024 23:28:07 +0000 Subject: [PATCH] Summary charts should show distinguish between severities according to severity colour. Closes #634. (#635) --- .../grouping/CheckSummaryChart/index.tsx | 60 +---- .../grouping/DetectionBenchmark/index.tsx | 2 +- .../grouping/DetectionPanel/index.tsx | 11 +- .../grouping/DetetctionSummaryChart/index.tsx | 215 +++++++++++------- .../dashboards/grouping/common/Detection.ts | 10 +- .../grouping/common/DetectionBenchmark.ts | 46 +++- .../dashboards/grouping/common/index.ts | 13 +- .../common/node/DetectionEmptyResultNode.ts | 17 +- .../common/node/DetectionErrorNode.ts | 17 +- .../common/node/DetectionHierarchyNode.ts | 4 +- .../common/node/DetectionResultNode.ts | 9 +- .../common/node/DetectionRunningNode.ts | 19 +- .../src/hooks/useDetectionGrouping.tsx | 32 ++- ui/dashboard/src/styles/index.css | 42 +++- ui/dashboard/tailwind.config.js | 4 +- 15 files changed, 320 insertions(+), 181 deletions(-) diff --git a/ui/dashboard/src/components/dashboards/grouping/CheckSummaryChart/index.tsx b/ui/dashboard/src/components/dashboards/grouping/CheckSummaryChart/index.tsx index 23c15d25..d51e44ea 100644 --- a/ui/dashboard/src/components/dashboards/grouping/CheckSummaryChart/index.tsx +++ b/ui/dashboard/src/components/dashboards/grouping/CheckSummaryChart/index.tsx @@ -1,9 +1,10 @@ import IntegerDisplay from "../../../IntegerDisplay"; import { CheckNodeStatus, CheckSummary } from "../common"; import { classNames } from "@powerpipe/utils/styles"; +import { ReactNode } from "react"; type ProgressBarGroupProps = { - children: JSX.Element | JSX.Element[]; + children: ReactNode; className?: string; }; @@ -38,7 +39,7 @@ const getWidth = (x, y) => { return percent >= 0.5 ? Math.round(percent) : 1; }; -const ProgressBarGroupTotal = ({ +export const ProgressBarGroupTotal = ({ className, total, }: ProgressBarGroupTotalProps) => ( @@ -105,13 +106,16 @@ const NonAlertProgressBarGroupTotal = ({ ); }; -const ProgressBarGroup = ({ children, className }: ProgressBarGroupProps) => ( +export const ProgressBarGroup = ({ + children, + className, +}: ProgressBarGroupProps) => (
{children}
); -const ProgressBar = ({ className, percent }: ProgressBarProps) => { +export const ProgressBar = ({ className, percent }: ProgressBarProps) => { if (!percent) { return null; } @@ -171,54 +175,6 @@ const CheckSummaryChart = ({ return (
- {/* 0 ? "rounded-l-sm" : null,*/} - {/* skip === 0 && info === 0 && ok === 0 && alarm === 0 && error > 0*/} - {/* ? "rounded-r-sm"*/} - {/* : null*/} - {/* )}*/} - {/* percent={error}*/} - {/*/>*/} - {/* 0 ? "rounded-l-sm" : null,*/} - {/* skip === 0 && info === 0 && ok === 0 && alarm > 0*/} - {/* ? "rounded-r-sm"*/} - {/* : null*/} - {/* )}*/} - {/* percent={alarm}*/} - {/*/>*/} - {/* 0 ? "rounded-l-sm" : null,*/} - {/* skip === 0 && info === 0 && ok > 0 ? "rounded-r-sm" : null*/} - {/* )}*/} - {/* percent={ok}*/} - {/*/>*/} - {/* 0*/} - {/* ? "rounded-l-sm"*/} - {/* : null,*/} - {/* skip === 0 && info > 0 ? "rounded-r-sm" : null*/} - {/* )}*/} - {/* percent={info}*/} - {/*/>*/} - {/* 0*/} - {/* ? "rounded-l-sm"*/} - {/* : null,*/} - {/* skip > 0 ? "rounded-r-sm" : null*/} - {/* )}*/} - {/* percent={skip}*/} - {/*/>*/}
{ properties: { loading: totalSummary.total === 0 && props.grouping.status === "running", - label: "Total Detections", + label: "Total", value: totalSummary.total, icon: totalSummary.total > 0 diff --git a/ui/dashboard/src/components/dashboards/grouping/DetectionPanel/index.tsx b/ui/dashboard/src/components/dashboards/grouping/DetectionPanel/index.tsx index f844d42d..c067917e 100644 --- a/ui/dashboard/src/components/dashboards/grouping/DetectionPanel/index.tsx +++ b/ui/dashboard/src/components/dashboards/grouping/DetectionPanel/index.tsx @@ -308,8 +308,13 @@ const recordChildResults = ( }; const DetectionPanel = ({ depth, node }: DetectionPanelProps) => { - const { firstChildSummaries, dispatch, groupingConfig, nodeStates } = - useDetectionGrouping(); + const { + firstChildSummaries, + hasSeverityResults, + dispatch, + groupingConfig, + nodeStates, + } = useDetectionGrouping(); const { enabled: panelControlsEnabled, panelControls, @@ -482,7 +487,9 @@ const DetectionPanel = ({ depth, node }: DetectionPanelProps) => {
{/*
{node.summary.total}
*/} diff --git a/ui/dashboard/src/components/dashboards/grouping/DetetctionSummaryChart/index.tsx b/ui/dashboard/src/components/dashboards/grouping/DetetctionSummaryChart/index.tsx index 75f99678..565d4739 100644 --- a/ui/dashboard/src/components/dashboards/grouping/DetetctionSummaryChart/index.tsx +++ b/ui/dashboard/src/components/dashboards/grouping/DetetctionSummaryChart/index.tsx @@ -1,54 +1,22 @@ -import Icon from "@powerpipe/components/Icon"; import LoadingIndicator from "@powerpipe/components/dashboards/LoadingIndicator"; -import { CheckNodeStatus, DetectionSummary } from "../common"; +import { + CheckNodeStatus, + DetectionSeveritySummary, + DetectionSummary, +} from "../common"; import { classNames } from "@powerpipe/utils/styles"; - -type ProgressBarGroupProps = { - children: JSX.Element | JSX.Element[]; - className?: string; -}; - -type ProgressBarProps = { - className?: string; - percent: number; -}; +import { + ProgressBar, + ProgressBarGroup, + ProgressBarGroupTotal, +} from "@powerpipe/components/dashboards/grouping/CheckSummaryChart"; type DetectionSummaryChartProps = { status: CheckNodeStatus; summary: DetectionSummary; + severitySummary: DetectionSeveritySummary; firstChildSummaries: DetectionSummary[]; -}; - -const getWidth = (x, y) => { - const percent = (x / (x + y)) * 100; - return percent >= 0.5 ? Math.round(percent) : 1; -}; - -const ProgressBarGroup = ({ children, className }: ProgressBarGroupProps) => ( -
- {children} -
-); - -const ProgressBar = ({ className, percent }: ProgressBarProps) => { - if (!percent) { - return null; - } - - return ( -
- ); + hasSeverityResults: boolean; }; export const getDetectionSummaryChartPercent = (value, total) => { @@ -60,69 +28,154 @@ export const getDetectionSummaryChartPercent = (value, total) => { return Math.max(rounded, 3); }; +const getSummaryTitle = ( + summary: DetectionSummary, + severitySummary: DetectionSeveritySummary, +): string => { + const titleParts: string[] = []; + if (summary.error) { + titleParts.push(`Error: ${summary.error.toLocaleString()}`); + } + if (severitySummary.critical) { + titleParts.push(`Critical: ${severitySummary.critical.toLocaleString()}`); + } + if (severitySummary.high) { + titleParts.push(`High: ${severitySummary.high.toLocaleString()}`); + } + if (severitySummary.medium) { + titleParts.push(`Medium: ${severitySummary.medium.toLocaleString()}`); + } + if (severitySummary.low) { + titleParts.push(`Low: ${severitySummary.low.toLocaleString()}`); + } + if (severitySummary.none) { + titleParts.push(`None: ${severitySummary.none.toLocaleString()}`); + } + if (titleParts.length === 0) { + return ""; + } + return titleParts.join(` +`); +}; + const DetectionSummaryChart = ({ status, summary, + severitySummary, firstChildSummaries, + hasSeverityResults, }: DetectionSummaryChartProps) => { - let maxAlerts = 0; - let maxNonAlerts = 0; + let maxFirstChildTotal = 0; // Calculate max alerts for (const firstChildSummary of firstChildSummaries) { const currentMaxAlerts = firstChildSummary.total; - if (currentMaxAlerts > maxAlerts) { - maxAlerts = currentMaxAlerts; + if (currentMaxAlerts > maxFirstChildTotal) { + maxFirstChildTotal = currentMaxAlerts; } } - // Calculate width for progress bar - let alertsWidth = getWidth(maxAlerts, maxNonAlerts); + // const maxFirstChildTotalDigits = maxFirstChildTotal.toString().length; + // const summaryTotalDigits = summary.total.toString().length; - const isRunning = status === "running"; + let isRunning = status === "running"; const hasTotal = summary.total > 0; return ( -
- {isRunning && !hasTotal && ( -
- -
- )} - - {hasTotal ? ( -
- +
+ {isRunning && !hasTotal && } + {/*{!isRunning && !hasTotal && (*/} + {/* */} + {/*)}*/} + {hasTotal && ( +
+ + + + + +
- ) : ( - !isRunning && ( -
- -
- ) )} - - {summary.total} +
); }; diff --git a/ui/dashboard/src/components/dashboards/grouping/common/Detection.ts b/ui/dashboard/src/components/dashboards/grouping/common/Detection.ts index 7b257267..b6a1d3f1 100644 --- a/ui/dashboard/src/components/dashboards/grouping/common/Detection.ts +++ b/ui/dashboard/src/components/dashboards/grouping/common/Detection.ts @@ -65,6 +65,7 @@ class Detection implements DetectionNode { this._results = this._build_check_results(data); this._summary = summary || { total: this.results?.length || 0, + error: !!error ? 1 : 0, }; this._tags = tags || {}; this._status = status; @@ -114,7 +115,12 @@ class Detection implements DetectionNode { } get severity_summary(): DetectionSeveritySummary { - return {}; + // Bubble up the node's severity - always zero though as we have no results + const summary: DetectionSeveritySummary = {}; + if (this._severity) { + summary[this._severity] = 0; + } + return summary; } get type(): GroupingNodeType { @@ -122,7 +128,7 @@ class Detection implements DetectionNode { } get summary(): DetectionSummary { - return { total: this._results?.length || 0 }; // this._summary; + return { total: this._results?.length || 0, error: this._error ? 1 : 0 }; // this._summary; } get error(): string | undefined { diff --git a/ui/dashboard/src/components/dashboards/grouping/common/DetectionBenchmark.ts b/ui/dashboard/src/components/dashboards/grouping/common/DetectionBenchmark.ts index 92937ea0..b73428a3 100644 --- a/ui/dashboard/src/components/dashboards/grouping/common/DetectionBenchmark.ts +++ b/ui/dashboard/src/components/dashboards/grouping/common/DetectionBenchmark.ts @@ -4,11 +4,11 @@ import { AddDetectionResultsAction, DetectionNode, DetectionNodeStatus, - GroupingNodeType, DetectionResult, DetectionRun, DetectionSeveritySummary, DetectionSummary, + GroupingNodeType, } from "@powerpipe/components/dashboards/grouping/common"; import { DashboardLayoutNode, PanelsMap } from "@powerpipe/types"; import { @@ -162,20 +162,62 @@ class DetectionBenchmark implements DetectionNode { get summary(): DetectionSummary { const summary = { total: 0, + error: 0, }; for (const benchmark of this._benchmarks) { const nestedSummary = benchmark.summary; summary.total += nestedSummary.total; + summary.error += nestedSummary.error; } for (const detection of this._detections) { const nestedSummary = detection.summary; summary.total += nestedSummary.total; + summary.error += nestedSummary.error; } return summary; } get severity_summary(): DetectionSeveritySummary { - return {}; + const summary: DetectionSeveritySummary = {}; + for (const benchmark of this._benchmarks) { + const nestedSummary = benchmark.severity_summary; + if ("low" in nestedSummary) { + summary.low = summary.low || 0; + summary.low += nestedSummary.low || 0; + } + if ("medium" in nestedSummary) { + summary.medium = summary.medium || 0; + summary.medium += nestedSummary.medium || 0; + } + if ("high" in nestedSummary) { + summary.high = summary.high || 0; + summary.high += nestedSummary.high || 0; + } + if ("critical" in nestedSummary) { + summary.critical = summary.critical || 0; + summary.critical += nestedSummary.critical || 0; + } + } + for (const detection of this._detections) { + const nestedSummary = detection.severity_summary; + if ("low" in nestedSummary) { + summary.low = summary.low || 0; + summary.low += nestedSummary.low || 0; + } + if ("medium" in nestedSummary) { + summary.medium = summary.medium || 0; + summary.medium += nestedSummary.medium || 0; + } + if ("high" in nestedSummary) { + summary.high = summary.high || 0; + summary.high += nestedSummary.high || 0; + } + if ("critical" in nestedSummary) { + summary.critical = summary.critical || 0; + summary.critical += nestedSummary.critical || 0; + } + } + return summary; } get status(): DetectionNodeStatus { diff --git a/ui/dashboard/src/components/dashboards/grouping/common/index.ts b/ui/dashboard/src/components/dashboards/grouping/common/index.ts index be4b414f..a4b7ae5f 100644 --- a/ui/dashboard/src/components/dashboards/grouping/common/index.ts +++ b/ui/dashboard/src/components/dashboards/grouping/common/index.ts @@ -74,11 +74,13 @@ export type CheckSeveritySummary = export type DetectionSeverity = "none" | "low" | "medium" | "high" | "critical"; -export type DetectionSeveritySummary = - | {} - | { - [key in DetectionSeverity]: number; - }; +export type DetectionSeveritySummary = { + none?: number; + low?: number; + medium?: number; + high?: number; + critical?: number; +}; export type CheckSummary = { alarm: number; @@ -90,6 +92,7 @@ export type CheckSummary = { export type DetectionSummary = { total: number; + error: number; }; export type CheckDynamicValueMap = { diff --git a/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionEmptyResultNode.ts b/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionEmptyResultNode.ts index 18105d91..3b61674e 100644 --- a/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionEmptyResultNode.ts +++ b/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionEmptyResultNode.ts @@ -34,21 +34,24 @@ class DetectionEmptyResultNode implements DetectionNode { return "empty_result"; } + get summary(): DetectionSummary { + return { + total: 0, + error: 0, + }; + } + get severity_summary(): DetectionSeveritySummary { // Bubble up the node's severity - always zero though as we have no results - const summary = {}; + const summary: DetectionSeveritySummary = {}; if (this._result.detection.severity) { summary[this._result.detection.severity] = 0; + } else { + summary["none"] = 0; } return summary; } - get summary(): DetectionSummary { - return { - total: 0, - }; - } - get status(): CheckNodeStatus { // If a control has no results, this node is complete return "complete"; diff --git a/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionErrorNode.ts b/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionErrorNode.ts index 894bec39..a78b0aca 100644 --- a/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionErrorNode.ts +++ b/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionErrorNode.ts @@ -34,21 +34,24 @@ class DetectionErrorNode implements DetectionNode { return "error"; } + get summary(): DetectionSummary { + return { + total: 1, + error: 1, + }; + } + get severity_summary(): DetectionSeveritySummary { // Bubble up the node's severity - always zero though as we have no results - const summary = {}; + const summary: DetectionSeveritySummary = {}; if (this._result.detection.severity) { summary[this._result.detection.severity] = 0; + } else { + summary["none"] = 0; } return summary; } - get summary(): DetectionSummary { - return { - total: 1, - }; - } - get status(): DetectionNodeStatus { // If a control has gone to error, this node is complete return "complete"; diff --git a/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionHierarchyNode.ts b/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionHierarchyNode.ts index 53a5ad69..f064f5e5 100644 --- a/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionHierarchyNode.ts +++ b/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionHierarchyNode.ts @@ -50,16 +50,18 @@ class DetectionHierarchyNode implements DetectionNode { get summary(): DetectionSummary { const summary = { total: 0, + error: 0, }; for (const child of this._children) { const nestedSummary = child.summary; summary.total += nestedSummary.total; + summary.error += nestedSummary.error; } return summary; } get severity_summary(): DetectionSeveritySummary { - const summary = {}; + const summary: DetectionSeveritySummary = {}; for (const child of this._children) { for (const [severity, count] of Object.entries(child.severity_summary)) { if (!summary[severity]) { diff --git a/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionResultNode.ts b/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionResultNode.ts index ff74635b..ff81a08c 100644 --- a/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionResultNode.ts +++ b/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionResultNode.ts @@ -50,16 +50,21 @@ class DetectionResultNode implements DetectionNode { } get severity_summary(): DetectionSeveritySummary { - const summary = {}; + const summary: DetectionSeveritySummary = {}; if (this._result.detection.severity) { summary[this._result.detection.severity] = this._result?.rows?.length || 0; + } else { + summary["none"] = 0; } return summary; } get summary(): DetectionSummary { - return { total: this._result?.rows?.length || 0 }; + return { + total: this._result?.rows?.length || 0, + error: this._result.error ? 1 : 0, + }; } get status(): CheckNodeStatus { diff --git a/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionRunningNode.ts b/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionRunningNode.ts index 35d7e961..019f406f 100644 --- a/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionRunningNode.ts +++ b/ui/dashboard/src/components/dashboards/grouping/common/node/DetectionRunningNode.ts @@ -1,10 +1,10 @@ import { - GroupingNodeType, DetectionNode, DetectionNodeStatus, DetectionResult, DetectionSeveritySummary, DetectionSummary, + GroupingNodeType, } from "../index"; class DetectionRunningNode implements DetectionNode { @@ -30,21 +30,24 @@ class DetectionRunningNode implements DetectionNode { return "running"; } + get summary(): DetectionSummary { + return { + total: 0, + error: 0, + }; + } + get severity_summary(): DetectionSeveritySummary { // Bubble up the node's severity - always zero though as we have no results - const summary = {}; + const summary: DetectionSeveritySummary = {}; if (this._result.detection.severity) { summary[this._result.detection.severity] = 0; + } else { + summary["none"] = 0; } return summary; } - get summary(): DetectionSummary { - return { - total: 0, - }; - } - get status(): DetectionNodeStatus { // This will bubble up through the hierarchy and put all ancestral nodes in a running state return "running"; diff --git a/ui/dashboard/src/hooks/useDetectionGrouping.tsx b/ui/dashboard/src/hooks/useDetectionGrouping.tsx index a98912ef..1423e1b4 100644 --- a/ui/dashboard/src/hooks/useDetectionGrouping.tsx +++ b/ui/dashboard/src/hooks/useDetectionGrouping.tsx @@ -60,11 +60,12 @@ export type CheckGroupFilterValues = { }; type ICheckGroupingContext = { - benchmark: DetectionBenchmarkType | null; + benchmark: DetectionBenchmarkType | {} | null; definition: PanelDefinition; grouping: DetectionNodeType | null; groupingConfig: DetectionDisplayGroup[]; firstChildSummaries: DetectionSummary[]; + hasSeverityResults: boolean; nodeStates: CheckGroupNodeStates; filterValues: CheckGroupFilterValues; dispatch(action: CheckGroupingAction): void; @@ -80,7 +81,20 @@ const GroupingActions: IActions = { const checkGroupingActions = Object.values(GroupingActions); -const GroupingContext = createContext(null); +const GroupingContext = createContext({ + benchmark: null, + definition: null, + grouping: null, + groupingConfig: [], + firstChildSummaries: [], + hasSeverityResults: false, + nodeStates: {}, + filterValues: { + detection_tag: { key: {}, value: {} }, + dimension: { key: {}, value: {} }, + }, + dispatch: () => {}, +}); const addBenchmarkTrunkNode = ( benchmark_trunk: DetectionBenchmarkType[], @@ -663,7 +677,7 @@ const useGroupingInternal = ( }; if (!definition || skip || !panelsMap) { - return [null, null, null, [], {}, filterValues]; + return [null, null, null, [], false, {}, filterValues]; } // @ts-ignore @@ -725,8 +739,17 @@ const useGroupingInternal = ( const results = new DetectionRootNode(result); const firstChildSummaries: DetectionSummary[] = []; + let hasSeverityResults: Boolean = false; for (const child of results.children) { firstChildSummaries.push(child.summary); + if ( + child.severity_summary.critical !== undefined || + child.severity_summary.high !== undefined || + child.severity_summary.medium !== undefined || + child.severity_summary.low !== undefined + ) { + hasSeverityResults = true; + } } return [ @@ -734,6 +757,7 @@ const useGroupingInternal = ( { ...rootBenchmarkPanel, children: definition.children }, results, firstChildSummaries, + hasSeverityResults, detectionNodeStates, filterValues, ] as const; @@ -754,6 +778,7 @@ const GroupingProvider = ({ panelDefinition, grouping, firstChildSummaries, + hasSeverityResults, tempNodeStates, filterValues, ] = useGroupingInternal(definition, panelsMap, groupingConfig); @@ -786,6 +811,7 @@ const GroupingProvider = ({ definition: panelDefinition, dispatch, firstChildSummaries, + hasSeverityResults, grouping, groupingConfig, nodeStates, diff --git a/ui/dashboard/src/styles/index.css b/ui/dashboard/src/styles/index.css index f545dd32..823e5157 100644 --- a/ui/dashboard/src/styles/index.css +++ b/ui/dashboard/src/styles/index.css @@ -7,9 +7,11 @@ --color-alert: 218 30 40; /*#DA1E28*/ --color-alert-animate: rgba(218, 30, 40, 0.8); /*#DA1E28*/ --color-alert-inverse: theme("colors.white"); - --color-orange: #ff832b; + --color-orange: 255 131 43; /*#FF832B*/ + --color-orange-animate: rgba(255, 131, 43, 0.8); /*#FF832B*/ --color-orange-inverse: theme("colors.white"); - --color-severity: #c9a00c; + --color-severity: 201 160 12; /*#C9A00C*/ + --color-severity-animate: rgba(201, 160, 12, 0.8); /*#C9A00C*/ --color-ok: 25 128 56; /*#198038*/ --color-ok-animate: rgba(25, 128, 56, 0.8); /*#198038*/ --color-ok-inverse: theme("colors.white"); @@ -61,9 +63,11 @@ --color-alert: 248 55 65; /*#F83741*/ --color-alert-animate: rgba(248, 55, 65, 0.8); /*#F83741*/ --color-alert-inverse: theme("colors.white"); - --color-orange: #ff832b; + --color-orange: 255 131 43; /*#FF832B*/ + --color-orange-animate: rgba(255, 131, 43, 0.8); /*#FF832B*/ --color-orange-inverse: theme("colors.white"); - --color-severity: #bd960b; + --color-severity: 189 150 11; /*#BD960B*/ + --color-severity-animate: rgba(189, 150, 11, 0.8); /*#BD960B*/ --color-ok: 36 161 72; /*#24a148*/ --color-ok-animate: rgba(36, 161, 72, 0.8); /*#24a148*/ --color-ok-inverse: theme("colors.white"); @@ -163,7 +167,8 @@ animation: barberpole 10s linear infinite; } -.summary-chart-alarm-animate { +.summary-chart-alarm-animate, +.summary-chart-severity-critical-animate { background-image: repeating-linear-gradient( -45deg, var(--color-alert-animate), @@ -175,6 +180,30 @@ animation: barberpole 10s linear infinite; } +.summary-chart-severity-high-animate { + background-image: repeating-linear-gradient( + -45deg, + var(--color-orange-animate), + var(--color-orange-animate) 0.5rem, + rgb(var(--color-orange)) 0.5rem, + rgb(var(--color-orange)) 1.25rem + ); + background-size: 200% 200%; + animation: barberpole 10s linear infinite; +} + +.summary-chart-severity-medium-animate { + background-image: repeating-linear-gradient( + -45deg, + var(--color-severity-animate), + var(--color-severity-animate) 0.5rem, + rgb(var(--color-severity)) 0.5rem, + rgb(var(--color-severity)) 1.25rem + ); + background-size: 200% 200%; + animation: barberpole 10s linear infinite; +} + .summary-chart-ok-animate { background-image: repeating-linear-gradient( -45deg, @@ -187,7 +216,8 @@ animation: barberpole 10s linear infinite; } -.summary-chart-info-animate { +.summary-chart-info-animate, +.summary-chart-severity-low-animate { background-image: repeating-linear-gradient( -45deg, var(--color-info-animate), diff --git a/ui/dashboard/tailwind.config.js b/ui/dashboard/tailwind.config.js index 3bd7db23..766f05f2 100644 --- a/ui/dashboard/tailwind.config.js +++ b/ui/dashboard/tailwind.config.js @@ -14,8 +14,8 @@ module.exports = { alert: "rgb(var(--color-alert) / )", "alert-light": "rgb(var(--color-alert) / 33.33)", "alert-inverse": "var(--color-alert-inverse)", - orange: "var(--color-orange)", - severity: "var(--color-severity)", + orange: "rgb(var(--color-orange) / )", + severity: "rgb(var(--color-severity) / )", ok: "rgb(var(--color-ok) / )", "ok-inverse": "var(--color-ok-inverse)", info: "rgb(var(--color-info) / )",