@camstack/ui-library 1.2.383 → 1.2.385
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/CHANGELOG.md +12 -0
- package/dist/composites/DeviceRunsPanel.d.ts +23 -0
- package/dist/composites/charts/TimeSeriesChart.d.ts +5 -1
- package/dist/composites/charts/chart-bands.d.ts +22 -0
- package/dist/composites/charts/chart-palette.d.ts +1 -1
- package/dist/composites/charts/chart-tooltip-model.d.ts +2 -0
- package/dist/composites/charts/chart-uplot.d.ts +3 -0
- package/dist/composites/charts/index.d.ts +1 -1
- package/dist/composites/device-history/HistoryChart.d.ts +5 -2
- package/dist/composites/device-history/history-runs.d.ts +29 -0
- package/dist/composites/device-history/index.d.ts +2 -0
- package/dist/composites/device-history/use-device-runs.d.ts +11 -0
- package/dist/composites/index.d.ts +1 -0
- package/dist/generated/system-hooks.d.ts +0 -6
- package/dist/index.cjs +342 -89
- package/dist/index.js +337 -87
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -11777,12 +11777,6 @@ var useIntegrationsCreate = /*#__PURE__*/ alias(() => trpc.integrations.create.u
|
|
|
11777
11777
|
var useIntegrationsUpdate = /*#__PURE__*/ alias(() => trpc.integrations.update.useMutation);
|
|
11778
11778
|
/** Generated alias around `trpc.integrations.delete.useMutation`. */
|
|
11779
11779
|
var useIntegrationsDelete = /*#__PURE__*/ alias(() => trpc.integrations.delete.useMutation);
|
|
11780
|
-
/** Generated alias around `trpc.integrations.getSettings.useQuery`. */
|
|
11781
|
-
var useIntegrationsGetSettings = /*#__PURE__*/ alias(() => trpc.integrations.getSettings.useQuery);
|
|
11782
|
-
/** Generated alias around `trpc.integrations.setSettings.useMutation`. */
|
|
11783
|
-
var useIntegrationsSetSettings = /*#__PURE__*/ alias(() => trpc.integrations.setSettings.useMutation);
|
|
11784
|
-
/** Generated alias around `trpc.integrations.clearSettings.useMutation`. */
|
|
11785
|
-
var useIntegrationsClearSettings = /*#__PURE__*/ alias(() => trpc.integrations.clearSettings.useMutation);
|
|
11786
11780
|
/** Generated alias around `trpc.integrations.getAvailableTypes.useQuery`. */
|
|
11787
11781
|
var useIntegrationsGetAvailableTypes = /*#__PURE__*/ alias(() => trpc.integrations.getAvailableTypes.useQuery);
|
|
11788
11782
|
/** Generated alias around `trpc.integrations.testConnection.useMutation`. */
|
|
@@ -24107,6 +24101,22 @@ function formatCursorTime(t, spanMs) {
|
|
|
24107
24101
|
return `${d.toLocaleDateString(void 0, DATE_DM)} ${d.toLocaleTimeString(void 0, TIME_HM)}`;
|
|
24108
24102
|
}
|
|
24109
24103
|
//#endregion
|
|
24104
|
+
//#region src/composites/charts/chart-bands.ts
|
|
24105
|
+
var TONE_TOKEN = {
|
|
24106
|
+
neutral: "foreground-subtle",
|
|
24107
|
+
info: "info",
|
|
24108
|
+
success: "success",
|
|
24109
|
+
warning: "warning",
|
|
24110
|
+
danger: "danger"
|
|
24111
|
+
};
|
|
24112
|
+
function bandToken(tone) {
|
|
24113
|
+
return TONE_TOKEN[tone];
|
|
24114
|
+
}
|
|
24115
|
+
/** The bands that contain `x` (edges included), in input order. */
|
|
24116
|
+
function bandsAt(bands, x) {
|
|
24117
|
+
return bands.filter((b) => x >= b.from && x <= b.to);
|
|
24118
|
+
}
|
|
24119
|
+
//#endregion
|
|
24110
24120
|
//#region src/composites/charts/chart-scale.ts
|
|
24111
24121
|
var LINEAR_MAX_MANTISSAS = [
|
|
24112
24122
|
1,
|
|
@@ -24338,6 +24348,23 @@ function gapShadeHook(spans) {
|
|
|
24338
24348
|
ctx.restore();
|
|
24339
24349
|
};
|
|
24340
24350
|
}
|
|
24351
|
+
/** Paint the bands behind the lines, each in its tone. */
|
|
24352
|
+
function bandShadeHook(bands) {
|
|
24353
|
+
return (u) => {
|
|
24354
|
+
const list = bands();
|
|
24355
|
+
if (list.length === 0) return;
|
|
24356
|
+
const ctx = u.ctx;
|
|
24357
|
+
ctx.save();
|
|
24358
|
+
for (const b of list) {
|
|
24359
|
+
const x0 = u.valToPos(b.from, "x", true);
|
|
24360
|
+
const x1 = u.valToPos(b.to, "x", true);
|
|
24361
|
+
ctx.fillStyle = withAlpha(resolveChartColor(bandToken(b.tone)), BAND_SHADE_ALPHA);
|
|
24362
|
+
ctx.fillRect(x0, u.bbox.top, Math.max(1, x1 - x0), u.bbox.height);
|
|
24363
|
+
}
|
|
24364
|
+
ctx.restore();
|
|
24365
|
+
};
|
|
24366
|
+
}
|
|
24367
|
+
var BAND_SHADE_ALPHA = .16;
|
|
24341
24368
|
var BYTE_UNITS = new Set([
|
|
24342
24369
|
"B",
|
|
24343
24370
|
"bytes",
|
|
@@ -24692,7 +24719,7 @@ function lineTooltipBody(input) {
|
|
|
24692
24719
|
preference: input.preference
|
|
24693
24720
|
})
|
|
24694
24721
|
}));
|
|
24695
|
-
return asBody(input.timeLabel, lines);
|
|
24722
|
+
return asBody(input.timeLabel, [...lines, ...input.extra ?? []]);
|
|
24696
24723
|
}
|
|
24697
24724
|
/** The state in force at `t`, and how long that span lasts. */
|
|
24698
24725
|
function stateSpanAt(segments, t) {
|
|
@@ -42821,6 +42848,176 @@ function CopyButton({ value, label, srLabel, className, disabled }) {
|
|
|
42821
42848
|
});
|
|
42822
42849
|
}
|
|
42823
42850
|
//#endregion
|
|
42851
|
+
//#region src/composites/device-history/history-runs.ts
|
|
42852
|
+
/** The context kept on each side of a run when a row opens it. */
|
|
42853
|
+
var RUN_WINDOW_MARGIN_MS = 15 * 6e4;
|
|
42854
|
+
function runStatus(run) {
|
|
42855
|
+
return run.state === "open" ? "running" : run.outcome ?? "unknown";
|
|
42856
|
+
}
|
|
42857
|
+
function runEnd(run, now) {
|
|
42858
|
+
return run.state === "open" || run.endedAt === null ? now : run.endedAt;
|
|
42859
|
+
}
|
|
42860
|
+
/** Elapsed time of a run; an open one counts up to `now`. `null` when a closed run has no duration. */
|
|
42861
|
+
function runDurationMs(run, now) {
|
|
42862
|
+
if (run.state === "open") return Math.max(0, now - run.startedAt);
|
|
42863
|
+
if (run.durationMs !== null) return run.durationMs;
|
|
42864
|
+
return run.endedAt === null ? null : Math.max(0, run.endedAt - run.startedAt);
|
|
42865
|
+
}
|
|
42866
|
+
function formatKwh(kwh) {
|
|
42867
|
+
return kwh === null ? "—" : `${kwh.toFixed(2)} kWh`;
|
|
42868
|
+
}
|
|
42869
|
+
function formatWatts(w) {
|
|
42870
|
+
return w === null ? "—" : `${String(Math.round(w))} W`;
|
|
42871
|
+
}
|
|
42872
|
+
function formatRunDuration(ms) {
|
|
42873
|
+
return ms === null ? "—" : formatDurationMs(ms);
|
|
42874
|
+
}
|
|
42875
|
+
var STATUS_TONE = {
|
|
42876
|
+
running: "info",
|
|
42877
|
+
completed: "success",
|
|
42878
|
+
aborted: "warning",
|
|
42879
|
+
error: "danger",
|
|
42880
|
+
unknown: "neutral"
|
|
42881
|
+
};
|
|
42882
|
+
function runTone(status) {
|
|
42883
|
+
return STATUS_TONE[status];
|
|
42884
|
+
}
|
|
42885
|
+
/** The window that frames a run: the run plus {@link RUN_WINDOW_MARGIN_MS} each side. */
|
|
42886
|
+
function runWindow(run, now) {
|
|
42887
|
+
return {
|
|
42888
|
+
from: run.startedAt - RUN_WINDOW_MARGIN_MS,
|
|
42889
|
+
to: runEnd(run, now) + RUN_WINDOW_MARGIN_MS
|
|
42890
|
+
};
|
|
42891
|
+
}
|
|
42892
|
+
/** One band per run that overlaps `window`; the label states the duration and the energy. */
|
|
42893
|
+
function runBands(runs, now, window, t) {
|
|
42894
|
+
const title = t("uiLibrary.history.runs.band", "Run");
|
|
42895
|
+
return runs.filter((r) => runEnd(r, now) > window.from && r.startedAt < window.to).map((r) => {
|
|
42896
|
+
const status = runStatus(r);
|
|
42897
|
+
const parts = [formatRunDuration(runDurationMs(r, now)), formatKwh(r.detail.energyKwh)];
|
|
42898
|
+
return {
|
|
42899
|
+
id: r.runId,
|
|
42900
|
+
from: r.startedAt,
|
|
42901
|
+
to: runEnd(r, now),
|
|
42902
|
+
title,
|
|
42903
|
+
label: status === "running" ? t("uiLibrary.history.runs.bandRunning", "running · {{parts}}", { parts: parts.join(" · ") }) : parts.join(" · "),
|
|
42904
|
+
tone: runTone(status)
|
|
42905
|
+
};
|
|
42906
|
+
});
|
|
42907
|
+
}
|
|
42908
|
+
//#endregion
|
|
42909
|
+
//#region src/composites/DeviceRunsPanel.tsx
|
|
42910
|
+
/**
|
|
42911
|
+
* DeviceRunsPanel — the runs of an appliance, newest first, on the device's
|
|
42912
|
+
* History tab: start, end, duration, energy, peak and mean power, outcome.
|
|
42913
|
+
* A row opens the run's window (the run plus a margin) in the history view.
|
|
42914
|
+
*
|
|
42915
|
+
* Presentational: the caller reads the runs (`useDeviceRuns`) and decides
|
|
42916
|
+
* whether the device has any — the panel never answers "no runs" itself, an
|
|
42917
|
+
* unanswered query is not an empty one (D315). A measurement that failed is
|
|
42918
|
+
* `—`, never `0` (D393).
|
|
42919
|
+
*/
|
|
42920
|
+
function statusLabel(status, t) {
|
|
42921
|
+
switch (status) {
|
|
42922
|
+
case "running": return t("uiLibrary.history.runs.status.running", "Running");
|
|
42923
|
+
case "completed": return t("uiLibrary.history.runs.status.completed", "Completed");
|
|
42924
|
+
case "aborted": return t("uiLibrary.history.runs.status.aborted", "Aborted");
|
|
42925
|
+
case "error": return t("uiLibrary.history.runs.status.error", "Error");
|
|
42926
|
+
case "unknown": return t("uiLibrary.history.runs.status.unknown", "Unknown");
|
|
42927
|
+
}
|
|
42928
|
+
}
|
|
42929
|
+
var formatStamp = (ms) => new Date(ms).toLocaleString(void 0, {
|
|
42930
|
+
dateStyle: "short",
|
|
42931
|
+
timeStyle: "short"
|
|
42932
|
+
});
|
|
42933
|
+
function runColumns(now, t) {
|
|
42934
|
+
return [
|
|
42935
|
+
{
|
|
42936
|
+
key: "start",
|
|
42937
|
+
header: t("uiLibrary.history.runs.start", "Start"),
|
|
42938
|
+
render: (r) => formatStamp(r.startedAt),
|
|
42939
|
+
sortValue: (r) => r.startedAt
|
|
42940
|
+
},
|
|
42941
|
+
{
|
|
42942
|
+
key: "end",
|
|
42943
|
+
header: t("uiLibrary.history.runs.end", "End"),
|
|
42944
|
+
render: (r) => r.state === "open" || r.endedAt === null ? t("uiLibrary.history.runs.runningSince", "Running since {{time}}", { time: formatStamp(r.startedAt) }) : formatStamp(r.endedAt),
|
|
42945
|
+
sortValue: (r) => r.endedAt
|
|
42946
|
+
},
|
|
42947
|
+
{
|
|
42948
|
+
key: "duration",
|
|
42949
|
+
header: t("uiLibrary.history.runs.duration", "Duration"),
|
|
42950
|
+
align: "right",
|
|
42951
|
+
render: (r) => formatRunDuration(runDurationMs(r, now)),
|
|
42952
|
+
sortValue: (r) => runDurationMs(r, now)
|
|
42953
|
+
},
|
|
42954
|
+
{
|
|
42955
|
+
key: "energy",
|
|
42956
|
+
header: t("uiLibrary.history.runs.energy", "Energy"),
|
|
42957
|
+
align: "right",
|
|
42958
|
+
render: (r) => formatKwh(r.detail.energyKwh),
|
|
42959
|
+
sortValue: (r) => r.detail.energyKwh
|
|
42960
|
+
},
|
|
42961
|
+
{
|
|
42962
|
+
key: "peak",
|
|
42963
|
+
header: t("uiLibrary.history.runs.peak", "Peak"),
|
|
42964
|
+
align: "right",
|
|
42965
|
+
render: (r) => formatWatts(r.detail.peakW),
|
|
42966
|
+
sortValue: (r) => r.detail.peakW
|
|
42967
|
+
},
|
|
42968
|
+
{
|
|
42969
|
+
key: "avg",
|
|
42970
|
+
header: t("uiLibrary.history.runs.avg", "Average"),
|
|
42971
|
+
align: "right",
|
|
42972
|
+
render: (r) => formatWatts(r.detail.avgW),
|
|
42973
|
+
sortValue: (r) => r.detail.avgW
|
|
42974
|
+
},
|
|
42975
|
+
{
|
|
42976
|
+
key: "outcome",
|
|
42977
|
+
header: t("uiLibrary.history.runs.outcome", "Outcome"),
|
|
42978
|
+
render: (r) => {
|
|
42979
|
+
const status = runStatus(r);
|
|
42980
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Badge, {
|
|
42981
|
+
variant: runTone(status),
|
|
42982
|
+
children: statusLabel(status, t)
|
|
42983
|
+
});
|
|
42984
|
+
},
|
|
42985
|
+
notSortableReason: t("uiLibrary.history.runs.outcomeNoSort", "Outcomes have no order")
|
|
42986
|
+
}
|
|
42987
|
+
];
|
|
42988
|
+
}
|
|
42989
|
+
function DeviceRunsPanel({ runs, now, onSelectWindow, className }) {
|
|
42990
|
+
const t = useUiText();
|
|
42991
|
+
const [expanded, setExpanded] = (0, react$1.useState)(true);
|
|
42992
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollapsibleCard, {
|
|
42993
|
+
className,
|
|
42994
|
+
expanded,
|
|
42995
|
+
onExpandedChange: setExpanded,
|
|
42996
|
+
header: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
42997
|
+
className: "flex items-center gap-2 min-w-0",
|
|
42998
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
42999
|
+
className: "text-xs font-semibold text-foreground truncate",
|
|
43000
|
+
children: t("uiLibrary.history.runs.title", "Runs")
|
|
43001
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
43002
|
+
className: "text-[10px] text-foreground-subtle shrink-0",
|
|
43003
|
+
children: t("uiLibrary.history.runs.count", {
|
|
43004
|
+
one: "{{count}} run",
|
|
43005
|
+
other: "{{count}} runs"
|
|
43006
|
+
}, { count: runs.length })
|
|
43007
|
+
})]
|
|
43008
|
+
}),
|
|
43009
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTable, {
|
|
43010
|
+
columns: runColumns(now, t),
|
|
43011
|
+
rows: runs,
|
|
43012
|
+
rowKey: (r) => r.runId,
|
|
43013
|
+
onRowClick: (r) => onSelectWindow(runWindow(r, now)),
|
|
43014
|
+
maxBodyHeight: TABLE_SCROLL_MAX_H,
|
|
43015
|
+
bordered: false,
|
|
43016
|
+
minWidthPx: 640
|
|
43017
|
+
})
|
|
43018
|
+
});
|
|
43019
|
+
}
|
|
43020
|
+
//#endregion
|
|
42824
43021
|
//#region src/composites/device-list/fuzzy-match.ts
|
|
42825
43022
|
/**
|
|
42826
43023
|
* fuzzy-match — case and separator-insensitive text search helper.
|
|
@@ -71771,6 +71968,7 @@ function latestValues(model) {
|
|
|
71771
71968
|
* for the cross-device History page, where the reader chose the series.
|
|
71772
71969
|
*/
|
|
71773
71970
|
var DEFAULT_HEIGHT = 120;
|
|
71971
|
+
var NO_BANDS = [];
|
|
71774
71972
|
function seriesSpan(range, xs) {
|
|
71775
71973
|
if (range !== void 0) return range.to - range.from;
|
|
71776
71974
|
if (xs.length < 2) return 0;
|
|
@@ -71797,18 +71995,25 @@ function seriesTooltip(input) {
|
|
|
71797
71995
|
value: values[i] ?? null,
|
|
71798
71996
|
quantity: sample.quantity,
|
|
71799
71997
|
unit: sample.unit ?? null
|
|
71998
|
+
})),
|
|
71999
|
+
extra: bandsAt(input.bands, at).map((b) => ({
|
|
72000
|
+
id: `band:${b.id}`,
|
|
72001
|
+
label: b.title,
|
|
72002
|
+
value: b.label
|
|
71800
72003
|
}))
|
|
71801
72004
|
});
|
|
71802
72005
|
},
|
|
71803
72006
|
onDataX: input.onDataX
|
|
71804
72007
|
};
|
|
71805
72008
|
}
|
|
71806
|
-
function TimeSeriesChart({ title, series, range, height = DEFAULT_HEIGHT, stacked = false, area = false, syncKey, formatValue, displayPreference, axisFor, emptyMessage, pending = false, actions, footer, windowToggle, className }) {
|
|
72009
|
+
function TimeSeriesChart({ title, series, bands = NO_BANDS, range, height = DEFAULT_HEIGHT, stacked = false, area = false, syncKey, formatValue, displayPreference, axisFor, emptyMessage, pending = false, actions, footer, windowToggle, className }) {
|
|
71807
72010
|
const t = useUiText();
|
|
71808
72011
|
const model = (0, react$1.useMemo)(() => buildTimeSeriesModel(series, stacked), [series, stacked]);
|
|
71809
72012
|
const [cursorIdx, setCursorIdx] = (0, react$1.useState)(null);
|
|
71810
72013
|
const modelRef = (0, react$1.useRef)(model);
|
|
71811
72014
|
modelRef.current = model;
|
|
72015
|
+
const bandsRef = (0, react$1.useRef)(bands);
|
|
72016
|
+
bandsRef.current = bands;
|
|
71812
72017
|
const rangeRef = (0, react$1.useRef)(range);
|
|
71813
72018
|
rangeRef.current = range;
|
|
71814
72019
|
const fmt = (0, react$1.useCallback)((v, unit) => (formatValue ?? formatChartValue)(v, unit), [formatValue]);
|
|
@@ -71937,7 +72142,7 @@ function TimeSeriesChart({ title, series, range, height = DEFAULT_HEIGHT, stacke
|
|
|
71937
72142
|
bands,
|
|
71938
72143
|
cursor: chartCursor(syncKey),
|
|
71939
72144
|
hooks: {
|
|
71940
|
-
drawClear: [gapShadeHook(() => modelRef.current.gaps)],
|
|
72145
|
+
drawClear: [bandShadeHook(() => bandsRef.current), gapShadeHook(() => modelRef.current.gaps)],
|
|
71941
72146
|
setCursor: [(u) => setCursorIdx(u.cursor.idx ?? null)]
|
|
71942
72147
|
}
|
|
71943
72148
|
};
|
|
@@ -71949,6 +72154,7 @@ function TimeSeriesChart({ title, series, range, height = DEFAULT_HEIGHT, stacke
|
|
|
71949
72154
|
const tooltip = (0, react$1.useMemo)(() => seriesTooltip({
|
|
71950
72155
|
model,
|
|
71951
72156
|
series,
|
|
72157
|
+
bands,
|
|
71952
72158
|
range,
|
|
71953
72159
|
preference: displayPreference,
|
|
71954
72160
|
onDataX: (dataX) => {
|
|
@@ -71957,6 +72163,7 @@ function TimeSeriesChart({ title, series, range, height = DEFAULT_HEIGHT, stacke
|
|
|
71957
72163
|
}), [
|
|
71958
72164
|
model,
|
|
71959
72165
|
series,
|
|
72166
|
+
bands,
|
|
71960
72167
|
range,
|
|
71961
72168
|
displayPreference
|
|
71962
72169
|
]);
|
|
@@ -72744,7 +72951,7 @@ function booleanLabels(key, t) {
|
|
|
72744
72951
|
function failure(entry) {
|
|
72745
72952
|
return entry !== void 0 && !entry.ok ? entry.error : null;
|
|
72746
72953
|
}
|
|
72747
|
-
function HistoryChart({ spec, entryFor, reads, window, compare, syncKey, actions }) {
|
|
72954
|
+
function HistoryChart({ spec, entryFor, reads, window, compare, syncKey, actions, runs, now }) {
|
|
72748
72955
|
const t = useUiText();
|
|
72749
72956
|
const pending = reads === null;
|
|
72750
72957
|
if (spec.type === "states") {
|
|
@@ -72819,13 +73026,15 @@ function HistoryChart({ spec, entryFor, reads, window, compare, syncKey, actions
|
|
|
72819
73026
|
compare,
|
|
72820
73027
|
syncKey,
|
|
72821
73028
|
actions,
|
|
73029
|
+
runs: spec.series.some((s) => s.key === "cap:power-meter.power") ? runs : void 0,
|
|
73030
|
+
now,
|
|
72822
73031
|
labelOf: (s) => spec.series.length > 1 || s.scope !== "" ? seriesLabel(s) : spec.title
|
|
72823
73032
|
});
|
|
72824
73033
|
}
|
|
72825
73034
|
function seriesLabel(s) {
|
|
72826
73035
|
return s.scope === "" ? s.displayName : `${s.displayName} · ${s.scope}`;
|
|
72827
73036
|
}
|
|
72828
|
-
function LinesChart({ title, series, entryFor, reads, window, compare, syncKey, actions, labelOf, toolbar, colorOf }) {
|
|
73037
|
+
function LinesChart({ title, series, entryFor, reads, window, compare, syncKey, actions, labelOf, toolbar, colorOf, runs, now }) {
|
|
72829
73038
|
const t = useUiText();
|
|
72830
73039
|
const errors = [...new Set(series.map((s) => failure(entryFor(s.key, false))).filter((e) => e !== null))];
|
|
72831
73040
|
const defs = (0, react$1.useMemo)(() => {
|
|
@@ -72875,6 +73084,12 @@ function LinesChart({ title, series, entryFor, reads, window, compare, syncKey,
|
|
|
72875
73084
|
colorOf,
|
|
72876
73085
|
t
|
|
72877
73086
|
]);
|
|
73087
|
+
const bands = (0, react$1.useMemo)(() => runs === void 0 ? [] : runBands(runs, now ?? window.to, window, t), [
|
|
73088
|
+
runs,
|
|
73089
|
+
now,
|
|
73090
|
+
window,
|
|
73091
|
+
t
|
|
73092
|
+
]);
|
|
72878
73093
|
if (errors.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReadFailed, {
|
|
72879
73094
|
title,
|
|
72880
73095
|
error: errors.join("; "),
|
|
@@ -72883,6 +73098,7 @@ function LinesChart({ title, series, entryFor, reads, window, compare, syncKey,
|
|
|
72883
73098
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimeSeriesChart, {
|
|
72884
73099
|
title,
|
|
72885
73100
|
series: defs,
|
|
73101
|
+
bands,
|
|
72886
73102
|
range: window,
|
|
72887
73103
|
syncKey,
|
|
72888
73104
|
pending: reads === null,
|
|
@@ -73218,6 +73434,24 @@ function HistoryWindowBar({ value, onChange, custom, onCustomChange, compare, on
|
|
|
73218
73434
|
});
|
|
73219
73435
|
}
|
|
73220
73436
|
//#endregion
|
|
73437
|
+
//#region src/composites/device-history/use-device-runs.ts
|
|
73438
|
+
/** How many runs the panel and the bands are given; the cap's page size. */
|
|
73439
|
+
var DEVICE_RUNS_PAGE = 50;
|
|
73440
|
+
var REFRESH_MS = 6e4;
|
|
73441
|
+
/** The newest runs, or `undefined` while unanswered, absent or empty. */
|
|
73442
|
+
function useDeviceRuns(deviceId) {
|
|
73443
|
+
const q = useDeviceRunsListRuns({
|
|
73444
|
+
deviceId,
|
|
73445
|
+
limit: 50
|
|
73446
|
+
}, {
|
|
73447
|
+
staleTime: REFRESH_MS,
|
|
73448
|
+
refetchInterval: REFRESH_MS,
|
|
73449
|
+
retry: false
|
|
73450
|
+
});
|
|
73451
|
+
if (q.status !== "success" || q.data.runs.length === 0) return void 0;
|
|
73452
|
+
return q.data.runs;
|
|
73453
|
+
}
|
|
73454
|
+
//#endregion
|
|
73221
73455
|
//#region src/composites/device-history/history-reads.ts
|
|
73222
73456
|
/**
|
|
73223
73457
|
* Batched history reads. `queryMany` answers up to 24 reads over one window
|
|
@@ -73502,7 +73736,9 @@ function DeviceHistoryView({ deviceId, fixedWindow, onNavigate }) {
|
|
|
73502
73736
|
const custom = fixedWindow ? null : decodeCustomWindow(customParam);
|
|
73503
73737
|
const compare = fixedWindow === void 0 && compareParam === "1";
|
|
73504
73738
|
const spanGuess = resolveHistoryWindow(windowId, Date.now(), custom);
|
|
73505
|
-
const
|
|
73739
|
+
const now = anchorNow(Date.now(), spanGuess.to - spanGuess.from);
|
|
73740
|
+
const range = resolveHistoryWindow(windowId, now, custom);
|
|
73741
|
+
const runs = useDeviceRuns(deviceId);
|
|
73506
73742
|
const { presence, list } = useDeviceSeriesList(deviceId);
|
|
73507
73743
|
const panels = useHistoryPanels();
|
|
73508
73744
|
const hidden = (0, react$1.useMemo)(() => new Set(panels.value.hidden[String(deviceId)] ?? []), [panels.value.hidden, deviceId]);
|
|
@@ -73570,81 +73806,95 @@ function DeviceHistoryView({ deviceId, fixedWindow, onNavigate }) {
|
|
|
73570
73806
|
description: t("uiLibrary.history.empty", "A value appears here once it changes, or at the next five-minute check.")
|
|
73571
73807
|
});
|
|
73572
73808
|
const syncKey = `device-history:${String(deviceId)}`;
|
|
73809
|
+
const showWindow = (w) => {
|
|
73810
|
+
setWindowParam("custom");
|
|
73811
|
+
setCustomParam(encodeCustomWindow(w));
|
|
73812
|
+
};
|
|
73573
73813
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
73574
73814
|
className: STACK_GAP,
|
|
73575
|
-
children: [
|
|
73576
|
-
|
|
73577
|
-
|
|
73578
|
-
|
|
73579
|
-
|
|
73580
|
-
|
|
73581
|
-
|
|
73582
|
-
|
|
73583
|
-
|
|
73584
|
-
|
|
73585
|
-
|
|
73586
|
-
|
|
73587
|
-
|
|
73588
|
-
|
|
73589
|
-
|
|
73590
|
-
|
|
73591
|
-
|
|
73592
|
-
|
|
73593
|
-
|
|
73594
|
-
|
|
73595
|
-
|
|
73596
|
-
|
|
73597
|
-
|
|
73598
|
-
|
|
73599
|
-
|
|
73600
|
-
|
|
73601
|
-
|
|
73602
|
-
|
|
73603
|
-
|
|
73604
|
-
|
|
73605
|
-
|
|
73606
|
-
|
|
73607
|
-
|
|
73608
|
-
|
|
73609
|
-
|
|
73610
|
-
|
|
73611
|
-
|
|
73612
|
-
|
|
73613
|
-
|
|
73614
|
-
|
|
73615
|
-
|
|
73616
|
-
|
|
73617
|
-
|
|
73618
|
-
|
|
73619
|
-
|
|
73620
|
-
|
|
73621
|
-
|
|
73622
|
-
|
|
73623
|
-
|
|
73624
|
-
|
|
73625
|
-
|
|
73626
|
-
|
|
73627
|
-
|
|
73628
|
-
|
|
73629
|
-
|
|
73630
|
-
|
|
73631
|
-
|
|
73632
|
-
|
|
73633
|
-
|
|
73634
|
-
|
|
73635
|
-
|
|
73636
|
-
|
|
73637
|
-
|
|
73638
|
-
|
|
73639
|
-
|
|
73640
|
-
|
|
73641
|
-
|
|
73642
|
-
|
|
73643
|
-
|
|
73644
|
-
|
|
73645
|
-
|
|
73646
|
-
|
|
73647
|
-
|
|
73815
|
+
children: [
|
|
73816
|
+
fixedWindow === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
73817
|
+
className: "flex flex-wrap items-center justify-between gap-2",
|
|
73818
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(HistoryWindowBar, {
|
|
73819
|
+
value: windowId,
|
|
73820
|
+
onChange: (id) => setWindowParam(id === "24h" ? null : id),
|
|
73821
|
+
custom,
|
|
73822
|
+
onCustomChange: (w) => setCustomParam(encodeCustomWindow(w)),
|
|
73823
|
+
compare,
|
|
73824
|
+
onCompareChange: (on) => setCompareParam(on ? "1" : null)
|
|
73825
|
+
}), hiddenCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Button, {
|
|
73826
|
+
variant: "ghost",
|
|
73827
|
+
size: "sm",
|
|
73828
|
+
onClick: showAllHidden,
|
|
73829
|
+
disabled: !panels.writable,
|
|
73830
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(EyeOff, {
|
|
73831
|
+
className: "h-3.5 w-3.5",
|
|
73832
|
+
"aria-hidden": "true"
|
|
73833
|
+
}), t("uiLibrary.history.showHidden", {
|
|
73834
|
+
one: "Show {{count}} hidden chart",
|
|
73835
|
+
other: "Show {{count}} hidden charts"
|
|
73836
|
+
}, { count: hiddenCount })]
|
|
73837
|
+
})]
|
|
73838
|
+
}),
|
|
73839
|
+
fixedWindow === void 0 && runs !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceRunsPanel, {
|
|
73840
|
+
runs,
|
|
73841
|
+
now,
|
|
73842
|
+
onSelectWindow: showWindow
|
|
73843
|
+
}),
|
|
73844
|
+
visible.map((section) => {
|
|
73845
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollapsibleCard, {
|
|
73846
|
+
expanded: !collapsed.has(section.id),
|
|
73847
|
+
onExpandedChange: (next) => setCollapsed((prev) => {
|
|
73848
|
+
const s = new Set(prev);
|
|
73849
|
+
if (next) s.delete(section.id);
|
|
73850
|
+
else s.add(section.id);
|
|
73851
|
+
return s;
|
|
73852
|
+
}),
|
|
73853
|
+
header: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
73854
|
+
className: "flex items-center gap-2 min-w-0",
|
|
73855
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
73856
|
+
className: "text-xs font-semibold text-foreground truncate",
|
|
73857
|
+
children: humanizeName(section.name)
|
|
73858
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
73859
|
+
className: "text-[10px] text-foreground-subtle shrink-0",
|
|
73860
|
+
children: t("uiLibrary.history.chartCount", {
|
|
73861
|
+
one: "{{count}} chart",
|
|
73862
|
+
other: "{{count}} charts"
|
|
73863
|
+
}, { count: section.charts.length })
|
|
73864
|
+
})]
|
|
73865
|
+
}),
|
|
73866
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
73867
|
+
className: "grid grid-cols-1 gap-4 2xl:grid-cols-2",
|
|
73868
|
+
children: section.charts.map((spec) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HistoryChart, {
|
|
73869
|
+
spec,
|
|
73870
|
+
entryFor,
|
|
73871
|
+
reads: readsData,
|
|
73872
|
+
window: range,
|
|
73873
|
+
compare,
|
|
73874
|
+
syncKey,
|
|
73875
|
+
runs,
|
|
73876
|
+
now,
|
|
73877
|
+
actions: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(KebabMenu, {
|
|
73878
|
+
title: t("uiLibrary.history.chartMenu", "Chart actions"),
|
|
73879
|
+
items: [{
|
|
73880
|
+
id: "open",
|
|
73881
|
+
label: t("uiLibrary.history.openInHistory", "Open in History"),
|
|
73882
|
+
icon: ChartLine,
|
|
73883
|
+
onClick: () => navigate(historyPageHref(refsOf(deviceId, spec), windowId))
|
|
73884
|
+
}, {
|
|
73885
|
+
id: "hide",
|
|
73886
|
+
label: t("uiLibrary.history.hide", "Hide"),
|
|
73887
|
+
icon: EyeOff,
|
|
73888
|
+
hidden: fixedWindow !== void 0,
|
|
73889
|
+
disabled: !panels.writable,
|
|
73890
|
+
onClick: () => setHidden(spec.id, true)
|
|
73891
|
+
}]
|
|
73892
|
+
})
|
|
73893
|
+
}, spec.id))
|
|
73894
|
+
})
|
|
73895
|
+
}, section.id);
|
|
73896
|
+
})
|
|
73897
|
+
]
|
|
73648
73898
|
});
|
|
73649
73899
|
}
|
|
73650
73900
|
function HistorySkeleton() {
|
|
@@ -73804,7 +74054,7 @@ function TimelineSlider({ markers, bands = [], selectedId = null, step = 5, aria
|
|
|
73804
74054
|
}
|
|
73805
74055
|
//#endregion
|
|
73806
74056
|
//#region src/ui-library-version.ts
|
|
73807
|
-
var uiLibraryVersion = "1.2.
|
|
74057
|
+
var uiLibraryVersion = "1.2.385";
|
|
73808
74058
|
//#endregion
|
|
73809
74059
|
//#region src/hooks/use-account-unit-preferences.ts
|
|
73810
74060
|
/**
|
|
@@ -74909,6 +75159,7 @@ exports.DEVICE_NAME_JOIN = DEVICE_NAME_JOIN;
|
|
|
74909
75159
|
exports.DEVICE_PICKER_GROUP_STORAGE_KEY = DEVICE_PICKER_GROUP_STORAGE_KEY;
|
|
74910
75160
|
exports.DEVICE_ROLE_META = DEVICE_ROLE_META;
|
|
74911
75161
|
exports.DEVICE_ROLE_NOUNS = DEVICE_ROLE_NOUNS;
|
|
75162
|
+
exports.DEVICE_RUNS_PAGE = DEVICE_RUNS_PAGE;
|
|
74912
75163
|
exports.DEVICE_TYPE_CONTROL = DEVICE_TYPE_CONTROL;
|
|
74913
75164
|
exports.DEVICE_TYPE_META = DEVICE_TYPE_META;
|
|
74914
75165
|
exports.DEVICE_TYPE_NOUNS = DEVICE_TYPE_NOUNS;
|
|
@@ -74939,6 +75190,7 @@ exports.DeviceMultiSelectField = DeviceMultiSelectField;
|
|
|
74939
75190
|
exports.DeviceName = DeviceName;
|
|
74940
75191
|
exports.DevicePicker = DevicePicker;
|
|
74941
75192
|
exports.DeviceQuickDetailProvider = DeviceQuickDetailProvider;
|
|
75193
|
+
exports.DeviceRunsPanel = DeviceRunsPanel;
|
|
74942
75194
|
exports.DeviceSelectField = DeviceSelectField;
|
|
74943
75195
|
exports.DeviceSelectorPicker = DeviceSelectorPicker;
|
|
74944
75196
|
exports.DeviceStepMatrix = DeviceStepMatrix;
|
|
@@ -75188,6 +75440,7 @@ exports.RIGHT = RIGHT;
|
|
|
75188
75440
|
exports.ROI_AREA_WARN_FRACTION = ROI_AREA_WARN_FRACTION;
|
|
75189
75441
|
exports.ROLE_DESCRIPTOR = ROLE_DESCRIPTOR;
|
|
75190
75442
|
exports.ROOT_DETECTOR_STEP_ID = ROOT_DETECTOR_STEP_ID;
|
|
75443
|
+
exports.RUN_WINDOW_MARGIN_MS = RUN_WINDOW_MARGIN_MS;
|
|
75191
75444
|
exports.Radar = Radar;
|
|
75192
75445
|
exports.RadialGauge = RadialGauge;
|
|
75193
75446
|
exports.Radio = Radio;
|
|
@@ -75685,6 +75938,8 @@ exports.roiTooLarge = roiTooLarge;
|
|
|
75685
75938
|
exports.roiTooLarge$1 = roiTooLarge;
|
|
75686
75939
|
exports.rootSourceState = rootSourceState;
|
|
75687
75940
|
exports.routerBasename = routerBasename;
|
|
75941
|
+
exports.runBands = runBands;
|
|
75942
|
+
exports.runWindow = runWindow;
|
|
75688
75943
|
exports.runningDurationSince = runningDurationSince;
|
|
75689
75944
|
exports.runningStatusParts = runningStatusParts;
|
|
75690
75945
|
exports.sameDeviceName = sameDeviceName;
|
|
@@ -76180,6 +76435,7 @@ exports.useDeviceProviderTestCreationField = useDeviceProviderTestCreationField;
|
|
|
76180
76435
|
exports.useDeviceProxy = useDeviceProxy;
|
|
76181
76436
|
exports.useDeviceProxy$1 = useDeviceProxy;
|
|
76182
76437
|
exports.useDeviceQuickDetailOpen = useDeviceQuickDetailOpen;
|
|
76438
|
+
exports.useDeviceRuns = useDeviceRuns;
|
|
76183
76439
|
exports.useDeviceRunsGetCurrentRun = useDeviceRunsGetCurrentRun;
|
|
76184
76440
|
exports.useDeviceRunsGetRun = useDeviceRunsGetRun;
|
|
76185
76441
|
exports.useDeviceRunsListRuns = useDeviceRunsListRuns;
|
|
@@ -76287,15 +76543,12 @@ exports.useIntegrationInstancesListInstances = useIntegrationInstancesListInstan
|
|
|
76287
76543
|
exports.useIntegrationInstancesSetInstanceEnabled = useIntegrationInstancesSetInstanceEnabled;
|
|
76288
76544
|
exports.useIntegrationInstancesTestInstance = useIntegrationInstancesTestInstance;
|
|
76289
76545
|
exports.useIntegrationInstancesUpdateInstance = useIntegrationInstancesUpdateInstance;
|
|
76290
|
-
exports.useIntegrationsClearSettings = useIntegrationsClearSettings;
|
|
76291
76546
|
exports.useIntegrationsCreate = useIntegrationsCreate;
|
|
76292
76547
|
exports.useIntegrationsDelete = useIntegrationsDelete;
|
|
76293
76548
|
exports.useIntegrationsGet = useIntegrationsGet;
|
|
76294
76549
|
exports.useIntegrationsGetAvailableTypes = useIntegrationsGetAvailableTypes;
|
|
76295
76550
|
exports.useIntegrationsGetByAddonId = useIntegrationsGetByAddonId;
|
|
76296
|
-
exports.useIntegrationsGetSettings = useIntegrationsGetSettings;
|
|
76297
76551
|
exports.useIntegrationsList = useIntegrationsList;
|
|
76298
|
-
exports.useIntegrationsSetSettings = useIntegrationsSetSettings;
|
|
76299
76552
|
exports.useIntegrationsTestConnection = useIntegrationsTestConnection;
|
|
76300
76553
|
exports.useIntegrationsUpdate = useIntegrationsUpdate;
|
|
76301
76554
|
exports.useIntercomEndTalkSession = useIntercomEndTalkSession;
|