mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix OverviewWorkloadStatus to satisfy tests
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
4d19a4ed47
commit
ed48d1611f
@ -6,8 +6,6 @@
|
|||||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||||
import type { IComputedValue } from "mobx";
|
import type { IComputedValue } from "mobx";
|
||||||
|
|
||||||
export const allowedResourcesInjectionToken = getInjectionToken<
|
export const allowedResourcesInjectionToken = getInjectionToken<IComputedValue<Set<string>>>({
|
||||||
IComputedValue<Set<string>>
|
|
||||||
>({
|
|
||||||
id: "allowed-resources",
|
id: "allowed-resources",
|
||||||
});
|
});
|
||||||
|
|||||||
@ -31,7 +31,7 @@ const NonInjectedOverviewStatuses = observer(
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<OverviewWorkloadStatus status={workload.status.get()} />
|
<OverviewWorkloadStatus workload={workload} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -10,90 +10,105 @@ import capitalize from "lodash/capitalize";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import type { DatasetTooltipLabel, PieChartData } from "../chart";
|
import type { DatasetTooltipLabel, PieChartData } from "../chart";
|
||||||
import { PieChart } from "../chart";
|
import { PieChart } from "../chart";
|
||||||
import { cssVar, object } from "../../utils";
|
import { object } from "../../utils";
|
||||||
import type { ThemeStore } from "../../themes/store";
|
import type { LensTheme } from "../../themes/store";
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import themeStoreInjectable from "../../themes/store.injectable";
|
import type { PascalCase } from "type-fest";
|
||||||
|
import type { IComputedValue } from "mobx";
|
||||||
|
import activeThemeInjectable from "../../themes/active.injectable";
|
||||||
|
import type { Workload } from "./workloads/workload-injection-token";
|
||||||
|
|
||||||
|
export type LowercaseOrPascalCase<T extends string> = Lowercase<T> | PascalCase<T>;
|
||||||
|
|
||||||
|
export type WorkloadStatus = Partial<Record<LowercaseOrPascalCase<keyof typeof statusBackgroundColorMapping>, number>>;
|
||||||
|
|
||||||
|
function toLowercase<T extends string>(src: T): Lowercase<T> {
|
||||||
|
return src.toLowerCase() as Lowercase<T>;
|
||||||
|
}
|
||||||
|
|
||||||
export interface OverviewWorkloadStatusProps {
|
export interface OverviewWorkloadStatusProps {
|
||||||
status: Partial<Record<string, number>>;
|
workload: Workload;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
themeStore: ThemeStore;
|
activeTheme: IComputedValue<LensTheme>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
const statusBackgroundColorMapping = {
|
||||||
class NonInjectedOverviewWorkloadStatus extends React.Component<OverviewWorkloadStatusProps & Dependencies> {
|
"running": "colorOk",
|
||||||
private elem: HTMLElement | null = null;
|
"scheduled": "colorOk",
|
||||||
|
"pending": "colorWarning",
|
||||||
|
"suspended": "colorWarning",
|
||||||
|
"evicted": "colorError",
|
||||||
|
"succeeded": "colorSuccess",
|
||||||
|
"failed": "colorError",
|
||||||
|
"terminated": "colorTerminated",
|
||||||
|
"terminating": "colorTerminated",
|
||||||
|
"unknown": "colorVague",
|
||||||
|
"complete": "colorSuccess",
|
||||||
|
} as const;
|
||||||
|
|
||||||
renderChart() {
|
const NonInjectedOverviewWorkloadStatus = observer((props: OverviewWorkloadStatusProps & Dependencies) => {
|
||||||
if (!this.elem) {
|
const {
|
||||||
return null;
|
workload,
|
||||||
|
activeTheme,
|
||||||
|
} = props;
|
||||||
|
const chartData: Required<PieChartData> = {
|
||||||
|
labels: [],
|
||||||
|
datasets: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const statuses = object.entries(workload.status.get()).filter(([, val]) => val > 0);
|
||||||
|
const theme = activeTheme.get();
|
||||||
|
|
||||||
|
if (statuses.length === 0) {
|
||||||
|
chartData.datasets.push({
|
||||||
|
data: [1],
|
||||||
|
backgroundColor: [theme.colors.pieChartDefaultColor],
|
||||||
|
label: "Empty",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const data: number[] = [];
|
||||||
|
const backgroundColor: string[] = [];
|
||||||
|
const tooltipLabels: DatasetTooltipLabel[] = [];
|
||||||
|
|
||||||
|
for (const [status, value] of statuses) {
|
||||||
|
data.push(value);
|
||||||
|
backgroundColor.push(theme.colors[statusBackgroundColorMapping[toLowercase(status)]]);
|
||||||
|
tooltipLabels.push(percent => `${capitalize(status)}: ${percent}`);
|
||||||
|
chartData.labels.push(`${capitalize(status)}: ${value}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cssVars = cssVar(this.elem);
|
chartData.datasets.push({
|
||||||
const chartData: Required<PieChartData> = {
|
data,
|
||||||
labels: [],
|
backgroundColor,
|
||||||
datasets: [],
|
label: "Status",
|
||||||
};
|
tooltipLabels,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const statuses = object.entries(this.props.status).filter(([, val]) => val > 0);
|
return (
|
||||||
|
<div className="OverviewWorkloadStatus">
|
||||||
if (statuses.length === 0) {
|
<div className="flex column align-center box grow">
|
||||||
chartData.datasets.push({
|
<PieChart
|
||||||
data: [1],
|
data={chartData}
|
||||||
backgroundColor: [this.props.themeStore.activeTheme.colors.pieChartDefaultColor],
|
options={{
|
||||||
label: "Empty",
|
elements: {
|
||||||
});
|
arc: {
|
||||||
} else {
|
borderWidth: 0,
|
||||||
const data: number[] = [];
|
},
|
||||||
const backgroundColor: string[] = [];
|
|
||||||
const tooltipLabels: DatasetTooltipLabel[] = [];
|
|
||||||
|
|
||||||
for (const [status, value] of statuses) {
|
|
||||||
data.push(value);
|
|
||||||
backgroundColor.push(cssVars.get(`--workload-status-${status.toLowerCase()}`).toString());
|
|
||||||
tooltipLabels.push(percent => `${capitalize(status)}: ${percent}`);
|
|
||||||
chartData.labels.push(`${capitalize(status)}: ${value}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
chartData.datasets.push({
|
|
||||||
data,
|
|
||||||
backgroundColor,
|
|
||||||
label: "Status",
|
|
||||||
tooltipLabels,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PieChart
|
|
||||||
data={chartData}
|
|
||||||
options={{
|
|
||||||
elements: {
|
|
||||||
arc: {
|
|
||||||
borderWidth: 0,
|
|
||||||
},
|
},
|
||||||
},
|
}}
|
||||||
}}
|
data-testid={`workload-overview-status-chart-${workload.title.toLowerCase().replace(/\s+/, "-")}`}
|
||||||
/>
|
/>
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div className="OverviewWorkloadStatus" ref={e => this.elem = e}>
|
|
||||||
<div className="flex column align-center box grow">
|
|
||||||
{this.renderChart()}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
</div>
|
||||||
}
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
export const OverviewWorkloadStatus = withInjectables<Dependencies, OverviewWorkloadStatusProps>(NonInjectedOverviewWorkloadStatus, {
|
export const OverviewWorkloadStatus = withInjectables<Dependencies, OverviewWorkloadStatusProps>(NonInjectedOverviewWorkloadStatus, {
|
||||||
getProps: (di, props) => ({
|
getProps: (di, props) => ({
|
||||||
...props,
|
...props,
|
||||||
themeStore: di.inject(themeStoreInjectable),
|
activeTheme: di.inject(activeThemeInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -104,7 +104,7 @@ class NonInjectedWorkloadsOverview extends React.Component<Dependencies> {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<SiblingsInTabLayout>
|
<SiblingsInTabLayout>
|
||||||
<div className="WorkloadsOverview flex column gaps">
|
<div className="WorkloadsOverview flex column gaps" data-testid="page-for-workloads-overview">
|
||||||
<div className="header flex gaps align-center">
|
<div className="header flex gaps align-center">
|
||||||
<h5 className="box grow">Overview</h5>
|
<h5 className="box grow">Overview</h5>
|
||||||
{this.renderLoadErrors()}
|
{this.renderLoadErrors()}
|
||||||
|
|||||||
@ -4,12 +4,13 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||||
import type { IComputedValue } from "mobx";
|
import type { IComputedValue } from "mobx";
|
||||||
|
import type { WorkloadStatus } from "../overview-workload-status";
|
||||||
|
|
||||||
export interface Workload {
|
export interface Workload {
|
||||||
resourceName: string;
|
resourceName: string;
|
||||||
open: () => void;
|
open: () => void;
|
||||||
amountOfItems: IComputedValue<number>;
|
amountOfItems: IComputedValue<number>;
|
||||||
status: IComputedValue<Partial<Record<string, number>>>;
|
status: IComputedValue<WorkloadStatus>;
|
||||||
title: string;
|
title: string;
|
||||||
orderNumber: number;
|
orderNumber: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,7 @@ export interface ChartProps {
|
|||||||
redraw?: boolean; // If true - recreate chart instance with no animation
|
redraw?: boolean; // If true - recreate chart instance with no animation
|
||||||
title?: string;
|
title?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
"data-testid"?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ChartKind {
|
export enum ChartKind {
|
||||||
@ -212,25 +213,26 @@ export class Chart extends React.Component<ChartProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { width, height, showChart, title, className } = this.props;
|
const { width, height, showChart, title, className, "data-testid": dataTestId } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div
|
||||||
<div className={cssNames("Chart", className)}>
|
className={cssNames("Chart", className)}
|
||||||
{title && <div className="chart-title">{title}</div>}
|
data-testid={dataTestId}
|
||||||
{showChart && (
|
>
|
||||||
<div className="chart-container">
|
{title && <div className="chart-title">{title}</div>}
|
||||||
<canvas
|
{showChart && (
|
||||||
ref={this.canvas}
|
<div className="chart-container">
|
||||||
width={width}
|
<canvas
|
||||||
height={height}
|
ref={this.canvas}
|
||||||
/>
|
width={width}
|
||||||
<div className="chartjs-tooltip flex column"></div>
|
height={height}
|
||||||
</div>
|
/>
|
||||||
)}
|
<div className="chartjs-tooltip flex column"></div>
|
||||||
{this.renderLegend()}
|
</div>
|
||||||
</div>
|
)}
|
||||||
</>
|
{this.renderLegend()}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user