@flanksource/clicky-ui 0.3.38 → 0.3.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -0
- package/dist/data/TimeseriesCoreBars.cjs +10 -36
- package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
- package/dist/data/TimeseriesCoreBars.d.ts +1 -1
- package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
- package/dist/data/TimeseriesCoreBars.js +8 -34
- package/dist/data/TimeseriesCoreBars.js.map +1 -1
- package/dist/data/TimeseriesGauge.cjs +12 -36
- package/dist/data/TimeseriesGauge.cjs.map +1 -1
- package/dist/data/TimeseriesGauge.d.ts +14 -4
- package/dist/data/TimeseriesGauge.d.ts.map +1 -1
- package/dist/data/TimeseriesGauge.js +10 -34
- package/dist/data/TimeseriesGauge.js.map +1 -1
- package/dist/data/TimeseriesPanel.cjs +82 -39
- package/dist/data/TimeseriesPanel.cjs.map +1 -1
- package/dist/data/TimeseriesPanel.d.ts +1 -1
- package/dist/data/TimeseriesPanel.d.ts.map +1 -1
- package/dist/data/TimeseriesPanel.js +82 -39
- package/dist/data/TimeseriesPanel.js.map +1 -1
- package/dist/data/TimeseriesPanel.model.cjs +1 -0
- package/dist/data/TimeseriesPanel.model.cjs.map +1 -1
- package/dist/data/TimeseriesPanel.model.d.ts +38 -2
- package/dist/data/TimeseriesPanel.model.d.ts.map +1 -1
- package/dist/data/TimeseriesPanel.model.js +1 -0
- package/dist/data/TimeseriesPanel.model.js.map +1 -1
- package/dist/data/WorkloadCard.cjs +65 -31
- package/dist/data/WorkloadCard.cjs.map +1 -1
- package/dist/data/WorkloadCard.d.ts +15 -5
- package/dist/data/WorkloadCard.d.ts.map +1 -1
- package/dist/data/WorkloadCard.js +67 -33
- package/dist/data/WorkloadCard.js.map +1 -1
- package/dist/data/WorkloadCard.model.cjs +16 -10
- package/dist/data/WorkloadCard.model.cjs.map +1 -1
- package/dist/data/WorkloadCard.model.d.ts +29 -1
- package/dist/data/WorkloadCard.model.d.ts.map +1 -1
- package/dist/data/WorkloadCard.model.js +17 -11
- package/dist/data/WorkloadCard.model.js.map +1 -1
- package/dist/data/timeseries-query.cjs +51 -0
- package/dist/data/timeseries-query.cjs.map +1 -0
- package/dist/data/timeseries-query.d.ts +31 -0
- package/dist/data/timeseries-query.d.ts.map +1 -0
- package/dist/data/timeseries-query.js +51 -0
- package/dist/data/timeseries-query.js.map +1 -0
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +1 -0
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +2 -2
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +3 -2
- package/dist/index.cjs +1 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkloadCard.d.ts","sourceRoot":"","sources":["../../src/data/WorkloadCard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAe1D,OAAO,
|
|
1
|
+
{"version":3,"file":"WorkloadCard.d.ts","sourceRoot":"","sources":["../../src/data/WorkloadCard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAe1D,OAAO,EAGL,KAAK,kBAAkB,EAExB,MAAM,mBAAmB,CAAC;AAQ3B,OAAO,EAOL,KAAK,mBAAmB,EAExB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B;;;;OAIG;IACH,OAAO,EAAE,mBAAmB,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6EAA6E;IAC7E,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAClD,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,SAAS,GACT,QAAQ,GACR,UAAU,GACV,OAAO,CAAC;AA2MZ;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,OAAO,EACP,OAAO,EACP,KAAY,EACZ,SAAgB,EAChB,UAAiB,EACjB,aAAa,EACb,IAAW,EACX,OAAmB,EACnB,OAAO,EACP,SAAS,GACV,EAAE,iBAAiB,+BA2OnB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs, jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useMemo } from "react";
|
|
3
3
|
import { K8SPod, K8SStatefulset, K8SDeployment, K8SIngress, K8SService } from "@flanksource/icons/mi";
|
|
4
4
|
import { cn } from "../lib/utils.js";
|
|
@@ -9,7 +9,8 @@ import { Icon } from "./Icon.js";
|
|
|
9
9
|
import { TimeseriesCoreBars } from "./TimeseriesCoreBars.js";
|
|
10
10
|
import { TimeseriesGauge } from "./TimeseriesGauge.js";
|
|
11
11
|
import { TimeseriesPanel } from "./TimeseriesPanel.js";
|
|
12
|
-
import {
|
|
12
|
+
import { workloadTypeLabel, workloadStatusLabel, workloadStatusTone, formatReplicaCounts } from "./WorkloadCard.model.js";
|
|
13
|
+
import { UiBox } from "../icons/components/UiBox.js";
|
|
13
14
|
import { UiChip } from "../icons/components/UiChip.js";
|
|
14
15
|
import { UiMemoryStick } from "../icons/components/UiMemoryStick.js";
|
|
15
16
|
import { UiHardDrive } from "../icons/components/UiHardDrive.js";
|
|
@@ -77,7 +78,7 @@ function metricGridClass(count) {
|
|
|
77
78
|
if (count === 2) return "grid-cols-2";
|
|
78
79
|
return "grid-cols-3";
|
|
79
80
|
}
|
|
80
|
-
const MEMORY_BAR_UNIT = { perBar: 1024 ** 3, label: "
|
|
81
|
+
const MEMORY_BAR_UNIT = { perBar: 1024 ** 3, label: "GiB", barLabel: "GiB" };
|
|
81
82
|
function WorkloadIcon({
|
|
82
83
|
icon,
|
|
83
84
|
title,
|
|
@@ -90,36 +91,69 @@ function WorkloadIcon({
|
|
|
90
91
|
}
|
|
91
92
|
function metricSeries(metric) {
|
|
92
93
|
const series = [
|
|
93
|
-
{
|
|
94
|
-
id: metric.value.id,
|
|
95
|
-
label: metric.valueLabel ?? "usage",
|
|
96
|
-
...metric.value.transform ? { transform: metric.value.transform } : {}
|
|
97
|
-
}
|
|
94
|
+
{ ...metric.value, label: metric.valueLabel ?? "usage" }
|
|
98
95
|
];
|
|
99
96
|
if (typeof metric.max === "object") {
|
|
100
|
-
series.push({
|
|
101
|
-
id: metric.max.id,
|
|
102
|
-
label: metric.maxLabel ?? "limit",
|
|
103
|
-
...metric.max.transform ? { transform: metric.max.transform } : {}
|
|
104
|
-
});
|
|
97
|
+
series.push({ ...metric.max, label: metric.maxLabel ?? "limit" });
|
|
105
98
|
}
|
|
106
99
|
return series;
|
|
107
100
|
}
|
|
101
|
+
function metricReferenceLines(metric) {
|
|
102
|
+
if (typeof metric.max !== "number") return [];
|
|
103
|
+
return [{ value: metric.max, label: metric.maxLabel ?? "capacity" }];
|
|
104
|
+
}
|
|
108
105
|
function hasMetric(metrics) {
|
|
109
106
|
return Boolean(metrics.cpu || metrics.memory || metrics.disk);
|
|
110
107
|
}
|
|
111
|
-
function HeaderMeta({
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
function HeaderMeta({
|
|
109
|
+
separator,
|
|
110
|
+
title,
|
|
111
|
+
children
|
|
112
|
+
}) {
|
|
113
|
+
return /* @__PURE__ */ jsxs("span", { className: "inline-flex min-w-0 items-center gap-1", title, children: [
|
|
114
|
+
separator ? /* @__PURE__ */ jsx(
|
|
114
115
|
"span",
|
|
115
116
|
{
|
|
116
117
|
className: "h-1 w-1 shrink-0 rounded-full bg-muted-foreground/40",
|
|
117
118
|
"aria-hidden": true
|
|
118
119
|
}
|
|
119
|
-
),
|
|
120
|
+
) : null,
|
|
120
121
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children })
|
|
121
122
|
] });
|
|
122
123
|
}
|
|
124
|
+
function headerMetaItems(workload, typeLabel) {
|
|
125
|
+
var _a;
|
|
126
|
+
const items = [];
|
|
127
|
+
if (typeLabel) items.push({ key: "type", content: typeLabel });
|
|
128
|
+
if (workload.namespace) {
|
|
129
|
+
items.push({ key: "namespace", content: workload.namespace });
|
|
130
|
+
}
|
|
131
|
+
if (workload.role) items.push({ key: "role", content: workload.role });
|
|
132
|
+
const replicaText = formatReplicaCounts(workload.replicas);
|
|
133
|
+
if (replicaText) items.push({ key: "replicas", content: replicaText });
|
|
134
|
+
if (workload.createdAt !== void 0) {
|
|
135
|
+
items.push({
|
|
136
|
+
key: "age",
|
|
137
|
+
content: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
138
|
+
"age ",
|
|
139
|
+
/* @__PURE__ */ jsx(Timestamp, { value: workload.createdAt, format: "relative" })
|
|
140
|
+
] })
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
(_a = workload.metadata) == null ? void 0 : _a.forEach((item, i) => {
|
|
144
|
+
const plain = typeof item.value === "string" || typeof item.value === "number";
|
|
145
|
+
items.push({
|
|
146
|
+
key: `meta-${i}`,
|
|
147
|
+
content: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
148
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/70", children: item.label }),
|
|
149
|
+
" ",
|
|
150
|
+
item.value
|
|
151
|
+
] }),
|
|
152
|
+
title: plain ? `${item.label}: ${item.value}` : item.label
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
return items;
|
|
156
|
+
}
|
|
123
157
|
function WorkloadCard({
|
|
124
158
|
workload,
|
|
125
159
|
metrics,
|
|
@@ -135,10 +169,10 @@ function WorkloadCard({
|
|
|
135
169
|
}) {
|
|
136
170
|
var _a;
|
|
137
171
|
const [expanded, setExpanded] = useState(false);
|
|
138
|
-
const
|
|
172
|
+
const typeLabel = workloadTypeLabel(workload);
|
|
139
173
|
const statusLabel = workloadStatusLabel(workload.status);
|
|
140
|
-
const
|
|
141
|
-
const workloadIcon = workload.icon ?? KIND_ICONS[workload.kind];
|
|
174
|
+
const metaItems = headerMetaItems(workload, typeLabel);
|
|
175
|
+
const workloadIcon = workload.icon ?? (workload.kind ? KIND_ICONS[workload.kind] : UiBox);
|
|
142
176
|
const sizeClasses = SIZE_CLASSES[size];
|
|
143
177
|
const panelMetrics = useMemo(() => {
|
|
144
178
|
const list = [];
|
|
@@ -205,7 +239,7 @@ function WorkloadCard({
|
|
|
205
239
|
WorkloadIcon,
|
|
206
240
|
{
|
|
207
241
|
icon: workloadIcon,
|
|
208
|
-
title:
|
|
242
|
+
title: typeLabel ?? workload.name,
|
|
209
243
|
className: cn("shrink-0 text-muted-foreground", sizeClasses.icon)
|
|
210
244
|
}
|
|
211
245
|
),
|
|
@@ -220,25 +254,24 @@ function WorkloadCard({
|
|
|
220
254
|
]
|
|
221
255
|
}
|
|
222
256
|
),
|
|
223
|
-
/* @__PURE__ */
|
|
257
|
+
metaItems.length > 0 ? /* @__PURE__ */ jsx(
|
|
224
258
|
"div",
|
|
225
259
|
{
|
|
226
260
|
className: cn(
|
|
227
261
|
"flex flex-wrap items-center text-muted-foreground",
|
|
228
262
|
sizeClasses.meta
|
|
229
263
|
),
|
|
230
|
-
children:
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
]
|
|
264
|
+
children: metaItems.map((item, i) => /* @__PURE__ */ jsx(
|
|
265
|
+
HeaderMeta,
|
|
266
|
+
{
|
|
267
|
+
separator: i > 0,
|
|
268
|
+
title: item.title,
|
|
269
|
+
children: item.content
|
|
270
|
+
},
|
|
271
|
+
item.key
|
|
272
|
+
))
|
|
240
273
|
}
|
|
241
|
-
)
|
|
274
|
+
) : null
|
|
242
275
|
] }),
|
|
243
276
|
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
244
277
|
statusLabel ? /* @__PURE__ */ jsx("span", { title: (_a = workload.status) == null ? void 0 : _a.message, children: /* @__PURE__ */ jsx(
|
|
@@ -355,6 +388,7 @@ function WorkloadCard({
|
|
|
355
388
|
title,
|
|
356
389
|
icon,
|
|
357
390
|
series: metricSeries(metric),
|
|
391
|
+
referenceLines: metricReferenceLines(metric),
|
|
358
392
|
...unit ? { unit } : {},
|
|
359
393
|
...metricProps,
|
|
360
394
|
expandable: false
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkloadCard.js","sources":["../../src/data/WorkloadCard.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport {\n K8SDeployment,\n K8SIngress,\n K8SPod,\n K8SService,\n K8SStatefulset,\n} from \"@flanksource/icons/mi\";\nimport { cn } from \"../lib/utils\";\nimport { Modal } from \"../overlay/Modal\";\nimport { Badge } from \"./Badge\";\nimport { Timestamp } from \"./cells/Timestamp\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { TimeseriesCoreBars } from \"./TimeseriesCoreBars\";\nimport { TimeseriesGauge } from \"./TimeseriesGauge\";\nimport {\n TimeseriesPanel,\n type TimeseriesResponse,\n type TimeseriesSeries,\n} from \"./TimeseriesPanel\";\nimport { UiChip, UiFullscreen, UiHardDrive, UiMemoryStick } from \"../icons\";\nimport {\n formatReplicaCounts,\n workloadKindLabel,\n workloadStatusLabel,\n workloadStatusTone,\n type WorkloadCardIcon,\n type WorkloadCardKind,\n type WorkloadCardMetrics,\n type WorkloadCardResourceMetric,\n type WorkloadCardWorkload,\n} from \"./WorkloadCard.model\";\n\nexport interface WorkloadCardProps {\n workload: WorkloadCardWorkload;\n metrics: WorkloadCardMetrics;\n baseUrl?: string;\n range?: string;\n refreshMs?: number;\n expandable?: boolean;\n /** Controls rendered beside status and history, owned by the host domain. */\n headerActions?: ReactNode;\n size?: WorkloadCardSize;\n variant?: WorkloadCardVariant;\n fetcher?: (url: string) => Promise<TimeseriesResponse>;\n className?: string;\n}\n\nexport type WorkloadCardSize = \"sm\" | \"md\" | \"lg\";\nexport type WorkloadCardVariant =\n | \"default\"\n | \"outline\"\n | \"subtle\"\n | \"elevated\"\n | \"ghost\";\n\ntype MetricKey = keyof WorkloadCardMetrics;\n\ntype PanelMetric = {\n key: MetricKey;\n title: string;\n unit?: string;\n icon: WorkloadCardIcon;\n metric: WorkloadCardResourceMetric;\n};\n\nconst KIND_ICONS: Record<WorkloadCardKind, StaticIconComponent> = {\n service: K8SService,\n ingress: K8SIngress,\n deployment: K8SDeployment,\n statefulset: K8SStatefulset,\n pod: K8SPod,\n};\n\ntype WorkloadCardSizeClasses = {\n root: string;\n header: string;\n titleGap: string;\n icon: string;\n name: string;\n meta: string;\n statusSize: \"xxs\" | \"xs\" | \"sm\";\n action: string;\n actionIcon: number;\n metricGrid: string;\n metricVariant: \"default\" | \"cell\";\n empty: string;\n};\n\nconst SIZE_CLASSES: Record<WorkloadCardSize, WorkloadCardSizeClasses> = {\n sm: {\n root: \"p-2\",\n header: \"mb-2 gap-2\",\n titleGap: \"gap-1\",\n icon: \"h-3.5 w-3.5\",\n name: \"text-xs\",\n meta: \"mt-0.5 gap-x-1.5 gap-y-0.5 text-[11px] leading-4\",\n statusSize: \"xxs\",\n action: \"h-5 w-5\",\n actionIcon: 12,\n metricGrid: \"grid-cols-1 gap-1.5\",\n metricVariant: \"cell\",\n empty: \"px-2 py-3 text-[11px]\",\n },\n md: {\n root: \"p-3\",\n header: \"mb-3 gap-2\",\n titleGap: \"gap-1.5\",\n icon: \"h-4 w-4\",\n name: \"text-sm\",\n meta: \"mt-0.5 gap-x-2 gap-y-0.5 text-xs\",\n statusSize: \"xs\",\n action: \"h-6 w-6\",\n actionIcon: 14,\n metricGrid: \"gap-3\",\n metricVariant: \"default\",\n empty: \"px-3 py-4 text-xs\",\n },\n lg: {\n root: \"p-4\",\n header: \"mb-4 gap-3\",\n titleGap: \"gap-2\",\n icon: \"h-5 w-5\",\n name: \"text-base\",\n meta: \"mt-1 gap-x-2 gap-y-1 text-xs\",\n statusSize: \"sm\",\n action: \"h-7 w-7\",\n actionIcon: 16,\n metricGrid: \"gap-4\",\n metricVariant: \"default\",\n empty: \"px-4 py-6 text-sm\",\n },\n};\n\nconst VARIANT_CLASSES: Record<WorkloadCardVariant, string> = {\n default: \"border-border bg-card text-card-foreground\",\n outline: \"border-border bg-background text-foreground\",\n subtle: \"border-transparent bg-muted/35 text-foreground\",\n elevated: \"border-border/70 bg-card text-card-foreground shadow-sm\",\n ghost: \"border-transparent bg-transparent text-foreground\",\n};\n\nfunction metricGridClass(count: number): string {\n if (count <= 1) return \"grid-cols-1\";\n if (count === 2) return \"grid-cols-2\";\n return \"grid-cols-3\";\n}\n\n// Memory renders as cores-style bars at one bar per gigabyte, matching CPU; bytes\n// are fed raw and TimeseriesCoreBars divides by perBar so captions read \"x GB\".\nconst MEMORY_BAR_UNIT = { perBar: 1024 ** 3, label: \"GB\", barLabel: \"GB\" };\n\nfunction WorkloadIcon({\n icon,\n title,\n className,\n}: {\n icon: WorkloadCardIcon;\n title: string;\n className?: string;\n}) {\n if (typeof icon === \"string\") {\n return (\n <Icon name={icon} title={title} {...(className ? { className } : {})} />\n );\n }\n return (\n <Icon icon={icon} title={title} {...(className ? { className } : {})} />\n );\n}\n\nfunction metricSeries(metric: WorkloadCardResourceMetric): TimeseriesSeries[] {\n const series: TimeseriesSeries[] = [\n {\n id: metric.value.id,\n label: metric.valueLabel ?? \"usage\",\n ...(metric.value.transform ? { transform: metric.value.transform } : {}),\n },\n ];\n if (typeof metric.max === \"object\") {\n series.push({\n id: metric.max.id,\n label: metric.maxLabel ?? \"limit\",\n ...(metric.max.transform ? { transform: metric.max.transform } : {}),\n });\n }\n return series;\n}\n\nfunction hasMetric(metrics: WorkloadCardMetrics): boolean {\n return Boolean(metrics.cpu || metrics.memory || metrics.disk);\n}\n\nfunction HeaderMeta({ children }: { children: ReactNode }) {\n return (\n <span className=\"inline-flex min-w-0 items-center gap-1\">\n <span\n className=\"h-1 w-1 shrink-0 rounded-full bg-muted-foreground/40\"\n aria-hidden\n />\n <span className=\"min-w-0 truncate\">{children}</span>\n </span>\n );\n}\n\n/**\n * WorkloadCard is a compact resource card for Kubernetes-style workloads. It\n * shows workload identity, status, replica/age metadata, and CPU/memory/disk\n * utilization backed by the existing time-series primitives: CPU and memory as\n * core-style bars (memory at one bar per GB) and disk as a linear progress bar.\n * Callers own the metric ids; the card only composes the supplied series.\n */\nexport function WorkloadCard({\n workload,\n metrics,\n baseUrl,\n range = \"1h\",\n refreshMs = 5000,\n expandable = true,\n headerActions,\n size = \"md\",\n variant = \"default\",\n fetcher,\n className,\n}: WorkloadCardProps) {\n const [expanded, setExpanded] = useState(false);\n const kindLabel = workloadKindLabel(workload.kind);\n const statusLabel = workloadStatusLabel(workload.status);\n const replicaText = formatReplicaCounts(workload.replicas);\n const workloadIcon = workload.icon ?? KIND_ICONS[workload.kind];\n const sizeClasses = SIZE_CLASSES[size];\n\n const panelMetrics = useMemo(() => {\n const list: PanelMetric[] = [];\n if (metrics.cpu) {\n list.push({\n key: \"cpu\",\n title: metrics.cpu.title ?? \"CPU\",\n unit: metrics.cpu.unit ?? \"short\",\n icon: metrics.cpu.icon ?? UiChip,\n metric: metrics.cpu,\n });\n }\n if (metrics.memory) {\n list.push({\n key: \"memory\",\n title: metrics.memory.title ?? \"Memory\",\n unit: metrics.memory.unit ?? \"bytes\",\n icon: metrics.memory.icon ?? UiMemoryStick,\n metric: metrics.memory,\n });\n }\n if (metrics.disk) {\n list.push({\n key: \"disk\",\n title: metrics.disk.title ?? \"Disk\",\n unit: metrics.disk.unit ?? \"bytes\",\n icon: metrics.disk.icon ?? UiHardDrive,\n metric: metrics.disk,\n });\n }\n return list;\n }, [metrics]);\n\n const metricProps = {\n ...(baseUrl !== undefined ? { baseUrl } : {}),\n range,\n refreshMs,\n ...(fetcher !== undefined ? { fetcher } : {}),\n };\n const canExpand = expandable && hasMetric(metrics);\n\n return (\n <div\n className={cn(\n \"w-full rounded-md border\",\n VARIANT_CLASSES[variant],\n sizeClasses.root,\n className,\n )}\n data-size={size}\n data-variant={variant}\n >\n <div\n className={cn(\"flex items-start justify-between\", sizeClasses.header)}\n >\n <div className=\"min-w-0\">\n <div\n className={cn(\"flex min-w-0 items-center\", sizeClasses.titleGap)}\n >\n <WorkloadIcon\n icon={workloadIcon}\n title={kindLabel}\n className={cn(\"shrink-0 text-muted-foreground\", sizeClasses.icon)}\n />\n <span\n className={cn(\"min-w-0 truncate font-medium\", sizeClasses.name)}\n title={workload.name}\n >\n {workload.name}\n </span>\n </div>\n <div\n className={cn(\n \"flex flex-wrap items-center text-muted-foreground\",\n sizeClasses.meta,\n )}\n >\n <span>{kindLabel}</span>\n {workload.namespace ? (\n <HeaderMeta>{workload.namespace}</HeaderMeta>\n ) : null}\n {workload.role ? <HeaderMeta>{workload.role}</HeaderMeta> : null}\n {replicaText ? <HeaderMeta>{replicaText}</HeaderMeta> : null}\n {workload.createdAt !== undefined ? (\n <HeaderMeta>\n age <Timestamp value={workload.createdAt} format=\"relative\" />\n </HeaderMeta>\n ) : null}\n </div>\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {statusLabel ? (\n <span title={workload.status?.message}>\n <Badge\n tone={workloadStatusTone(workload.status)}\n variant=\"soft\"\n size={sizeClasses.statusSize}\n >\n {statusLabel}\n </Badge>\n </span>\n ) : null}\n {headerActions}\n {canExpand ? (\n <button\n type=\"button\"\n aria-label={`Open ${workload.name} history`}\n title=\"History\"\n onClick={() => setExpanded(true)}\n className={cn(\n \"inline-flex items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\",\n sizeClasses.action,\n )}\n >\n <Icon\n icon={UiFullscreen}\n width={sizeClasses.actionIcon}\n height={sizeClasses.actionIcon}\n />\n </button>\n ) : null}\n </div>\n </div>\n\n {hasMetric(metrics) ? (\n <div\n className={cn(\n \"grid items-start gap-3\",\n sizeClasses.metricVariant === \"cell\"\n ? sizeClasses.metricGrid\n : cn(\n metricGridClass(panelMetrics.length),\n sizeClasses.metricGrid,\n ),\n )}\n >\n {metrics.cpu ? (\n <TimeseriesCoreBars\n title={metrics.cpu.title ?? \"CPU\"}\n icon={metrics.cpu.icon ?? UiChip}\n value={metrics.cpu.value}\n {...(metrics.cpu.max !== undefined\n ? { max: metrics.cpu.max }\n : {})}\n {...(metrics.cpu.thresholds\n ? { thresholds: metrics.cpu.thresholds }\n : {})}\n {...(metrics.cpu.orientation\n ? { orientation: metrics.cpu.orientation }\n : {})}\n {...(metrics.cpu.showValue !== undefined\n ? { showValue: metrics.cpu.showValue }\n : {})}\n variant={sizeClasses.metricVariant}\n {...metricProps}\n />\n ) : null}\n {metrics.memory ? (\n <TimeseriesCoreBars\n title={metrics.memory.title ?? \"Memory\"}\n icon={metrics.memory.icon ?? UiMemoryStick}\n value={metrics.memory.value}\n unit={MEMORY_BAR_UNIT}\n variant={sizeClasses.metricVariant}\n {...(metrics.memory.max !== undefined\n ? { max: metrics.memory.max }\n : {})}\n {...(metrics.memory.thresholds\n ? { thresholds: metrics.memory.thresholds }\n : {})}\n {...metricProps}\n />\n ) : null}\n {metrics.disk ? (\n <TimeseriesGauge\n title={metrics.disk.title ?? \"Disk\"}\n icon={metrics.disk.icon ?? UiHardDrive}\n value={metrics.disk.value}\n unit={metrics.disk.unit ?? \"bytes\"}\n shape=\"linear\"\n expandable={false}\n centerDisplay={metrics.disk.centerDisplay ?? \"value\"}\n variant={sizeClasses.metricVariant}\n {...(metrics.disk.max !== undefined\n ? { max: metrics.disk.max }\n : {})}\n {...(metrics.disk.thresholds\n ? { thresholds: metrics.disk.thresholds }\n : {})}\n {...metricProps}\n />\n ) : null}\n </div>\n ) : (\n <div\n className={cn(\n \"rounded-md border border-dashed border-border text-center text-muted-foreground\",\n sizeClasses.empty,\n )}\n >\n No metrics configured\n </div>\n )}\n\n <Modal\n open={expanded}\n onClose={() => setExpanded(false)}\n title={`${workload.name} history`}\n size=\"xl\"\n >\n <div className=\"flex flex-col gap-3\">\n {panelMetrics.map(({ key, title, unit, icon, metric }) => (\n <TimeseriesPanel\n key={key}\n title={title}\n icon={icon}\n series={metricSeries(metric)}\n {...(unit ? { unit } : {})}\n {...metricProps}\n expandable={false}\n />\n ))}\n </div>\n </Modal>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkloadCard.js","sources":["../../src/data/WorkloadCard.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport {\n K8SDeployment,\n K8SIngress,\n K8SPod,\n K8SService,\n K8SStatefulset,\n} from \"@flanksource/icons/mi\";\nimport { cn } from \"../lib/utils\";\nimport { Modal } from \"../overlay/Modal\";\nimport { Badge } from \"./Badge\";\nimport { Timestamp } from \"./cells/Timestamp\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { TimeseriesCoreBars } from \"./TimeseriesCoreBars\";\nimport { TimeseriesGauge } from \"./TimeseriesGauge\";\nimport {\n TimeseriesPanel,\n type TimeseriesReferenceLine,\n type TimeseriesResponse,\n type TimeseriesSeries,\n} from \"./TimeseriesPanel\";\nimport {\n UiBox,\n UiChip,\n UiFullscreen,\n UiHardDrive,\n UiMemoryStick,\n} from \"../icons\";\nimport {\n formatReplicaCounts,\n workloadStatusLabel,\n workloadStatusTone,\n workloadTypeLabel,\n type WorkloadCardIcon,\n type WorkloadCardKind,\n type WorkloadCardMetrics,\n type WorkloadCardResourceMetric,\n type WorkloadCardWorkload,\n} from \"./WorkloadCard.model\";\n\nexport interface WorkloadCardProps {\n workload: WorkloadCardWorkload;\n /**\n * CPU/memory/disk series. Each is requested as `baseUrl + id` via `fetcher`,\n * or loaded by its own `load` function (then `id` is the cache key and must\n * be unique per data source).\n */\n metrics: WorkloadCardMetrics;\n baseUrl?: string;\n range?: string;\n refreshMs?: number;\n expandable?: boolean;\n /** Controls rendered beside status and history, owned by the host domain. */\n headerActions?: ReactNode;\n size?: WorkloadCardSize;\n variant?: WorkloadCardVariant;\n fetcher?: (url: string) => Promise<TimeseriesResponse>;\n className?: string;\n}\n\nexport type WorkloadCardSize = \"sm\" | \"md\" | \"lg\";\nexport type WorkloadCardVariant =\n | \"default\"\n | \"outline\"\n | \"subtle\"\n | \"elevated\"\n | \"ghost\";\n\ntype MetricKey = keyof WorkloadCardMetrics;\n\ntype PanelMetric = {\n key: MetricKey;\n title: string;\n unit?: string;\n icon: WorkloadCardIcon;\n metric: WorkloadCardResourceMetric;\n};\n\nconst KIND_ICONS: Record<WorkloadCardKind, StaticIconComponent> = {\n service: K8SService,\n ingress: K8SIngress,\n deployment: K8SDeployment,\n statefulset: K8SStatefulset,\n pod: K8SPod,\n};\n\ntype WorkloadCardSizeClasses = {\n root: string;\n header: string;\n titleGap: string;\n icon: string;\n name: string;\n meta: string;\n statusSize: \"xxs\" | \"xs\" | \"sm\";\n action: string;\n actionIcon: number;\n metricGrid: string;\n metricVariant: \"default\" | \"cell\";\n empty: string;\n};\n\nconst SIZE_CLASSES: Record<WorkloadCardSize, WorkloadCardSizeClasses> = {\n sm: {\n root: \"p-2\",\n header: \"mb-2 gap-2\",\n titleGap: \"gap-1\",\n icon: \"h-3.5 w-3.5\",\n name: \"text-xs\",\n meta: \"mt-0.5 gap-x-1.5 gap-y-0.5 text-[11px] leading-4\",\n statusSize: \"xxs\",\n action: \"h-5 w-5\",\n actionIcon: 12,\n metricGrid: \"grid-cols-1 gap-1.5\",\n metricVariant: \"cell\",\n empty: \"px-2 py-3 text-[11px]\",\n },\n md: {\n root: \"p-3\",\n header: \"mb-3 gap-2\",\n titleGap: \"gap-1.5\",\n icon: \"h-4 w-4\",\n name: \"text-sm\",\n meta: \"mt-0.5 gap-x-2 gap-y-0.5 text-xs\",\n statusSize: \"xs\",\n action: \"h-6 w-6\",\n actionIcon: 14,\n metricGrid: \"gap-3\",\n metricVariant: \"default\",\n empty: \"px-3 py-4 text-xs\",\n },\n lg: {\n root: \"p-4\",\n header: \"mb-4 gap-3\",\n titleGap: \"gap-2\",\n icon: \"h-5 w-5\",\n name: \"text-base\",\n meta: \"mt-1 gap-x-2 gap-y-1 text-xs\",\n statusSize: \"sm\",\n action: \"h-7 w-7\",\n actionIcon: 16,\n metricGrid: \"gap-4\",\n metricVariant: \"default\",\n empty: \"px-4 py-6 text-sm\",\n },\n};\n\nconst VARIANT_CLASSES: Record<WorkloadCardVariant, string> = {\n default: \"border-border bg-card text-card-foreground\",\n outline: \"border-border bg-background text-foreground\",\n subtle: \"border-transparent bg-muted/35 text-foreground\",\n elevated: \"border-border/70 bg-card text-card-foreground shadow-sm\",\n ghost: \"border-transparent bg-transparent text-foreground\",\n};\n\nfunction metricGridClass(count: number): string {\n if (count <= 1) return \"grid-cols-1\";\n if (count === 2) return \"grid-cols-2\";\n return \"grid-cols-3\";\n}\n\n// Memory renders as cores-style bars at one bar per gibibyte, matching CPU; bytes\n// are fed raw and TimeseriesCoreBars divides by perBar so captions read \"x GiB\".\nconst MEMORY_BAR_UNIT = { perBar: 1024 ** 3, label: \"GiB\", barLabel: \"GiB\" };\n\nfunction WorkloadIcon({\n icon,\n title,\n className,\n}: {\n icon: WorkloadCardIcon;\n title: string;\n className?: string;\n}) {\n if (typeof icon === \"string\") {\n return (\n <Icon name={icon} title={title} {...(className ? { className } : {})} />\n );\n }\n return (\n <Icon icon={icon} title={title} {...(className ? { className } : {})} />\n );\n}\n\nfunction metricSeries(metric: WorkloadCardResourceMetric): TimeseriesSeries[] {\n const series: TimeseriesSeries[] = [\n { ...metric.value, label: metric.valueLabel ?? \"usage\" },\n ];\n if (typeof metric.max === \"object\") {\n series.push({ ...metric.max, label: metric.maxLabel ?? \"limit\" });\n }\n return series;\n}\n\n// A fixed numeric max has no series to plot, so the history chart draws it as\n// a flat capacity line instead.\nfunction metricReferenceLines(\n metric: WorkloadCardResourceMetric,\n): TimeseriesReferenceLine[] {\n if (typeof metric.max !== \"number\") return [];\n return [{ value: metric.max, label: metric.maxLabel ?? \"capacity\" }];\n}\n\nfunction hasMetric(metrics: WorkloadCardMetrics): boolean {\n return Boolean(metrics.cpu || metrics.memory || metrics.disk);\n}\n\ntype HeaderMetaItem = { key: string; content: ReactNode; title?: string };\n\nfunction HeaderMeta({\n separator,\n title,\n children,\n}: {\n separator: boolean;\n title?: string | undefined;\n children: ReactNode;\n}) {\n return (\n <span className=\"inline-flex min-w-0 items-center gap-1\" title={title}>\n {separator ? (\n <span\n className=\"h-1 w-1 shrink-0 rounded-full bg-muted-foreground/40\"\n aria-hidden\n />\n ) : null}\n <span className=\"min-w-0 truncate\">{children}</span>\n </span>\n );\n}\n\nfunction headerMetaItems(\n workload: WorkloadCardWorkload,\n typeLabel: string | undefined,\n): HeaderMetaItem[] {\n const items: HeaderMetaItem[] = [];\n if (typeLabel) items.push({ key: \"type\", content: typeLabel });\n if (workload.namespace) {\n items.push({ key: \"namespace\", content: workload.namespace });\n }\n if (workload.role) items.push({ key: \"role\", content: workload.role });\n const replicaText = formatReplicaCounts(workload.replicas);\n if (replicaText) items.push({ key: \"replicas\", content: replicaText });\n if (workload.createdAt !== undefined) {\n items.push({\n key: \"age\",\n content: (\n <>\n age <Timestamp value={workload.createdAt} format=\"relative\" />\n </>\n ),\n });\n }\n workload.metadata?.forEach((item, i) => {\n const plain =\n typeof item.value === \"string\" || typeof item.value === \"number\";\n items.push({\n key: `meta-${i}`,\n content: (\n <>\n <span className=\"text-muted-foreground/70\">{item.label}</span>{\" \"}\n {item.value}\n </>\n ),\n title: plain ? `${item.label}: ${item.value}` : item.label,\n });\n });\n return items;\n}\n\n/**\n * WorkloadCard is a compact resource card for a workload: a Kubernetes\n * resource (`kind`) or anything else (a free-form `type`, `icon` and\n * `metadata`). It shows identity, status, subtitle metadata, and\n * CPU/memory/disk utilization backed by the existing time-series primitives:\n * CPU and memory as core-style bars (memory at one bar per GiB) and disk as a\n * linear progress bar. Callers own the metric series (URL ids or `load`\n * functions); the card only composes them.\n *\n * Like the timeseries widgets it renders, it needs a react-query\n * `QueryClientProvider` above it.\n */\nexport function WorkloadCard({\n workload,\n metrics,\n baseUrl,\n range = \"1h\",\n refreshMs = 5000,\n expandable = true,\n headerActions,\n size = \"md\",\n variant = \"default\",\n fetcher,\n className,\n}: WorkloadCardProps) {\n const [expanded, setExpanded] = useState(false);\n const typeLabel = workloadTypeLabel(workload);\n const statusLabel = workloadStatusLabel(workload.status);\n const metaItems = headerMetaItems(workload, typeLabel);\n const workloadIcon =\n workload.icon ?? (workload.kind ? KIND_ICONS[workload.kind] : UiBox);\n const sizeClasses = SIZE_CLASSES[size];\n\n const panelMetrics = useMemo(() => {\n const list: PanelMetric[] = [];\n if (metrics.cpu) {\n list.push({\n key: \"cpu\",\n title: metrics.cpu.title ?? \"CPU\",\n unit: metrics.cpu.unit ?? \"short\",\n icon: metrics.cpu.icon ?? UiChip,\n metric: metrics.cpu,\n });\n }\n if (metrics.memory) {\n list.push({\n key: \"memory\",\n title: metrics.memory.title ?? \"Memory\",\n unit: metrics.memory.unit ?? \"bytes\",\n icon: metrics.memory.icon ?? UiMemoryStick,\n metric: metrics.memory,\n });\n }\n if (metrics.disk) {\n list.push({\n key: \"disk\",\n title: metrics.disk.title ?? \"Disk\",\n unit: metrics.disk.unit ?? \"bytes\",\n icon: metrics.disk.icon ?? UiHardDrive,\n metric: metrics.disk,\n });\n }\n return list;\n }, [metrics]);\n\n const metricProps = {\n ...(baseUrl !== undefined ? { baseUrl } : {}),\n range,\n refreshMs,\n ...(fetcher !== undefined ? { fetcher } : {}),\n };\n const canExpand = expandable && hasMetric(metrics);\n\n return (\n <div\n className={cn(\n \"w-full rounded-md border\",\n VARIANT_CLASSES[variant],\n sizeClasses.root,\n className,\n )}\n data-size={size}\n data-variant={variant}\n >\n <div\n className={cn(\"flex items-start justify-between\", sizeClasses.header)}\n >\n <div className=\"min-w-0\">\n <div\n className={cn(\"flex min-w-0 items-center\", sizeClasses.titleGap)}\n >\n <WorkloadIcon\n icon={workloadIcon}\n title={typeLabel ?? workload.name}\n className={cn(\"shrink-0 text-muted-foreground\", sizeClasses.icon)}\n />\n <span\n className={cn(\"min-w-0 truncate font-medium\", sizeClasses.name)}\n title={workload.name}\n >\n {workload.name}\n </span>\n </div>\n {metaItems.length > 0 ? (\n <div\n className={cn(\n \"flex flex-wrap items-center text-muted-foreground\",\n sizeClasses.meta,\n )}\n >\n {metaItems.map((item, i) => (\n <HeaderMeta\n key={item.key}\n separator={i > 0}\n title={item.title}\n >\n {item.content}\n </HeaderMeta>\n ))}\n </div>\n ) : null}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {statusLabel ? (\n <span title={workload.status?.message}>\n <Badge\n tone={workloadStatusTone(workload.status)}\n variant=\"soft\"\n size={sizeClasses.statusSize}\n >\n {statusLabel}\n </Badge>\n </span>\n ) : null}\n {headerActions}\n {canExpand ? (\n <button\n type=\"button\"\n aria-label={`Open ${workload.name} history`}\n title=\"History\"\n onClick={() => setExpanded(true)}\n className={cn(\n \"inline-flex items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\",\n sizeClasses.action,\n )}\n >\n <Icon\n icon={UiFullscreen}\n width={sizeClasses.actionIcon}\n height={sizeClasses.actionIcon}\n />\n </button>\n ) : null}\n </div>\n </div>\n\n {hasMetric(metrics) ? (\n <div\n className={cn(\n \"grid items-start gap-3\",\n sizeClasses.metricVariant === \"cell\"\n ? sizeClasses.metricGrid\n : cn(\n metricGridClass(panelMetrics.length),\n sizeClasses.metricGrid,\n ),\n )}\n >\n {metrics.cpu ? (\n <TimeseriesCoreBars\n title={metrics.cpu.title ?? \"CPU\"}\n icon={metrics.cpu.icon ?? UiChip}\n value={metrics.cpu.value}\n {...(metrics.cpu.max !== undefined\n ? { max: metrics.cpu.max }\n : {})}\n {...(metrics.cpu.thresholds\n ? { thresholds: metrics.cpu.thresholds }\n : {})}\n {...(metrics.cpu.orientation\n ? { orientation: metrics.cpu.orientation }\n : {})}\n {...(metrics.cpu.showValue !== undefined\n ? { showValue: metrics.cpu.showValue }\n : {})}\n variant={sizeClasses.metricVariant}\n {...metricProps}\n />\n ) : null}\n {metrics.memory ? (\n <TimeseriesCoreBars\n title={metrics.memory.title ?? \"Memory\"}\n icon={metrics.memory.icon ?? UiMemoryStick}\n value={metrics.memory.value}\n unit={MEMORY_BAR_UNIT}\n variant={sizeClasses.metricVariant}\n {...(metrics.memory.max !== undefined\n ? { max: metrics.memory.max }\n : {})}\n {...(metrics.memory.thresholds\n ? { thresholds: metrics.memory.thresholds }\n : {})}\n {...metricProps}\n />\n ) : null}\n {metrics.disk ? (\n <TimeseriesGauge\n title={metrics.disk.title ?? \"Disk\"}\n icon={metrics.disk.icon ?? UiHardDrive}\n value={metrics.disk.value}\n unit={metrics.disk.unit ?? \"bytes\"}\n shape=\"linear\"\n expandable={false}\n centerDisplay={metrics.disk.centerDisplay ?? \"value\"}\n variant={sizeClasses.metricVariant}\n {...(metrics.disk.max !== undefined\n ? { max: metrics.disk.max }\n : {})}\n {...(metrics.disk.thresholds\n ? { thresholds: metrics.disk.thresholds }\n : {})}\n {...metricProps}\n />\n ) : null}\n </div>\n ) : (\n <div\n className={cn(\n \"rounded-md border border-dashed border-border text-center text-muted-foreground\",\n sizeClasses.empty,\n )}\n >\n No metrics configured\n </div>\n )}\n\n <Modal\n open={expanded}\n onClose={() => setExpanded(false)}\n title={`${workload.name} history`}\n size=\"xl\"\n >\n <div className=\"flex flex-col gap-3\">\n {panelMetrics.map(({ key, title, unit, icon, metric }) => (\n <TimeseriesPanel\n key={key}\n title={title}\n icon={icon}\n series={metricSeries(metric)}\n referenceLines={metricReferenceLines(metric)}\n {...(unit ? { unit } : {})}\n {...metricProps}\n expandable={false}\n />\n ))}\n </div>\n </Modal>\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -14,21 +14,26 @@ function workloadKindLabel(kind) {
|
|
|
14
14
|
return "Pod";
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
+
function workloadTypeLabel(workload) {
|
|
18
|
+
if (workload.type) return workload.type;
|
|
19
|
+
return workload.kind ? workloadKindLabel(workload.kind) : void 0;
|
|
20
|
+
}
|
|
17
21
|
function workloadStatusLabel(status) {
|
|
18
22
|
return (status == null ? void 0 : status.label) ?? (status == null ? void 0 : status.code) ?? (status == null ? void 0 : status.health);
|
|
19
23
|
}
|
|
20
24
|
function workloadStatusTone(status) {
|
|
25
|
+
var _a;
|
|
21
26
|
if (status == null ? void 0 : status.tone) return status.tone;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
switch ((_a = status == null ? void 0 : status.health) == null ? void 0 : _a.trim().toLowerCase()) {
|
|
28
|
+
case "healthy":
|
|
29
|
+
return "success";
|
|
30
|
+
case "warning":
|
|
31
|
+
return "warning";
|
|
32
|
+
case "unhealthy":
|
|
33
|
+
return "danger";
|
|
34
|
+
default:
|
|
35
|
+
return "neutral";
|
|
36
|
+
}
|
|
32
37
|
}
|
|
33
38
|
function formatReplicaCounts(replicas) {
|
|
34
39
|
if (!replicas) return void 0;
|
|
@@ -48,4 +53,5 @@ exports.formatReplicaCounts = formatReplicaCounts;
|
|
|
48
53
|
exports.workloadKindLabel = workloadKindLabel;
|
|
49
54
|
exports.workloadStatusLabel = workloadStatusLabel;
|
|
50
55
|
exports.workloadStatusTone = workloadStatusTone;
|
|
56
|
+
exports.workloadTypeLabel = workloadTypeLabel;
|
|
51
57
|
//# sourceMappingURL=WorkloadCard.model.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkloadCard.model.cjs","sources":["../../src/data/WorkloadCard.model.ts"],"sourcesContent":["import type { BadgeTone } from \"./Badge\";\nimport type { StaticIconComponent } from \"./Icon\";\nimport type { ProgressBarsOrientation } from \"./ProgressBars\";\nimport type { GaugeSeries } from \"./TimeseriesGauge\";\n\nexport type WorkloadCardKind =\n | \"service\"\n | \"ingress\"\n | \"deployment\"\n | \"statefulset\"\n | \"pod\";\n\nexport type WorkloadCardIcon = string | StaticIconComponent;\n\nexport interface WorkloadCardReplicas {\n ready?: number;\n desired?: number;\n available?: number;\n}\n\nexport interface WorkloadCardStatus {\n label?: string;\n code?: string;\n health?: string;\n message?: string;\n tone?: BadgeTone;\n}\n\nexport interface WorkloadCardWorkload {\n kind
|
|
1
|
+
{"version":3,"file":"WorkloadCard.model.cjs","sources":["../../src/data/WorkloadCard.model.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { BadgeTone } from \"./Badge\";\nimport type { StaticIconComponent } from \"./Icon\";\nimport type { ProgressBarsOrientation } from \"./ProgressBars\";\nimport type { GaugeSeries } from \"./TimeseriesGauge\";\n\nexport type WorkloadCardKind =\n | \"service\"\n | \"ingress\"\n | \"deployment\"\n | \"statefulset\"\n | \"pod\";\n\nexport type WorkloadCardIcon = string | StaticIconComponent;\n\nexport interface WorkloadCardReplicas {\n ready?: number;\n desired?: number;\n available?: number;\n}\n\nexport interface WorkloadCardStatus {\n /** Badge text; falls back to `code`, then `health`. Never affects the tone. */\n label?: string;\n code?: string;\n /** Drives the tone: healthy → success, warning → warning, unhealthy → danger. */\n health?: string;\n /** Hover text for the status badge. */\n message?: string;\n /** Explicit badge tone; overrides the `health` mapping. */\n tone?: BadgeTone;\n}\n\n/** One caller-defined fact shown in the card's subtitle row, e.g. a region. */\nexport interface WorkloadCardMetadataItem {\n label: string;\n value: ReactNode;\n}\n\n/**\n * The workload a card describes. Kubernetes workloads set `kind` (which picks\n * the icon and type label); anything else sets a free-form `type` label and\n * its own `icon`, and describes itself through `metadata`.\n */\nexport interface WorkloadCardWorkload {\n /** Kubernetes kind; picks the default icon and type label. */\n kind?: WorkloadCardKind;\n /** Display label for the workload type, e.g. \"EC2 instance\". Overrides the kind label. */\n type?: string;\n name: string;\n namespace?: string;\n role?: string;\n createdAt?: string | number | Date;\n replicas?: WorkloadCardReplicas;\n status?: WorkloadCardStatus;\n icon?: WorkloadCardIcon;\n /** Extra label/value facts rendered after the built-ins in the subtitle row. */\n metadata?: ReadonlyArray<WorkloadCardMetadataItem>;\n}\n\nexport interface WorkloadCardResourceMetric {\n title?: string;\n value: GaugeSeries;\n max?: GaugeSeries | number;\n valueLabel?: string;\n maxLabel?: string;\n unit?: string;\n icon?: WorkloadCardIcon;\n thresholds?: [warning: number, danger: number];\n centerDisplay?: \"value\" | \"percent\";\n}\n\nexport interface WorkloadCardCpuMetric extends WorkloadCardResourceMetric {\n orientation?: ProgressBarsOrientation;\n showValue?: boolean;\n}\n\nexport interface WorkloadCardMetrics {\n cpu?: WorkloadCardCpuMetric;\n memory?: WorkloadCardResourceMetric;\n disk?: WorkloadCardResourceMetric;\n}\n\nexport function workloadKindLabel(kind: WorkloadCardKind): string {\n switch (kind) {\n case \"statefulset\":\n return \"StatefulSet\";\n case \"deployment\":\n return \"Deployment\";\n case \"service\":\n return \"Service\";\n case \"ingress\":\n return \"Ingress\";\n case \"pod\":\n return \"Pod\";\n }\n}\n\n/** The type label shown in the subtitle: `type`, else the kind's label. */\nexport function workloadTypeLabel(\n workload: Pick<WorkloadCardWorkload, \"kind\" | \"type\">,\n): string | undefined {\n if (workload.type) return workload.type;\n return workload.kind ? workloadKindLabel(workload.kind) : undefined;\n}\n\nexport function workloadStatusLabel(\n status: WorkloadCardStatus | undefined,\n): string | undefined {\n return status?.label ?? status?.code ?? status?.health;\n}\n\n/**\n * The status badge tone: an explicit `tone`, else a fixed mapping of `health`\n * (healthy → success, warning → warning, unhealthy → danger, anything else →\n * neutral). Free-text `label`/`code` never affect the tone — substring guesses\n * misfire (\"NotReady\" contains \"ready\", \"Broken\" contains \"ok\").\n */\nexport function workloadStatusTone(\n status: WorkloadCardStatus | undefined,\n): BadgeTone {\n if (status?.tone) return status.tone;\n switch (status?.health?.trim().toLowerCase()) {\n case \"healthy\":\n return \"success\";\n case \"warning\":\n return \"warning\";\n case \"unhealthy\":\n return \"danger\";\n default:\n return \"neutral\";\n }\n}\n\nexport function formatReplicaCounts(\n replicas: WorkloadCardReplicas | undefined,\n): string | undefined {\n if (!replicas) return undefined;\n if (replicas.ready !== undefined && replicas.desired !== undefined) {\n return `${replicas.ready}/${replicas.desired} ready`;\n }\n if (replicas.available !== undefined && replicas.desired !== undefined) {\n return `${replicas.available}/${replicas.desired} available`;\n }\n if (replicas.ready !== undefined) return `${replicas.ready} ready`;\n if (replicas.desired !== undefined) return `${replicas.desired} desired`;\n if (replicas.available !== undefined)\n return `${replicas.available} available`;\n return undefined;\n}\n"],"names":[],"mappings":";;AAmFO,SAAS,kBAAkB,MAAgC;AAChE,UAAQ,MAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EAAA;AAEb;AAGO,SAAS,kBACd,UACoB;AACpB,MAAI,SAAS,KAAM,QAAO,SAAS;AACnC,SAAO,SAAS,OAAO,kBAAkB,SAAS,IAAI,IAAI;AAC5D;AAEO,SAAS,oBACd,QACoB;AACpB,UAAO,iCAAQ,WAAS,iCAAQ,UAAQ,iCAAQ;AAClD;AAQO,SAAS,mBACd,QACW;;AACX,MAAI,iCAAQ,KAAM,QAAO,OAAO;AAChC,WAAQ,sCAAQ,WAAR,mBAAgB,OAAO,eAAY;AAAA,IACzC,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EAAA;AAEb;AAEO,SAAS,oBACd,UACoB;AACpB,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,SAAS,UAAU,UAAa,SAAS,YAAY,QAAW;AAClE,WAAO,GAAG,SAAS,KAAK,IAAI,SAAS,OAAO;AAAA,EAC9C;AACA,MAAI,SAAS,cAAc,UAAa,SAAS,YAAY,QAAW;AACtE,WAAO,GAAG,SAAS,SAAS,IAAI,SAAS,OAAO;AAAA,EAClD;AACA,MAAI,SAAS,UAAU,OAAW,QAAO,GAAG,SAAS,KAAK;AAC1D,MAAI,SAAS,YAAY,OAAW,QAAO,GAAG,SAAS,OAAO;AAC9D,MAAI,SAAS,cAAc;AACzB,WAAO,GAAG,SAAS,SAAS;AAC9B,SAAO;AACT;;;;;;"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
import { BadgeTone } from './Badge';
|
|
2
3
|
import { StaticIconComponent } from './Icon';
|
|
3
4
|
import { ProgressBarsOrientation } from './ProgressBars';
|
|
@@ -10,14 +11,31 @@ export interface WorkloadCardReplicas {
|
|
|
10
11
|
available?: number;
|
|
11
12
|
}
|
|
12
13
|
export interface WorkloadCardStatus {
|
|
14
|
+
/** Badge text; falls back to `code`, then `health`. Never affects the tone. */
|
|
13
15
|
label?: string;
|
|
14
16
|
code?: string;
|
|
17
|
+
/** Drives the tone: healthy → success, warning → warning, unhealthy → danger. */
|
|
15
18
|
health?: string;
|
|
19
|
+
/** Hover text for the status badge. */
|
|
16
20
|
message?: string;
|
|
21
|
+
/** Explicit badge tone; overrides the `health` mapping. */
|
|
17
22
|
tone?: BadgeTone;
|
|
18
23
|
}
|
|
24
|
+
/** One caller-defined fact shown in the card's subtitle row, e.g. a region. */
|
|
25
|
+
export interface WorkloadCardMetadataItem {
|
|
26
|
+
label: string;
|
|
27
|
+
value: ReactNode;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The workload a card describes. Kubernetes workloads set `kind` (which picks
|
|
31
|
+
* the icon and type label); anything else sets a free-form `type` label and
|
|
32
|
+
* its own `icon`, and describes itself through `metadata`.
|
|
33
|
+
*/
|
|
19
34
|
export interface WorkloadCardWorkload {
|
|
20
|
-
kind
|
|
35
|
+
/** Kubernetes kind; picks the default icon and type label. */
|
|
36
|
+
kind?: WorkloadCardKind;
|
|
37
|
+
/** Display label for the workload type, e.g. "EC2 instance". Overrides the kind label. */
|
|
38
|
+
type?: string;
|
|
21
39
|
name: string;
|
|
22
40
|
namespace?: string;
|
|
23
41
|
role?: string;
|
|
@@ -25,6 +43,8 @@ export interface WorkloadCardWorkload {
|
|
|
25
43
|
replicas?: WorkloadCardReplicas;
|
|
26
44
|
status?: WorkloadCardStatus;
|
|
27
45
|
icon?: WorkloadCardIcon;
|
|
46
|
+
/** Extra label/value facts rendered after the built-ins in the subtitle row. */
|
|
47
|
+
metadata?: ReadonlyArray<WorkloadCardMetadataItem>;
|
|
28
48
|
}
|
|
29
49
|
export interface WorkloadCardResourceMetric {
|
|
30
50
|
title?: string;
|
|
@@ -47,7 +67,15 @@ export interface WorkloadCardMetrics {
|
|
|
47
67
|
disk?: WorkloadCardResourceMetric;
|
|
48
68
|
}
|
|
49
69
|
export declare function workloadKindLabel(kind: WorkloadCardKind): string;
|
|
70
|
+
/** The type label shown in the subtitle: `type`, else the kind's label. */
|
|
71
|
+
export declare function workloadTypeLabel(workload: Pick<WorkloadCardWorkload, "kind" | "type">): string | undefined;
|
|
50
72
|
export declare function workloadStatusLabel(status: WorkloadCardStatus | undefined): string | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* The status badge tone: an explicit `tone`, else a fixed mapping of `health`
|
|
75
|
+
* (healthy → success, warning → warning, unhealthy → danger, anything else →
|
|
76
|
+
* neutral). Free-text `label`/`code` never affect the tone — substring guesses
|
|
77
|
+
* misfire ("NotReady" contains "ready", "Broken" contains "ok").
|
|
78
|
+
*/
|
|
51
79
|
export declare function workloadStatusTone(status: WorkloadCardStatus | undefined): BadgeTone;
|
|
52
80
|
export declare function formatReplicaCounts(replicas: WorkloadCardReplicas | undefined): string | undefined;
|
|
53
81
|
//# sourceMappingURL=WorkloadCard.model.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkloadCard.model.d.ts","sourceRoot":"","sources":["../../src/data/WorkloadCard.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,SAAS,GACT,YAAY,GACZ,aAAa,GACb,KAAK,CAAC;AAEV,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,mBAAmB,CAAC;AAE5D,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"WorkloadCard.model.d.ts","sourceRoot":"","sources":["../../src/data/WorkloadCard.model.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,21 +12,26 @@ function workloadKindLabel(kind) {
|
|
|
12
12
|
return "Pod";
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
function workloadTypeLabel(workload) {
|
|
16
|
+
if (workload.type) return workload.type;
|
|
17
|
+
return workload.kind ? workloadKindLabel(workload.kind) : void 0;
|
|
18
|
+
}
|
|
15
19
|
function workloadStatusLabel(status) {
|
|
16
20
|
return (status == null ? void 0 : status.label) ?? (status == null ? void 0 : status.code) ?? (status == null ? void 0 : status.health);
|
|
17
21
|
}
|
|
18
22
|
function workloadStatusTone(status) {
|
|
23
|
+
var _a;
|
|
19
24
|
if (status == null ? void 0 : status.tone) return status.tone;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
switch ((_a = status == null ? void 0 : status.health) == null ? void 0 : _a.trim().toLowerCase()) {
|
|
26
|
+
case "healthy":
|
|
27
|
+
return "success";
|
|
28
|
+
case "warning":
|
|
29
|
+
return "warning";
|
|
30
|
+
case "unhealthy":
|
|
31
|
+
return "danger";
|
|
32
|
+
default:
|
|
33
|
+
return "neutral";
|
|
34
|
+
}
|
|
30
35
|
}
|
|
31
36
|
function formatReplicaCounts(replicas) {
|
|
32
37
|
if (!replicas) return void 0;
|
|
@@ -46,6 +51,7 @@ export {
|
|
|
46
51
|
formatReplicaCounts,
|
|
47
52
|
workloadKindLabel,
|
|
48
53
|
workloadStatusLabel,
|
|
49
|
-
workloadStatusTone
|
|
54
|
+
workloadStatusTone,
|
|
55
|
+
workloadTypeLabel
|
|
50
56
|
};
|
|
51
57
|
//# sourceMappingURL=WorkloadCard.model.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkloadCard.model.js","sources":["../../src/data/WorkloadCard.model.ts"],"sourcesContent":["import type { BadgeTone } from \"./Badge\";\nimport type { StaticIconComponent } from \"./Icon\";\nimport type { ProgressBarsOrientation } from \"./ProgressBars\";\nimport type { GaugeSeries } from \"./TimeseriesGauge\";\n\nexport type WorkloadCardKind =\n | \"service\"\n | \"ingress\"\n | \"deployment\"\n | \"statefulset\"\n | \"pod\";\n\nexport type WorkloadCardIcon = string | StaticIconComponent;\n\nexport interface WorkloadCardReplicas {\n ready?: number;\n desired?: number;\n available?: number;\n}\n\nexport interface WorkloadCardStatus {\n label?: string;\n code?: string;\n health?: string;\n message?: string;\n tone?: BadgeTone;\n}\n\nexport interface WorkloadCardWorkload {\n kind
|
|
1
|
+
{"version":3,"file":"WorkloadCard.model.js","sources":["../../src/data/WorkloadCard.model.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { BadgeTone } from \"./Badge\";\nimport type { StaticIconComponent } from \"./Icon\";\nimport type { ProgressBarsOrientation } from \"./ProgressBars\";\nimport type { GaugeSeries } from \"./TimeseriesGauge\";\n\nexport type WorkloadCardKind =\n | \"service\"\n | \"ingress\"\n | \"deployment\"\n | \"statefulset\"\n | \"pod\";\n\nexport type WorkloadCardIcon = string | StaticIconComponent;\n\nexport interface WorkloadCardReplicas {\n ready?: number;\n desired?: number;\n available?: number;\n}\n\nexport interface WorkloadCardStatus {\n /** Badge text; falls back to `code`, then `health`. Never affects the tone. */\n label?: string;\n code?: string;\n /** Drives the tone: healthy → success, warning → warning, unhealthy → danger. */\n health?: string;\n /** Hover text for the status badge. */\n message?: string;\n /** Explicit badge tone; overrides the `health` mapping. */\n tone?: BadgeTone;\n}\n\n/** One caller-defined fact shown in the card's subtitle row, e.g. a region. */\nexport interface WorkloadCardMetadataItem {\n label: string;\n value: ReactNode;\n}\n\n/**\n * The workload a card describes. Kubernetes workloads set `kind` (which picks\n * the icon and type label); anything else sets a free-form `type` label and\n * its own `icon`, and describes itself through `metadata`.\n */\nexport interface WorkloadCardWorkload {\n /** Kubernetes kind; picks the default icon and type label. */\n kind?: WorkloadCardKind;\n /** Display label for the workload type, e.g. \"EC2 instance\". Overrides the kind label. */\n type?: string;\n name: string;\n namespace?: string;\n role?: string;\n createdAt?: string | number | Date;\n replicas?: WorkloadCardReplicas;\n status?: WorkloadCardStatus;\n icon?: WorkloadCardIcon;\n /** Extra label/value facts rendered after the built-ins in the subtitle row. */\n metadata?: ReadonlyArray<WorkloadCardMetadataItem>;\n}\n\nexport interface WorkloadCardResourceMetric {\n title?: string;\n value: GaugeSeries;\n max?: GaugeSeries | number;\n valueLabel?: string;\n maxLabel?: string;\n unit?: string;\n icon?: WorkloadCardIcon;\n thresholds?: [warning: number, danger: number];\n centerDisplay?: \"value\" | \"percent\";\n}\n\nexport interface WorkloadCardCpuMetric extends WorkloadCardResourceMetric {\n orientation?: ProgressBarsOrientation;\n showValue?: boolean;\n}\n\nexport interface WorkloadCardMetrics {\n cpu?: WorkloadCardCpuMetric;\n memory?: WorkloadCardResourceMetric;\n disk?: WorkloadCardResourceMetric;\n}\n\nexport function workloadKindLabel(kind: WorkloadCardKind): string {\n switch (kind) {\n case \"statefulset\":\n return \"StatefulSet\";\n case \"deployment\":\n return \"Deployment\";\n case \"service\":\n return \"Service\";\n case \"ingress\":\n return \"Ingress\";\n case \"pod\":\n return \"Pod\";\n }\n}\n\n/** The type label shown in the subtitle: `type`, else the kind's label. */\nexport function workloadTypeLabel(\n workload: Pick<WorkloadCardWorkload, \"kind\" | \"type\">,\n): string | undefined {\n if (workload.type) return workload.type;\n return workload.kind ? workloadKindLabel(workload.kind) : undefined;\n}\n\nexport function workloadStatusLabel(\n status: WorkloadCardStatus | undefined,\n): string | undefined {\n return status?.label ?? status?.code ?? status?.health;\n}\n\n/**\n * The status badge tone: an explicit `tone`, else a fixed mapping of `health`\n * (healthy → success, warning → warning, unhealthy → danger, anything else →\n * neutral). Free-text `label`/`code` never affect the tone — substring guesses\n * misfire (\"NotReady\" contains \"ready\", \"Broken\" contains \"ok\").\n */\nexport function workloadStatusTone(\n status: WorkloadCardStatus | undefined,\n): BadgeTone {\n if (status?.tone) return status.tone;\n switch (status?.health?.trim().toLowerCase()) {\n case \"healthy\":\n return \"success\";\n case \"warning\":\n return \"warning\";\n case \"unhealthy\":\n return \"danger\";\n default:\n return \"neutral\";\n }\n}\n\nexport function formatReplicaCounts(\n replicas: WorkloadCardReplicas | undefined,\n): string | undefined {\n if (!replicas) return undefined;\n if (replicas.ready !== undefined && replicas.desired !== undefined) {\n return `${replicas.ready}/${replicas.desired} ready`;\n }\n if (replicas.available !== undefined && replicas.desired !== undefined) {\n return `${replicas.available}/${replicas.desired} available`;\n }\n if (replicas.ready !== undefined) return `${replicas.ready} ready`;\n if (replicas.desired !== undefined) return `${replicas.desired} desired`;\n if (replicas.available !== undefined)\n return `${replicas.available} available`;\n return undefined;\n}\n"],"names":[],"mappings":"AAmFO,SAAS,kBAAkB,MAAgC;AAChE,UAAQ,MAAA;AAAA,IACN,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EAAA;AAEb;AAGO,SAAS,kBACd,UACoB;AACpB,MAAI,SAAS,KAAM,QAAO,SAAS;AACnC,SAAO,SAAS,OAAO,kBAAkB,SAAS,IAAI,IAAI;AAC5D;AAEO,SAAS,oBACd,QACoB;AACpB,UAAO,iCAAQ,WAAS,iCAAQ,UAAQ,iCAAQ;AAClD;AAQO,SAAS,mBACd,QACW;AArCN;AAsCL,MAAI,iCAAQ,KAAM,QAAO,OAAO;AAChC,WAAQ,sCAAQ,WAAR,mBAAgB,OAAO,eAAY;AAAA,IACzC,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EAAA;AAEb;AAEO,SAAS,oBACd,UACoB;AACpB,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,SAAS,UAAU,UAAa,SAAS,YAAY,QAAW;AAClE,WAAO,GAAG,SAAS,KAAK,IAAI,SAAS,OAAO;AAAA,EAC9C;AACA,MAAI,SAAS,cAAc,UAAa,SAAS,YAAY,QAAW;AACtE,WAAO,GAAG,SAAS,SAAS,IAAI,SAAS,OAAO;AAAA,EAClD;AACA,MAAI,SAAS,UAAU,OAAW,QAAO,GAAG,SAAS,KAAK;AAC1D,MAAI,SAAS,YAAY,OAAW,QAAO,GAAG,SAAS,OAAO;AAC9D,MAAI,SAAS,cAAc;AACzB,WAAO,GAAG,SAAS,SAAS;AAC9B,SAAO;AACT;"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const reactQuery = require("@tanstack/react-query");
|
|
4
|
+
const defaultTimeseriesFetcher = async (url) => {
|
|
5
|
+
const res = await fetch(url);
|
|
6
|
+
if (!res.ok) throw new Error(`metrics request failed: ${res.status}`);
|
|
7
|
+
return res.json();
|
|
8
|
+
};
|
|
9
|
+
function timeseriesRequestUrl(url, range) {
|
|
10
|
+
const u = new URL(url, window.location.origin);
|
|
11
|
+
if (range) u.searchParams.set("since", range);
|
|
12
|
+
return u.pathname + u.search;
|
|
13
|
+
}
|
|
14
|
+
function timeseriesQueryOptions(source, { baseUrl = "", range, refreshMs, fetcher }) {
|
|
15
|
+
const shared = {
|
|
16
|
+
refetchInterval: refreshMs > 0 ? refreshMs : false,
|
|
17
|
+
staleTime: 0,
|
|
18
|
+
retry: 0
|
|
19
|
+
};
|
|
20
|
+
const { load } = source;
|
|
21
|
+
if (load) {
|
|
22
|
+
return {
|
|
23
|
+
...shared,
|
|
24
|
+
queryKey: ["timeseries", "load", source.id, range],
|
|
25
|
+
queryFn: ({ signal }) => load({ range, signal })
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const requestUrl = timeseriesRequestUrl(baseUrl + source.id, range);
|
|
29
|
+
return {
|
|
30
|
+
...shared,
|
|
31
|
+
queryKey: ["timeseries", requestUrl],
|
|
32
|
+
queryFn: () => fetcher(requestUrl)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function useTimeseriesQueries(sources, options) {
|
|
36
|
+
return reactQuery.useQueries({
|
|
37
|
+
queries: sources.map((source) => timeseriesQueryOptions(source, options))
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function latestValue(resp) {
|
|
41
|
+
var _a;
|
|
42
|
+
const points = resp == null ? void 0 : resp.points;
|
|
43
|
+
if (!points || points.length === 0) return void 0;
|
|
44
|
+
return (_a = points[points.length - 1]) == null ? void 0 : _a.value;
|
|
45
|
+
}
|
|
46
|
+
exports.defaultTimeseriesFetcher = defaultTimeseriesFetcher;
|
|
47
|
+
exports.latestValue = latestValue;
|
|
48
|
+
exports.timeseriesQueryOptions = timeseriesQueryOptions;
|
|
49
|
+
exports.timeseriesRequestUrl = timeseriesRequestUrl;
|
|
50
|
+
exports.useTimeseriesQueries = useTimeseriesQueries;
|
|
51
|
+
//# sourceMappingURL=timeseries-query.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeseries-query.cjs","sources":["../../src/data/timeseries-query.ts"],"sourcesContent":["import { useQueries, type UseQueryOptions, type UseQueryResult } from \"@tanstack/react-query\";\nimport type { SeriesLoader, TimeseriesResponse } from \"./TimeseriesPanel.model\";\n\n/** Loads a metric by URL; the legacy data path of the timeseries widgets. */\nexport type TimeseriesFetcher = (url: string) => Promise<TimeseriesResponse>;\n\n/** One series the widgets poll: a metric id, optionally backed by a loader. */\nexport interface TimeseriesSource {\n id: string;\n load?: SeriesLoader | undefined;\n}\n\nexport interface TimeseriesQueryOptions {\n /** Prefix for URL-backed sources; ignored by sources with a `load`. */\n baseUrl?: string;\n range: string;\n refreshMs: number;\n fetcher: TimeseriesFetcher;\n}\n\nexport const defaultTimeseriesFetcher: TimeseriesFetcher = async (url) => {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`metrics request failed: ${res.status}`);\n return res.json();\n};\n\n/** `baseUrl + id` resolved to a same-origin path with `?since=<range>`. */\nexport function timeseriesRequestUrl(url: string, range: string): string {\n const u = new URL(url, window.location.origin);\n if (range) u.searchParams.set(\"since\", range);\n return u.pathname + u.search;\n}\n\n/**\n * The react-query options for one series. URL-backed sources key on the\n * request URL (unchanged from before loaders existed); loader-backed sources\n * key on `[\"timeseries\", \"load\", id, range]`, so the id is the cache identity\n * and callers must keep it unique per data source.\n */\nexport function timeseriesQueryOptions(\n source: TimeseriesSource,\n { baseUrl = \"\", range, refreshMs, fetcher }: TimeseriesQueryOptions,\n): UseQueryOptions<TimeseriesResponse, Error, TimeseriesResponse, readonly unknown[]> {\n const shared = {\n refetchInterval: refreshMs > 0 ? refreshMs : (false as const),\n staleTime: 0,\n retry: 0,\n };\n const { load } = source;\n if (load) {\n return {\n ...shared,\n queryKey: [\"timeseries\", \"load\", source.id, range],\n queryFn: ({ signal }: { signal: AbortSignal }) => load({ range, signal }),\n };\n }\n const requestUrl = timeseriesRequestUrl(baseUrl + source.id, range);\n return {\n ...shared,\n queryKey: [\"timeseries\", requestUrl],\n queryFn: () => fetcher(requestUrl),\n };\n}\n\n/** Polls every source in parallel; results are index-aligned with `sources`. */\nexport function useTimeseriesQueries(\n sources: readonly TimeseriesSource[],\n options: TimeseriesQueryOptions,\n): UseQueryResult<TimeseriesResponse>[] {\n return useQueries({\n queries: sources.map((source) => timeseriesQueryOptions(source, options)),\n });\n}\n\n/** The value of the last point, or undefined when the series is empty. */\nexport function latestValue(resp: TimeseriesResponse | undefined): number | undefined {\n const points = resp?.points;\n if (!points || points.length === 0) return undefined;\n return points[points.length - 1]?.value;\n}\n"],"names":["useQueries"],"mappings":";;;AAoBO,MAAM,2BAA8C,OAAO,QAAQ;AACxE,QAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,2BAA2B,IAAI,MAAM,EAAE;AACpE,SAAO,IAAI,KAAA;AACb;AAGO,SAAS,qBAAqB,KAAa,OAAuB;AACvE,QAAM,IAAI,IAAI,IAAI,KAAK,OAAO,SAAS,MAAM;AAC7C,MAAI,MAAO,GAAE,aAAa,IAAI,SAAS,KAAK;AAC5C,SAAO,EAAE,WAAW,EAAE;AACxB;AAQO,SAAS,uBACd,QACA,EAAE,UAAU,IAAI,OAAO,WAAW,WACkD;AACpF,QAAM,SAAS;AAAA,IACb,iBAAiB,YAAY,IAAI,YAAa;AAAA,IAC9C,WAAW;AAAA,IACX,OAAO;AAAA,EAAA;AAET,QAAM,EAAE,SAAS;AACjB,MAAI,MAAM;AACR,WAAO;AAAA,MACL,GAAG;AAAA,MACH,UAAU,CAAC,cAAc,QAAQ,OAAO,IAAI,KAAK;AAAA,MACjD,SAAS,CAAC,EAAE,OAAA,MAAsC,KAAK,EAAE,OAAO,OAAA,CAAQ;AAAA,IAAA;AAAA,EAE5E;AACA,QAAM,aAAa,qBAAqB,UAAU,OAAO,IAAI,KAAK;AAClE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU,CAAC,cAAc,UAAU;AAAA,IACnC,SAAS,MAAM,QAAQ,UAAU;AAAA,EAAA;AAErC;AAGO,SAAS,qBACd,SACA,SACsC;AACtC,SAAOA,sBAAW;AAAA,IAChB,SAAS,QAAQ,IAAI,CAAC,WAAW,uBAAuB,QAAQ,OAAO,CAAC;AAAA,EAAA,CACzE;AACH;AAGO,SAAS,YAAY,MAA0D;;AACpF,QAAM,SAAS,6BAAM;AACrB,MAAI,CAAC,UAAU,OAAO,WAAW,EAAG,QAAO;AAC3C,UAAO,YAAO,OAAO,SAAS,CAAC,MAAxB,mBAA2B;AACpC;;;;;;"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
import { SeriesLoader, TimeseriesResponse } from './TimeseriesPanel.model';
|
|
3
|
+
/** Loads a metric by URL; the legacy data path of the timeseries widgets. */
|
|
4
|
+
export type TimeseriesFetcher = (url: string) => Promise<TimeseriesResponse>;
|
|
5
|
+
/** One series the widgets poll: a metric id, optionally backed by a loader. */
|
|
6
|
+
export interface TimeseriesSource {
|
|
7
|
+
id: string;
|
|
8
|
+
load?: SeriesLoader | undefined;
|
|
9
|
+
}
|
|
10
|
+
export interface TimeseriesQueryOptions {
|
|
11
|
+
/** Prefix for URL-backed sources; ignored by sources with a `load`. */
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
range: string;
|
|
14
|
+
refreshMs: number;
|
|
15
|
+
fetcher: TimeseriesFetcher;
|
|
16
|
+
}
|
|
17
|
+
export declare const defaultTimeseriesFetcher: TimeseriesFetcher;
|
|
18
|
+
/** `baseUrl + id` resolved to a same-origin path with `?since=<range>`. */
|
|
19
|
+
export declare function timeseriesRequestUrl(url: string, range: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* The react-query options for one series. URL-backed sources key on the
|
|
22
|
+
* request URL (unchanged from before loaders existed); loader-backed sources
|
|
23
|
+
* key on `["timeseries", "load", id, range]`, so the id is the cache identity
|
|
24
|
+
* and callers must keep it unique per data source.
|
|
25
|
+
*/
|
|
26
|
+
export declare function timeseriesQueryOptions(source: TimeseriesSource, { baseUrl, range, refreshMs, fetcher }: TimeseriesQueryOptions): UseQueryOptions<TimeseriesResponse, Error, TimeseriesResponse, readonly unknown[]>;
|
|
27
|
+
/** Polls every source in parallel; results are index-aligned with `sources`. */
|
|
28
|
+
export declare function useTimeseriesQueries(sources: readonly TimeseriesSource[], options: TimeseriesQueryOptions): UseQueryResult<TimeseriesResponse>[];
|
|
29
|
+
/** The value of the last point, or undefined when the series is empty. */
|
|
30
|
+
export declare function latestValue(resp: TimeseriesResponse | undefined): number | undefined;
|
|
31
|
+
//# sourceMappingURL=timeseries-query.d.ts.map
|