@devicechain/widgets 0.22.0 → 0.23.0
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 +15 -0
- package/dist/access-strings.d.ts +6 -0
- package/dist/chunks/{aggregate-feed-6ZYKOQOB.js → aggregate-feed-BD3CHNFU.js} +5 -4
- package/dist/chunks/aggregate-feed-BD3CHNFU.js.map +7 -0
- package/dist/chunks/{aggregate-widgets-WVXAW3UL.js → aggregate-widgets-HZQI5HTX.js} +3 -2
- package/dist/chunks/{aggregate-widgets-WVXAW3UL.js.map → aggregate-widgets-HZQI5HTX.js.map} +1 -1
- package/dist/chunks/alarm-widgets-7UY6MIYZ.js +9 -0
- package/dist/chunks/alarm-widgets-7UY6MIYZ.js.map +7 -0
- package/dist/chunks/chunk-6OGI4UFJ.js +367 -0
- package/dist/chunks/chunk-6OGI4UFJ.js.map +7 -0
- package/dist/chunks/chunk-BRH66T5F.js +15 -0
- package/dist/chunks/chunk-BRH66T5F.js.map +7 -0
- package/dist/chunks/chunk-FM7OI5TQ.js +87 -0
- package/dist/chunks/chunk-FM7OI5TQ.js.map +7 -0
- package/dist/chunks/chunk-USRYKW2J.js +55 -0
- package/dist/chunks/chunk-USRYKW2J.js.map +7 -0
- package/dist/chunks/{chunk-S2OMBJLI.js → chunk-WBKHYZU2.js} +7 -3
- package/dist/chunks/{chunk-S2OMBJLI.js.map → chunk-WBKHYZU2.js.map} +2 -2
- package/dist/chunks/chunk-XSLFHCNI.js +419 -0
- package/dist/chunks/chunk-XSLFHCNI.js.map +7 -0
- package/dist/chunks/{control-widgets-UDS4ET3T.js → control-widgets-3V2LSSRF.js} +4 -2
- package/dist/chunks/{control-widgets-UDS4ET3T.js.map → control-widgets-3V2LSSRF.js.map} +1 -1
- package/dist/chunks/entity-selector-3JJFI4DT.js +7 -0
- package/dist/chunks/entity-selector-3JJFI4DT.js.map +7 -0
- package/dist/chunks/{fleet-feed-FK4ZMKIK.js → fleet-feed-5QGDLOV5.js} +27 -7
- package/dist/chunks/fleet-feed-5QGDLOV5.js.map +7 -0
- package/dist/chunks/table-6EVV7QZH.js +7 -0
- package/dist/chunks/table-6EVV7QZH.js.map +7 -0
- package/dist/connected-widget.d.ts +2 -0
- package/dist/dashboard-renderer.d.ts +1 -0
- package/dist/fleet-feed.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +478 -1142
- package/dist/index.js.map +4 -4
- package/dist/preload.d.ts +2 -0
- package/dist/widgets/alarm-count.d.ts +0 -46
- package/dist/widgets/alarm-lazy.d.ts +123 -0
- package/dist/widgets/alarm-table.d.ts +0 -76
- package/dist/widgets/alarm-widgets.d.ts +2 -0
- package/dist/widgets/command-button.d.ts +0 -38
- package/dist/widgets/control-lazy.d.ts +38 -0
- package/dist/widgets/control-widgets.d.ts +1 -0
- package/dist/widgets/entity-selector.d.ts +0 -15
- package/dist/widgets/gauge.d.ts +4 -0
- package/dist/widgets/lazy-chunk.d.ts +2 -1
- package/dist/widgets/selection-lazy.d.ts +16 -0
- package/dist/widgets/table-lazy.d.ts +39 -0
- package/dist/widgets/table.d.ts +0 -38
- package/dist/widgets/time-series-chart.d.ts +4 -0
- package/package.json +10 -7
- package/dist/chunks/aggregate-feed-6ZYKOQOB.js.map +0 -7
- package/dist/chunks/chunk-YPFB6DAL.js +0 -157
- package/dist/chunks/chunk-YPFB6DAL.js.map +0 -7
- package/dist/chunks/fleet-feed-FK4ZMKIK.js.map +0 -7
package/dist/index.js
CHANGED
|
@@ -1,27 +1,44 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Table
|
|
3
|
+
} from "./chunks/chunk-USRYKW2J.js";
|
|
4
|
+
import {
|
|
5
|
+
alarmSubscription,
|
|
6
|
+
commandSubscription,
|
|
7
|
+
measurementSpan,
|
|
8
|
+
measurementWindow,
|
|
9
|
+
membersMode
|
|
10
|
+
} from "./chunks/chunk-2D7JNKFE.js";
|
|
11
|
+
import {
|
|
12
|
+
accessStrings
|
|
13
|
+
} from "./chunks/chunk-BRH66T5F.js";
|
|
14
|
+
import {
|
|
15
|
+
AlarmCount,
|
|
16
|
+
AlarmTable,
|
|
17
|
+
highestSeverity,
|
|
18
|
+
severityColor,
|
|
19
|
+
severityLabel,
|
|
20
|
+
severityRank
|
|
21
|
+
} from "./chunks/chunk-6OGI4UFJ.js";
|
|
22
|
+
import {
|
|
23
|
+
CommandButton,
|
|
2
24
|
buildPayload,
|
|
3
25
|
commandStatusColor,
|
|
4
26
|
commandStatusLabel,
|
|
5
27
|
defaultValues,
|
|
6
28
|
isScalar,
|
|
7
29
|
isTerminalStatus,
|
|
8
|
-
parseBool,
|
|
9
30
|
parseParameterSchema,
|
|
10
31
|
validateParams
|
|
11
|
-
} from "./chunks/chunk-
|
|
32
|
+
} from "./chunks/chunk-XSLFHCNI.js";
|
|
33
|
+
import {
|
|
34
|
+
EntitySelector
|
|
35
|
+
} from "./chunks/chunk-FM7OI5TQ.js";
|
|
12
36
|
import {
|
|
13
37
|
readRange
|
|
14
38
|
} from "./chunks/chunk-ZR74ORIT.js";
|
|
15
39
|
import {
|
|
16
40
|
LevelReadout
|
|
17
41
|
} from "./chunks/chunk-XQQQNTBX.js";
|
|
18
|
-
import {
|
|
19
|
-
alarmSubscription,
|
|
20
|
-
commandSubscription,
|
|
21
|
-
measurementSpan,
|
|
22
|
-
measurementWindow,
|
|
23
|
-
membersMode
|
|
24
|
-
} from "./chunks/chunk-2D7JNKFE.js";
|
|
25
42
|
|
|
26
43
|
// src/dashboard-renderer.tsx
|
|
27
44
|
import {
|
|
@@ -47,7 +64,7 @@ import {
|
|
|
47
64
|
WidgetTimeRangeProvider,
|
|
48
65
|
WidgetTokenStyles
|
|
49
66
|
} from "@devicechain/widget-sdk";
|
|
50
|
-
import { Fragment
|
|
67
|
+
import { Fragment, useCallback as useCallback2, useEffect as useEffect4, useLayoutEffect, useMemo as useMemo5, useRef as useRef2, useState as useState6 } from "react";
|
|
51
68
|
|
|
52
69
|
// src/connected-widget.tsx
|
|
53
70
|
import {
|
|
@@ -61,7 +78,8 @@ import {
|
|
|
61
78
|
WidgetSelectProvider,
|
|
62
79
|
useWidgetTimeRange as useWidgetTimeRange2
|
|
63
80
|
} from "@devicechain/widget-sdk";
|
|
64
|
-
import {
|
|
81
|
+
import { isForbiddenError } from "@devicechain/client";
|
|
82
|
+
import { useEffect as useEffect3, useMemo as useMemo4, useState as useState5 } from "react";
|
|
65
83
|
|
|
66
84
|
// src/use-held.ts
|
|
67
85
|
import { useState } from "react";
|
|
@@ -1095,7 +1113,7 @@ function lazyChunk(importer) {
|
|
|
1095
1113
|
throw err;
|
|
1096
1114
|
}
|
|
1097
1115
|
));
|
|
1098
|
-
function component(name) {
|
|
1116
|
+
function component(name, alsoPreload) {
|
|
1099
1117
|
function LazyChunkWidget(props) {
|
|
1100
1118
|
const [mod, setMod] = useState2(loaded);
|
|
1101
1119
|
const [error, setError] = useState2();
|
|
@@ -1108,13 +1126,14 @@ function lazyChunk(importer) {
|
|
|
1108
1126
|
return /* @__PURE__ */ jsx(Component2, { ...props });
|
|
1109
1127
|
}
|
|
1110
1128
|
LazyChunkWidget.displayName = `Lazy(${name})`;
|
|
1129
|
+
LazyChunkWidget.preload = alsoPreload ? () => Promise.all([load(), alsoPreload()]).then(([m]) => m) : load;
|
|
1111
1130
|
return LazyChunkWidget;
|
|
1112
1131
|
}
|
|
1113
1132
|
return { load, component };
|
|
1114
1133
|
}
|
|
1115
1134
|
|
|
1116
1135
|
// src/widgets/aggregate-lazy.tsx
|
|
1117
|
-
var chunk = lazyChunk(() => import("./chunks/aggregate-widgets-
|
|
1136
|
+
var chunk = lazyChunk(() => import("./chunks/aggregate-widgets-HZQI5HTX.js"));
|
|
1118
1137
|
var loadAggregateWidgets = chunk.load;
|
|
1119
1138
|
var statCardWidget = defineWidget({
|
|
1120
1139
|
descriptor: builtinWidgetDescriptors["stat-card"],
|
|
@@ -1133,784 +1152,85 @@ var fleetTableWidget = defineWidget({
|
|
|
1133
1152
|
implementation: { kind: "trusted-react", component: chunk.component("FleetTable") }
|
|
1134
1153
|
});
|
|
1135
1154
|
|
|
1136
|
-
// src/widgets/alarm-
|
|
1137
|
-
import {
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
fitValueFontCss,
|
|
1142
|
-
FIT_MIN_FONT_PX,
|
|
1143
|
-
fontVar,
|
|
1144
|
-
optString,
|
|
1145
|
-
spaceVar,
|
|
1146
|
-
useSeverityColors,
|
|
1147
|
-
useStickyChars,
|
|
1148
|
-
useWidgetScale,
|
|
1149
|
-
WidgetFrame
|
|
1150
|
-
} from "@devicechain/widget-sdk";
|
|
1151
|
-
|
|
1152
|
-
// src/widgets/severity.ts
|
|
1153
|
-
import { css } from "@devicechain/widget-sdk";
|
|
1154
|
-
var LEVEL_OF = {
|
|
1155
|
-
CRITICAL: "critical",
|
|
1156
|
-
MAJOR: "major",
|
|
1157
|
-
MINOR: "minor",
|
|
1158
|
-
WARNING: "warning"
|
|
1159
|
-
};
|
|
1160
|
-
var SEVERITY_ORDER = {
|
|
1161
|
-
CRITICAL: 0,
|
|
1162
|
-
MAJOR: 1,
|
|
1163
|
-
MINOR: 2,
|
|
1164
|
-
WARNING: 3,
|
|
1165
|
-
INDETERMINATE: 4
|
|
1166
|
-
};
|
|
1167
|
-
function severityColor(colors, severity) {
|
|
1168
|
-
const level = LEVEL_OF[severity];
|
|
1169
|
-
return level ? colors[level] : css("muted-foreground");
|
|
1170
|
-
}
|
|
1171
|
-
function severityRank(severity) {
|
|
1172
|
-
return SEVERITY_ORDER[severity] ?? 99;
|
|
1173
|
-
}
|
|
1174
|
-
function severityLabel(severity) {
|
|
1175
|
-
if (!severity) return "";
|
|
1176
|
-
return severity.charAt(0).toUpperCase() + severity.slice(1).toLowerCase();
|
|
1177
|
-
}
|
|
1178
|
-
function highestSeverity(severities) {
|
|
1179
|
-
let best;
|
|
1180
|
-
for (const s of severities) {
|
|
1181
|
-
if (best === void 0 || severityRank(s) < severityRank(best)) best = s;
|
|
1182
|
-
}
|
|
1183
|
-
return best;
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
// src/widgets/alarm-count.tsx
|
|
1187
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
1188
|
-
var ALARM_COUNT_CAPTION_ROOM_PX = 20;
|
|
1189
|
-
function AlarmCountBody({ data }) {
|
|
1190
|
-
const { size, scale } = useWidgetScale();
|
|
1191
|
-
const severity = useSeverityColors();
|
|
1192
|
-
const { total, alarms, loading } = data;
|
|
1193
|
-
const worst = highestSeverity(alarms.map((a) => a.severity));
|
|
1194
|
-
const alerting = total > 0 && worst != null;
|
|
1195
|
-
const color = alerting ? severityColor(severity, worst) : css2("muted-foreground");
|
|
1196
|
-
const display = loading && total === 0 ? "\u2014" : String(total);
|
|
1197
|
-
const chars = useStickyChars(display.length);
|
|
1198
|
-
const floor = Math.round(FIT_MIN_FONT_PX * scale);
|
|
1199
|
-
const measured = size.width > 0 && size.height > 0;
|
|
1200
|
-
const valueFont = measured ? fitValueFont(
|
|
1201
|
-
{ width: size.width, height: Math.max(1, size.height - ALARM_COUNT_CAPTION_ROOM_PX * scale) },
|
|
1202
|
-
chars,
|
|
1203
|
-
{ floor }
|
|
1204
|
-
) : (
|
|
1205
|
-
// First frame: the same curve in cq units, resolved by the browser against the frame's
|
|
1206
|
-
// column (it does not take the caption's room off; the first measure does).
|
|
1207
|
-
fitValueFontCss(chars, { floor })
|
|
1208
|
-
);
|
|
1209
|
-
const unit = total === 1 ? "alarm" : "alarms";
|
|
1210
|
-
const ariaLabel = alerting ? `${total} ${unit}, worst severity ${severityLabel(worst)}` : `${total} ${unit}`;
|
|
1211
|
-
return /* @__PURE__ */ jsxs(
|
|
1212
|
-
"div",
|
|
1213
|
-
{
|
|
1214
|
-
style: {
|
|
1215
|
-
display: "flex",
|
|
1216
|
-
flexDirection: "column",
|
|
1217
|
-
justifyContent: "safe center",
|
|
1218
|
-
alignItems: "center",
|
|
1219
|
-
height: "100%",
|
|
1220
|
-
boxSizing: "border-box",
|
|
1221
|
-
overflow: "hidden",
|
|
1222
|
-
textAlign: "center"
|
|
1223
|
-
},
|
|
1224
|
-
children: [
|
|
1225
|
-
/* @__PURE__ */ jsx2(
|
|
1226
|
-
"div",
|
|
1227
|
-
{
|
|
1228
|
-
"aria-label": ariaLabel,
|
|
1229
|
-
style: {
|
|
1230
|
-
fontSize: valueFont,
|
|
1231
|
-
fontWeight: 700,
|
|
1232
|
-
lineHeight: 1,
|
|
1233
|
-
whiteSpace: "nowrap",
|
|
1234
|
-
fontVariantNumeric: "tabular-nums",
|
|
1235
|
-
color
|
|
1236
|
-
},
|
|
1237
|
-
children: display
|
|
1238
|
-
}
|
|
1239
|
-
),
|
|
1240
|
-
/* @__PURE__ */ jsxs(
|
|
1241
|
-
"div",
|
|
1242
|
-
{
|
|
1243
|
-
style: {
|
|
1244
|
-
fontSize: fontVar("xs"),
|
|
1245
|
-
color: css2("muted-foreground"),
|
|
1246
|
-
marginTop: spaceVar(1),
|
|
1247
|
-
textTransform: "uppercase",
|
|
1248
|
-
letterSpacing: "0.05em"
|
|
1249
|
-
},
|
|
1250
|
-
children: [
|
|
1251
|
-
/* @__PURE__ */ jsx2("span", { children: unit }),
|
|
1252
|
-
alerting ? /* @__PURE__ */ jsx2("span", { children: ` \xB7 worst ${severityLabel(worst)}` }) : null
|
|
1253
|
-
]
|
|
1254
|
-
}
|
|
1255
|
-
)
|
|
1256
|
-
]
|
|
1257
|
-
}
|
|
1258
|
-
);
|
|
1259
|
-
}
|
|
1260
|
-
function AlarmCount({ widget, data }) {
|
|
1261
|
-
return /* @__PURE__ */ jsx2(WidgetFrame, { title: optString(widget.options, "title"), children: /* @__PURE__ */ jsx2(AlarmCountBody, { data }) });
|
|
1262
|
-
}
|
|
1263
|
-
var alarmCountWidget = defineWidget2({
|
|
1264
|
-
descriptor: builtinWidgetDescriptors["alarm-count"],
|
|
1265
|
-
implementation: { kind: "trusted-react", component: AlarmCount }
|
|
1266
|
-
});
|
|
1267
|
-
|
|
1268
|
-
// src/widgets/alarm-table.tsx
|
|
1269
|
-
import { Fragment, useState as useState3 } from "react";
|
|
1270
|
-
import {
|
|
1271
|
-
css as css3,
|
|
1272
|
-
fontVar as fontVar2,
|
|
1273
|
-
defineWidget as defineWidget3,
|
|
1274
|
-
FlashValue,
|
|
1275
|
-
formatDateTime,
|
|
1276
|
-
optBoolean,
|
|
1277
|
-
optNumber,
|
|
1278
|
-
optString as optString2,
|
|
1279
|
-
useElementSize,
|
|
1280
|
-
useSeverityColors as useSeverityColors2,
|
|
1281
|
-
useWidgetSelect,
|
|
1282
|
-
useWidgetTimeZone,
|
|
1283
|
-
WidgetFrame as WidgetFrame2
|
|
1284
|
-
} from "@devicechain/widget-sdk";
|
|
1285
|
-
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1286
|
-
var cell = { padding: "6px 10px", textAlign: "left", whiteSpace: "nowrap" };
|
|
1287
|
-
var headCell = {
|
|
1288
|
-
...cell,
|
|
1289
|
-
position: "sticky",
|
|
1290
|
-
top: 0,
|
|
1291
|
-
background: css3("card"),
|
|
1292
|
-
fontSize: fontVar2("xs"),
|
|
1293
|
-
fontWeight: 600,
|
|
1294
|
-
textTransform: "uppercase",
|
|
1295
|
-
letterSpacing: "0.04em",
|
|
1296
|
-
color: css3("muted-foreground"),
|
|
1297
|
-
borderBottom: `1px solid ${css3("border")}`
|
|
1298
|
-
};
|
|
1299
|
-
var ALARM_TABLE_NARROW_PX = 480;
|
|
1300
|
-
var narrowCell = {
|
|
1301
|
-
...cell,
|
|
1302
|
-
padding: "6px 6px",
|
|
1303
|
-
whiteSpace: "normal",
|
|
1304
|
-
overflowWrap: "break-word",
|
|
1305
|
-
wordBreak: "normal"
|
|
1306
|
-
};
|
|
1307
|
-
function hyphenBreaks(text) {
|
|
1308
|
-
const parts = text.split("-").map((p, i, all) => i < all.length - 1 ? `${p}-` : p);
|
|
1309
|
-
return parts.map((part, i) => /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1310
|
-
i > 0 ? /* @__PURE__ */ jsx3("wbr", {}) : null,
|
|
1311
|
-
part
|
|
1312
|
-
] }, i));
|
|
1313
|
-
}
|
|
1314
|
-
function statusLabel(alarm) {
|
|
1315
|
-
if (alarm.state === "CLEARED") return "Cleared";
|
|
1316
|
-
return alarm.acknowledged ? "Acknowledged" : "Active";
|
|
1317
|
-
}
|
|
1318
|
-
function AlarmTable({ widget, data, actions }) {
|
|
1319
|
-
const { alarms, total, loading } = data;
|
|
1320
|
-
const canAct = actions?.can("alarm:write") ?? false;
|
|
1321
|
-
const [sizeRef, size] = useElementSize();
|
|
1322
|
-
const severity = useSeverityColors2();
|
|
1323
|
-
const narrow = size.width > 0 && size.width < ALARM_TABLE_NARROW_PX;
|
|
1324
|
-
const columns = 5 + (narrow ? 0 : 2) + (canAct ? 1 : 0);
|
|
1325
|
-
const text = narrow ? narrowCell : cell;
|
|
1326
|
-
const precision = optNumber(widget.options, "precision");
|
|
1327
|
-
const flash = optBoolean(widget.options, "flashOnChange");
|
|
1328
|
-
const select = useWidgetSelect();
|
|
1329
|
-
const timeZone = useWidgetTimeZone();
|
|
1330
|
-
const selectionTarget = optString2(widget.options, "selectionTarget");
|
|
1331
|
-
const drillTo = select && selectionTarget ? { select, slot: selectionTarget } : void 0;
|
|
1332
|
-
return /* @__PURE__ */ jsx3(WidgetFrame2, { title: optString2(widget.options, "title"), flush: true, children: /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
|
|
1333
|
-
/* @__PURE__ */ jsx3("div", { ref: sizeRef, style: { flex: 1, minHeight: 0, overflow: "auto" }, children: /* @__PURE__ */ jsxs2(
|
|
1334
|
-
"table",
|
|
1335
|
-
{
|
|
1336
|
-
style: {
|
|
1337
|
-
width: "100%",
|
|
1338
|
-
borderCollapse: "collapse",
|
|
1339
|
-
fontSize: fontVar2("md"),
|
|
1340
|
-
color: css3("foreground"),
|
|
1341
|
-
fontVariantNumeric: "tabular-nums"
|
|
1342
|
-
},
|
|
1343
|
-
children: [
|
|
1344
|
-
/* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
|
|
1345
|
-
/* @__PURE__ */ jsx3("th", { style: { ...headCell, width: 4, padding: 0 }, "aria-hidden": "true" }),
|
|
1346
|
-
/* @__PURE__ */ jsx3("th", { scope: "col", style: headCell, children: "Severity" }),
|
|
1347
|
-
narrow ? null : /* @__PURE__ */ jsx3("th", { scope: "col", style: headCell, children: "Status" }),
|
|
1348
|
-
/* @__PURE__ */ jsx3("th", { scope: "col", style: headCell, children: "Originator" }),
|
|
1349
|
-
/* @__PURE__ */ jsx3("th", { scope: "col", style: headCell, children: "Alarm" }),
|
|
1350
|
-
/* @__PURE__ */ jsx3("th", { scope: "col", style: { ...headCell, textAlign: "right" }, children: "Value" }),
|
|
1351
|
-
narrow ? null : /* @__PURE__ */ jsx3("th", { scope: "col", style: headCell, children: "Raised" }),
|
|
1352
|
-
canAct ? /* @__PURE__ */ jsx3("th", { scope: "col", style: { ...headCell, textAlign: "right" }, children: "Actions" }) : null
|
|
1353
|
-
] }) }),
|
|
1354
|
-
/* @__PURE__ */ jsx3("tbody", { children: alarms.length === 0 ? /* @__PURE__ */ jsx3("tr", { children: /* @__PURE__ */ jsx3("td", { colSpan: columns, style: { ...cell, textAlign: "center", color: css3("muted-foreground") }, children: loading ? "Loading\u2026" : "No alarms" }) }) : alarms.map((alarm) => {
|
|
1355
|
-
const color = severityColor(severity, alarm.severity);
|
|
1356
|
-
return /* @__PURE__ */ jsxs2("tr", { style: { borderBottom: `1px solid ${css3("border")}` }, children: [
|
|
1357
|
-
/* @__PURE__ */ jsx3("td", { "aria-hidden": "true", style: { padding: 0, width: 4, background: color } }),
|
|
1358
|
-
/* @__PURE__ */ jsx3("td", { style: cell, children: /* @__PURE__ */ jsxs2("span", { style: { display: "inline-flex", alignItems: "center", gap: 6 }, children: [
|
|
1359
|
-
/* @__PURE__ */ jsx3(
|
|
1360
|
-
"span",
|
|
1361
|
-
{
|
|
1362
|
-
"aria-hidden": "true",
|
|
1363
|
-
style: { width: 8, height: 8, borderRadius: "50%", background: color, flexShrink: 0 }
|
|
1364
|
-
}
|
|
1365
|
-
),
|
|
1366
|
-
severityLabel(alarm.severity)
|
|
1367
|
-
] }) }),
|
|
1368
|
-
narrow ? null : /* @__PURE__ */ jsx3("td", { style: { ...cell, color: css3("muted-foreground") }, children: statusLabel(alarm) }),
|
|
1369
|
-
/* @__PURE__ */ jsx3("td", { style: text, children: /* @__PURE__ */ jsx3(OriginatorCell, { alarm, drillTo }) }),
|
|
1370
|
-
/* @__PURE__ */ jsx3("td", { style: text, children: hyphenBreaks(alarm.alarmKey) }),
|
|
1371
|
-
/* @__PURE__ */ jsx3("td", { style: { ...cell, textAlign: "right" }, children: /* @__PURE__ */ jsx3(
|
|
1372
|
-
FlashValue,
|
|
1373
|
-
{
|
|
1374
|
-
value: alarm.lastValue,
|
|
1375
|
-
precision,
|
|
1376
|
-
enabled: flash,
|
|
1377
|
-
identity: alarm.token
|
|
1378
|
-
}
|
|
1379
|
-
) }),
|
|
1380
|
-
narrow ? null : /* @__PURE__ */ jsx3("td", { style: { ...cell, color: css3("muted-foreground") }, children: formatDateTime(alarm.raisedTime, timeZone) }),
|
|
1381
|
-
canAct ? /* @__PURE__ */ jsx3("td", { style: { ...cell, textAlign: "right" }, children: /* @__PURE__ */ jsx3(AlarmRowActions, { alarm, actions }) }) : null
|
|
1382
|
-
] }, alarm.token);
|
|
1383
|
-
}) })
|
|
1384
|
-
]
|
|
1385
|
-
}
|
|
1386
|
-
) }),
|
|
1387
|
-
total > alarms.length ? /* @__PURE__ */ jsxs2(
|
|
1388
|
-
"div",
|
|
1389
|
-
{
|
|
1390
|
-
style: {
|
|
1391
|
-
padding: "4px 10px",
|
|
1392
|
-
fontSize: fontVar2("xs"),
|
|
1393
|
-
color: css3("muted-foreground"),
|
|
1394
|
-
borderTop: `1px solid ${css3("border")}`
|
|
1395
|
-
},
|
|
1396
|
-
children: [
|
|
1397
|
-
"Showing ",
|
|
1398
|
-
alarms.length,
|
|
1399
|
-
" of ",
|
|
1400
|
-
total
|
|
1401
|
-
]
|
|
1402
|
-
}
|
|
1403
|
-
) : null
|
|
1404
|
-
] }) });
|
|
1405
|
-
}
|
|
1406
|
-
function OriginatorCell({
|
|
1407
|
-
alarm,
|
|
1408
|
-
drillTo
|
|
1409
|
-
}) {
|
|
1410
|
-
if (drillTo && alarm.originatorType === "device" && alarm.originatorToken) {
|
|
1411
|
-
const token = alarm.originatorToken;
|
|
1412
|
-
return /* @__PURE__ */ jsx3(
|
|
1413
|
-
"button",
|
|
1414
|
-
{
|
|
1415
|
-
type: "button",
|
|
1416
|
-
onClick: () => drillTo.select({ slot: drillTo.slot, binding: { kind: "device", deviceToken: token } }),
|
|
1417
|
-
title: `Show ${token} in the linked widgets`,
|
|
1418
|
-
style: {
|
|
1419
|
-
padding: 0,
|
|
1420
|
-
border: "none",
|
|
1421
|
-
background: "none",
|
|
1422
|
-
font: "inherit",
|
|
1423
|
-
color: css3("primary"),
|
|
1424
|
-
cursor: "pointer",
|
|
1425
|
-
textDecoration: "underline",
|
|
1426
|
-
textUnderlineOffset: 2
|
|
1427
|
-
},
|
|
1428
|
-
children: hyphenBreaks(token)
|
|
1429
|
-
}
|
|
1430
|
-
);
|
|
1431
|
-
}
|
|
1432
|
-
return /* @__PURE__ */ jsx3(Fragment2, { children: hyphenBreaks(alarm.originatorToken ?? alarm.originatorType) });
|
|
1433
|
-
}
|
|
1434
|
-
var actionButton = {
|
|
1435
|
-
padding: "2px 8px",
|
|
1436
|
-
fontSize: fontVar2("sm"),
|
|
1437
|
-
lineHeight: 1.4,
|
|
1438
|
-
borderRadius: 4,
|
|
1439
|
-
border: `1px solid ${css3("border")}`,
|
|
1440
|
-
background: css3("card"),
|
|
1441
|
-
color: css3("foreground"),
|
|
1442
|
-
cursor: "pointer"
|
|
1443
|
-
};
|
|
1444
|
-
function AlarmRowActions({ alarm, actions }) {
|
|
1445
|
-
const severity = useSeverityColors2();
|
|
1446
|
-
const [pending, setPending] = useState3(null);
|
|
1447
|
-
const [failed, setFailed] = useState3(false);
|
|
1448
|
-
if (alarm.state !== "ACTIVE") {
|
|
1449
|
-
return /* @__PURE__ */ jsx3("span", { style: { color: css3("muted-foreground") }, children: "\u2014" });
|
|
1450
|
-
}
|
|
1451
|
-
const run = (kind, op) => {
|
|
1452
|
-
setPending(kind);
|
|
1453
|
-
setFailed(false);
|
|
1454
|
-
let promise;
|
|
1455
|
-
try {
|
|
1456
|
-
promise = op();
|
|
1457
|
-
} catch {
|
|
1458
|
-
setFailed(true);
|
|
1459
|
-
setPending(null);
|
|
1460
|
-
return;
|
|
1461
|
-
}
|
|
1462
|
-
promise.catch(() => setFailed(true)).finally(() => setPending(null));
|
|
1463
|
-
};
|
|
1464
|
-
return /* @__PURE__ */ jsxs2("span", { style: { display: "inline-flex", gap: 6, justifyContent: "flex-end", alignItems: "center" }, children: [
|
|
1465
|
-
failed ? /* @__PURE__ */ jsx3(
|
|
1466
|
-
"span",
|
|
1467
|
-
{
|
|
1468
|
-
role: "img",
|
|
1469
|
-
"aria-label": "Action failed \u2014 retry",
|
|
1470
|
-
title: "Action failed \u2014 retry",
|
|
1471
|
-
style: { color: severityColor(severity, "CRITICAL"), fontSize: fontVar2("sm") },
|
|
1472
|
-
children: "\u26A0"
|
|
1473
|
-
}
|
|
1474
|
-
) : null,
|
|
1475
|
-
!alarm.acknowledged ? /* @__PURE__ */ jsx3(
|
|
1476
|
-
"button",
|
|
1477
|
-
{
|
|
1478
|
-
type: "button",
|
|
1479
|
-
style: { ...actionButton, opacity: pending ? 0.6 : 1 },
|
|
1480
|
-
disabled: pending !== null,
|
|
1481
|
-
"aria-busy": pending === "ack",
|
|
1482
|
-
"aria-label": `Acknowledge alarm ${alarm.alarmKey}`,
|
|
1483
|
-
onClick: () => run("ack", () => actions.acknowledgeAlarm(alarm.token)),
|
|
1484
|
-
children: pending === "ack" ? "\u2026" : "Ack"
|
|
1485
|
-
}
|
|
1486
|
-
) : null,
|
|
1487
|
-
/* @__PURE__ */ jsx3(
|
|
1488
|
-
"button",
|
|
1489
|
-
{
|
|
1490
|
-
type: "button",
|
|
1491
|
-
style: { ...actionButton, opacity: pending ? 0.6 : 1 },
|
|
1492
|
-
disabled: pending !== null,
|
|
1493
|
-
"aria-busy": pending === "clear",
|
|
1494
|
-
"aria-label": `Clear alarm ${alarm.alarmKey}`,
|
|
1495
|
-
onClick: () => run("clear", () => actions.clearAlarm(alarm.token)),
|
|
1496
|
-
children: pending === "clear" ? "\u2026" : "Clear"
|
|
1497
|
-
}
|
|
1498
|
-
)
|
|
1499
|
-
] });
|
|
1500
|
-
}
|
|
1501
|
-
var alarmTableWidget = defineWidget3({
|
|
1155
|
+
// src/widgets/alarm-lazy.tsx
|
|
1156
|
+
import { defineWidget as defineWidget2 } from "@devicechain/widget-sdk";
|
|
1157
|
+
var chunk2 = lazyChunk(() => import("./chunks/alarm-widgets-7UY6MIYZ.js"));
|
|
1158
|
+
var loadAlarmWidgets = chunk2.load;
|
|
1159
|
+
var alarmTableWidget = defineWidget2({
|
|
1502
1160
|
descriptor: builtinWidgetDescriptors["alarm-table"],
|
|
1503
|
-
implementation: { kind: "trusted-react", component: AlarmTable }
|
|
1161
|
+
implementation: { kind: "trusted-react", component: chunk2.component("AlarmTable") }
|
|
1504
1162
|
});
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
import {
|
|
1509
|
-
css as css4,
|
|
1510
|
-
fontVar as fontVar3,
|
|
1511
|
-
defineWidget as defineWidget4,
|
|
1512
|
-
formatDateTime as formatDateTime2,
|
|
1513
|
-
optString as optString3,
|
|
1514
|
-
useWidgetTimeZone as useWidgetTimeZone2,
|
|
1515
|
-
WidgetFrame as WidgetFrame3
|
|
1516
|
-
} from "@devicechain/widget-sdk";
|
|
1517
|
-
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1518
|
-
function CommandButton({ widget, data, actions }) {
|
|
1519
|
-
const commandName = optString3(widget.options, "commandName");
|
|
1520
|
-
const commandLabel = optString3(widget.options, "commandLabel") ?? commandName;
|
|
1521
|
-
const parameterSchema = optString3(widget.options, "parameterSchema") ?? null;
|
|
1522
|
-
const params = useMemo(() => parseParameterSchema(parameterSchema), [parameterSchema]);
|
|
1523
|
-
const schemaKey = `${commandName ?? ""}::${parameterSchema ?? ""}`;
|
|
1524
|
-
const [values, setValues] = useState4(() => defaultValues(params));
|
|
1525
|
-
const [errors, setErrors] = useState4({});
|
|
1526
|
-
const [pending, setPending] = useState4(false);
|
|
1527
|
-
const [sendError, setSendError] = useState4(null);
|
|
1528
|
-
const [sentToken, setSentToken] = useState4(null);
|
|
1529
|
-
const sendGen = useRef(0);
|
|
1530
|
-
useEffect2(() => {
|
|
1531
|
-
sendGen.current += 1;
|
|
1532
|
-
setValues(defaultValues(params));
|
|
1533
|
-
setErrors({});
|
|
1534
|
-
setSendError(null);
|
|
1535
|
-
setSentToken(null);
|
|
1536
|
-
}, [schemaKey]);
|
|
1537
|
-
const canWrite = actions?.can("command:write") ?? false;
|
|
1538
|
-
const hasSeam = typeof actions?.sendCommand === "function";
|
|
1539
|
-
const deviceToken = data.deviceToken;
|
|
1540
|
-
const formDisabled = !canWrite || !hasSeam || pending;
|
|
1541
|
-
const canSend = !formDisabled && !!deviceToken && !!commandName;
|
|
1542
|
-
const setField = (name, value) => {
|
|
1543
|
-
setValues((prev) => ({ ...prev, [name]: value }));
|
|
1544
|
-
setErrors((prev) => prev[name] ? { ...prev, [name]: "" } : prev);
|
|
1545
|
-
setSendError(null);
|
|
1546
|
-
};
|
|
1547
|
-
const send = () => {
|
|
1548
|
-
if (!deviceToken || !commandName || !actions?.sendCommand) return;
|
|
1549
|
-
const found = validateParams(params, values);
|
|
1550
|
-
const active = Object.fromEntries(Object.entries(found).filter(([, v]) => v));
|
|
1551
|
-
if (Object.keys(active).length > 0) {
|
|
1552
|
-
setErrors(active);
|
|
1553
|
-
return;
|
|
1554
|
-
}
|
|
1555
|
-
const payload = buildPayload(params, values);
|
|
1556
|
-
const gen = sendGen.current;
|
|
1557
|
-
setPending(true);
|
|
1558
|
-
setSendError(null);
|
|
1559
|
-
let promise;
|
|
1560
|
-
try {
|
|
1561
|
-
promise = actions.sendCommand(deviceToken, commandName, payload);
|
|
1562
|
-
} catch {
|
|
1563
|
-
setSendError(SEND_FAILED);
|
|
1564
|
-
setPending(false);
|
|
1565
|
-
return;
|
|
1566
|
-
}
|
|
1567
|
-
promise.then((dispatch) => {
|
|
1568
|
-
if (gen !== sendGen.current) return;
|
|
1569
|
-
if (dispatch.status === "rejected") {
|
|
1570
|
-
setSendError(dispatch.reason);
|
|
1571
|
-
return;
|
|
1572
|
-
}
|
|
1573
|
-
setSentToken(dispatch.token);
|
|
1574
|
-
}).catch(() => {
|
|
1575
|
-
if (gen === sendGen.current) setSendError(SEND_FAILED);
|
|
1576
|
-
}).finally(() => {
|
|
1577
|
-
if (gen === sendGen.current) setPending(false);
|
|
1578
|
-
});
|
|
1579
|
-
};
|
|
1580
|
-
return /* @__PURE__ */ jsx4(WidgetFrame3, { title: optString3(widget.options, "title"), children: /* @__PURE__ */ jsx4("div", { style: { display: "flex", flexDirection: "column", height: "100%", gap: 10, overflowY: "auto" }, children: !commandName ? /* @__PURE__ */ jsx4("div", { style: { ...hint, margin: "auto" }, children: "No command configured." }) : /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
1581
|
-
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 8, flexShrink: 0 }, children: [
|
|
1582
|
-
params.map(
|
|
1583
|
-
(param) => isScalar(param) ? /* @__PURE__ */ jsx4(
|
|
1584
|
-
ParamField,
|
|
1585
|
-
{
|
|
1586
|
-
widgetId: widget.id,
|
|
1587
|
-
param,
|
|
1588
|
-
value: values[param.name] ?? "",
|
|
1589
|
-
error: errors[param.name],
|
|
1590
|
-
disabled: formDisabled,
|
|
1591
|
-
onChange: (v) => setField(param.name, v)
|
|
1592
|
-
},
|
|
1593
|
-
param.name
|
|
1594
|
-
) : (
|
|
1595
|
-
// A structured (OBJECT) parameter isn't form-editable. A REQUIRED one
|
|
1596
|
-
// blocks sending (validateParams flags it); flag that in the note.
|
|
1597
|
-
/* @__PURE__ */ jsxs3("div", { style: { ...hint, color: param.required ? commandStatusColor("FAILED") : css4("muted-foreground") }, children: [
|
|
1598
|
-
param.name,
|
|
1599
|
-
": ",
|
|
1600
|
-
param.required ? "required " : "",
|
|
1601
|
-
"structured parameter \u2014 not supported here."
|
|
1602
|
-
] }, param.name)
|
|
1603
|
-
)
|
|
1604
|
-
),
|
|
1605
|
-
/* @__PURE__ */ jsx4(
|
|
1606
|
-
"button",
|
|
1607
|
-
{
|
|
1608
|
-
type: "button",
|
|
1609
|
-
style: { ...sendButton, opacity: canSend ? 1 : 0.55, cursor: canSend ? "pointer" : "not-allowed" },
|
|
1610
|
-
disabled: !canSend,
|
|
1611
|
-
"aria-busy": pending,
|
|
1612
|
-
onClick: send,
|
|
1613
|
-
children: pending ? "Sending\u2026" : `Send ${commandLabel}`
|
|
1614
|
-
}
|
|
1615
|
-
),
|
|
1616
|
-
!canWrite ? /* @__PURE__ */ jsx4("div", { style: hint, children: "You don\u2019t have permission to issue commands." }) : !hasSeam ? /* @__PURE__ */ jsx4("div", { style: hint, children: "Commands aren\u2019t available in this view." }) : !deviceToken ? /* @__PURE__ */ jsx4("div", { style: hint, children: "No device is selected for this command." }) : null,
|
|
1617
|
-
sendError ? /* @__PURE__ */ jsx4("div", { role: "alert", style: { ...hint, color: commandStatusColor("FAILED") }, children: sendError }) : null
|
|
1618
|
-
] }),
|
|
1619
|
-
/* @__PURE__ */ jsx4(CommandHistory, { commands: data.commands, sentToken, loading: data.loading, error: data.error })
|
|
1620
|
-
] }) }) });
|
|
1621
|
-
}
|
|
1622
|
-
function ParamField({
|
|
1623
|
-
widgetId,
|
|
1624
|
-
param,
|
|
1625
|
-
value,
|
|
1626
|
-
error,
|
|
1627
|
-
disabled,
|
|
1628
|
-
onChange
|
|
1629
|
-
}) {
|
|
1630
|
-
const labelId = `cmd-${widgetId}-${param.name}`;
|
|
1631
|
-
const unit = param.unit ? ` (${param.unit})` : "";
|
|
1632
|
-
return /* @__PURE__ */ jsxs3("label", { htmlFor: labelId, style: { display: "flex", flexDirection: "column", gap: 3 }, children: [
|
|
1633
|
-
/* @__PURE__ */ jsxs3("span", { style: { fontSize: fontVar3("sm"), color: css4("muted-foreground") }, children: [
|
|
1634
|
-
param.name,
|
|
1635
|
-
unit,
|
|
1636
|
-
param.required ? /* @__PURE__ */ jsx4("span", { style: { color: commandStatusColor("FAILED") }, children: " *" }) : null
|
|
1637
|
-
] }),
|
|
1638
|
-
/* @__PURE__ */ jsx4(ParamInput, { id: labelId, param, value, disabled, onChange }),
|
|
1639
|
-
error ? /* @__PURE__ */ jsx4("span", { style: { fontSize: fontVar3("xs"), color: commandStatusColor("FAILED") }, children: error }) : null
|
|
1640
|
-
] });
|
|
1641
|
-
}
|
|
1642
|
-
function ParamInput({
|
|
1643
|
-
id,
|
|
1644
|
-
param,
|
|
1645
|
-
value,
|
|
1646
|
-
disabled,
|
|
1647
|
-
onChange
|
|
1648
|
-
}) {
|
|
1649
|
-
if (param.enum && param.enum.length > 0) {
|
|
1650
|
-
return /* @__PURE__ */ jsxs3("select", { id, style: inputStyle, value, disabled, onChange: (e) => onChange(e.target.value), children: [
|
|
1651
|
-
!param.required ? /* @__PURE__ */ jsx4("option", { value: "", children: "\u2014" }) : null,
|
|
1652
|
-
param.enum.map((opt) => /* @__PURE__ */ jsx4("option", { value: opt, children: opt }, opt))
|
|
1653
|
-
] });
|
|
1654
|
-
}
|
|
1655
|
-
if (param.dataType === "BOOLEAN") {
|
|
1656
|
-
return /* @__PURE__ */ jsx4(
|
|
1657
|
-
"input",
|
|
1658
|
-
{
|
|
1659
|
-
id,
|
|
1660
|
-
type: "checkbox",
|
|
1661
|
-
style: { width: 16, height: 16 },
|
|
1662
|
-
checked: parseBool(value),
|
|
1663
|
-
disabled,
|
|
1664
|
-
onChange: (e) => onChange(e.target.checked ? "true" : "false")
|
|
1665
|
-
}
|
|
1666
|
-
);
|
|
1667
|
-
}
|
|
1668
|
-
const numeric = param.dataType === "INT" || param.dataType === "DOUBLE";
|
|
1669
|
-
return /* @__PURE__ */ jsx4(
|
|
1670
|
-
"input",
|
|
1671
|
-
{
|
|
1672
|
-
id,
|
|
1673
|
-
type: numeric ? "number" : "text",
|
|
1674
|
-
style: inputStyle,
|
|
1675
|
-
value,
|
|
1676
|
-
disabled,
|
|
1677
|
-
min: param.minValue ?? void 0,
|
|
1678
|
-
max: param.maxValue ?? void 0,
|
|
1679
|
-
step: param.dataType === "INT" ? 1 : "any",
|
|
1680
|
-
placeholder: param.default ?? void 0,
|
|
1681
|
-
onChange: (e) => onChange(e.target.value)
|
|
1682
|
-
}
|
|
1683
|
-
);
|
|
1684
|
-
}
|
|
1685
|
-
function CommandHistory({
|
|
1686
|
-
commands,
|
|
1687
|
-
sentToken,
|
|
1688
|
-
loading,
|
|
1689
|
-
error
|
|
1690
|
-
}) {
|
|
1691
|
-
const empty = commands.length === 0;
|
|
1692
|
-
const timeZone = useWidgetTimeZone2();
|
|
1693
|
-
return /* @__PURE__ */ jsx4(
|
|
1694
|
-
"div",
|
|
1695
|
-
{
|
|
1696
|
-
style: {
|
|
1697
|
-
flex: 1,
|
|
1698
|
-
minHeight: 0,
|
|
1699
|
-
overflow: "auto",
|
|
1700
|
-
borderTop: `1px solid ${css4("border")}`,
|
|
1701
|
-
paddingTop: 6
|
|
1702
|
-
},
|
|
1703
|
-
children: empty ? /* @__PURE__ */ jsx4("div", { style: { ...hint, textAlign: "center", color: error ? commandStatusColor("FAILED") : css4("muted-foreground") }, children: error ? "Couldn\u2019t load command history." : loading ? "Loading\u2026" : "No commands issued yet." }) : /* @__PURE__ */ jsx4("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 4 }, children: commands.map((command) => /* @__PURE__ */ jsxs3(
|
|
1704
|
-
"li",
|
|
1705
|
-
{
|
|
1706
|
-
style: {
|
|
1707
|
-
display: "flex",
|
|
1708
|
-
alignItems: "center",
|
|
1709
|
-
gap: 8,
|
|
1710
|
-
fontSize: fontVar3("sm"),
|
|
1711
|
-
// Highlight the command just issued from this widget.
|
|
1712
|
-
fontWeight: command.token === sentToken ? 600 : 400
|
|
1713
|
-
},
|
|
1714
|
-
children: [
|
|
1715
|
-
/* @__PURE__ */ jsx4(StatusBadge, { status: command.status }),
|
|
1716
|
-
/* @__PURE__ */ jsx4("span", { style: { color: css4("foreground"), whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: command.name }),
|
|
1717
|
-
/* @__PURE__ */ jsx4("span", { style: { marginLeft: "auto", color: css4("muted-foreground"), whiteSpace: "nowrap" }, children: formatDateTime2(command.queuedTime, timeZone) })
|
|
1718
|
-
]
|
|
1719
|
-
},
|
|
1720
|
-
command.token
|
|
1721
|
-
)) })
|
|
1722
|
-
}
|
|
1723
|
-
);
|
|
1724
|
-
}
|
|
1725
|
-
function StatusBadge({ status }) {
|
|
1726
|
-
const color = commandStatusColor(status);
|
|
1727
|
-
return /* @__PURE__ */ jsxs3(
|
|
1728
|
-
"span",
|
|
1729
|
-
{
|
|
1730
|
-
style: {
|
|
1731
|
-
display: "inline-flex",
|
|
1732
|
-
alignItems: "center",
|
|
1733
|
-
gap: 4,
|
|
1734
|
-
flexShrink: 0,
|
|
1735
|
-
fontSize: fontVar3("xs"),
|
|
1736
|
-
fontWeight: 600,
|
|
1737
|
-
color
|
|
1738
|
-
},
|
|
1739
|
-
children: [
|
|
1740
|
-
/* @__PURE__ */ jsx4("span", { "aria-hidden": "true", style: { width: 7, height: 7, borderRadius: "50%", background: color } }),
|
|
1741
|
-
commandStatusLabel(status)
|
|
1742
|
-
]
|
|
1743
|
-
}
|
|
1744
|
-
);
|
|
1745
|
-
}
|
|
1746
|
-
var hint = { fontSize: fontVar3("xs"), color: css4("muted-foreground") };
|
|
1747
|
-
var SEND_FAILED = "Couldn\u2019t issue the command. Try again.";
|
|
1748
|
-
var inputStyle = {
|
|
1749
|
-
width: "100%",
|
|
1750
|
-
boxSizing: "border-box",
|
|
1751
|
-
padding: "4px 8px",
|
|
1752
|
-
fontSize: fontVar3("md"),
|
|
1753
|
-
borderRadius: 4,
|
|
1754
|
-
border: `1px solid ${css4("border")}`,
|
|
1755
|
-
background: css4("background"),
|
|
1756
|
-
color: css4("foreground")
|
|
1757
|
-
};
|
|
1758
|
-
var sendButton = {
|
|
1759
|
-
padding: "6px 12px",
|
|
1760
|
-
fontSize: fontVar3("md"),
|
|
1761
|
-
fontWeight: 600,
|
|
1762
|
-
borderRadius: 4,
|
|
1763
|
-
border: "none",
|
|
1764
|
-
background: css4("primary"),
|
|
1765
|
-
color: css4("background"),
|
|
1766
|
-
marginTop: 2
|
|
1767
|
-
};
|
|
1768
|
-
var commandButtonWidget = defineWidget4({
|
|
1769
|
-
descriptor: builtinWidgetDescriptors["command-button"],
|
|
1770
|
-
implementation: { kind: "trusted-react", component: CommandButton }
|
|
1163
|
+
var alarmCountWidget = defineWidget2({
|
|
1164
|
+
descriptor: builtinWidgetDescriptors["alarm-count"],
|
|
1165
|
+
implementation: { kind: "trusted-react", component: chunk2.component("AlarmCount") }
|
|
1771
1166
|
});
|
|
1772
1167
|
|
|
1773
1168
|
// src/widgets/control-lazy.tsx
|
|
1774
|
-
import { defineWidget as
|
|
1775
|
-
var
|
|
1776
|
-
var loadControlWidgets =
|
|
1777
|
-
var commandSliderWidget =
|
|
1169
|
+
import { defineWidget as defineWidget3 } from "@devicechain/widget-sdk";
|
|
1170
|
+
var chunk3 = lazyChunk(() => import("./chunks/control-widgets-3V2LSSRF.js"));
|
|
1171
|
+
var loadControlWidgets = chunk3.load;
|
|
1172
|
+
var commandSliderWidget = defineWidget3({
|
|
1778
1173
|
descriptor: builtinWidgetDescriptors["command-slider"],
|
|
1779
|
-
implementation: { kind: "trusted-react", component:
|
|
1174
|
+
implementation: { kind: "trusted-react", component: chunk3.component("CommandSlider") }
|
|
1780
1175
|
});
|
|
1781
|
-
var commandToggleWidget =
|
|
1176
|
+
var commandToggleWidget = defineWidget3({
|
|
1782
1177
|
descriptor: builtinWidgetDescriptors["command-toggle"],
|
|
1783
|
-
implementation: { kind: "trusted-react", component:
|
|
1178
|
+
implementation: { kind: "trusted-react", component: chunk3.component("CommandToggle") }
|
|
1179
|
+
});
|
|
1180
|
+
var commandButtonWidget = defineWidget3({
|
|
1181
|
+
descriptor: builtinWidgetDescriptors["command-button"],
|
|
1182
|
+
implementation: { kind: "trusted-react", component: chunk3.component("CommandButton") }
|
|
1784
1183
|
});
|
|
1785
1184
|
|
|
1786
|
-
// src/widgets/
|
|
1787
|
-
import {
|
|
1788
|
-
import
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
defineWidget as defineWidget6,
|
|
1792
|
-
optString as optString4,
|
|
1793
|
-
useCandidates,
|
|
1794
|
-
useWidgetSelect as useWidgetSelect2,
|
|
1795
|
-
WidgetFrame as WidgetFrame4
|
|
1796
|
-
} from "@devicechain/widget-sdk";
|
|
1797
|
-
import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1798
|
-
function tokenOf(b) {
|
|
1799
|
-
return b.kind === "device" ? b.deviceToken : b.anchor.targetToken;
|
|
1800
|
-
}
|
|
1801
|
-
var control = {
|
|
1802
|
-
width: "100%",
|
|
1803
|
-
fontSize: fontVar4("md"),
|
|
1804
|
-
padding: "8px 10px",
|
|
1805
|
-
borderRadius: 6,
|
|
1806
|
-
border: `1px solid ${css5("border")}`,
|
|
1807
|
-
background: css5("background"),
|
|
1808
|
-
color: css5("foreground")
|
|
1809
|
-
};
|
|
1810
|
-
var hint2 = {
|
|
1811
|
-
fontSize: fontVar4("sm"),
|
|
1812
|
-
color: css5("muted-foreground")
|
|
1813
|
-
};
|
|
1814
|
-
function EntitySelector({ widget }) {
|
|
1815
|
-
const select = useWidgetSelect2();
|
|
1816
|
-
const target = optString4(widget.options, "selectionTarget");
|
|
1817
|
-
const { candidates, loading, error, wired } = useCandidates(target);
|
|
1818
|
-
const title = optString4(widget.options, "title");
|
|
1819
|
-
const [pending, setPending] = useState5(null);
|
|
1820
|
-
const selected = candidates.find((c) => c.selected);
|
|
1821
|
-
const selectedToken = selected ? tokenOf(selected.binding) : "";
|
|
1822
|
-
useEffect3(() => {
|
|
1823
|
-
if (pending !== null && (selectedToken === pending || !candidates.some((c) => tokenOf(c.binding) === pending))) {
|
|
1824
|
-
setPending(null);
|
|
1825
|
-
}
|
|
1826
|
-
}, [candidates, selectedToken, pending]);
|
|
1827
|
-
const inert = !select || !target || !wired;
|
|
1828
|
-
const value = pending ?? selectedToken;
|
|
1829
|
-
const onChange = (e) => {
|
|
1830
|
-
const token = e.target.value;
|
|
1831
|
-
if (!token) return;
|
|
1832
|
-
const candidate = candidates.find((c) => tokenOf(c.binding) === token);
|
|
1833
|
-
if (select && target && candidate) {
|
|
1834
|
-
setPending(token);
|
|
1835
|
-
select({ slot: target, binding: candidate.binding });
|
|
1836
|
-
}
|
|
1837
|
-
};
|
|
1838
|
-
return /* @__PURE__ */ jsx5(WidgetFrame4, { title, children: /* @__PURE__ */ jsx5(
|
|
1839
|
-
"div",
|
|
1840
|
-
{
|
|
1841
|
-
style: {
|
|
1842
|
-
display: "flex",
|
|
1843
|
-
flexDirection: "column",
|
|
1844
|
-
gap: 8,
|
|
1845
|
-
height: "100%",
|
|
1846
|
-
boxSizing: "border-box",
|
|
1847
|
-
overflow: "auto"
|
|
1848
|
-
},
|
|
1849
|
-
children: inert ? /* @__PURE__ */ jsx5("span", { style: hint2, children: select && target ? "Selection isn\u2019t available here." : select ? "No target slot configured." : "Selection is available on the live dashboard." }) : /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
1850
|
-
/* @__PURE__ */ jsxs4(
|
|
1851
|
-
"select",
|
|
1852
|
-
{
|
|
1853
|
-
style: { ...control, opacity: loading ? 0.6 : 1 },
|
|
1854
|
-
value,
|
|
1855
|
-
disabled: candidates.length === 0,
|
|
1856
|
-
onChange,
|
|
1857
|
-
"aria-label": title || `Select ${target}`,
|
|
1858
|
-
children: [
|
|
1859
|
-
/* @__PURE__ */ jsx5("option", { value: "", disabled: true, children: loading ? "Loading\u2026" : candidates.length === 0 ? "No options" : "Select\u2026" }),
|
|
1860
|
-
candidates.map((c) => /* @__PURE__ */ jsx5("option", { value: tokenOf(c.binding), children: c.label }, tokenOf(c.binding)))
|
|
1861
|
-
]
|
|
1862
|
-
}
|
|
1863
|
-
),
|
|
1864
|
-
error ? /* @__PURE__ */ jsx5("span", { style: hint2, children: "Couldn\u2019t load options." }) : null
|
|
1865
|
-
] })
|
|
1866
|
-
}
|
|
1867
|
-
) });
|
|
1868
|
-
}
|
|
1869
|
-
var entitySelectorWidget = defineWidget6({
|
|
1185
|
+
// src/widgets/selection-lazy.tsx
|
|
1186
|
+
import { defineWidget as defineWidget4 } from "@devicechain/widget-sdk";
|
|
1187
|
+
var chunk4 = lazyChunk(() => import("./chunks/entity-selector-3JJFI4DT.js"));
|
|
1188
|
+
var loadSelectionWidgets = chunk4.load;
|
|
1189
|
+
var entitySelectorWidget = defineWidget4({
|
|
1870
1190
|
descriptor: builtinWidgetDescriptors["entity-selector"],
|
|
1871
|
-
implementation: { kind: "trusted-react", component: EntitySelector }
|
|
1191
|
+
implementation: { kind: "trusted-react", component: chunk4.component("EntitySelector") }
|
|
1872
1192
|
});
|
|
1873
1193
|
|
|
1874
1194
|
// src/widgets/gauge.tsx
|
|
1875
|
-
import { useMemo
|
|
1195
|
+
import { useMemo } from "react";
|
|
1876
1196
|
import {
|
|
1877
|
-
defineWidget as
|
|
1197
|
+
defineWidget as defineWidget5,
|
|
1878
1198
|
flashBackgroundStyle,
|
|
1879
1199
|
formatValue,
|
|
1880
|
-
optBoolean
|
|
1881
|
-
optNumber
|
|
1882
|
-
optString
|
|
1200
|
+
optBoolean,
|
|
1201
|
+
optNumber,
|
|
1202
|
+
optString,
|
|
1883
1203
|
optThresholds,
|
|
1884
1204
|
pickSample,
|
|
1885
1205
|
primaryMeasurementName,
|
|
1886
1206
|
useFlashOnChange,
|
|
1887
|
-
useWidgetScale
|
|
1888
|
-
WidgetFrame
|
|
1207
|
+
useWidgetScale,
|
|
1208
|
+
WidgetFrame
|
|
1889
1209
|
} from "@devicechain/widget-sdk";
|
|
1890
|
-
import { buildGaugeOption, EChart, gaugeReadoutBox, useChartTheme } from "@devicechain/widget-sdk/echarts";
|
|
1891
|
-
import { jsx as
|
|
1210
|
+
import { buildGaugeOption, EChart, gaugeReadoutBox, loadChartEngine, useChartTheme } from "@devicechain/widget-sdk/echarts";
|
|
1211
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
1892
1212
|
function Gauge({ widget, data }) {
|
|
1893
1213
|
const name = primaryMeasurementName(widget);
|
|
1894
1214
|
const sample = pickSample(data.latest, name);
|
|
1895
|
-
return /* @__PURE__ */
|
|
1215
|
+
return /* @__PURE__ */ jsx2(WidgetFrame, { title: optString(widget.options, "title") ?? name, sampleTime: sample?.occurredTime ?? null, flush: true, children: /* @__PURE__ */ jsx2(GaugeBody, { widget, data }) });
|
|
1896
1216
|
}
|
|
1897
1217
|
function GaugeBody({ widget, data }) {
|
|
1898
1218
|
const theme = useChartTheme();
|
|
1899
|
-
const { size, scale } =
|
|
1219
|
+
const { size, scale } = useWidgetScale();
|
|
1900
1220
|
const name = primaryMeasurementName(widget);
|
|
1901
1221
|
const sample = pickSample(data.latest, name);
|
|
1902
|
-
const min =
|
|
1903
|
-
const max =
|
|
1904
|
-
const unit =
|
|
1905
|
-
const precision =
|
|
1906
|
-
const thresholds =
|
|
1907
|
-
const option =
|
|
1222
|
+
const min = optNumber(widget.options, "min");
|
|
1223
|
+
const max = optNumber(widget.options, "max");
|
|
1224
|
+
const unit = optString(widget.options, "unit");
|
|
1225
|
+
const precision = optNumber(widget.options, "precision");
|
|
1226
|
+
const thresholds = useMemo(() => optThresholds(widget.options, "thresholds"), [widget.options]);
|
|
1227
|
+
const option = useMemo(
|
|
1908
1228
|
() => buildGaugeOption(sample?.value ?? null, theme, { min, max, thresholds, scale, readout: "none", emptyNeedle: "none" }, size),
|
|
1909
1229
|
[sample?.value, theme, min, max, thresholds, scale, size]
|
|
1910
1230
|
);
|
|
1911
1231
|
const flashDirection = useFlashOnChange(
|
|
1912
1232
|
sample?.value,
|
|
1913
|
-
|
|
1233
|
+
optBoolean(widget.options, "flashOnChange"),
|
|
1914
1234
|
sample && `${sample.deviceToken}:${sample.name}`
|
|
1915
1235
|
);
|
|
1916
1236
|
const box = gaugeReadoutBox(size);
|
|
@@ -1923,9 +1243,9 @@ function GaugeBody({ widget, data }) {
|
|
|
1923
1243
|
"aria-valuenow": Math.min(range.range.max, Math.max(range.range.min, value)),
|
|
1924
1244
|
"aria-valuetext": `${formatValue(value, precision)}${unit ? ` ${unit}` : ""}`
|
|
1925
1245
|
} : {};
|
|
1926
|
-
return /* @__PURE__ */
|
|
1927
|
-
/* @__PURE__ */
|
|
1928
|
-
/* @__PURE__ */
|
|
1246
|
+
return /* @__PURE__ */ jsxs("div", { style: { position: "relative", width: "100%", height: "100%", ...flashBackgroundStyle(flashDirection) }, ...meter, children: [
|
|
1247
|
+
/* @__PURE__ */ jsx2(EChart, { option }),
|
|
1248
|
+
/* @__PURE__ */ jsx2(
|
|
1929
1249
|
"div",
|
|
1930
1250
|
{
|
|
1931
1251
|
style: {
|
|
@@ -1939,7 +1259,7 @@ function GaugeBody({ widget, data }) {
|
|
|
1939
1259
|
justifyContent: "center",
|
|
1940
1260
|
pointerEvents: "none"
|
|
1941
1261
|
},
|
|
1942
|
-
children: /* @__PURE__ */
|
|
1262
|
+
children: /* @__PURE__ */ jsx2(
|
|
1943
1263
|
LevelReadout,
|
|
1944
1264
|
{
|
|
1945
1265
|
text: formatValue(value, precision),
|
|
@@ -1952,27 +1272,28 @@ function GaugeBody({ widget, data }) {
|
|
|
1952
1272
|
)
|
|
1953
1273
|
] });
|
|
1954
1274
|
}
|
|
1955
|
-
|
|
1275
|
+
Gauge.preload = loadChartEngine;
|
|
1276
|
+
var gaugeWidget = defineWidget5({
|
|
1956
1277
|
descriptor: builtinWidgetDescriptors["gauge"],
|
|
1957
1278
|
implementation: { kind: "trusted-react", component: Gauge }
|
|
1958
1279
|
});
|
|
1959
1280
|
|
|
1960
1281
|
// src/widgets/image.tsx
|
|
1961
1282
|
import {
|
|
1962
|
-
css
|
|
1963
|
-
defineWidget as
|
|
1964
|
-
fontVar
|
|
1965
|
-
optString as
|
|
1966
|
-
WidgetFrame as
|
|
1283
|
+
css,
|
|
1284
|
+
defineWidget as defineWidget6,
|
|
1285
|
+
fontVar,
|
|
1286
|
+
optString as optString2,
|
|
1287
|
+
WidgetFrame as WidgetFrame2
|
|
1967
1288
|
} from "@devicechain/widget-sdk";
|
|
1968
|
-
import { jsx as
|
|
1289
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1969
1290
|
var FITS = /* @__PURE__ */ new Set(["contain", "cover", "fill"]);
|
|
1970
1291
|
function Image({ widget }) {
|
|
1971
|
-
const url =
|
|
1972
|
-
const alt =
|
|
1973
|
-
const fitOption =
|
|
1292
|
+
const url = optString2(widget.options, "url");
|
|
1293
|
+
const alt = optString2(widget.options, "alt") ?? "";
|
|
1294
|
+
const fitOption = optString2(widget.options, "fit");
|
|
1974
1295
|
const objectFit = fitOption && FITS.has(fitOption) ? fitOption : "contain";
|
|
1975
|
-
return /* @__PURE__ */
|
|
1296
|
+
return /* @__PURE__ */ jsx3(WidgetFrame2, { title: optString2(widget.options, "title"), flush: true, children: url ? /* @__PURE__ */ jsx3("img", { src: url, alt, style: { width: "100%", height: "100%", objectFit, display: "block" } }) : /* @__PURE__ */ jsx3(
|
|
1976
1297
|
"div",
|
|
1977
1298
|
{
|
|
1978
1299
|
style: {
|
|
@@ -1980,40 +1301,40 @@ function Image({ widget }) {
|
|
|
1980
1301
|
alignItems: "center",
|
|
1981
1302
|
justifyContent: "center",
|
|
1982
1303
|
height: "100%",
|
|
1983
|
-
color:
|
|
1984
|
-
fontSize:
|
|
1304
|
+
color: css("muted-foreground"),
|
|
1305
|
+
fontSize: fontVar("md")
|
|
1985
1306
|
},
|
|
1986
1307
|
children: "No image URL"
|
|
1987
1308
|
}
|
|
1988
1309
|
) });
|
|
1989
1310
|
}
|
|
1990
|
-
var imageWidget =
|
|
1311
|
+
var imageWidget = defineWidget6({
|
|
1991
1312
|
descriptor: builtinWidgetDescriptors["image"],
|
|
1992
1313
|
implementation: { kind: "trusted-react", component: Image }
|
|
1993
1314
|
});
|
|
1994
1315
|
|
|
1995
1316
|
// src/widgets/label.tsx
|
|
1996
1317
|
import {
|
|
1997
|
-
css as
|
|
1998
|
-
defineWidget as
|
|
1999
|
-
fontVar as
|
|
2000
|
-
spaceVar
|
|
2001
|
-
optNumber as
|
|
2002
|
-
optString as
|
|
2003
|
-
WidgetFrame as
|
|
1318
|
+
css as css2,
|
|
1319
|
+
defineWidget as defineWidget7,
|
|
1320
|
+
fontVar as fontVar2,
|
|
1321
|
+
spaceVar,
|
|
1322
|
+
optNumber as optNumber2,
|
|
1323
|
+
optString as optString3,
|
|
1324
|
+
WidgetFrame as WidgetFrame3
|
|
2004
1325
|
} from "@devicechain/widget-sdk";
|
|
2005
|
-
import { jsx as
|
|
1326
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
2006
1327
|
var justify = {
|
|
2007
1328
|
left: "flex-start",
|
|
2008
1329
|
center: "center",
|
|
2009
1330
|
right: "flex-end"
|
|
2010
1331
|
};
|
|
2011
1332
|
function Label({ widget }) {
|
|
2012
|
-
const text =
|
|
2013
|
-
const align =
|
|
2014
|
-
const authored =
|
|
2015
|
-
const fontSize = authored !== void 0 ? `calc(${authored}px * var(--dc-scale, 1))` :
|
|
2016
|
-
return /* @__PURE__ */
|
|
1333
|
+
const text = optString3(widget.options, "text") ?? "";
|
|
1334
|
+
const align = optString3(widget.options, "align") ?? "center";
|
|
1335
|
+
const authored = optNumber2(widget.options, "fontSize");
|
|
1336
|
+
const fontSize = authored !== void 0 ? `calc(${authored}px * var(--dc-scale, 1))` : fontVar2("lg");
|
|
1337
|
+
return /* @__PURE__ */ jsx4(WidgetFrame3, { title: optString3(widget.options, "title"), flush: true, children: /* @__PURE__ */ jsx4(
|
|
2017
1338
|
"div",
|
|
2018
1339
|
{
|
|
2019
1340
|
style: {
|
|
@@ -2025,14 +1346,14 @@ function Label({ widget }) {
|
|
|
2025
1346
|
overflow: "hidden",
|
|
2026
1347
|
// A label is often one row tall: the frame's uniform inset would leave it a line's
|
|
2027
1348
|
// height or less, so it keeps a slim vertical inset and the usual side inset.
|
|
2028
|
-
padding: `${
|
|
1349
|
+
padding: `${spaceVar(1)} ${spaceVar(3)}`
|
|
2029
1350
|
},
|
|
2030
|
-
children: /* @__PURE__ */
|
|
1351
|
+
children: /* @__PURE__ */ jsx4(
|
|
2031
1352
|
"span",
|
|
2032
1353
|
{
|
|
2033
1354
|
style: {
|
|
2034
1355
|
fontSize,
|
|
2035
|
-
color:
|
|
1356
|
+
color: css2("foreground"),
|
|
2036
1357
|
textAlign: align,
|
|
2037
1358
|
whiteSpace: "pre-wrap"
|
|
2038
1359
|
},
|
|
@@ -2042,65 +1363,65 @@ function Label({ widget }) {
|
|
|
2042
1363
|
}
|
|
2043
1364
|
) });
|
|
2044
1365
|
}
|
|
2045
|
-
var labelWidget =
|
|
1366
|
+
var labelWidget = defineWidget7({
|
|
2046
1367
|
descriptor: builtinWidgetDescriptors["label"],
|
|
2047
1368
|
implementation: { kind: "trusted-react", component: Label }
|
|
2048
1369
|
});
|
|
2049
1370
|
|
|
2050
1371
|
// src/widgets/latest-card.tsx
|
|
2051
|
-
import { useMemo as
|
|
1372
|
+
import { useMemo as useMemo2 } from "react";
|
|
2052
1373
|
import {
|
|
2053
1374
|
bandAt,
|
|
2054
|
-
css as
|
|
2055
|
-
defineWidget as
|
|
2056
|
-
fitValueFont
|
|
2057
|
-
fitValueFontCss
|
|
2058
|
-
FIT_MIN_FONT_PX
|
|
1375
|
+
css as css3,
|
|
1376
|
+
defineWidget as defineWidget8,
|
|
1377
|
+
fitValueFont,
|
|
1378
|
+
fitValueFontCss,
|
|
1379
|
+
FIT_MIN_FONT_PX,
|
|
2059
1380
|
flashTextStyle,
|
|
2060
|
-
fontVar as
|
|
1381
|
+
fontVar as fontVar3,
|
|
2061
1382
|
formatTimestamp,
|
|
2062
1383
|
formatValue as formatValue2,
|
|
2063
1384
|
levelColor,
|
|
2064
|
-
optBoolean as
|
|
2065
|
-
optNumber as
|
|
2066
|
-
optString as
|
|
1385
|
+
optBoolean as optBoolean2,
|
|
1386
|
+
optNumber as optNumber3,
|
|
1387
|
+
optString as optString4,
|
|
2067
1388
|
optThresholds as optThresholds2,
|
|
2068
1389
|
pickSample as pickSample2,
|
|
2069
1390
|
primaryMeasurementName as primaryMeasurementName2,
|
|
2070
|
-
spaceVar as
|
|
2071
|
-
useSeverityColors
|
|
2072
|
-
useStickyChars
|
|
1391
|
+
spaceVar as spaceVar2,
|
|
1392
|
+
useSeverityColors,
|
|
1393
|
+
useStickyChars,
|
|
2073
1394
|
useFlashOnChange as useFlashOnChange2,
|
|
2074
|
-
useWidgetTimeZone
|
|
2075
|
-
WidgetFrame as
|
|
1395
|
+
useWidgetTimeZone,
|
|
1396
|
+
WidgetFrame as WidgetFrame4
|
|
2076
1397
|
} from "@devicechain/widget-sdk";
|
|
2077
|
-
import { jsx as
|
|
1398
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2078
1399
|
var TIMESTAMP_ROOM_PX = 18;
|
|
2079
1400
|
function LatestCard({ widget, data }) {
|
|
2080
|
-
const severity =
|
|
2081
|
-
const timeZone =
|
|
1401
|
+
const severity = useSeverityColors();
|
|
1402
|
+
const timeZone = useWidgetTimeZone();
|
|
2082
1403
|
const name = primaryMeasurementName2(widget);
|
|
2083
1404
|
const sample = pickSample2(data.latest, name);
|
|
2084
|
-
const title =
|
|
2085
|
-
const unit =
|
|
2086
|
-
const precision =
|
|
1405
|
+
const title = optString4(widget.options, "title") ?? name;
|
|
1406
|
+
const unit = optString4(widget.options, "unit");
|
|
1407
|
+
const precision = optNumber3(widget.options, "precision");
|
|
2087
1408
|
const display = formatValue2(sample?.value, precision);
|
|
2088
|
-
const thresholds =
|
|
1409
|
+
const thresholds = useMemo2(() => optThresholds2(widget.options, "thresholds"), [widget.options]);
|
|
2089
1410
|
const band = bandAt(thresholds, sample?.value);
|
|
2090
|
-
const valueColor = levelColor(severity, band?.level) ??
|
|
1411
|
+
const valueColor = levelColor(severity, band?.level) ?? css3("foreground");
|
|
2091
1412
|
const flashDirection = useFlashOnChange2(
|
|
2092
1413
|
sample?.value,
|
|
2093
|
-
|
|
1414
|
+
optBoolean2(widget.options, "flashOnChange"),
|
|
2094
1415
|
sample && `${sample.deviceToken}:${sample.name}`
|
|
2095
1416
|
);
|
|
2096
|
-
const chars =
|
|
2097
|
-
return /* @__PURE__ */
|
|
2098
|
-
const floor = Math.round(
|
|
1417
|
+
const chars = useStickyChars(display.length + (sample?.value != null && unit ? Math.ceil(unit.length / 2) + 1 : 0));
|
|
1418
|
+
return /* @__PURE__ */ jsx5(WidgetFrame4, { title, sampleTime: sample?.occurredTime ?? null, children: ({ size, scale }) => {
|
|
1419
|
+
const floor = Math.round(FIT_MIN_FONT_PX * scale);
|
|
2099
1420
|
const measured = size.width > 0 && size.height > 0;
|
|
2100
|
-
const valuePx = measured ?
|
|
2101
|
-
const valueFont = valuePx ??
|
|
1421
|
+
const valuePx = measured ? fitValueFont(size, chars, { floor }) : void 0;
|
|
1422
|
+
const valueFont = valuePx ?? fitValueFontCss(chars, { floor });
|
|
2102
1423
|
const showTimestamp = valuePx === void 0 || size.height - Math.ceil(valuePx * 1.1) >= TIMESTAMP_ROOM_PX * scale;
|
|
2103
|
-
return /* @__PURE__ */
|
|
1424
|
+
return /* @__PURE__ */ jsxs2(
|
|
2104
1425
|
"div",
|
|
2105
1426
|
{
|
|
2106
1427
|
style: {
|
|
@@ -2112,7 +1433,7 @@ function LatestCard({ widget, data }) {
|
|
|
2112
1433
|
overflow: "hidden"
|
|
2113
1434
|
},
|
|
2114
1435
|
children: [
|
|
2115
|
-
/* @__PURE__ */
|
|
1436
|
+
/* @__PURE__ */ jsxs2(
|
|
2116
1437
|
"div",
|
|
2117
1438
|
{
|
|
2118
1439
|
"data-threshold-level": band?.level,
|
|
@@ -2130,13 +1451,13 @@ function LatestCard({ widget, data }) {
|
|
|
2130
1451
|
},
|
|
2131
1452
|
children: [
|
|
2132
1453
|
display,
|
|
2133
|
-
sample?.value != null && unit ? /* @__PURE__ */
|
|
1454
|
+
sample?.value != null && unit ? /* @__PURE__ */ jsx5(
|
|
2134
1455
|
"span",
|
|
2135
1456
|
{
|
|
2136
1457
|
style: {
|
|
2137
1458
|
fontSize: valuePx !== void 0 ? Math.round(valuePx / 2) : `calc(${valueFont} / 2)`,
|
|
2138
|
-
color:
|
|
2139
|
-
marginLeft:
|
|
1459
|
+
color: css3("muted-foreground"),
|
|
1460
|
+
marginLeft: spaceVar2(1)
|
|
2140
1461
|
},
|
|
2141
1462
|
children: unit
|
|
2142
1463
|
}
|
|
@@ -2144,64 +1465,65 @@ function LatestCard({ widget, data }) {
|
|
|
2144
1465
|
]
|
|
2145
1466
|
}
|
|
2146
1467
|
),
|
|
2147
|
-
sample?.occurredTime && showTimestamp ? /* @__PURE__ */
|
|
1468
|
+
sample?.occurredTime && showTimestamp ? /* @__PURE__ */ jsx5("div", { style: { fontSize: fontVar3("xs"), color: css3("muted-foreground"), marginTop: spaceVar2(1) }, children: formatTimestamp(sample.occurredTime, timeZone) }) : null
|
|
2148
1469
|
]
|
|
2149
1470
|
}
|
|
2150
1471
|
);
|
|
2151
1472
|
} });
|
|
2152
1473
|
}
|
|
2153
|
-
var latestCardWidget =
|
|
1474
|
+
var latestCardWidget = defineWidget8({
|
|
2154
1475
|
descriptor: builtinWidgetDescriptors["latest-card"],
|
|
2155
1476
|
implementation: { kind: "trusted-react", component: LatestCard }
|
|
2156
1477
|
});
|
|
2157
1478
|
|
|
2158
1479
|
// src/widgets/level-lazy.tsx
|
|
2159
|
-
import { defineWidget as
|
|
2160
|
-
|
|
2161
|
-
var
|
|
2162
|
-
var
|
|
2163
|
-
var
|
|
1480
|
+
import { defineWidget as defineWidget9 } from "@devicechain/widget-sdk";
|
|
1481
|
+
import { loadChartEngine as loadChartEngine2 } from "@devicechain/widget-sdk/echarts";
|
|
1482
|
+
var chunk5 = lazyChunk(() => import("./chunks/level-widgets-MJB7TOLU.js"));
|
|
1483
|
+
var loadLevelWidgets = chunk5.load;
|
|
1484
|
+
var lazyComponent = chunk5.component;
|
|
1485
|
+
var linearGaugeWidget = defineWidget9({
|
|
2164
1486
|
descriptor: builtinWidgetDescriptors["linear-gauge"],
|
|
2165
1487
|
implementation: { kind: "trusted-react", component: lazyComponent("LinearGauge") }
|
|
2166
1488
|
});
|
|
2167
|
-
var levelGaugeWidget =
|
|
1489
|
+
var levelGaugeWidget = defineWidget9({
|
|
2168
1490
|
descriptor: builtinWidgetDescriptors["level-gauge"],
|
|
2169
1491
|
implementation: { kind: "trusted-react", component: lazyComponent("LevelGauge") }
|
|
2170
1492
|
});
|
|
2171
|
-
var batteryWidget =
|
|
1493
|
+
var batteryWidget = defineWidget9({
|
|
2172
1494
|
descriptor: builtinWidgetDescriptors["battery"],
|
|
2173
1495
|
implementation: { kind: "trusted-react", component: lazyComponent("Battery") }
|
|
2174
1496
|
});
|
|
2175
|
-
var statusLightWidget =
|
|
1497
|
+
var statusLightWidget = defineWidget9({
|
|
2176
1498
|
descriptor: builtinWidgetDescriptors["status-light"],
|
|
2177
1499
|
implementation: { kind: "trusted-react", component: lazyComponent("StatusLight") }
|
|
2178
1500
|
});
|
|
2179
|
-
var signalBarsWidget =
|
|
1501
|
+
var signalBarsWidget = defineWidget9({
|
|
2180
1502
|
descriptor: builtinWidgetDescriptors["signal-bars"],
|
|
2181
1503
|
implementation: { kind: "trusted-react", component: lazyComponent("SignalBars") }
|
|
2182
1504
|
});
|
|
2183
|
-
var compassWidget =
|
|
1505
|
+
var compassWidget = defineWidget9({
|
|
2184
1506
|
descriptor: builtinWidgetDescriptors["compass"],
|
|
2185
|
-
implementation: { kind: "trusted-react", component: lazyComponent("Compass") }
|
|
1507
|
+
implementation: { kind: "trusted-react", component: lazyComponent("Compass", loadChartEngine2) }
|
|
2186
1508
|
});
|
|
2187
|
-
var progressRingWidget =
|
|
1509
|
+
var progressRingWidget = defineWidget9({
|
|
2188
1510
|
descriptor: builtinWidgetDescriptors["progress-ring"],
|
|
2189
1511
|
implementation: { kind: "trusted-react", component: lazyComponent("ProgressRing") }
|
|
2190
1512
|
});
|
|
2191
1513
|
|
|
2192
1514
|
// src/widgets/map.tsx
|
|
2193
|
-
import { useEffect as
|
|
1515
|
+
import { useEffect as useEffect2, useRef, useState as useState3 } from "react";
|
|
2194
1516
|
import { renderableBasemap, resolveBasemap } from "@devicechain/client";
|
|
2195
1517
|
|
|
2196
1518
|
// src/basemap-context.tsx
|
|
2197
1519
|
import { createContext, useContext } from "react";
|
|
2198
|
-
import { jsx as
|
|
1520
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
2199
1521
|
var TenantBasemapContext = createContext(null);
|
|
2200
1522
|
function TenantBasemapProvider({
|
|
2201
1523
|
basemap,
|
|
2202
1524
|
children
|
|
2203
1525
|
}) {
|
|
2204
|
-
return /* @__PURE__ */
|
|
1526
|
+
return /* @__PURE__ */ jsx6(TenantBasemapContext.Provider, { value: basemap, children });
|
|
2205
1527
|
}
|
|
2206
1528
|
function useTenantBasemap() {
|
|
2207
1529
|
return useContext(TenantBasemapContext);
|
|
@@ -2209,13 +1531,13 @@ function useTenantBasemap() {
|
|
|
2209
1531
|
|
|
2210
1532
|
// src/map-runtime-context.tsx
|
|
2211
1533
|
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
2212
|
-
import { jsx as
|
|
1534
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2213
1535
|
var MapRuntimeContext = createContext2(null);
|
|
2214
1536
|
function MapRuntimeProvider({
|
|
2215
1537
|
runtime,
|
|
2216
1538
|
children
|
|
2217
1539
|
}) {
|
|
2218
|
-
return /* @__PURE__ */
|
|
1540
|
+
return /* @__PURE__ */ jsx7(MapRuntimeContext.Provider, { value: runtime, children });
|
|
2219
1541
|
}
|
|
2220
1542
|
function useMapRuntime() {
|
|
2221
1543
|
return useContext2(MapRuntimeContext);
|
|
@@ -2223,11 +1545,11 @@ function useMapRuntime() {
|
|
|
2223
1545
|
|
|
2224
1546
|
// src/widgets/map.tsx
|
|
2225
1547
|
import {
|
|
2226
|
-
css as
|
|
2227
|
-
fontVar as
|
|
2228
|
-
defineWidget as
|
|
2229
|
-
optString as
|
|
2230
|
-
WidgetFrame as
|
|
1548
|
+
css as css4,
|
|
1549
|
+
fontVar as fontVar4,
|
|
1550
|
+
defineWidget as defineWidget10,
|
|
1551
|
+
optString as optString5,
|
|
1552
|
+
WidgetFrame as WidgetFrame5
|
|
2231
1553
|
} from "@devicechain/widget-sdk";
|
|
2232
1554
|
|
|
2233
1555
|
// src/widgets/map-geometry.ts
|
|
@@ -2323,7 +1645,7 @@ function loadLandStyle() {
|
|
|
2323
1645
|
}
|
|
2324
1646
|
|
|
2325
1647
|
// src/widgets/map.tsx
|
|
2326
|
-
import { jsx as
|
|
1648
|
+
import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2327
1649
|
var mapLibrePromise;
|
|
2328
1650
|
function loadMapLibre(runtime) {
|
|
2329
1651
|
if (!mapLibrePromise) {
|
|
@@ -2339,20 +1661,20 @@ function loadMapLibre(runtime) {
|
|
|
2339
1661
|
}
|
|
2340
1662
|
var SINGLE_DEVICE_ZOOM = 14;
|
|
2341
1663
|
function MapWidget({ widget, data }) {
|
|
2342
|
-
const title =
|
|
1664
|
+
const title = optString5(widget.options, "title");
|
|
2343
1665
|
const positions = placeable(data.locations);
|
|
2344
1666
|
const runtime = useMapRuntime();
|
|
2345
1667
|
const basemap = renderableBasemap(
|
|
2346
1668
|
resolveBasemap(
|
|
2347
1669
|
{
|
|
2348
|
-
tileUrl:
|
|
2349
|
-
attribution:
|
|
1670
|
+
tileUrl: optString5(widget.options, "tileUrl"),
|
|
1671
|
+
attribution: optString5(widget.options, "attribution")
|
|
2350
1672
|
},
|
|
2351
1673
|
useTenantBasemap()
|
|
2352
1674
|
)
|
|
2353
1675
|
);
|
|
2354
1676
|
if (data.forbidden) {
|
|
2355
|
-
return /* @__PURE__ */
|
|
1677
|
+
return /* @__PURE__ */ jsx8(WidgetFrame5, { title, children: /* @__PURE__ */ jsx8(
|
|
2356
1678
|
MapNotice,
|
|
2357
1679
|
{
|
|
2358
1680
|
glyph: "\u{1F512}",
|
|
@@ -2362,7 +1684,7 @@ function MapWidget({ widget, data }) {
|
|
|
2362
1684
|
) });
|
|
2363
1685
|
}
|
|
2364
1686
|
if (!runtime) {
|
|
2365
|
-
return /* @__PURE__ */
|
|
1687
|
+
return /* @__PURE__ */ jsx8(WidgetFrame5, { title, children: /* @__PURE__ */ jsx8(
|
|
2366
1688
|
MapNotice,
|
|
2367
1689
|
{
|
|
2368
1690
|
glyph: "\u{1F9E9}",
|
|
@@ -2372,10 +1694,10 @@ function MapWidget({ widget, data }) {
|
|
|
2372
1694
|
) });
|
|
2373
1695
|
}
|
|
2374
1696
|
if (data.loading && positions.length === 0) {
|
|
2375
|
-
return /* @__PURE__ */
|
|
1697
|
+
return /* @__PURE__ */ jsx8(WidgetFrame5, { title, children: /* @__PURE__ */ jsx8(MapNotice, { heading: "Loading\u2026" }) });
|
|
2376
1698
|
}
|
|
2377
1699
|
if (positions.length === 0) {
|
|
2378
|
-
return /* @__PURE__ */
|
|
1700
|
+
return /* @__PURE__ */ jsx8(WidgetFrame5, { title, children: /* @__PURE__ */ jsx8(
|
|
2379
1701
|
MapNotice,
|
|
2380
1702
|
{
|
|
2381
1703
|
heading: data.deviceTokens.length === 0 ? "No devices selected" : "No positions reported",
|
|
@@ -2383,11 +1705,11 @@ function MapWidget({ widget, data }) {
|
|
|
2383
1705
|
}
|
|
2384
1706
|
) });
|
|
2385
1707
|
}
|
|
2386
|
-
return /* @__PURE__ */
|
|
1708
|
+
return /* @__PURE__ */ jsx8(WidgetFrame5, { title, flush: true, children: /* @__PURE__ */ jsx8(LiveMap, { basemap, positions, runtime }) });
|
|
2387
1709
|
}
|
|
2388
1710
|
function PlainPanel({ positions, note }) {
|
|
2389
1711
|
const points = projectToPanel(positions);
|
|
2390
|
-
return /* @__PURE__ */
|
|
1712
|
+
return /* @__PURE__ */ jsxs3(
|
|
2391
1713
|
"div",
|
|
2392
1714
|
{
|
|
2393
1715
|
"data-testid": "map-plain-panel",
|
|
@@ -2396,10 +1718,10 @@ function PlainPanel({ positions, note }) {
|
|
|
2396
1718
|
width: "100%",
|
|
2397
1719
|
height: "100%",
|
|
2398
1720
|
overflow: "hidden",
|
|
2399
|
-
background:
|
|
1721
|
+
background: css4("muted")
|
|
2400
1722
|
},
|
|
2401
1723
|
children: [
|
|
2402
|
-
positions.map((position, i) => /* @__PURE__ */
|
|
1724
|
+
positions.map((position, i) => /* @__PURE__ */ jsx8(
|
|
2403
1725
|
Marker,
|
|
2404
1726
|
{
|
|
2405
1727
|
position,
|
|
@@ -2412,7 +1734,7 @@ function PlainPanel({ positions, note }) {
|
|
|
2412
1734
|
},
|
|
2413
1735
|
position.deviceToken
|
|
2414
1736
|
)),
|
|
2415
|
-
/* @__PURE__ */
|
|
1737
|
+
/* @__PURE__ */ jsx8(
|
|
2416
1738
|
"div",
|
|
2417
1739
|
{
|
|
2418
1740
|
"data-testid": "map-no-tiles-note",
|
|
@@ -2422,11 +1744,11 @@ function PlainPanel({ positions, note }) {
|
|
|
2422
1744
|
right: 0,
|
|
2423
1745
|
bottom: 0,
|
|
2424
1746
|
padding: "4px 8px",
|
|
2425
|
-
fontSize:
|
|
1747
|
+
fontSize: fontVar4("sm"),
|
|
2426
1748
|
lineHeight: 1.3,
|
|
2427
1749
|
textAlign: "center",
|
|
2428
|
-
color:
|
|
2429
|
-
background:
|
|
1750
|
+
color: css4("muted-foreground"),
|
|
1751
|
+
background: css4("card"),
|
|
2430
1752
|
opacity: 0.9
|
|
2431
1753
|
},
|
|
2432
1754
|
children: note
|
|
@@ -2441,13 +1763,13 @@ function LiveMap({
|
|
|
2441
1763
|
positions,
|
|
2442
1764
|
runtime
|
|
2443
1765
|
}) {
|
|
2444
|
-
const containerRef =
|
|
2445
|
-
const mapRef =
|
|
2446
|
-
const markersRef =
|
|
2447
|
-
const [status, setStatus] =
|
|
1766
|
+
const containerRef = useRef(null);
|
|
1767
|
+
const mapRef = useRef(null);
|
|
1768
|
+
const markersRef = useRef([]);
|
|
1769
|
+
const [status, setStatus] = useState3("loading");
|
|
2448
1770
|
const tileUrl = basemap?.tileUrl ?? null;
|
|
2449
1771
|
const attribution = basemap?.attribution ?? null;
|
|
2450
|
-
|
|
1772
|
+
useEffect2(() => {
|
|
2451
1773
|
let cancelled = false;
|
|
2452
1774
|
setStatus("loading");
|
|
2453
1775
|
Promise.all([
|
|
@@ -2475,7 +1797,7 @@ function LiveMap({
|
|
|
2475
1797
|
mapRef.current = null;
|
|
2476
1798
|
};
|
|
2477
1799
|
}, [tileUrl, attribution, runtime.workerUrl]);
|
|
2478
|
-
|
|
1800
|
+
useEffect2(() => {
|
|
2479
1801
|
const map = mapRef.current;
|
|
2480
1802
|
if (status !== "ready" || !map) return;
|
|
2481
1803
|
let live = true;
|
|
@@ -2504,7 +1826,7 @@ function LiveMap({
|
|
|
2504
1826
|
};
|
|
2505
1827
|
}, [status, positionsKey(positions)]);
|
|
2506
1828
|
if (status === "unavailable") {
|
|
2507
|
-
return /* @__PURE__ */
|
|
1829
|
+
return /* @__PURE__ */ jsx8(
|
|
2508
1830
|
PlainPanel,
|
|
2509
1831
|
{
|
|
2510
1832
|
positions,
|
|
@@ -2512,7 +1834,7 @@ function LiveMap({
|
|
|
2512
1834
|
}
|
|
2513
1835
|
);
|
|
2514
1836
|
}
|
|
2515
|
-
return /* @__PURE__ */
|
|
1837
|
+
return /* @__PURE__ */ jsx8("div", { ref: containerRef, "data-testid": "map-canvas", style: { width: "100%", height: "100%" } });
|
|
2516
1838
|
}
|
|
2517
1839
|
function positionsKey(positions) {
|
|
2518
1840
|
return positions.map((p) => `${p.deviceToken}:${p.latitude}:${p.longitude}:${p.heading ?? ""}`).join("|");
|
|
@@ -2521,8 +1843,8 @@ var MARKER_DOT_STYLE = {
|
|
|
2521
1843
|
width: "12px",
|
|
2522
1844
|
height: "12px",
|
|
2523
1845
|
borderRadius: "50%",
|
|
2524
|
-
background:
|
|
2525
|
-
border: `2px solid ${
|
|
1846
|
+
background: css4("primary"),
|
|
1847
|
+
border: `2px solid ${css4("card")}`,
|
|
2526
1848
|
boxShadow: "0 0 0 1px rgba(0,0,0,0.25)",
|
|
2527
1849
|
cursor: "default"
|
|
2528
1850
|
};
|
|
@@ -2531,7 +1853,7 @@ function Marker({
|
|
|
2531
1853
|
style
|
|
2532
1854
|
}) {
|
|
2533
1855
|
const label = describePosition(position);
|
|
2534
|
-
return /* @__PURE__ */
|
|
1856
|
+
return /* @__PURE__ */ jsx8(
|
|
2535
1857
|
"div",
|
|
2536
1858
|
{
|
|
2537
1859
|
"data-testid": "map-marker",
|
|
@@ -2543,7 +1865,7 @@ function Marker({
|
|
|
2543
1865
|
);
|
|
2544
1866
|
}
|
|
2545
1867
|
function MapNotice({ glyph, heading, detail }) {
|
|
2546
|
-
return /* @__PURE__ */
|
|
1868
|
+
return /* @__PURE__ */ jsxs3(
|
|
2547
1869
|
"div",
|
|
2548
1870
|
{
|
|
2549
1871
|
style: {
|
|
@@ -2557,115 +1879,68 @@ function MapNotice({ glyph, heading, detail }) {
|
|
|
2557
1879
|
height: "100%",
|
|
2558
1880
|
boxSizing: "border-box",
|
|
2559
1881
|
textAlign: "center",
|
|
2560
|
-
color:
|
|
1882
|
+
color: css4("muted-foreground")
|
|
2561
1883
|
},
|
|
2562
1884
|
children: [
|
|
2563
|
-
glyph ? /* @__PURE__ */
|
|
2564
|
-
/* @__PURE__ */
|
|
2565
|
-
detail ? /* @__PURE__ */
|
|
1885
|
+
glyph ? /* @__PURE__ */ jsx8("div", { style: { fontSize: fontVar4("xl"), lineHeight: 1 }, "aria-hidden": "true", children: glyph }) : null,
|
|
1886
|
+
/* @__PURE__ */ jsx8("div", { style: { fontSize: fontVar4("md"), fontWeight: 600 }, children: heading }),
|
|
1887
|
+
detail ? /* @__PURE__ */ jsx8("div", { style: { fontSize: fontVar4("sm"), opacity: 0.8 }, children: detail }) : null
|
|
2566
1888
|
]
|
|
2567
1889
|
}
|
|
2568
1890
|
);
|
|
2569
1891
|
}
|
|
2570
|
-
var mapWidget =
|
|
1892
|
+
var mapWidget = defineWidget10({
|
|
2571
1893
|
descriptor: builtinWidgetDescriptors["map"],
|
|
2572
1894
|
implementation: { kind: "trusted-react", component: MapWidget }
|
|
2573
1895
|
});
|
|
2574
1896
|
|
|
2575
|
-
// src/widgets/table.tsx
|
|
2576
|
-
import {
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
spaceVar as spaceVar4,
|
|
2581
|
-
FlashValue as FlashValue2,
|
|
2582
|
-
formatTimestamp as formatTimestamp2,
|
|
2583
|
-
optBoolean as optBoolean4,
|
|
2584
|
-
optNumber as optNumber5,
|
|
2585
|
-
optString as optString10,
|
|
2586
|
-
useWidgetTimeZone as useWidgetTimeZone4,
|
|
2587
|
-
WidgetFrame as WidgetFrame10
|
|
2588
|
-
} from "@devicechain/widget-sdk";
|
|
2589
|
-
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2590
|
-
var cell2 = { padding: `${spaceVar4(1)} ${spaceVar4(3)}`, textAlign: "left" };
|
|
2591
|
-
var headCell2 = {
|
|
2592
|
-
...cell2,
|
|
2593
|
-
fontSize: fontVar9("xs"),
|
|
2594
|
-
fontWeight: 600,
|
|
2595
|
-
textTransform: "uppercase",
|
|
2596
|
-
letterSpacing: "0.04em",
|
|
2597
|
-
color: css10("muted-foreground"),
|
|
2598
|
-
borderBottom: `1px solid ${css10("border")}`
|
|
2599
|
-
};
|
|
2600
|
-
function Table({ widget, data }) {
|
|
2601
|
-
const timeZone = useWidgetTimeZone4();
|
|
2602
|
-
const rows = Object.values(data.latest).sort((a, b) => a.name.localeCompare(b.name));
|
|
2603
|
-
const precision = optNumber5(widget.options, "precision");
|
|
2604
|
-
const flash = optBoolean4(widget.options, "flashOnChange");
|
|
2605
|
-
return /* @__PURE__ */ jsx13(WidgetFrame10, { title: optString10(widget.options, "title"), flush: true, children: /* @__PURE__ */ jsx13("div", { style: { height: "100%", overflow: "auto" }, children: /* @__PURE__ */ jsxs8("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: fontVar9("md"), color: css10("foreground") }, children: [
|
|
2606
|
-
/* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsxs8("tr", { children: [
|
|
2607
|
-
/* @__PURE__ */ jsx13("th", { style: headCell2, children: "Measurement" }),
|
|
2608
|
-
/* @__PURE__ */ jsx13("th", { style: headCell2, children: "Value" }),
|
|
2609
|
-
/* @__PURE__ */ jsx13("th", { style: headCell2, children: "Time" })
|
|
2610
|
-
] }) }),
|
|
2611
|
-
/* @__PURE__ */ jsx13("tbody", { children: rows.length === 0 ? /* @__PURE__ */ jsx13("tr", { children: /* @__PURE__ */ jsx13("td", { colSpan: 3, style: { ...cell2, textAlign: "center", color: css10("muted-foreground") }, children: "No data yet" }) }) : rows.map((row) => /* @__PURE__ */ jsxs8("tr", { children: [
|
|
2612
|
-
/* @__PURE__ */ jsx13("td", { style: cell2, children: row.name }),
|
|
2613
|
-
/* @__PURE__ */ jsx13("td", { style: { ...cell2, fontVariantNumeric: "tabular-nums" }, children: /* @__PURE__ */ jsx13(
|
|
2614
|
-
FlashValue2,
|
|
2615
|
-
{
|
|
2616
|
-
value: row.value,
|
|
2617
|
-
precision,
|
|
2618
|
-
enabled: flash,
|
|
2619
|
-
identity: `${row.deviceToken}:${row.name}`
|
|
2620
|
-
}
|
|
2621
|
-
) }),
|
|
2622
|
-
/* @__PURE__ */ jsx13("td", { style: { ...cell2, color: css10("muted-foreground") }, children: formatTimestamp2(row.occurredTime, timeZone) })
|
|
2623
|
-
] }, row.name)) })
|
|
2624
|
-
] }) }) });
|
|
2625
|
-
}
|
|
2626
|
-
var tableWidget = defineWidget13({
|
|
1897
|
+
// src/widgets/table-lazy.tsx
|
|
1898
|
+
import { defineWidget as defineWidget11 } from "@devicechain/widget-sdk";
|
|
1899
|
+
var chunk6 = lazyChunk(() => import("./chunks/table-6EVV7QZH.js"));
|
|
1900
|
+
var loadTableWidget = chunk6.load;
|
|
1901
|
+
var tableWidget = defineWidget11({
|
|
2627
1902
|
descriptor: builtinWidgetDescriptors["table"],
|
|
2628
|
-
implementation: { kind: "trusted-react", component: Table }
|
|
1903
|
+
implementation: { kind: "trusted-react", component: chunk6.component("Table") }
|
|
2629
1904
|
});
|
|
2630
1905
|
|
|
2631
1906
|
// src/widgets/time-series-chart.tsx
|
|
2632
|
-
import { useMemo as
|
|
1907
|
+
import { useMemo as useMemo3 } from "react";
|
|
2633
1908
|
import { isValidSpanSeconds, spanLabel } from "@devicechain/dashboards";
|
|
2634
1909
|
import {
|
|
2635
|
-
css as
|
|
2636
|
-
defineWidget as
|
|
2637
|
-
fontVar as
|
|
2638
|
-
formatDateTime
|
|
2639
|
-
formatTimestamp as
|
|
2640
|
-
optNumber as
|
|
2641
|
-
optString as
|
|
1910
|
+
css as css5,
|
|
1911
|
+
defineWidget as defineWidget12,
|
|
1912
|
+
fontVar as fontVar5,
|
|
1913
|
+
formatDateTime,
|
|
1914
|
+
formatTimestamp as formatTimestamp2,
|
|
1915
|
+
optNumber as optNumber4,
|
|
1916
|
+
optString as optString6,
|
|
2642
1917
|
optThresholds as optThresholds3,
|
|
2643
|
-
spaceVar as
|
|
2644
|
-
useWidgetScale as
|
|
1918
|
+
spaceVar as spaceVar3,
|
|
1919
|
+
useWidgetScale as useWidgetScale2,
|
|
2645
1920
|
useWidgetTimeRange,
|
|
2646
|
-
useWidgetTimeZone as
|
|
1921
|
+
useWidgetTimeZone as useWidgetTimeZone2,
|
|
2647
1922
|
viewerLocale,
|
|
2648
|
-
WidgetFrame as
|
|
1923
|
+
WidgetFrame as WidgetFrame6
|
|
2649
1924
|
} from "@devicechain/widget-sdk";
|
|
2650
|
-
import { buildLineOption, EChart as EChart2, useChartTheme as useChartTheme2 } from "@devicechain/widget-sdk/echarts";
|
|
2651
|
-
import { jsx as
|
|
1925
|
+
import { buildLineOption, EChart as EChart2, loadChartEngine as loadChartEngine3, useChartTheme as useChartTheme2 } from "@devicechain/widget-sdk/echarts";
|
|
1926
|
+
import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2652
1927
|
function TimeSeriesChart({ widget, data }) {
|
|
2653
|
-
return /* @__PURE__ */
|
|
1928
|
+
return /* @__PURE__ */ jsx9(WidgetFrame6, { title: optString6(widget.options, "title"), flush: true, children: /* @__PURE__ */ jsx9(TimeSeriesBody, { widget, data }) });
|
|
2654
1929
|
}
|
|
2655
1930
|
function TimeSeriesBody({ widget, data }) {
|
|
2656
1931
|
const theme = useChartTheme2();
|
|
2657
|
-
const { size, scale } =
|
|
1932
|
+
const { size, scale } = useWidgetScale2();
|
|
2658
1933
|
const measurements = widget.datasource?.measurements;
|
|
2659
|
-
const unit =
|
|
2660
|
-
const precision =
|
|
2661
|
-
const thresholds =
|
|
2662
|
-
const option =
|
|
2663
|
-
() => buildLineOption(data.samples, theme, { measurements, unit, precision, thresholds, scale }, size),
|
|
2664
|
-
[data.samples, theme, measurements, unit, precision, thresholds, scale, size]
|
|
1934
|
+
const unit = optString6(widget.options, "unit");
|
|
1935
|
+
const precision = optNumber4(widget.options, "precision");
|
|
1936
|
+
const thresholds = useMemo3(() => optThresholds3(widget.options, "thresholds"), [widget.options]);
|
|
1937
|
+
const option = useMemo3(
|
|
1938
|
+
() => buildLineOption(data.samples, theme, { measurements, unit, precision, thresholds, scale, gaps: data.gaps }, size),
|
|
1939
|
+
[data.samples, data.gaps, theme, measurements, unit, precision, thresholds, scale, size]
|
|
2665
1940
|
);
|
|
2666
|
-
return /* @__PURE__ */
|
|
2667
|
-
/* @__PURE__ */
|
|
2668
|
-
/* @__PURE__ */
|
|
1941
|
+
return /* @__PURE__ */ jsxs4("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
|
|
1942
|
+
/* @__PURE__ */ jsx9(EChart2, { option }),
|
|
1943
|
+
/* @__PURE__ */ jsx9(SpanBadge, { widget, data })
|
|
2669
1944
|
] });
|
|
2670
1945
|
}
|
|
2671
1946
|
var SPAN_STRINGS = {
|
|
@@ -2683,8 +1958,8 @@ var SPAN_STRINGS = {
|
|
|
2683
1958
|
var DAY_MS = 864e5;
|
|
2684
1959
|
function SpanBadge({ widget, data }) {
|
|
2685
1960
|
const range = useWidgetTimeRange();
|
|
2686
|
-
const timeZone =
|
|
2687
|
-
const pinned =
|
|
1961
|
+
const timeZone = useWidgetTimeZone2();
|
|
1962
|
+
const pinned = optNumber4(widget.options, "windowSeconds");
|
|
2688
1963
|
const span = isValidSpanSeconds(pinned) ? pinned : range?.spanSeconds;
|
|
2689
1964
|
const showSpan = range !== void 0 && span !== range.spanSeconds;
|
|
2690
1965
|
const cutAt = data.truncatedBefore;
|
|
@@ -2692,10 +1967,10 @@ function SpanBadge({ widget, data }) {
|
|
|
2692
1967
|
const words = viewerLocale()?.toLowerCase().startsWith("es") ? SPAN_STRINGS.es : SPAN_STRINGS.en;
|
|
2693
1968
|
const label = span === void 0 ? "" : spanLabel(span);
|
|
2694
1969
|
const end = range?.paused && range.pausedAt !== void 0 ? range.pausedAt : Date.now();
|
|
2695
|
-
const time = cutAt ? end - Date.parse(cutAt) > DAY_MS ?
|
|
1970
|
+
const time = cutAt ? end - Date.parse(cutAt) > DAY_MS ? formatDateTime(cutAt, timeZone) : formatTimestamp2(cutAt, timeZone) : "";
|
|
2696
1971
|
const text = [showSpan ? label : "", cutAt ? words.from(time) : ""].filter(Boolean).join(" \xB7 ");
|
|
2697
1972
|
const title = [showSpan ? words.pinned(label) : "", cutAt ? words.cut(time, label) : ""].filter(Boolean).join(" ");
|
|
2698
|
-
return /* @__PURE__ */
|
|
1973
|
+
return /* @__PURE__ */ jsx9(
|
|
2699
1974
|
"span",
|
|
2700
1975
|
{
|
|
2701
1976
|
"data-chart-span": showSpan ? label : "",
|
|
@@ -2703,13 +1978,13 @@ function SpanBadge({ widget, data }) {
|
|
|
2703
1978
|
title,
|
|
2704
1979
|
style: {
|
|
2705
1980
|
position: "absolute",
|
|
2706
|
-
top:
|
|
2707
|
-
right:
|
|
2708
|
-
padding: `0 ${
|
|
2709
|
-
fontSize:
|
|
1981
|
+
top: spaceVar3(1),
|
|
1982
|
+
right: spaceVar3(2),
|
|
1983
|
+
padding: `0 ${spaceVar3(1)}`,
|
|
1984
|
+
fontSize: fontVar5("xs"),
|
|
2710
1985
|
whiteSpace: "nowrap",
|
|
2711
|
-
color:
|
|
2712
|
-
background:
|
|
1986
|
+
color: css5("muted-foreground"),
|
|
1987
|
+
background: css5("muted"),
|
|
2713
1988
|
borderRadius: 4,
|
|
2714
1989
|
pointerEvents: "auto"
|
|
2715
1990
|
},
|
|
@@ -2717,7 +1992,8 @@ function SpanBadge({ widget, data }) {
|
|
|
2717
1992
|
}
|
|
2718
1993
|
);
|
|
2719
1994
|
}
|
|
2720
|
-
|
|
1995
|
+
TimeSeriesChart.preload = loadChartEngine3;
|
|
1996
|
+
var timeSeriesChartWidget = defineWidget12({
|
|
2721
1997
|
descriptor: builtinWidgetDescriptors["timeseries-chart"],
|
|
2722
1998
|
implementation: { kind: "trusted-react", component: TimeSeriesChart }
|
|
2723
1999
|
});
|
|
@@ -2762,20 +2038,20 @@ function defaultWidgetRegistry() {
|
|
|
2762
2038
|
|
|
2763
2039
|
// src/connected-widget.tsx
|
|
2764
2040
|
import {
|
|
2765
|
-
optString as
|
|
2041
|
+
optString as optString7,
|
|
2766
2042
|
useAlarmStream,
|
|
2767
2043
|
useCommandStream,
|
|
2768
2044
|
useDatasourceAvailability,
|
|
2769
2045
|
useLocationStream,
|
|
2770
2046
|
useMeasurementStream,
|
|
2771
2047
|
useWidgetCandidates,
|
|
2772
|
-
useWidgetSelect
|
|
2773
|
-
WidgetFrame as
|
|
2048
|
+
useWidgetSelect,
|
|
2049
|
+
WidgetFrame as WidgetFrame8
|
|
2774
2050
|
} from "@devicechain/widget-sdk";
|
|
2775
2051
|
|
|
2776
2052
|
// src/widget-containment.tsx
|
|
2777
|
-
import { Component, createContext as createContext3, useCallback, useContext as useContext3, useState as
|
|
2778
|
-
import { WidgetFrame as
|
|
2053
|
+
import { Component, createContext as createContext3, useCallback, useContext as useContext3, useState as useState4 } from "react";
|
|
2054
|
+
import { WidgetFrame as WidgetFrame7 } from "@devicechain/widget-sdk";
|
|
2779
2055
|
|
|
2780
2056
|
// src/widget-host.ts
|
|
2781
2057
|
function describeError(error) {
|
|
@@ -2833,7 +2109,7 @@ function narrowCandidates(candidates, descriptor, report) {
|
|
|
2833
2109
|
}
|
|
2834
2110
|
|
|
2835
2111
|
// src/widget-containment.tsx
|
|
2836
|
-
import { jsx as
|
|
2112
|
+
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2837
2113
|
var MESSAGE_STYLE = {
|
|
2838
2114
|
display: "flex",
|
|
2839
2115
|
flexDirection: "column",
|
|
@@ -2877,23 +2153,23 @@ var WidgetErrorBoundary = class extends Component {
|
|
|
2877
2153
|
render() {
|
|
2878
2154
|
const { error } = this.state;
|
|
2879
2155
|
if (!error) return this.props.children;
|
|
2880
|
-
return /* @__PURE__ */
|
|
2881
|
-
/* @__PURE__ */
|
|
2882
|
-
/* @__PURE__ */
|
|
2883
|
-
/* @__PURE__ */
|
|
2884
|
-
/* @__PURE__ */
|
|
2156
|
+
return /* @__PURE__ */ jsx10(WidgetFrame7, { title: this.props.title, children: /* @__PURE__ */ jsxs5("div", { style: MESSAGE_STYLE, role: "alert", children: [
|
|
2157
|
+
/* @__PURE__ */ jsx10("div", { style: { fontSize: 20, lineHeight: 1 }, "aria-hidden": "true", children: "\u26A0" }),
|
|
2158
|
+
/* @__PURE__ */ jsx10("div", { style: { fontSize: 13, fontWeight: 600 }, children: "This widget failed to render" }),
|
|
2159
|
+
/* @__PURE__ */ jsx10("div", { style: { fontSize: 11, opacity: 0.8, wordBreak: "break-word" }, children: error.message }),
|
|
2160
|
+
/* @__PURE__ */ jsx10("button", { type: "button", style: BUTTON_STYLE, onClick: this.reset, children: "Reset widget" })
|
|
2885
2161
|
] }) });
|
|
2886
2162
|
}
|
|
2887
2163
|
};
|
|
2888
2164
|
function WidgetContainment({ title, resetKey, children }) {
|
|
2889
|
-
const [messages, setMessages] =
|
|
2165
|
+
const [messages, setMessages] = useState4([]);
|
|
2890
2166
|
const report = useCallback((message) => {
|
|
2891
2167
|
setMessages((prev) => prev.includes(message) ? prev : [...prev, message].slice(-3));
|
|
2892
2168
|
}, []);
|
|
2893
2169
|
const clear = useCallback(() => setMessages([]), []);
|
|
2894
|
-
return /* @__PURE__ */
|
|
2895
|
-
/* @__PURE__ */
|
|
2896
|
-
messages.length > 0 && /* @__PURE__ */
|
|
2170
|
+
return /* @__PURE__ */ jsxs5("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
|
|
2171
|
+
/* @__PURE__ */ jsx10(ReportContext.Provider, { value: report, children: /* @__PURE__ */ jsx10(WidgetErrorBoundary, { title, resetKey, onReset: clear, children }) }),
|
|
2172
|
+
messages.length > 0 && /* @__PURE__ */ jsxs5(
|
|
2897
2173
|
"div",
|
|
2898
2174
|
{
|
|
2899
2175
|
role: "status",
|
|
@@ -2912,8 +2188,8 @@ function WidgetContainment({ title, resetKey, children }) {
|
|
|
2912
2188
|
alignItems: "center"
|
|
2913
2189
|
},
|
|
2914
2190
|
children: [
|
|
2915
|
-
/* @__PURE__ */
|
|
2916
|
-
/* @__PURE__ */
|
|
2191
|
+
/* @__PURE__ */ jsx10("span", { style: { flex: 1, wordBreak: "break-word" }, children: messages.join(" \xB7 ") }),
|
|
2192
|
+
/* @__PURE__ */ jsx10("button", { type: "button", "aria-label": "Dismiss", onClick: clear, style: { cursor: "pointer" }, children: "\xD7" })
|
|
2917
2193
|
]
|
|
2918
2194
|
}
|
|
2919
2195
|
)
|
|
@@ -2921,27 +2197,31 @@ function WidgetContainment({ title, resetKey, children }) {
|
|
|
2921
2197
|
}
|
|
2922
2198
|
|
|
2923
2199
|
// src/connected-widget.tsx
|
|
2924
|
-
import { jsx as
|
|
2200
|
+
import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2925
2201
|
function ConnectedWidget(props) {
|
|
2926
2202
|
const { widget } = props;
|
|
2927
2203
|
const registry = props.registry ?? defaultWidgetRegistry();
|
|
2928
2204
|
const resetKey = JSON.stringify([widget.type, widget.options ?? null, widget.datasource ?? null]);
|
|
2929
|
-
return /* @__PURE__ */
|
|
2205
|
+
return /* @__PURE__ */ jsx11(WidgetContainment, { title: optString7(widget.options, "title"), resetKey, children: /* @__PURE__ */ jsx11(ConnectedWidgetBody, { ...props, registry }) });
|
|
2930
2206
|
}
|
|
2931
|
-
function ConnectedWidgetBody({ widget, hub, registry, actions, initialSamples }) {
|
|
2207
|
+
function ConnectedWidgetBody({ widget, hub, registry, actions, initialSamples, initialSamplesAsOf, onReconnect }) {
|
|
2932
2208
|
const unresolved = widget.type === UNKNOWN_WIDGET_TYPE;
|
|
2933
2209
|
const descriptor = unresolved ? void 0 : registry.descriptor(widget.type);
|
|
2934
2210
|
const implementation = unresolved ? void 0 : registry.implementation(widget.type);
|
|
2935
2211
|
const readsDatasource = descriptor !== void 0 && descriptor.datasource.mode !== "none";
|
|
2936
2212
|
const availability = useDatasourceAvailability(hub, readsDatasource ? widget.datasource : void 0);
|
|
2213
|
+
const supported = useDatasourceSupported(hub, readsDatasource ? widget.datasource : void 0);
|
|
2214
|
+
if (!supported) {
|
|
2215
|
+
return /* @__PURE__ */ jsx11(WidgetNotForCustomerUsersFrame, { widget });
|
|
2216
|
+
}
|
|
2937
2217
|
if (availability === "unavailable") {
|
|
2938
|
-
return /* @__PURE__ */
|
|
2218
|
+
return /* @__PURE__ */ jsx11(WidgetUnavailableFrame, { widget });
|
|
2939
2219
|
}
|
|
2940
2220
|
if (widget.type === UNKNOWN_WIDGET_TYPE) {
|
|
2941
|
-
return /* @__PURE__ */
|
|
2221
|
+
return /* @__PURE__ */ jsx11(UnresolvedWidgetFrame, { storedType: widget.raw.type, reason: widget.reason });
|
|
2942
2222
|
}
|
|
2943
2223
|
if (!descriptor || !implementation) {
|
|
2944
|
-
return /* @__PURE__ */
|
|
2224
|
+
return /* @__PURE__ */ jsx11(
|
|
2945
2225
|
UnresolvedWidgetFrame,
|
|
2946
2226
|
{
|
|
2947
2227
|
storedType: widget.type,
|
|
@@ -2949,7 +2229,7 @@ function ConnectedWidgetBody({ widget, hub, registry, actions, initialSamples })
|
|
|
2949
2229
|
}
|
|
2950
2230
|
);
|
|
2951
2231
|
}
|
|
2952
|
-
return /* @__PURE__ */
|
|
2232
|
+
return /* @__PURE__ */ jsx11(HostScope, { descriptor, actions, children: (hostActions) => /* @__PURE__ */ jsx11(
|
|
2953
2233
|
ChannelBody,
|
|
2954
2234
|
{
|
|
2955
2235
|
widget,
|
|
@@ -2957,183 +2237,205 @@ function ConnectedWidgetBody({ widget, hub, registry, actions, initialSamples })
|
|
|
2957
2237
|
descriptor,
|
|
2958
2238
|
Component: implementation.component,
|
|
2959
2239
|
actions: hostActions,
|
|
2960
|
-
initialSamples
|
|
2240
|
+
initialSamples,
|
|
2241
|
+
initialSamplesAsOf,
|
|
2242
|
+
onReconnect
|
|
2961
2243
|
}
|
|
2962
2244
|
) });
|
|
2963
2245
|
}
|
|
2246
|
+
function useDatasourceSupported(hub, datasource) {
|
|
2247
|
+
const key = datasource ? JSON.stringify(datasource) : null;
|
|
2248
|
+
const [refused, setRefused] = useState5(null);
|
|
2249
|
+
useEffect3(() => {
|
|
2250
|
+
if (!datasource || !hub.isDatasourceSupported) return;
|
|
2251
|
+
let cancelled = false;
|
|
2252
|
+
hub.isDatasourceSupported(datasource).then(
|
|
2253
|
+
(ok) => {
|
|
2254
|
+
if (!cancelled) setRefused(ok ? null : key);
|
|
2255
|
+
},
|
|
2256
|
+
() => {
|
|
2257
|
+
if (!cancelled) setRefused(null);
|
|
2258
|
+
}
|
|
2259
|
+
);
|
|
2260
|
+
return () => {
|
|
2261
|
+
cancelled = true;
|
|
2262
|
+
};
|
|
2263
|
+
}, [hub, key]);
|
|
2264
|
+
return refused === null || refused !== key;
|
|
2265
|
+
}
|
|
2964
2266
|
function HostScope({
|
|
2965
2267
|
descriptor,
|
|
2966
2268
|
actions,
|
|
2967
2269
|
children
|
|
2968
2270
|
}) {
|
|
2969
2271
|
const report = useReportRejection();
|
|
2970
|
-
const select =
|
|
2272
|
+
const select = useWidgetSelect();
|
|
2971
2273
|
const candidates = useWidgetCandidates();
|
|
2972
|
-
const narrowed =
|
|
2973
|
-
const narrowedSelect =
|
|
2974
|
-
const narrowedCandidates =
|
|
2274
|
+
const narrowed = useMemo4(() => narrowActions(actions, descriptor, report), [actions, descriptor, report]);
|
|
2275
|
+
const narrowedSelect = useMemo4(() => narrowSelect(select, descriptor), [select, descriptor]);
|
|
2276
|
+
const narrowedCandidates = useMemo4(
|
|
2975
2277
|
() => narrowCandidates(candidates, descriptor, report),
|
|
2976
2278
|
[candidates, descriptor, report]
|
|
2977
2279
|
);
|
|
2978
|
-
return /* @__PURE__ */
|
|
2280
|
+
return /* @__PURE__ */ jsx11(WidgetSelectProvider, { select: narrowedSelect, children: /* @__PURE__ */ jsx11(WidgetCandidatesProvider, { candidates: narrowedCandidates, children: children(narrowed) }) });
|
|
2979
2281
|
}
|
|
2980
2282
|
function ChannelBody(props) {
|
|
2981
2283
|
switch (props.descriptor.channel) {
|
|
2982
2284
|
case "alarm":
|
|
2983
|
-
return /* @__PURE__ */
|
|
2285
|
+
return /* @__PURE__ */ jsx11(AlarmConnectedWidget, { ...props });
|
|
2984
2286
|
case "control":
|
|
2985
|
-
return /* @__PURE__ */
|
|
2287
|
+
return /* @__PURE__ */ jsx11(ControlConnectedWidget, { ...props });
|
|
2986
2288
|
case "location":
|
|
2987
|
-
return /* @__PURE__ */
|
|
2289
|
+
return /* @__PURE__ */ jsx11(LocationConnectedWidget, { ...props });
|
|
2988
2290
|
case "aggregate":
|
|
2989
|
-
return /* @__PURE__ */
|
|
2291
|
+
return /* @__PURE__ */ jsx11(AggregateConnectedWidget, { ...props });
|
|
2990
2292
|
case "selection":
|
|
2991
2293
|
case "none":
|
|
2992
|
-
return /* @__PURE__ */
|
|
2294
|
+
return /* @__PURE__ */ jsx11(StaticConnectedWidget, { ...props });
|
|
2993
2295
|
case "measurement":
|
|
2994
|
-
return /* @__PURE__ */
|
|
2296
|
+
return /* @__PURE__ */ jsx11(MeasurementConnectedWidget, { ...props });
|
|
2995
2297
|
}
|
|
2996
2298
|
}
|
|
2997
2299
|
function StaticConnectedWidget({ widget, Component: Component2, actions }) {
|
|
2998
|
-
return /* @__PURE__ */
|
|
2300
|
+
return /* @__PURE__ */ jsx11(Component2, { widget, data: null, actions });
|
|
2999
2301
|
}
|
|
3000
|
-
var FleetFeed = lazyChunk(() => import("./chunks/fleet-feed-
|
|
2302
|
+
var FleetFeed = lazyChunk(() => import("./chunks/fleet-feed-5QGDLOV5.js")).component("default");
|
|
3001
2303
|
function MeasurementConnectedWidget(props) {
|
|
3002
2304
|
const { widget, hub, descriptor, Component: Component2, actions } = props;
|
|
3003
2305
|
const members = membersMode(descriptor, widget);
|
|
3004
2306
|
if (members || widget.datasource?.kind === "anchor") {
|
|
3005
|
-
return /* @__PURE__ */
|
|
2307
|
+
return /* @__PURE__ */ jsx11(FleetFeed, { hub, widget, descriptor, Component: Component2, actions, ErrorFrame: WidgetErrorFrame, refuse: !members });
|
|
3006
2308
|
}
|
|
3007
|
-
return /* @__PURE__ */
|
|
2309
|
+
return /* @__PURE__ */ jsx11(StreamConnectedWidget, { ...props });
|
|
3008
2310
|
}
|
|
3009
|
-
function StreamConnectedWidget({ widget, hub, descriptor, Component: Component2, actions, initialSamples }) {
|
|
2311
|
+
function StreamConnectedWidget({ widget, hub, descriptor, Component: Component2, actions, initialSamples, initialSamplesAsOf, onReconnect }) {
|
|
3010
2312
|
const range = useWidgetTimeRange2();
|
|
3011
|
-
const now =
|
|
2313
|
+
const now = useMemo4(() => hub.now ? () => hub.now() : Date.now, [hub]);
|
|
3012
2314
|
const data = useMeasurementStream(hub, widget.datasource, {
|
|
3013
2315
|
window: measurementWindow(descriptor, widget),
|
|
3014
2316
|
windowSeconds: measurementSpan(descriptor, widget, range?.spanSeconds),
|
|
3015
2317
|
pausedAt: range?.paused ? range.pausedAt : void 0,
|
|
3016
2318
|
now,
|
|
3017
|
-
initialSamples
|
|
2319
|
+
initialSamples,
|
|
2320
|
+
initialSamplesAsOf,
|
|
2321
|
+
onReconnect
|
|
3018
2322
|
});
|
|
3019
|
-
const freshness =
|
|
2323
|
+
const freshness = useMemo4(() => {
|
|
3020
2324
|
if (descriptor.freshness !== true) return void 0;
|
|
3021
|
-
const pinned =
|
|
2325
|
+
const pinned = optString7(widget.options, "measurement");
|
|
3022
2326
|
const names = pinned ? [pinned] : widget.datasource?.measurements;
|
|
3023
2327
|
return {
|
|
3024
2328
|
at: newestSampleTime(data.latest, names),
|
|
3025
2329
|
staleAfterSeconds: resolveStaleAfterSeconds(widget.options)
|
|
3026
2330
|
};
|
|
3027
2331
|
}, [descriptor, widget.options, widget.datasource, data.latest]);
|
|
3028
|
-
if (data.error) return /* @__PURE__ */
|
|
3029
|
-
return /* @__PURE__ */
|
|
2332
|
+
if (data.error) return /* @__PURE__ */ jsx11(WidgetErrorFrame, { widget, error: data.error });
|
|
2333
|
+
return /* @__PURE__ */ jsx11(WidgetFreshnessProvider, { freshness, children: /* @__PURE__ */ jsx11(Component2, { widget, data, actions }) });
|
|
3030
2334
|
}
|
|
3031
|
-
var AggregateFeed = lazyChunk(() => import("./chunks/aggregate-feed-
|
|
2335
|
+
var AggregateFeed = lazyChunk(() => import("./chunks/aggregate-feed-BD3CHNFU.js")).component("default");
|
|
3032
2336
|
function AggregateConnectedWidget({ widget, hub, descriptor, Component: Component2, actions }) {
|
|
3033
2337
|
const props = { hub, widget, descriptor, Component: Component2, actions, ErrorFrame: WidgetErrorFrame };
|
|
3034
|
-
return widget.datasource?.kind === "anchor" ? /* @__PURE__ */
|
|
2338
|
+
return widget.datasource?.kind === "anchor" ? /* @__PURE__ */ jsx11(FleetFeed, { ...props, refuse: true }) : /* @__PURE__ */ jsx11(AggregateFeed, { ...props });
|
|
3035
2339
|
}
|
|
3036
2340
|
function AlarmConnectedWidget({ widget, hub, descriptor, Component: Component2, actions }) {
|
|
3037
2341
|
const range = useWidgetTimeRange2();
|
|
3038
2342
|
const live = useAlarmStream(hub, alarmSubscription(descriptor, widget));
|
|
3039
2343
|
const data = useHeld(live, range?.paused === true, (s) => !s.loading);
|
|
3040
2344
|
if (data.error && data.alarms.length === 0 && data.total === 0) {
|
|
3041
|
-
return /* @__PURE__ */
|
|
2345
|
+
return /* @__PURE__ */ jsx11(WidgetErrorFrame, { widget, error: data.error });
|
|
3042
2346
|
}
|
|
3043
|
-
return /* @__PURE__ */
|
|
2347
|
+
return /* @__PURE__ */ jsx11(Component2, { widget, data, actions });
|
|
3044
2348
|
}
|
|
3045
2349
|
function ControlConnectedWidget({ widget, hub, descriptor, Component: Component2, actions }) {
|
|
3046
2350
|
const data = useCommandStream(hub, commandSubscription(descriptor, widget));
|
|
3047
|
-
return /* @__PURE__ */
|
|
2351
|
+
return /* @__PURE__ */ jsx11(Component2, { widget, data, actions });
|
|
3048
2352
|
}
|
|
3049
2353
|
function LocationConnectedWidget({ widget, hub, Component: Component2, actions }) {
|
|
3050
2354
|
const range = useWidgetTimeRange2();
|
|
3051
2355
|
const live = useLocationStream(hub, { datasource: widget.datasource });
|
|
3052
2356
|
const data = useHeld(live, range?.paused === true, (s) => !s.loading);
|
|
3053
2357
|
if (data.error && data.locations.length === 0) {
|
|
3054
|
-
return /* @__PURE__ */
|
|
2358
|
+
return /* @__PURE__ */ jsx11(WidgetErrorFrame, { widget, error: data.error });
|
|
3055
2359
|
}
|
|
3056
|
-
return /* @__PURE__ */
|
|
2360
|
+
return /* @__PURE__ */ jsx11(Component2, { widget, data, actions });
|
|
3057
2361
|
}
|
|
2362
|
+
var STATE_STYLE = {
|
|
2363
|
+
display: "flex",
|
|
2364
|
+
flexDirection: "column",
|
|
2365
|
+
alignItems: "center",
|
|
2366
|
+
justifyContent: "center",
|
|
2367
|
+
gap: 4,
|
|
2368
|
+
width: "100%",
|
|
2369
|
+
height: "100%",
|
|
2370
|
+
padding: 12,
|
|
2371
|
+
boxSizing: "border-box",
|
|
2372
|
+
textAlign: "center",
|
|
2373
|
+
color: "hsl(var(--muted-foreground))"
|
|
2374
|
+
};
|
|
3058
2375
|
function UnresolvedWidgetFrame({
|
|
3059
2376
|
storedType: stored,
|
|
3060
2377
|
reason
|
|
3061
2378
|
}) {
|
|
3062
2379
|
const storedType = typeof stored === "string" ? stored : "";
|
|
3063
2380
|
const heading = (reason?.code ?? "unregistered") === "unregistered" ? "This widget needs a newer viewer" : "This widget cannot be shown here";
|
|
3064
|
-
return /* @__PURE__ */
|
|
2381
|
+
return /* @__PURE__ */ jsx11(WidgetFrame8, { children: /* @__PURE__ */ jsxs6(
|
|
3065
2382
|
"div",
|
|
3066
2383
|
{
|
|
3067
|
-
style:
|
|
3068
|
-
display: "flex",
|
|
3069
|
-
flexDirection: "column",
|
|
3070
|
-
alignItems: "center",
|
|
3071
|
-
justifyContent: "center",
|
|
3072
|
-
gap: 4,
|
|
3073
|
-
width: "100%",
|
|
3074
|
-
height: "100%",
|
|
3075
|
-
padding: 12,
|
|
3076
|
-
boxSizing: "border-box",
|
|
3077
|
-
textAlign: "center",
|
|
3078
|
-
color: "hsl(var(--muted-foreground))"
|
|
3079
|
-
},
|
|
2384
|
+
style: STATE_STYLE,
|
|
3080
2385
|
children: [
|
|
3081
|
-
/* @__PURE__ */
|
|
3082
|
-
storedType && !reason?.message.includes(storedType) && /* @__PURE__ */
|
|
2386
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 13, fontWeight: 600 }, children: heading }),
|
|
2387
|
+
storedType && !reason?.message.includes(storedType) && /* @__PURE__ */ jsxs6("div", { style: { fontSize: 11, opacity: 0.8 }, children: [
|
|
3083
2388
|
"Widget type: ",
|
|
3084
2389
|
storedType
|
|
3085
2390
|
] }),
|
|
3086
|
-
reason && /* @__PURE__ */
|
|
2391
|
+
reason && /* @__PURE__ */ jsx11("div", { style: { fontSize: 11, opacity: 0.8, wordBreak: "break-word" }, children: reason.message })
|
|
3087
2392
|
]
|
|
3088
2393
|
}
|
|
3089
2394
|
) });
|
|
3090
2395
|
}
|
|
2396
|
+
function WidgetForbiddenFrame({ widget }) {
|
|
2397
|
+
return /* @__PURE__ */ jsx11(WidgetFrame8, { title: optString7(widget.options, "title"), children: /* @__PURE__ */ jsxs6("div", { role: "status", style: STATE_STYLE, children: [
|
|
2398
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 20, lineHeight: 1 }, "aria-hidden": "true", children: "\u2298" }),
|
|
2399
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 13, fontWeight: 600 }, children: accessStrings().forbidden })
|
|
2400
|
+
] }) });
|
|
2401
|
+
}
|
|
3091
2402
|
function WidgetUnavailableFrame({ widget }) {
|
|
3092
|
-
return /* @__PURE__ */
|
|
2403
|
+
return /* @__PURE__ */ jsx11(WidgetFrame8, { title: optString7(widget.options, "title"), children: /* @__PURE__ */ jsxs6(
|
|
3093
2404
|
"div",
|
|
3094
2405
|
{
|
|
3095
|
-
style:
|
|
3096
|
-
display: "flex",
|
|
3097
|
-
flexDirection: "column",
|
|
3098
|
-
alignItems: "center",
|
|
3099
|
-
justifyContent: "center",
|
|
3100
|
-
gap: 4,
|
|
3101
|
-
width: "100%",
|
|
3102
|
-
height: "100%",
|
|
3103
|
-
padding: 12,
|
|
3104
|
-
boxSizing: "border-box",
|
|
3105
|
-
textAlign: "center",
|
|
3106
|
-
color: "hsl(var(--muted-foreground))"
|
|
3107
|
-
},
|
|
2406
|
+
style: STATE_STYLE,
|
|
3108
2407
|
children: [
|
|
3109
|
-
/* @__PURE__ */
|
|
3110
|
-
/* @__PURE__ */
|
|
3111
|
-
/* @__PURE__ */
|
|
2408
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 20, lineHeight: 1 }, "aria-hidden": "true", children: "\u2298" }),
|
|
2409
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 13, fontWeight: 600 }, children: "Device unavailable" }),
|
|
2410
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 11, opacity: 0.8 }, children: "The bound device no longer exists." })
|
|
2411
|
+
]
|
|
2412
|
+
}
|
|
2413
|
+
) });
|
|
2414
|
+
}
|
|
2415
|
+
function WidgetNotForCustomerUsersFrame({ widget }) {
|
|
2416
|
+
return /* @__PURE__ */ jsx11(WidgetFrame8, { title: optString7(widget.options, "title"), children: /* @__PURE__ */ jsxs6(
|
|
2417
|
+
"div",
|
|
2418
|
+
{
|
|
2419
|
+
role: "status",
|
|
2420
|
+
style: STATE_STYLE,
|
|
2421
|
+
children: [
|
|
2422
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 20, lineHeight: 1 }, "aria-hidden": "true", children: "\u2298" }),
|
|
2423
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 13, fontWeight: 600 }, children: "Not available for customer users" }),
|
|
2424
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 11, opacity: 0.8 }, children: "This widget is bound to an area or an asset, which customer users cannot view." })
|
|
3112
2425
|
]
|
|
3113
2426
|
}
|
|
3114
2427
|
) });
|
|
3115
2428
|
}
|
|
3116
2429
|
function WidgetErrorFrame({ widget, error }) {
|
|
3117
|
-
return /* @__PURE__ */
|
|
2430
|
+
if (isForbiddenError(error)) return /* @__PURE__ */ jsx11(WidgetForbiddenFrame, { widget });
|
|
2431
|
+
return /* @__PURE__ */ jsx11(WidgetFrame8, { title: optString7(widget.options, "title"), children: /* @__PURE__ */ jsxs6(
|
|
3118
2432
|
"div",
|
|
3119
2433
|
{
|
|
3120
|
-
style:
|
|
3121
|
-
display: "flex",
|
|
3122
|
-
flexDirection: "column",
|
|
3123
|
-
alignItems: "center",
|
|
3124
|
-
justifyContent: "center",
|
|
3125
|
-
gap: 4,
|
|
3126
|
-
width: "100%",
|
|
3127
|
-
height: "100%",
|
|
3128
|
-
padding: 12,
|
|
3129
|
-
boxSizing: "border-box",
|
|
3130
|
-
textAlign: "center",
|
|
3131
|
-
color: "hsl(var(--muted-foreground))"
|
|
3132
|
-
},
|
|
2434
|
+
style: STATE_STYLE,
|
|
3133
2435
|
children: [
|
|
3134
|
-
/* @__PURE__ */
|
|
3135
|
-
/* @__PURE__ */
|
|
3136
|
-
/* @__PURE__ */
|
|
2436
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 20, lineHeight: 1 }, children: "\u26A0" }),
|
|
2437
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 13, fontWeight: 600 }, children: "Data unavailable" }),
|
|
2438
|
+
/* @__PURE__ */ jsx11("div", { style: { fontSize: 11, opacity: 0.8, wordBreak: "break-word" }, children: String(error) })
|
|
3137
2439
|
]
|
|
3138
2440
|
}
|
|
3139
2441
|
) });
|
|
@@ -3147,7 +2449,7 @@ import {
|
|
|
3147
2449
|
WidgetThemeRootProvider,
|
|
3148
2450
|
WidgetTimeZoneProvider
|
|
3149
2451
|
} from "@devicechain/widget-sdk";
|
|
3150
|
-
import { Fragment as
|
|
2452
|
+
import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3151
2453
|
function DashboardRenderer({
|
|
3152
2454
|
definition,
|
|
3153
2455
|
hub,
|
|
@@ -3163,14 +2465,14 @@ function DashboardRenderer({
|
|
|
3163
2465
|
density,
|
|
3164
2466
|
timeRange
|
|
3165
2467
|
}) {
|
|
3166
|
-
const widgets =
|
|
2468
|
+
const widgets = useMemo5(() => resolveWidgets(definition.widgets, bindings), [definition.widgets, bindings]);
|
|
3167
2469
|
const registry = registryProp ?? defaultWidgetRegistry();
|
|
3168
2470
|
const defaultSeconds = definition.timeRange?.defaultSeconds;
|
|
3169
|
-
const range =
|
|
2471
|
+
const range = useMemo5(
|
|
3170
2472
|
() => timeRange ?? initialTimeRange(defaultSeconds),
|
|
3171
2473
|
[timeRange, defaultSeconds]
|
|
3172
2474
|
);
|
|
3173
|
-
const histories = useWidgetHistories(widgets, seedHistory, registry, range);
|
|
2475
|
+
const { histories, reseed } = useWidgetHistories(widgets, seedHistory, registry, range);
|
|
3174
2476
|
const { grid, background: bg, frame: canvasFrame } = definition.canvas;
|
|
3175
2477
|
const effectiveSizing = sizing ?? definition.canvas.sizing;
|
|
3176
2478
|
const effectiveDensity = density ?? definition.canvas.density ?? DEFAULT_CANVAS_DENSITY;
|
|
@@ -3178,7 +2480,7 @@ function DashboardRenderer({
|
|
|
3178
2480
|
const { canvas } = definition;
|
|
3179
2481
|
const shapeKey = useCallback2((width) => JSON.stringify(layoutShape(canvas, width, scale)), [canvas, scale]);
|
|
3180
2482
|
const [boardRef, containerWidth] = useContainerWidth(shapeKey);
|
|
3181
|
-
const layout =
|
|
2483
|
+
const layout = useMemo5(
|
|
3182
2484
|
() => effectiveLayout(definition, containerWidth, {
|
|
3183
2485
|
scale,
|
|
3184
2486
|
limitsOf: (w) => w.type === UNKNOWN_WIDGET_TYPE2 ? void 0 : spanLimitsOfLayout(registry.descriptor(w.type)?.layout)
|
|
@@ -3187,7 +2489,7 @@ function DashboardRenderer({
|
|
|
3187
2489
|
);
|
|
3188
2490
|
const { breakpoint, columns } = layout;
|
|
3189
2491
|
const lengths = gridCss(grid, columns);
|
|
3190
|
-
return /* @__PURE__ */
|
|
2492
|
+
return /* @__PURE__ */ jsxs7(
|
|
3191
2493
|
"div",
|
|
3192
2494
|
{
|
|
3193
2495
|
ref: boardRef,
|
|
@@ -3196,8 +2498,8 @@ function DashboardRenderer({
|
|
|
3196
2498
|
"data-time-paused": range.paused ? "" : void 0,
|
|
3197
2499
|
style: { ...sizingStyle(effectiveSizing, bg), ...tokenStyle(scale) },
|
|
3198
2500
|
children: [
|
|
3199
|
-
/* @__PURE__ */
|
|
3200
|
-
/* @__PURE__ */
|
|
2501
|
+
/* @__PURE__ */ jsx12(WidgetTokenStyles, {}),
|
|
2502
|
+
/* @__PURE__ */ jsx12(WidgetDensityProvider, { scale, children: /* @__PURE__ */ jsx12(WidgetThemeRootProvider, { root: themeRoot, children: /* @__PURE__ */ jsx12(WidgetTimeZoneProvider, { timeZone, children: /* @__PURE__ */ jsx12(WidgetTimeRangeProvider, { range, children: /* @__PURE__ */ jsx12(WidgetSelectProvider2, { select, children: /* @__PURE__ */ jsx12(WidgetCandidatesProvider2, { candidates, children: /* @__PURE__ */ jsx12("div", { style: { padding: lengths.padding }, children: /* @__PURE__ */ jsx12("div", { style: { containerType: "inline-size" }, children: /* @__PURE__ */ jsx12(
|
|
3201
2503
|
"div",
|
|
3202
2504
|
{
|
|
3203
2505
|
"data-grid": "",
|
|
@@ -3210,7 +2512,7 @@ function DashboardRenderer({
|
|
|
3210
2512
|
width: "100%",
|
|
3211
2513
|
...{ "--dc-cell": lengths.cell }
|
|
3212
2514
|
},
|
|
3213
|
-
children: /* @__PURE__ */
|
|
2515
|
+
children: /* @__PURE__ */ jsx12(
|
|
3214
2516
|
PlacedWidgets,
|
|
3215
2517
|
{
|
|
3216
2518
|
widgets,
|
|
@@ -3218,14 +2520,16 @@ function DashboardRenderer({
|
|
|
3218
2520
|
columns,
|
|
3219
2521
|
grid: layout.grid,
|
|
3220
2522
|
lengths,
|
|
3221
|
-
render: (widget) => /* @__PURE__ */
|
|
2523
|
+
render: (widget) => /* @__PURE__ */ jsx12(WidgetFrameStyleProvider, { frame: resolveFrame(canvasFrame, widgetFrame(widget)), children: /* @__PURE__ */ jsx12(WidgetSubjectProvider, { label: widgetSubjectLabel(widget), children: /* @__PURE__ */ jsx12(
|
|
3222
2524
|
ConnectedWidget,
|
|
3223
2525
|
{
|
|
3224
2526
|
widget,
|
|
3225
2527
|
hub,
|
|
3226
2528
|
registry,
|
|
3227
2529
|
actions,
|
|
3228
|
-
initialSamples: histories[widget.id]
|
|
2530
|
+
initialSamples: histories[widget.id]?.samples,
|
|
2531
|
+
initialSamplesAsOf: histories[widget.id]?.asOf,
|
|
2532
|
+
onReconnect: () => reseed(widget.id)
|
|
3229
2533
|
}
|
|
3230
2534
|
) }) })
|
|
3231
2535
|
}
|
|
@@ -3299,20 +2603,20 @@ function PlacedWidgets({
|
|
|
3299
2603
|
const relative = (host) => (dependents.get(host) ?? []).map(({ widget, placement }) => (
|
|
3300
2604
|
// data-widget names the box a widget occupies, so a check over the rendered board (the
|
|
3301
2605
|
// readability gate in apps/board-replay) can find it.
|
|
3302
|
-
/* @__PURE__ */
|
|
2606
|
+
/* @__PURE__ */ jsxs7("div", { "data-widget": widget.id, "data-host": host, style: relativeBoxStyle(placement, lengths), children: [
|
|
3303
2607
|
render(widget),
|
|
3304
2608
|
relative(widget.id)
|
|
3305
2609
|
] }, widget.id)
|
|
3306
2610
|
));
|
|
3307
|
-
return /* @__PURE__ */
|
|
2611
|
+
return /* @__PURE__ */ jsx12(Fragment2, { children: placed.map(({ widget, placement }) => {
|
|
3308
2612
|
if (placement.mode !== "grid") return null;
|
|
3309
2613
|
const style = gridItemStyle(grid.get(widget.id) ?? placement, columns);
|
|
3310
|
-
return /* @__PURE__ */
|
|
3311
|
-
/* @__PURE__ */
|
|
2614
|
+
return /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
2615
|
+
/* @__PURE__ */ jsx12("div", { "data-widget": widget.id, style, children: render(widget) }),
|
|
3312
2616
|
dependents.has(widget.id) ? (
|
|
3313
2617
|
// The host's area again, as a layer for its relative widgets to be positioned in.
|
|
3314
2618
|
// It takes no pointer events itself, so the host underneath stays usable.
|
|
3315
|
-
/* @__PURE__ */
|
|
2619
|
+
/* @__PURE__ */ jsx12("div", { style: { ...style, position: "relative", pointerEvents: "none", zIndex: RELATIVE_Z }, children: relative(widget.id) })
|
|
3316
2620
|
) : null
|
|
3317
2621
|
] }, widget.id);
|
|
3318
2622
|
}) });
|
|
@@ -3342,9 +2646,9 @@ function widgetSubjectLabel(widget) {
|
|
|
3342
2646
|
return void 0;
|
|
3343
2647
|
}
|
|
3344
2648
|
function useContainerWidth(keyOf) {
|
|
3345
|
-
const ref =
|
|
3346
|
-
const [width, setWidth] =
|
|
3347
|
-
const keyOfRef =
|
|
2649
|
+
const ref = useRef2(null);
|
|
2650
|
+
const [width, setWidth] = useState6(0);
|
|
2651
|
+
const keyOfRef = useRef2(keyOf);
|
|
3348
2652
|
const measure = useCallback2(() => {
|
|
3349
2653
|
const el = ref.current;
|
|
3350
2654
|
if (!el) return;
|
|
@@ -3364,6 +2668,7 @@ function useContainerWidth(keyOf) {
|
|
|
3364
2668
|
}, [measure]);
|
|
3365
2669
|
return [ref, width];
|
|
3366
2670
|
}
|
|
2671
|
+
var RESEED_RETRY_MS = 3e4;
|
|
3367
2672
|
function seedKey(widget, registry) {
|
|
3368
2673
|
if (widget.type === UNKNOWN_WIDGET_TYPE2 || registry.descriptor(widget.type)?.channel !== "measurement") {
|
|
3369
2674
|
return void 0;
|
|
@@ -3371,15 +2676,21 @@ function seedKey(widget, registry) {
|
|
|
3371
2676
|
return JSON.stringify(widget.datasource ?? null);
|
|
3372
2677
|
}
|
|
3373
2678
|
function useWidgetHistories(widgets, enabled, registry, range) {
|
|
3374
|
-
const [seeds, setSeeds] =
|
|
3375
|
-
const requested =
|
|
3376
|
-
const
|
|
3377
|
-
|
|
2679
|
+
const [seeds, setSeeds] = useState6({});
|
|
2680
|
+
const requested = useRef2({});
|
|
2681
|
+
const reseeds = useRef2({});
|
|
2682
|
+
const [reseedTick, bumpReseeds] = useState6(0);
|
|
2683
|
+
const mounted = useRef2(true);
|
|
2684
|
+
useEffect4(() => {
|
|
3378
2685
|
mounted.current = true;
|
|
3379
2686
|
return () => {
|
|
3380
2687
|
mounted.current = false;
|
|
3381
2688
|
};
|
|
3382
2689
|
}, []);
|
|
2690
|
+
const reseed = useCallback2((id) => {
|
|
2691
|
+
reseeds.current[id] = (reseeds.current[id] ?? 0) + 1;
|
|
2692
|
+
bumpReseeds((n) => n + 1);
|
|
2693
|
+
}, []);
|
|
3383
2694
|
const wanted = widgets.flatMap((w) => {
|
|
3384
2695
|
const key = seedKey(w, registry);
|
|
3385
2696
|
if (key === void 0) return [];
|
|
@@ -3388,7 +2699,7 @@ function useWidgetHistories(widgets, enabled, registry, range) {
|
|
|
3388
2699
|
return [[w.id, key, span]];
|
|
3389
2700
|
});
|
|
3390
2701
|
const wantedKey = JSON.stringify(wanted);
|
|
3391
|
-
|
|
2702
|
+
useEffect4(() => {
|
|
3392
2703
|
if (!enabled) {
|
|
3393
2704
|
requested.current = {};
|
|
3394
2705
|
setSeeds({});
|
|
@@ -3398,28 +2709,42 @@ function useWidgetHistories(widgets, enabled, registry, range) {
|
|
|
3398
2709
|
const byId = new Map(widgets.map((w) => [w.id, w]));
|
|
3399
2710
|
const next = {};
|
|
3400
2711
|
for (const [id, key, span] of wanted) {
|
|
3401
|
-
const
|
|
2712
|
+
const base = `${key}|${span ?? ""}|`;
|
|
2713
|
+
const n = reseeds.current[id] ?? 0;
|
|
2714
|
+
const asked = `${base}${range.paused && n ? "p" : n}`;
|
|
2715
|
+
const previous = requested.current[id];
|
|
2716
|
+
if (previous === asked || range.paused && previous?.startsWith(base)) {
|
|
2717
|
+
next[id] = previous;
|
|
2718
|
+
continue;
|
|
2719
|
+
}
|
|
3402
2720
|
next[id] = asked;
|
|
3403
|
-
if (requested.current[id] === asked) continue;
|
|
3404
2721
|
const widget = byId.get(id);
|
|
3405
|
-
if (
|
|
3406
|
-
const
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
2722
|
+
if (widget?.datasource?.kind !== "device") continue;
|
|
2723
|
+
const end = range.paused && range.pausedAt !== void 0 ? range.pausedAt : now;
|
|
2724
|
+
const historyWindow = span === null ? defaultHistoryWindow() : historyWindowFor(span, end);
|
|
2725
|
+
const current = () => mounted.current && requested.current[id] === asked;
|
|
2726
|
+
void fetchWidgetHistory(widget, historyWindow, { rethrow: n > 0 }).then(
|
|
2727
|
+
(samples) => {
|
|
2728
|
+
if (!current()) return;
|
|
2729
|
+
setSeeds((prev) => ({ ...prev, [id]: { key, samples, asOf: end } }));
|
|
2730
|
+
},
|
|
2731
|
+
() => {
|
|
2732
|
+
setTimeout(() => current() && reseed(id), RESEED_RETRY_MS);
|
|
2733
|
+
}
|
|
2734
|
+
);
|
|
3411
2735
|
}
|
|
3412
2736
|
requested.current = next;
|
|
3413
|
-
}, [wantedKey, enabled]);
|
|
3414
|
-
|
|
2737
|
+
}, [wantedKey, enabled, reseedTick, range.paused]);
|
|
2738
|
+
const histories = useMemo5(() => {
|
|
3415
2739
|
const out = {};
|
|
3416
2740
|
if (!enabled) return out;
|
|
3417
2741
|
for (const w of widgets) {
|
|
3418
2742
|
const seed = seeds[w.id];
|
|
3419
|
-
out[w.id] = seed && seed.key === seedKey(w, registry) ? seed
|
|
2743
|
+
out[w.id] = seed && seed.key === seedKey(w, registry) ? seed : void 0;
|
|
3420
2744
|
}
|
|
3421
2745
|
return out;
|
|
3422
2746
|
}, [widgets, seeds, enabled, registry]);
|
|
2747
|
+
return { histories, reseed };
|
|
3423
2748
|
}
|
|
3424
2749
|
|
|
3425
2750
|
// src/time-range-bar.tsx
|
|
@@ -3434,17 +2759,17 @@ import {
|
|
|
3434
2759
|
spanLabel as spanLabel2,
|
|
3435
2760
|
withSpan
|
|
3436
2761
|
} from "@devicechain/dashboards";
|
|
3437
|
-
import { useCallback as useCallback3, useEffect as
|
|
3438
|
-
import { jsx as
|
|
2762
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo6, useRef as useRef3, useState as useState7 } from "react";
|
|
2763
|
+
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3439
2764
|
function useBoardTimeRange(defaultSeconds, link = {}) {
|
|
3440
|
-
const [state, setState] =
|
|
3441
|
-
const lastDefault =
|
|
3442
|
-
|
|
2765
|
+
const [state, setState] = useState7(() => initialTimeRange2(defaultSeconds, link));
|
|
2766
|
+
const lastDefault = useRef3(defaultSeconds);
|
|
2767
|
+
useEffect5(() => {
|
|
3443
2768
|
if (lastDefault.current === defaultSeconds) return;
|
|
3444
2769
|
lastDefault.current = defaultSeconds;
|
|
3445
2770
|
setState((s) => withSpan(s, isValidSpanSeconds2(defaultSeconds) ? defaultSeconds : DEFAULT_TIME_RANGE_SECONDS));
|
|
3446
2771
|
}, [defaultSeconds]);
|
|
3447
|
-
const controls =
|
|
2772
|
+
const controls = useMemo6(
|
|
3448
2773
|
() => ({
|
|
3449
2774
|
setSpan: (spanSeconds) => setState((s) => withSpan(s, spanSeconds)),
|
|
3450
2775
|
pause: () => setState((s) => pauseRange(s, Date.now())),
|
|
@@ -3477,7 +2802,7 @@ function PausedIndicator({
|
|
|
3477
2802
|
labels = DEFAULT_TIME_RANGE_LABELS
|
|
3478
2803
|
}) {
|
|
3479
2804
|
const time = pausedAt === void 0 ? void 0 : new Date(pausedAt).toLocaleTimeString();
|
|
3480
|
-
return /* @__PURE__ */
|
|
2805
|
+
return /* @__PURE__ */ jsxs8(
|
|
3481
2806
|
"span",
|
|
3482
2807
|
{
|
|
3483
2808
|
role: "status",
|
|
@@ -3498,10 +2823,10 @@ function PausedIndicator({
|
|
|
3498
2823
|
borderRadius: 4
|
|
3499
2824
|
},
|
|
3500
2825
|
children: [
|
|
3501
|
-
/* @__PURE__ */
|
|
2826
|
+
/* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: "\u23F8" }),
|
|
3502
2827
|
labels.paused,
|
|
3503
|
-
time ? /* @__PURE__ */
|
|
3504
|
-
/* @__PURE__ */
|
|
2828
|
+
time ? /* @__PURE__ */ jsx13("span", { style: { fontWeight: 400, textTransform: "none" }, children: ` ${time}` }) : null,
|
|
2829
|
+
/* @__PURE__ */ jsx13("span", { "data-time-range-actions-live": "", style: { fontWeight: 400, textTransform: "none" }, children: `\xB7 ${labels.actionsLive}` })
|
|
3505
2830
|
]
|
|
3506
2831
|
}
|
|
3507
2832
|
);
|
|
@@ -3513,7 +2838,7 @@ function TimeRangeBar({
|
|
|
3513
2838
|
}) {
|
|
3514
2839
|
const preset = presetIdOf(state.spanSeconds);
|
|
3515
2840
|
const onPause = useCallback3(() => state.paused ? controls.resume() : controls.pause(), [state.paused, controls]);
|
|
3516
|
-
return /* @__PURE__ */
|
|
2841
|
+
return /* @__PURE__ */ jsxs8(
|
|
3517
2842
|
"div",
|
|
3518
2843
|
{
|
|
3519
2844
|
"data-time-range-bar": "",
|
|
@@ -3521,8 +2846,8 @@ function TimeRangeBar({
|
|
|
3521
2846
|
"aria-label": labels.range,
|
|
3522
2847
|
style: { display: "inline-flex", alignItems: "center", gap: 6, flexWrap: "wrap" },
|
|
3523
2848
|
children: [
|
|
3524
|
-
preset === void 0 ? /* @__PURE__ */
|
|
3525
|
-
TIME_RANGE_PRESETS.map((p) => /* @__PURE__ */
|
|
2849
|
+
preset === void 0 ? /* @__PURE__ */ jsx13("button", { type: "button", "aria-pressed": "true", "data-range": spanLabel2(state.spanSeconds), style: button(true), children: spanLabel2(state.spanSeconds) }) : null,
|
|
2850
|
+
TIME_RANGE_PRESETS.map((p) => /* @__PURE__ */ jsx13(
|
|
3526
2851
|
"button",
|
|
3527
2852
|
{
|
|
3528
2853
|
type: "button",
|
|
@@ -3534,13 +2859,23 @@ function TimeRangeBar({
|
|
|
3534
2859
|
},
|
|
3535
2860
|
p.id
|
|
3536
2861
|
)),
|
|
3537
|
-
/* @__PURE__ */
|
|
3538
|
-
state.paused ? /* @__PURE__ */
|
|
2862
|
+
/* @__PURE__ */ jsx13("button", { type: "button", "aria-pressed": state.paused, "data-time-range-pause": "", onClick: onPause, style: button(state.paused), children: state.paused ? labels.resume : labels.pause }),
|
|
2863
|
+
state.paused ? /* @__PURE__ */ jsx13(PausedIndicator, { pausedAt: state.pausedAt, labels }) : null
|
|
3539
2864
|
]
|
|
3540
2865
|
}
|
|
3541
2866
|
);
|
|
3542
2867
|
}
|
|
3543
2868
|
|
|
2869
|
+
// src/preload.ts
|
|
2870
|
+
async function preloadWidgets(registry, types) {
|
|
2871
|
+
const loads = [];
|
|
2872
|
+
for (const type of new Set(types)) {
|
|
2873
|
+
const preload = registry.implementation(type)?.component?.preload;
|
|
2874
|
+
if (typeof preload === "function") loads.push(preload().catch(() => void 0));
|
|
2875
|
+
}
|
|
2876
|
+
await Promise.all(loads);
|
|
2877
|
+
}
|
|
2878
|
+
|
|
3544
2879
|
// src/registry.ts
|
|
3545
2880
|
var entries = Object.entries(builtinWidgetDescriptors);
|
|
3546
2881
|
var WIDGET_CHANNEL = Object.freeze(
|
|
@@ -3551,7 +2886,7 @@ var WIDGET_BINDS_DATASOURCE = Object.freeze(
|
|
|
3551
2886
|
);
|
|
3552
2887
|
|
|
3553
2888
|
// src/index.ts
|
|
3554
|
-
import { pickSample as pickSample3, optBoolean as
|
|
2889
|
+
import { pickSample as pickSample3, optBoolean as optBoolean3 } from "@devicechain/widget-sdk";
|
|
3555
2890
|
|
|
3556
2891
|
// src/options.ts
|
|
3557
2892
|
import {
|
|
@@ -3625,12 +2960,12 @@ function stripUnknownWidgetOptions(widget, catalog) {
|
|
|
3625
2960
|
|
|
3626
2961
|
// src/index.ts
|
|
3627
2962
|
import {
|
|
3628
|
-
WidgetFrame as
|
|
2963
|
+
WidgetFrame as WidgetFrame9,
|
|
3629
2964
|
WidgetSubjectProvider as WidgetSubjectProvider2,
|
|
3630
2965
|
WidgetSelectProvider as WidgetSelectProvider3,
|
|
3631
|
-
useWidgetSelect as
|
|
2966
|
+
useWidgetSelect as useWidgetSelect2,
|
|
3632
2967
|
WidgetTimeZoneProvider as WidgetTimeZoneProvider2,
|
|
3633
|
-
useWidgetTimeZone as
|
|
2968
|
+
useWidgetTimeZone as useWidgetTimeZone3,
|
|
3634
2969
|
WidgetThemeRootProvider as WidgetThemeRootProvider2,
|
|
3635
2970
|
useWidgetThemeRoot,
|
|
3636
2971
|
WidgetCandidatesProvider as WidgetCandidatesProvider3,
|
|
@@ -3638,8 +2973,8 @@ import {
|
|
|
3638
2973
|
useFlashOnChange as useFlashOnChange3,
|
|
3639
2974
|
flashTextStyle as flashTextStyle2,
|
|
3640
2975
|
flashBackgroundStyle as flashBackgroundStyle2,
|
|
3641
|
-
FlashValue
|
|
3642
|
-
fitValueFont as
|
|
2976
|
+
FlashValue,
|
|
2977
|
+
fitValueFont as fitValueFont2,
|
|
3643
2978
|
useMeasurementStream as useMeasurementStream2,
|
|
3644
2979
|
useAlarmStream as useAlarmStream2,
|
|
3645
2980
|
useCommandStream as useCommandStream2,
|
|
@@ -3650,8 +2985,8 @@ import {
|
|
|
3650
2985
|
HubConnectionBadge,
|
|
3651
2986
|
useResolvedBindings,
|
|
3652
2987
|
useSlotCandidates,
|
|
3653
|
-
useCandidates
|
|
3654
|
-
css as
|
|
2988
|
+
useCandidates,
|
|
2989
|
+
css as css6
|
|
3655
2990
|
} from "@devicechain/widget-sdk";
|
|
3656
2991
|
import {
|
|
3657
2992
|
EChart as EChart3,
|
|
@@ -3670,7 +3005,7 @@ export {
|
|
|
3670
3005
|
DashboardRenderer,
|
|
3671
3006
|
EChart3 as EChart,
|
|
3672
3007
|
EntitySelector,
|
|
3673
|
-
|
|
3008
|
+
FlashValue,
|
|
3674
3009
|
Gauge,
|
|
3675
3010
|
HubConnectionBadge,
|
|
3676
3011
|
Image,
|
|
@@ -3687,7 +3022,7 @@ export {
|
|
|
3687
3022
|
WIDGET_CHANNEL,
|
|
3688
3023
|
WIDGET_OPTIONS,
|
|
3689
3024
|
WidgetCandidatesProvider3 as WidgetCandidatesProvider,
|
|
3690
|
-
|
|
3025
|
+
WidgetFrame9 as WidgetFrame,
|
|
3691
3026
|
WidgetSelectProvider3 as WidgetSelectProvider,
|
|
3692
3027
|
WidgetSubjectProvider2 as WidgetSubjectProvider,
|
|
3693
3028
|
WidgetThemeRootProvider2 as WidgetThemeRootProvider,
|
|
@@ -3702,11 +3037,11 @@ export {
|
|
|
3702
3037
|
commandStatusColor,
|
|
3703
3038
|
commandStatusLabel,
|
|
3704
3039
|
createBuiltinWidgetRegistry,
|
|
3705
|
-
|
|
3040
|
+
css6 as css,
|
|
3706
3041
|
defaultValues,
|
|
3707
3042
|
describePosition,
|
|
3708
3043
|
enumOptionValues,
|
|
3709
|
-
|
|
3044
|
+
fitValueFont2 as fitValueFont,
|
|
3710
3045
|
flashBackgroundStyle2 as flashBackgroundStyle,
|
|
3711
3046
|
flashTextStyle2 as flashTextStyle,
|
|
3712
3047
|
formatDegrees,
|
|
@@ -3716,10 +3051,11 @@ export {
|
|
|
3716
3051
|
landStyleFrom,
|
|
3717
3052
|
loadLandStyle,
|
|
3718
3053
|
numberOptionSpec,
|
|
3719
|
-
|
|
3054
|
+
optBoolean3 as optBoolean,
|
|
3720
3055
|
parseParameterSchema,
|
|
3721
3056
|
pickSample3 as pickSample,
|
|
3722
3057
|
placeable,
|
|
3058
|
+
preloadWidgets,
|
|
3723
3059
|
projectToPanel,
|
|
3724
3060
|
rasterStyleFor,
|
|
3725
3061
|
resolveChartTheme,
|
|
@@ -3730,7 +3066,7 @@ export {
|
|
|
3730
3066
|
stripUnknownOptions,
|
|
3731
3067
|
useAlarmStream2 as useAlarmStream,
|
|
3732
3068
|
useBoardTimeRange,
|
|
3733
|
-
|
|
3069
|
+
useCandidates,
|
|
3734
3070
|
useChartTheme3 as useChartTheme,
|
|
3735
3071
|
useCommandStream2 as useCommandStream,
|
|
3736
3072
|
useDashboardHub,
|
|
@@ -3744,9 +3080,9 @@ export {
|
|
|
3744
3080
|
useSlotCandidates,
|
|
3745
3081
|
useTenantBasemap,
|
|
3746
3082
|
useWidgetCandidates2 as useWidgetCandidates,
|
|
3747
|
-
|
|
3083
|
+
useWidgetSelect2 as useWidgetSelect,
|
|
3748
3084
|
useWidgetThemeRoot,
|
|
3749
|
-
|
|
3085
|
+
useWidgetTimeZone3 as useWidgetTimeZone,
|
|
3750
3086
|
validateDefinitionOptions,
|
|
3751
3087
|
validateParams,
|
|
3752
3088
|
validateWidgetOptions,
|