@procaaso/alphinity-ui-components 1.1.3 → 1.4.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 +11 -0
- package/dist/index.cjs +154 -116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +175 -100
- package/dist/index.d.ts +175 -100
- package/dist/index.js +157 -119
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -477,11 +477,12 @@ var ControlPanel = ({
|
|
|
477
477
|
secondSetpointValue,
|
|
478
478
|
onSecondSetpointChange,
|
|
479
479
|
modeConfigs = {},
|
|
480
|
-
defaultUnit
|
|
480
|
+
defaultUnit,
|
|
481
481
|
defaultLabel = "Setpoint",
|
|
482
|
-
defaultMin
|
|
483
|
-
defaultMax
|
|
484
|
-
defaultPrecision
|
|
482
|
+
defaultMin,
|
|
483
|
+
defaultMax,
|
|
484
|
+
defaultPrecision,
|
|
485
|
+
scaling,
|
|
485
486
|
status = "normal",
|
|
486
487
|
collapsed = false,
|
|
487
488
|
onCollapseChange,
|
|
@@ -503,11 +504,11 @@ var ControlPanel = ({
|
|
|
503
504
|
onCollapseChange?.(!newExpanded);
|
|
504
505
|
};
|
|
505
506
|
const currentModeConfig = modeConfigs[selectedMode] || {};
|
|
506
|
-
const currentUnit = currentModeConfig.unit || defaultUnit;
|
|
507
|
+
const currentUnit = currentModeConfig.unit || defaultUnit || scaling?.units || "Units";
|
|
507
508
|
const currentLabel = currentModeConfig.label || defaultLabel;
|
|
508
|
-
const currentMin = currentModeConfig.min ?? defaultMin;
|
|
509
|
-
const currentMax = currentModeConfig.max ?? defaultMax;
|
|
510
|
-
const currentPrecision = currentModeConfig.precision ?? defaultPrecision;
|
|
509
|
+
const currentMin = currentModeConfig.min ?? defaultMin ?? scaling?.euLow ?? 0;
|
|
510
|
+
const currentMax = currentModeConfig.max ?? defaultMax ?? scaling?.euHigh ?? 100;
|
|
511
|
+
const currentPrecision = currentModeConfig.precision ?? defaultPrecision ?? scaling?.decimals ?? 2;
|
|
511
512
|
const hasSecondSetpoint = currentModeConfig.hasSecondSetpoint || false;
|
|
512
513
|
const baseClass = "ui-control-panel";
|
|
513
514
|
const statusClass = status ? `ui-control-panel--${status}` : "";
|
|
@@ -934,8 +935,11 @@ function DeviceControlPanel({
|
|
|
934
935
|
toastDuration = 3e3,
|
|
935
936
|
onModeChange,
|
|
936
937
|
onParameterChange,
|
|
938
|
+
onParameterActivate,
|
|
937
939
|
onStart,
|
|
938
940
|
onStop,
|
|
941
|
+
startPending = false,
|
|
942
|
+
stopPending = false,
|
|
939
943
|
onCustomAction,
|
|
940
944
|
onOpenConfig,
|
|
941
945
|
showConfigButton = true,
|
|
@@ -1644,6 +1648,36 @@ function DeviceControlPanel({
|
|
|
1644
1648
|
},
|
|
1645
1649
|
children: param.options?.map((opt) => /* @__PURE__ */ jsx8("option", { value: opt.value, children: opt.label }, opt.value))
|
|
1646
1650
|
}
|
|
1651
|
+
) : onParameterActivate && !param.readOnly ? (
|
|
1652
|
+
// Tappable value: defer editing to the consumer's editor (e.g. a
|
|
1653
|
+
// numpad dialog). Commit happens via onParameterChange.
|
|
1654
|
+
/* @__PURE__ */ jsxs7(
|
|
1655
|
+
"button",
|
|
1656
|
+
{
|
|
1657
|
+
type: "button",
|
|
1658
|
+
onClick: () => onParameterActivate(param.id, localParameterValues[param.id] ?? param.value),
|
|
1659
|
+
style: {
|
|
1660
|
+
width: "100%",
|
|
1661
|
+
height: touchSize,
|
|
1662
|
+
display: "flex",
|
|
1663
|
+
alignItems: "center",
|
|
1664
|
+
backgroundColor: "#ffffff",
|
|
1665
|
+
color: textColor,
|
|
1666
|
+
border: `1px solid ${borderColor}`,
|
|
1667
|
+
borderRadius: "6px",
|
|
1668
|
+
padding: "0 12px",
|
|
1669
|
+
fontSize: `${fontSize.input}px`,
|
|
1670
|
+
fontFamily: "Arial, sans-serif",
|
|
1671
|
+
fontWeight: 600,
|
|
1672
|
+
textAlign: "left",
|
|
1673
|
+
cursor: "pointer"
|
|
1674
|
+
},
|
|
1675
|
+
children: [
|
|
1676
|
+
localParameterValues[param.id] ?? param.value,
|
|
1677
|
+
param.unit ? ` ${param.unit}` : ""
|
|
1678
|
+
]
|
|
1679
|
+
}
|
|
1680
|
+
)
|
|
1647
1681
|
) : /* @__PURE__ */ jsx8(
|
|
1648
1682
|
"input",
|
|
1649
1683
|
{
|
|
@@ -1682,11 +1716,10 @@ function DeviceControlPanel({
|
|
|
1682
1716
|
"button",
|
|
1683
1717
|
{
|
|
1684
1718
|
onClick: onStart,
|
|
1685
|
-
disabled: binding.state.isRunning,
|
|
1686
1719
|
style: {
|
|
1687
1720
|
flex: 1,
|
|
1688
1721
|
height: touchSize,
|
|
1689
|
-
backgroundColor:
|
|
1722
|
+
backgroundColor: "#10b981",
|
|
1690
1723
|
color: "#ffffff",
|
|
1691
1724
|
border: "none",
|
|
1692
1725
|
borderRadius: "6px",
|
|
@@ -1694,21 +1727,20 @@ function DeviceControlPanel({
|
|
|
1694
1727
|
fontWeight: 700,
|
|
1695
1728
|
fontFamily: "Arial, sans-serif",
|
|
1696
1729
|
letterSpacing: "0.5px",
|
|
1697
|
-
cursor:
|
|
1698
|
-
opacity:
|
|
1730
|
+
cursor: "pointer",
|
|
1731
|
+
opacity: 1
|
|
1699
1732
|
},
|
|
1700
|
-
children: "START"
|
|
1733
|
+
children: startPending ? "STARTING\u2026" : "START"
|
|
1701
1734
|
}
|
|
1702
1735
|
),
|
|
1703
1736
|
activeCapabilities?.canStop && /* @__PURE__ */ jsx8(
|
|
1704
1737
|
"button",
|
|
1705
1738
|
{
|
|
1706
1739
|
onClick: onStop,
|
|
1707
|
-
disabled: !binding.state.isRunning,
|
|
1708
1740
|
style: {
|
|
1709
1741
|
flex: 1,
|
|
1710
1742
|
height: touchSize,
|
|
1711
|
-
backgroundColor:
|
|
1743
|
+
backgroundColor: "#ef4444",
|
|
1712
1744
|
color: "#ffffff",
|
|
1713
1745
|
border: "none",
|
|
1714
1746
|
borderRadius: "6px",
|
|
@@ -1716,10 +1748,10 @@ function DeviceControlPanel({
|
|
|
1716
1748
|
fontWeight: 700,
|
|
1717
1749
|
fontFamily: "Arial, sans-serif",
|
|
1718
1750
|
letterSpacing: "0.5px",
|
|
1719
|
-
cursor:
|
|
1720
|
-
opacity:
|
|
1751
|
+
cursor: "pointer",
|
|
1752
|
+
opacity: 1
|
|
1721
1753
|
},
|
|
1722
|
-
children: "STOP"
|
|
1754
|
+
children: stopPending ? "STOPPING\u2026" : "STOP"
|
|
1723
1755
|
}
|
|
1724
1756
|
)
|
|
1725
1757
|
] }),
|
|
@@ -4354,12 +4386,13 @@ function DataOverlay({
|
|
|
4354
4386
|
scale = 1,
|
|
4355
4387
|
statusColorMap
|
|
4356
4388
|
}) {
|
|
4357
|
-
const { value, display, history } = telemetry;
|
|
4389
|
+
const { value, display, history, scaling } = telemetry;
|
|
4358
4390
|
const showValue = display?.showValue ?? true;
|
|
4359
4391
|
const showStatus = display?.showStatus ?? true;
|
|
4360
4392
|
const showSparkline = display?.showSparkline ?? false;
|
|
4361
4393
|
const label = display?.label;
|
|
4362
|
-
const precision = display?.precision;
|
|
4394
|
+
const precision = scaling?.decimals ?? display?.precision;
|
|
4395
|
+
const unit = scaling?.units ?? value.unit;
|
|
4363
4396
|
const sparklineColor = display?.sparklineColor;
|
|
4364
4397
|
const textColor = display?.textColor;
|
|
4365
4398
|
const backgroundColor = display?.backgroundColor;
|
|
@@ -4383,7 +4416,7 @@ function DataOverlay({
|
|
|
4383
4416
|
const colors = backgroundColor && backgroundColor !== "status" ? { bg: backgroundColor, text: textColor || "#ffffff", border: backgroundColor } : statusColors;
|
|
4384
4417
|
const finalTextColor = textColor || colors.text;
|
|
4385
4418
|
const formattedValue = formatValue(value.value);
|
|
4386
|
-
const displayText =
|
|
4419
|
+
const displayText = unit ? `${formattedValue} ${unit}` : formattedValue;
|
|
4387
4420
|
const sparklinePath = (() => {
|
|
4388
4421
|
if (!showSparkline || !history || history.length < 2) return "";
|
|
4389
4422
|
const width = 70 * scale;
|
|
@@ -4391,8 +4424,9 @@ function DataOverlay({
|
|
|
4391
4424
|
const padding = 5 * scale;
|
|
4392
4425
|
const effectiveWidth = width - padding * 2;
|
|
4393
4426
|
const effectiveHeight = height - padding * 2;
|
|
4394
|
-
const
|
|
4395
|
-
const
|
|
4427
|
+
const hasEuRange = scaling?.euLow !== void 0 && scaling?.euHigh !== void 0 && scaling.euHigh !== scaling.euLow;
|
|
4428
|
+
const min = hasEuRange ? scaling.euLow : Math.min(...history);
|
|
4429
|
+
const max = hasEuRange ? scaling.euHigh : Math.max(...history);
|
|
4396
4430
|
const range = max - min || 1;
|
|
4397
4431
|
const points = history.map((val, i) => {
|
|
4398
4432
|
const xPos = i / (history.length - 1) * effectiveWidth + padding;
|
|
@@ -7553,8 +7587,12 @@ function createControlBinding(nodeId, deviceConfig, actions) {
|
|
|
7553
7587
|
}
|
|
7554
7588
|
|
|
7555
7589
|
// src/hooks/useDeviceControls.ts
|
|
7556
|
-
import { useState as useState15, useCallback as useCallback8 } from "react";
|
|
7557
|
-
function
|
|
7590
|
+
import { useState as useState15, useCallback as useCallback8, useRef as useRef6 } from "react";
|
|
7591
|
+
function commandKey(nodeId, kind, suffix) {
|
|
7592
|
+
return suffix ? `${nodeId}:${kind}:${suffix}` : `${nodeId}:${kind}`;
|
|
7593
|
+
}
|
|
7594
|
+
function useDeviceControls(initialBindings, options) {
|
|
7595
|
+
const { commandTimeoutMs } = options ?? {};
|
|
7558
7596
|
const [controls, setControls] = useState15(() => {
|
|
7559
7597
|
const map = /* @__PURE__ */ new Map();
|
|
7560
7598
|
if (initialBindings) {
|
|
@@ -7564,6 +7602,11 @@ function useDeviceControls(initialBindings) {
|
|
|
7564
7602
|
}
|
|
7565
7603
|
return map;
|
|
7566
7604
|
});
|
|
7605
|
+
const pendingRef = useRef6(/* @__PURE__ */ new Map());
|
|
7606
|
+
const [pendingCommands, setPendingCommands] = useState15(() => /* @__PURE__ */ new Set());
|
|
7607
|
+
const syncPending = useCallback8(() => {
|
|
7608
|
+
setPendingCommands(new Set(pendingRef.current.keys()));
|
|
7609
|
+
}, []);
|
|
7567
7610
|
const updateControl = useCallback8((nodeId, updates) => {
|
|
7568
7611
|
setControls((prev) => {
|
|
7569
7612
|
const newMap = new Map(prev);
|
|
@@ -7653,121 +7696,112 @@ function useDeviceControls(initialBindings) {
|
|
|
7653
7696
|
},
|
|
7654
7697
|
[controls]
|
|
7655
7698
|
);
|
|
7656
|
-
const
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
lastCommandTime: Date.now(),
|
|
7665
|
-
lastCommandResult: { success: true, message: `Mode changed to ${mode}` }
|
|
7666
|
-
});
|
|
7667
|
-
} catch (error) {
|
|
7668
|
-
updateDeviceState(nodeId, {
|
|
7669
|
-
currentMode: binding.state.currentMode,
|
|
7670
|
-
lastCommandResult: {
|
|
7671
|
-
success: false,
|
|
7672
|
-
message: error instanceof Error ? error.message : "Mode change failed"
|
|
7673
|
-
}
|
|
7674
|
-
});
|
|
7699
|
+
const isCommandPending = useCallback8(
|
|
7700
|
+
(nodeId, kind) => {
|
|
7701
|
+
if (kind) {
|
|
7702
|
+
const prefix2 = `${nodeId}:${kind}`;
|
|
7703
|
+
for (const key of pendingCommands) {
|
|
7704
|
+
if (key === prefix2 || key.startsWith(`${prefix2}:`)) return true;
|
|
7705
|
+
}
|
|
7706
|
+
return false;
|
|
7675
7707
|
}
|
|
7708
|
+
const prefix = `${nodeId}:`;
|
|
7709
|
+
for (const key of pendingCommands) {
|
|
7710
|
+
if (key.startsWith(prefix)) return true;
|
|
7711
|
+
}
|
|
7712
|
+
return false;
|
|
7676
7713
|
},
|
|
7677
|
-
[
|
|
7714
|
+
[pendingCommands]
|
|
7678
7715
|
);
|
|
7679
|
-
const
|
|
7680
|
-
|
|
7681
|
-
const
|
|
7682
|
-
if (
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
await binding.actions.onParameterChange?.(parameterId, value);
|
|
7686
|
-
updateDeviceState(nodeId, {
|
|
7687
|
-
lastCommandTime: Date.now(),
|
|
7688
|
-
lastCommandResult: { success: true, message: `Parameter ${parameterId} updated` }
|
|
7689
|
-
});
|
|
7690
|
-
} catch (error) {
|
|
7691
|
-
updateDeviceState(nodeId, {
|
|
7692
|
-
lastCommandResult: {
|
|
7693
|
-
success: false,
|
|
7694
|
-
message: error instanceof Error ? error.message : "Parameter change failed"
|
|
7695
|
-
}
|
|
7696
|
-
});
|
|
7697
|
-
}
|
|
7716
|
+
const markPending = useCallback8(
|
|
7717
|
+
(key, delta) => {
|
|
7718
|
+
const next = (pendingRef.current.get(key) ?? 0) + delta;
|
|
7719
|
+
if (next > 0) pendingRef.current.set(key, next);
|
|
7720
|
+
else pendingRef.current.delete(key);
|
|
7721
|
+
syncPending();
|
|
7698
7722
|
},
|
|
7699
|
-
[
|
|
7723
|
+
[syncPending]
|
|
7700
7724
|
);
|
|
7701
|
-
const
|
|
7702
|
-
async (nodeId) => {
|
|
7725
|
+
const runCommand = useCallback8(
|
|
7726
|
+
async (nodeId, key, invoke, messages) => {
|
|
7703
7727
|
const binding = controls.get(nodeId);
|
|
7704
7728
|
if (!binding) return;
|
|
7705
|
-
|
|
7729
|
+
markPending(key, 1);
|
|
7730
|
+
let timer;
|
|
7706
7731
|
try {
|
|
7707
|
-
|
|
7732
|
+
const action = Promise.resolve(invoke(binding));
|
|
7733
|
+
if (commandTimeoutMs && commandTimeoutMs > 0) {
|
|
7734
|
+
await Promise.race([
|
|
7735
|
+
action,
|
|
7736
|
+
new Promise((_, reject) => {
|
|
7737
|
+
timer = setTimeout(
|
|
7738
|
+
() => reject(new Error(`${messages.success.replace(/ sent$/, "")} timed out (unconfirmed)`)),
|
|
7739
|
+
commandTimeoutMs
|
|
7740
|
+
);
|
|
7741
|
+
})
|
|
7742
|
+
]);
|
|
7743
|
+
} else {
|
|
7744
|
+
await action;
|
|
7745
|
+
}
|
|
7708
7746
|
updateDeviceState(nodeId, {
|
|
7709
|
-
status: "normal",
|
|
7710
7747
|
lastCommandTime: Date.now(),
|
|
7711
|
-
lastCommandResult: { success: true, message:
|
|
7748
|
+
lastCommandResult: { success: true, message: messages.success }
|
|
7712
7749
|
});
|
|
7713
7750
|
} catch (error) {
|
|
7714
7751
|
updateDeviceState(nodeId, {
|
|
7715
|
-
|
|
7716
|
-
status: "fault",
|
|
7752
|
+
lastCommandTime: Date.now(),
|
|
7717
7753
|
lastCommandResult: {
|
|
7718
7754
|
success: false,
|
|
7719
|
-
message: error instanceof Error ? error.message :
|
|
7755
|
+
message: error instanceof Error ? error.message : messages.failure
|
|
7720
7756
|
}
|
|
7721
7757
|
});
|
|
7758
|
+
} finally {
|
|
7759
|
+
if (timer) clearTimeout(timer);
|
|
7760
|
+
markPending(key, -1);
|
|
7722
7761
|
}
|
|
7723
7762
|
},
|
|
7724
|
-
[controls, updateDeviceState]
|
|
7763
|
+
[controls, updateDeviceState, markPending, commandTimeoutMs]
|
|
7764
|
+
);
|
|
7765
|
+
const sendModeChange = useCallback8(
|
|
7766
|
+
(nodeId, mode) => runCommand(
|
|
7767
|
+
nodeId,
|
|
7768
|
+
commandKey(nodeId, "mode"),
|
|
7769
|
+
(binding) => binding.actions.onModeChange?.(mode),
|
|
7770
|
+
{ success: `Mode ${mode} command sent`, failure: "Mode change failed" }
|
|
7771
|
+
),
|
|
7772
|
+
[runCommand]
|
|
7773
|
+
);
|
|
7774
|
+
const sendParameterChange = useCallback8(
|
|
7775
|
+
(nodeId, parameterId, value) => runCommand(
|
|
7776
|
+
nodeId,
|
|
7777
|
+
commandKey(nodeId, "parameter", parameterId),
|
|
7778
|
+
(binding) => binding.actions.onParameterChange?.(parameterId, value),
|
|
7779
|
+
{ success: `Parameter ${parameterId} command sent`, failure: "Parameter change failed" }
|
|
7780
|
+
),
|
|
7781
|
+
[runCommand]
|
|
7782
|
+
);
|
|
7783
|
+
const sendStartCommand = useCallback8(
|
|
7784
|
+
(nodeId) => runCommand(nodeId, commandKey(nodeId, "start"), (binding) => binding.actions.onStart?.(), {
|
|
7785
|
+
success: "Start command sent",
|
|
7786
|
+
failure: "Start command failed"
|
|
7787
|
+
}),
|
|
7788
|
+
[runCommand]
|
|
7725
7789
|
);
|
|
7726
7790
|
const sendStopCommand = useCallback8(
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
await binding.actions.onStop?.();
|
|
7733
|
-
updateDeviceState(nodeId, {
|
|
7734
|
-
status: "off",
|
|
7735
|
-
lastCommandTime: Date.now(),
|
|
7736
|
-
lastCommandResult: { success: true, message: "Device stopped" }
|
|
7737
|
-
});
|
|
7738
|
-
} catch (error) {
|
|
7739
|
-
updateDeviceState(nodeId, {
|
|
7740
|
-
isRunning: true,
|
|
7741
|
-
status: "fault",
|
|
7742
|
-
lastCommandResult: {
|
|
7743
|
-
success: false,
|
|
7744
|
-
message: error instanceof Error ? error.message : "Stop failed"
|
|
7745
|
-
}
|
|
7746
|
-
});
|
|
7747
|
-
}
|
|
7748
|
-
},
|
|
7749
|
-
[controls, updateDeviceState]
|
|
7791
|
+
(nodeId) => runCommand(nodeId, commandKey(nodeId, "stop"), (binding) => binding.actions.onStop?.(), {
|
|
7792
|
+
success: "Stop command sent",
|
|
7793
|
+
failure: "Stop command failed"
|
|
7794
|
+
}),
|
|
7795
|
+
[runCommand]
|
|
7750
7796
|
);
|
|
7751
7797
|
const sendCustomAction = useCallback8(
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
lastCommandResult: { success: true, message: `Action ${actionId} executed` }
|
|
7760
|
-
});
|
|
7761
|
-
} catch (error) {
|
|
7762
|
-
updateDeviceState(nodeId, {
|
|
7763
|
-
lastCommandResult: {
|
|
7764
|
-
success: false,
|
|
7765
|
-
message: error instanceof Error ? error.message : "Action failed"
|
|
7766
|
-
}
|
|
7767
|
-
});
|
|
7768
|
-
}
|
|
7769
|
-
},
|
|
7770
|
-
[controls, updateDeviceState]
|
|
7798
|
+
(nodeId, actionId) => runCommand(
|
|
7799
|
+
nodeId,
|
|
7800
|
+
commandKey(nodeId, "action", actionId),
|
|
7801
|
+
(binding) => binding.actions.onCustomAction?.(actionId),
|
|
7802
|
+
{ success: `Action ${actionId} command sent`, failure: "Action failed" }
|
|
7803
|
+
),
|
|
7804
|
+
[runCommand]
|
|
7771
7805
|
);
|
|
7772
7806
|
return {
|
|
7773
7807
|
controls,
|
|
@@ -7778,6 +7812,10 @@ function useDeviceControls(initialBindings) {
|
|
|
7778
7812
|
setControlBinding,
|
|
7779
7813
|
removeControlBinding,
|
|
7780
7814
|
getControlBinding,
|
|
7815
|
+
// In-flight command visibility (interaction state, not device state).
|
|
7816
|
+
// `isCommandPending` is the stable query surface; the raw key set is
|
|
7817
|
+
// intentionally not exported (its key format is an implementation detail).
|
|
7818
|
+
isCommandPending,
|
|
7781
7819
|
// Command helpers
|
|
7782
7820
|
sendModeChange,
|
|
7783
7821
|
sendParameterChange,
|
|
@@ -8066,7 +8104,7 @@ function useDeviceConfigs(initialConfigs) {
|
|
|
8066
8104
|
}
|
|
8067
8105
|
|
|
8068
8106
|
// src/components/DeviceConfigPanel/DeviceConfigPanel.tsx
|
|
8069
|
-
import { useState as useState17, useEffect as useEffect12, useMemo, useRef as
|
|
8107
|
+
import { useState as useState17, useEffect as useEffect12, useMemo, useRef as useRef7 } from "react";
|
|
8070
8108
|
import { Fragment as Fragment9, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
8071
8109
|
function DeviceConfigPanel({
|
|
8072
8110
|
binding,
|
|
@@ -8108,7 +8146,7 @@ function DeviceConfigPanel({
|
|
|
8108
8146
|
});
|
|
8109
8147
|
const [showToast, setShowToast] = useState17(true);
|
|
8110
8148
|
const [bindingId, setBindingId] = useState17(binding?.nodeId || null);
|
|
8111
|
-
const lastResultTimestampRef =
|
|
8149
|
+
const lastResultTimestampRef = useRef7(0);
|
|
8112
8150
|
if (binding && binding.nodeId !== bindingId) {
|
|
8113
8151
|
const values = {};
|
|
8114
8152
|
binding.parameters.forEach((param) => {
|