@adcops/autocore-react 3.3.75 → 3.3.77
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/dist/components/Indicator.d.ts +29 -52
- package/dist/components/Indicator.d.ts.map +1 -1
- package/dist/components/Indicator.js +1 -1
- package/dist/components/ams/AmsProvider.d.ts +7 -0
- package/dist/components/ams/AmsProvider.d.ts.map +1 -1
- package/dist/components/ams/AssetDetailView.d.ts.map +1 -1
- package/dist/components/ams/AssetDetailView.js +1 -1
- package/dist/components/ams/AssetRegistryTable.d.ts.map +1 -1
- package/dist/components/ams/AssetRegistryTable.js +1 -1
- package/dist/components/ams/CalibrationEntryDialog.d.ts.map +1 -1
- package/dist/components/ams/CalibrationEntryDialog.js +1 -1
- package/dist/components/ams/MissingAssetsBanner.d.ts +11 -0
- package/dist/components/ams/MissingAssetsBanner.d.ts.map +1 -0
- package/dist/components/ams/MissingAssetsBanner.js +1 -0
- package/dist/components/ams/PlaceholderHealthPanel.d.ts +3 -0
- package/dist/components/ams/PlaceholderHealthPanel.d.ts.map +1 -0
- package/dist/components/ams/PlaceholderHealthPanel.js +1 -0
- package/dist/components/ams/index.d.ts +2 -0
- package/dist/components/ams/index.d.ts.map +1 -1
- package/dist/components/ams/index.js +1 -1
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/network/NetworkPanel.d.ts +8 -0
- package/dist/components/network/NetworkPanel.d.ts.map +1 -0
- package/dist/components/network/NetworkPanel.js +1 -0
- package/dist/components/network/NetworkProvider.d.ts +72 -0
- package/dist/components/network/NetworkProvider.d.ts.map +1 -0
- package/dist/components/network/NetworkProvider.js +1 -0
- package/dist/components/network/StagedChangeBanner.d.ts +8 -0
- package/dist/components/network/StagedChangeBanner.d.ts.map +1 -0
- package/dist/components/network/StagedChangeBanner.js +1 -0
- package/dist/components/network/index.d.ts +7 -0
- package/dist/components/network/index.d.ts.map +1 -0
- package/dist/components/network/index.js +1 -0
- package/dist/components/tis/ProjectManager.d.ts +7 -0
- package/dist/components/tis/ProjectManager.d.ts.map +1 -0
- package/dist/components/tis/ProjectManager.js +1 -0
- package/dist/components/tis/ResultHistoryTable.d.ts.map +1 -1
- package/dist/components/tis/ResultHistoryTable.js +1 -1
- package/package.json +1 -1
- package/src/components/Indicator.tsx +166 -162
- package/src/components/ams/AmsProvider.tsx +7 -0
- package/src/components/ams/AssetDetailView.tsx +287 -4
- package/src/components/ams/AssetRegistryTable.tsx +325 -21
- package/src/components/ams/CalibrationEntryDialog.tsx +163 -30
- package/src/components/ams/MissingAssetsBanner.tsx +124 -0
- package/src/components/ams/PlaceholderHealthPanel.tsx +188 -0
- package/src/components/ams/index.ts +2 -0
- package/src/components/index.ts +26 -0
- package/src/components/network/NetworkPanel.tsx +363 -0
- package/src/components/network/NetworkProvider.tsx +349 -0
- package/src/components/network/StagedChangeBanner.tsx +101 -0
- package/src/components/network/index.ts +17 -0
- package/src/components/tis/ProjectManager.tsx +392 -0
- package/src/components/tis/ResultHistoryTable.tsx +126 -188
|
@@ -1,67 +1,44 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import {
|
|
3
|
-
import { IndicatorColor } from "../core/IndicatorColor";
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { IndicatorColor } from '../core/IndicatorColor';
|
|
4
3
|
export { IndicatorColor };
|
|
5
|
-
interface IndicatorProps {
|
|
4
|
+
export interface IndicatorProps {
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
6
|
+
* State to be displayed.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* <Indicator label={<span><i className="pi pi-check"></i> Icon and Text</span>} />
|
|
13
|
-
* <Indicator label={<YourCustomIconComponent />} />
|
|
14
|
-
* ```
|
|
15
|
-
*/
|
|
16
|
-
label?: React.ReactNode;
|
|
17
|
-
/**
|
|
18
|
-
* State to be displayed<br/>
|
|
19
|
-
*
|
|
20
|
-
* Available states: **on**, **off** and **not available**:
|
|
21
|
-
*
|
|
22
|
-
* * `true` is treated as **on**
|
|
23
|
-
* * `false` is treated as **off**
|
|
24
|
-
* * `undefined` is treated as **not available**
|
|
25
|
-
*/
|
|
26
|
-
value?: boolean | undefined;
|
|
27
|
-
/**
|
|
28
|
-
* CSS color for **enabled** state
|
|
8
|
+
* * `true` → on
|
|
9
|
+
* * `false` → off
|
|
10
|
+
* * `undefined` → not available (invalid color)
|
|
29
11
|
*/
|
|
12
|
+
value?: boolean;
|
|
13
|
+
/** CSS color when value is true. Defaults to IndicatorColor.IndicatorGreen. */
|
|
30
14
|
onColor?: string;
|
|
31
|
-
/**
|
|
32
|
-
* CSS color for **disabled** state
|
|
33
|
-
*/
|
|
15
|
+
/** CSS color when value is false. Defaults to IndicatorColor.IndicatorOff (gray). */
|
|
34
16
|
offColor?: string;
|
|
35
|
-
/**
|
|
36
|
-
* CSS color for **not available** state
|
|
37
|
-
*/
|
|
17
|
+
/** CSS color when value is undefined. Defaults to IndicatorColor.IndicatorInvalid (black). */
|
|
38
18
|
invalidColor?: string;
|
|
39
19
|
/**
|
|
40
|
-
*
|
|
20
|
+
* Optional broadcast topic to subscribe to. The latest broadcast value
|
|
21
|
+
* is used when `value` is left undefined; an explicit `value` always
|
|
22
|
+
* wins so callers can drive the indicator from React state instead.
|
|
41
23
|
*/
|
|
24
|
+
topic?: string;
|
|
25
|
+
/** Additional CSS class names applied to the outer box. */
|
|
42
26
|
className?: string;
|
|
27
|
+
/** Inline style overrides for the outer box. */
|
|
28
|
+
style?: React.CSSProperties;
|
|
43
29
|
/**
|
|
44
|
-
*
|
|
30
|
+
* Legacy text label rendered next to a small color swatch. Mutually
|
|
31
|
+
* exclusive with `children` — pass one or the other. Plain strings or
|
|
32
|
+
* React nodes both work.
|
|
45
33
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
static contextType: React.Context<EventEmitterContextType>;
|
|
54
|
-
protected unsubscribeTopicId: number | null;
|
|
55
|
-
static defaultProps: {
|
|
56
|
-
onColor: string;
|
|
57
|
-
offColor: string;
|
|
58
|
-
invalidColor: string;
|
|
59
|
-
};
|
|
60
|
-
constructor(props: IndicatorProps);
|
|
61
|
-
componentDidMount(): void;
|
|
62
|
-
componentDidUpdate(prevProps: IndicatorProps): void;
|
|
63
|
-
componentWillUnmount(): void;
|
|
64
|
-
render(): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
label?: React.ReactNode;
|
|
35
|
+
/**
|
|
36
|
+
* Icon (or any node) to display on top of the colored backdrop.
|
|
37
|
+
* Use this for the modern square-button-shaped indicator, e.g.
|
|
38
|
+
* `<Indicator ...><i className="pi pi-power-off" /></Indicator>`.
|
|
39
|
+
*/
|
|
40
|
+
children?: React.ReactNode;
|
|
65
41
|
}
|
|
42
|
+
export declare const Indicator: React.FC<IndicatorProps>;
|
|
66
43
|
export default Indicator;
|
|
67
44
|
//# sourceMappingURL=Indicator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Indicator.d.ts","sourceRoot":"","sources":["../../src/components/Indicator.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Indicator.d.ts","sourceRoot":"","sources":["../../src/components/Indicator.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,MAAM,WAAW,cAAc;IAC3B;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8FAA8F;IAC9F,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,gDAAgD;IAChD,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAE5B;;;;OAIG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAExB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B;AAiBD,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA8F9C,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useContext,useEffect,useState}from"react";import clsx from"clsx";import{EventEmitterContext}from"../core/EventEmitterContext";import{IndicatorColor}from"../core/IndicatorColor";export{IndicatorColor};const pickColor=(o,t,r,e)=>!0===o?t:!1===o?r:e;export const Indicator=({value:o,onColor:t=IndicatorColor.IndicatorGreen,offColor:r=IndicatorColor.IndicatorOff,invalidColor:e=IndicatorColor.IndicatorInvalid,topic:n,className:i,style:s,label:a,children:c})=>{const{subscribe:l,unsubscribe:d}=useContext(EventEmitterContext),[u,x]=useState(void 0);useEffect(()=>{if(!n||!l)return;const o=l(n,o=>{x(null==o?void 0:!!o)});return()=>{try{d&&void 0!==o&&d(o)}catch{}}},[n,l,d]);const p=pickColor(void 0!==o?o:u,t,r,e);if(null!=c){const o={backgroundColor:p,color:"white",display:"inline-flex",alignItems:"center",justifyContent:"center",borderRadius:0,boxShadow:"inset 0 1px 3px rgba(0, 0, 0, 0.45)",boxSizing:"border-box",...s};return _jsx("span",{className:clsx("indicator",i),style:o,role:"status","aria-label":"string"==typeof a?a:void 0,children:c})}const m={alignItems:"center",width:"auto",flex:"0 0 auto",...s},f={backgroundColor:p,width:"22px",borderRadius:0,boxShadow:"inset 0 1px 2px rgba(0, 0, 0, 0.4)"};return _jsxs("div",{className:clsx("p-inputgroup indicator",i),style:m,role:"status",children:[_jsx("span",{className:"p-inputgroup-addon",style:f,children:" "}),void 0!==a&&_jsx("span",{className:"p-inputgroup-addon",children:a})]})};export default Indicator;
|
|
@@ -18,6 +18,13 @@ export interface AmsRole {
|
|
|
18
18
|
description: string | null;
|
|
19
19
|
/** Test method IDs whose start_test will pick up an asset in this role. */
|
|
20
20
|
used_by: string[];
|
|
21
|
+
/** Module names whose configs reference this role via
|
|
22
|
+
* `${ams.by_location.<location>.*}` placeholders. Surfaces in the
|
|
23
|
+
* AIS Role dropdown so the operator can see *why* a role exists
|
|
24
|
+
* even when no test method directly resolves it (e.g., a load_cell
|
|
25
|
+
* feeding NI bridge channel calibration). Empty for purely
|
|
26
|
+
* test-method-driven roles. */
|
|
27
|
+
used_by_modules: string[];
|
|
21
28
|
}
|
|
22
29
|
export type AmsRoleRegistry = {
|
|
23
30
|
[assetType: string]: AmsRole[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmsProvider.d.ts","sourceRoot":"","sources":["../../../src/components/ams/AmsProvider.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,EAOV,KAAK,SAAS,EACjB,MAAM,OAAO,CAAC;AAQf,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC;AAChC,MAAM,MAAM,iBAAiB,GAAG;IAAE,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAA;CAAE,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACpB,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,2EAA2E;IAC3E,OAAO,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"AmsProvider.d.ts","sourceRoot":"","sources":["../../../src/components/ams/AmsProvider.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,EAOV,KAAK,SAAS,EACjB,MAAM,OAAO,CAAC;AAQf,MAAM,MAAM,aAAa,GAAG,GAAG,CAAC;AAChC,MAAM,MAAM,iBAAiB,GAAG;IAAE,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAA;CAAE,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACpB,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,2EAA2E;IAC3E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;oCAKgC;IAChC,eAAe,EAAE,MAAM,EAAE,CAAC;CAC7B;AACD,MAAM,MAAM,eAAe,GAAG;IAAE,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,CAAA;CAAE,CAAC;AAEjE,MAAM,WAAW,SAAS;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,iBAAiB,CAAC;IACjD,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,KAAK,EAAE,eAAe,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACpD,gBAAgB,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACzD,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACzE,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACpD,SAAS,EAAE,YAAY,CAAC;IACxB,YAAY,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;CACxD;AA0BD,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,SAAS,CAAC;CACvB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAmIlD,CAAC;AAMF,eAAO,MAAM,MAAM,uBAAwC,CAAC;AAC5D,eAAO,MAAM,aAAa,yBAAyC,CAAC;AACpE,eAAO,MAAM,WAAW,uBAAyC,CAAC;AAClE,eAAO,MAAM,YAAY,iBAAyC,CAAC;AACnE,eAAO,MAAM,YAAY,uBAAyC,CAAC;AACnE,eAAO,MAAM,eAAe,wCA7KF,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,CAgLvD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetDetailView.d.ts","sourceRoot":"","sources":["../../../src/components/ams/AssetDetailView.tsx"],"names":[],"mappings":"AAQA,OAAO,
|
|
1
|
+
{"version":3,"file":"AssetDetailView.d.ts","sourceRoot":"","sources":["../../../src/components/ams/AssetDetailView.tsx"],"names":[],"mappings":"AAQA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAU/D,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAwPnC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useEffect,useState}from"react";import{Button}from"primereact/button";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{useAms}from"./AmsProvider";import{CalibrationEntryDialog}from"./CalibrationEntryDialog";export const AssetDetailView=()=>{const{selection:e,schemas:
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useContext,useEffect,useState}from"react";import{Button}from"primereact/button";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{ConfirmDialog,confirmDialog}from"primereact/confirmdialog";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useAms}from"./AmsProvider";import{CalibrationEntryDialog}from"./CalibrationEntryDialog";export const AssetDetailView=()=>{const{selection:e,schemas:t,roles:s,readAsset:r,listCalibrations:a,readCalibration:i,readUsage:l,refreshAssets:n,setSelection:o}=useAms(),{invoke:d}=useContext(EventEmitterContext),[c,m]=useState(null),[_,p]=useState([]),[u,h]=useState(null),[x,f]=useState(!1),[y,j]=useState(!1),g=async()=>{if(!e.assetId)return m(null),p([]),void h(null);const t=await r(e.assetId);m(t);const s=await a(e.assetId),n=await Promise.all(s.map(t=>i(e.assetId,t)));p(n.filter(Boolean));const o=await l(e.assetId);h(o)};if(useEffect(()=>{g()},[e.assetId]),!e.assetId)return _jsx("div",{style:{padding:"1rem",color:"#9ca3af"},children:"Select an asset from the registry to see its details."});if(!c)return _jsx("div",{style:{padding:"1rem"},children:"Loading…"});const b=t[c.asset_type]?.label??c.asset_type,v=s[c.asset_type]?.find(e=>e.location===c.location),C=v?v.label??v.location:c.location,S=Array.isArray(t[c.asset_type]?.fields)?t[c.asset_type].fields:[],w=c.custom??{},A=v?.used_by_modules??[];return _jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[_jsxs("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr auto 1fr",gap:"0.5rem 1.5rem",alignItems:"baseline"},children:[_jsx("strong",{children:"Asset ID"})," ",_jsx("span",{children:c.asset_id}),_jsx("strong",{children:"Type"})," ",_jsx("span",{children:b}),_jsx("strong",{children:"Serial"})," ",_jsx("span",{children:c.serial||_jsx("em",{style:{color:"#9ca3af"},children:"(none)"})}),_jsx("strong",{children:"Role"})," ",_jsx("span",{children:C||_jsx("em",{style:{color:"#9ca3af"},children:"(none)"})}),_jsx("strong",{children:"Status"})," ",_jsx("span",{children:c.status}),_jsx("strong",{children:"Installed"}),_jsx("span",{children:c.install_date?new Date(c.install_date).toLocaleString():"—"}),_jsx("strong",{children:"Current Cal"}),_jsx("span",{children:c.current_calibration_id??_jsx("em",{style:{color:"#f59e0b"},children:"none"})}),_jsx("strong",{children:"Cycles"})," ",_jsx("span",{children:u?.cycles??0})]}),A.length>0&&_jsxs("div",{style:{fontSize:"0.875rem",color:"#34d399"},children:["✓ Feeds module ",1===A.length?"config":"configs",":"," ",_jsx("strong",{children:A.join(", ")})," — ","their ",_jsxs("code",{children:["$","${ams.by_location."+c.location+".*}"]})," ","placeholders will resolve to the values below."]}),S.length>0&&_jsxs("div",{children:[_jsx("h4",{style:{margin:"0 0 0.5rem 0"},children:"Nameplate"}),_jsx("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.25rem 1rem",alignItems:"baseline",fontSize:"0.9rem"},children:S.map(e=>{const t=w[e.name],s=null!=t&&""!==t,r=e.label??e.name,a=s?e.units?`${t} ${e.units}`:String(t):"(not set)";return _jsxs(React.Fragment,{children:[_jsx("strong",{title:e.description??void 0,children:r}),_jsx("span",{style:{color:s?void 0:"#f59e0b"},children:a})]},e.name)})})]}),_jsx(SubLocationsPanel,{schema:t[c.asset_type]?.sub_locations,values:c.sub_locations}),_jsx(SubLocationsCalibrationPanel,{schema:t[c.asset_type]?.sub_locations,currentCalibration:_.find(e=>e.cal_id===c.current_calibration_id)}),_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[_jsx("h4",{style:{margin:0},children:"Calibration History"}),_jsxs("div",{style:{display:"flex",gap:"0.5rem"},children:["active"===c.status&&_jsx(Button,{label:"Retire",icon:"pi pi-power-off",severity:"warning",outlined:!0,onClick:async()=>{if(c)try{const e=await d("ams.update_asset",MessageType.Request,{asset_id:c.asset_id,status:"retired"});e?.success&&(await n(),await g())}catch(e){}},tooltip:"Mark inactive. The asset stays on disk; deletion is a separate action available after retirement.",tooltipOptions:{position:"left"}}),"retired"===c.status&&_jsx(Button,{label:"Delete",icon:"pi pi-trash",severity:"danger",outlined:!0,loading:y,onClick:()=>{c&&confirmDialog({message:_jsxs("div",{children:[_jsxs("p",{style:{marginTop:0},children:["Permanently delete asset ",_jsx("code",{children:c.asset_id}),"?"]}),_jsx("p",{style:{marginBottom:0,fontSize:"0.875rem",color:"#9ca3af"},children:"This removes the AMS record (nameplate, calibration history, usage counters). Historical test records that referenced this asset are unaffected — they carry the full asset and calibration data inline."})]}),header:"Delete asset",icon:"pi pi-exclamation-triangle",acceptLabel:"Delete",rejectLabel:"Cancel",acceptClassName:"p-button-danger",accept:()=>{(async()=>{if(c){j(!0);try{const e=await d("ams.delete_asset",MessageType.Request,{asset_id:c.asset_id});e?.success?(o({assetType:null,assetId:null}),await n()):alert(`Delete failed: ${e?.error_message??"unknown error"}`)}catch(e){alert(`Delete threw: ${e?.message??e}`)}finally{j(!1)}}})()}})},tooltip:"Permanent. Removes the AMS record; historical test snapshots are preserved inline.",tooltipOptions:{position:"left"}}),_jsx(Button,{label:"+ Calibration",icon:"pi pi-plus",onClick:()=>f(!0)})]})]}),_jsx(ConfirmDialog,{}),_jsxs(DataTable,{value:_,size:"small",stripedRows:!0,emptyMessage:"No calibrations recorded for this asset.",children:[_jsx(Column,{field:"cal_id",header:"Cal ID"}),_jsx(Column,{field:"performed_at",header:"Performed",body:e=>e.performed_at?new Date(e.performed_at).toLocaleString():"—"}),_jsx(Column,{field:"performed_by",header:"By"}),_jsx(Column,{field:"expires_at",header:"Expires",body:e=>e.expires_at?new Date(e.expires_at).toLocaleDateString():"—"}),_jsx(Column,{field:"cert_ref",header:"Cert"}),_jsx(Column,{header:"Values",body:e=>_jsx("code",{style:{fontSize:"0.75rem"},children:JSON.stringify(e.values)})})]}),_jsx(CalibrationEntryDialog,{visible:x,assetId:c.asset_id,assetType:c.asset_type,onHide:()=>f(!1),onAdded:()=>{g()}})]})};const SubLocationsPanel=({schema:e,values:t})=>{if(!e||!Array.isArray(e.keys)||!Array.isArray(e.fields))return null;const s=t&&"object"==typeof t?t:{};return _jsxs("div",{children:[_jsx("h4",{style:{margin:"0 0 0.5rem 0"},children:e.label??"Sub-locations"}),_jsx("div",{style:{overflowX:"auto"},children:_jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.875rem"},children:[_jsx("thead",{children:_jsxs("tr",{children:[_jsx("th",{style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:e.key_label??"Key"}),e.fields.map(e=>_jsxs("th",{title:e.description??void 0,style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:[e.label??e.name,e.units?` [${e.units}]`:""]},e.name))]})}),_jsx("tbody",{children:e.keys.map(t=>{const r=s[t]??{};return _jsxs("tr",{children:[_jsx("td",{style:{padding:"0.25rem 0.5rem",fontWeight:600},children:t}),e.fields.map(e=>{const t=r[e.name],s=null!=t&&""!==t;return _jsx("td",{style:{padding:"0.25rem 0.5rem",color:s?void 0:"#f59e0b"},children:s?String(t):"(not set)"},e.name)})]},t)})})]})})]})},SubLocationsCalibrationPanel=({schema:e,currentCalibration:t})=>{if(!e||!Array.isArray(e.keys)||!Array.isArray(e.calibration_fields)||0===e.calibration_fields.length)return null;if(!t)return null;const s=t.values&&"object"==typeof t.values?t.values:{};return _jsxs("div",{children:[_jsx("h4",{style:{margin:"0 0 0.5rem 0"},children:"Current Calibration — Per-axis Values"}),_jsx("div",{style:{overflowX:"auto"},children:_jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.875rem"},children:[_jsx("thead",{children:_jsxs("tr",{children:[_jsx("th",{style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:e.key_label??"Key"}),e.calibration_fields.map(e=>_jsxs("th",{style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:[e.label??e.name,e.units?` [${e.units}]`:""]},e.name))]})}),_jsx("tbody",{children:e.keys.map(t=>{const r=s[t]??{};return _jsxs("tr",{children:[_jsx("td",{style:{padding:"0.25rem 0.5rem",fontWeight:600},children:t}),e.calibration_fields.map(e=>{const t=r[e.name],s=null!=t&&""!==t;return _jsx("td",{style:{padding:"0.25rem 0.5rem",color:s?void 0:"#f59e0b"},children:s?String(t):"(not set)"},e.name)})]},t)})})]})})]})};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetRegistryTable.d.ts","sourceRoot":"","sources":["../../../src/components/ams/AssetRegistryTable.tsx"],"names":[],"mappings":"AAOA,OAAO,
|
|
1
|
+
{"version":3,"file":"AssetRegistryTable.d.ts","sourceRoot":"","sources":["../../../src/components/ams/AssetRegistryTable.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAmD,MAAM,OAAO,CAAC;AA6HxE,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAqftC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useContext,useMemo,useState}from"react";import{Button}from"primereact/button";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Dropdown}from"primereact/dropdown";import{InputText}from"primereact/inputtext";import{Dialog}from"primereact/dialog";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useAms}from"./AmsProvider";const ROLE_OTHER="__other__",EMPTY_ADD={open:!1,assetType:"",serial:"",roleSelection:"",location:""};function roleLabel(e){return e.label??e.location}function roleUsageSummary(e){return
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useContext,useEffect,useMemo,useState}from"react";import{Button}from"primereact/button";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Dropdown}from"primereact/dropdown";import{InputText}from"primereact/inputtext";import{Dialog}from"primereact/dialog";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useAms}from"./AmsProvider";const ROLE_OTHER="__other__",EMPTY_ADD={open:!1,assetType:"",serial:"",roleSelection:"",location:"",customFields:{},subLocationFields:{}};function roleLabel(e){return e.label??e.location}function roleUsageSummary(e){const s=[];return e.used_by.length>0&&s.push(`Used by test method${1===e.used_by.length?"":"s"}: ${e.used_by.join(", ")}`),e.used_by_modules.length>0&&s.push(`Used by module${1===e.used_by_modules.length?"":"s"}: ${e.used_by_modules.join(", ")}`),0===s.length?"Not referenced by any test method or module.":s.join(" • ")}function fieldsFor(e,s){const t=e?.[s]?.fields;return Array.isArray(t)?t:[]}function subLocationsFor(e,s){const t=e?.[s]?.sub_locations;return t&&Array.isArray(t.keys)&&Array.isArray(t.fields)?t:null}function coerceField(e,s){if(void 0!==s&&""!==s)switch(e.type){case"f32":case"f64":case"i8":case"i16":case"i32":case"i64":case"u8":case"u16":case"u32":case"u64":{const e=Number(s);return Number.isFinite(e)?e:void 0}case"bool":return"true"===s||"1"===s;default:return s}}export const AssetRegistryTable=()=>{const{schemas:e,roles:s,assets:t,refreshAssets:o,setSelection:l,selection:a}=useAms(),{invoke:r}=useContext(EventEmitterContext),[i,n]=useState(null),[c,d]=useState(null),[u,m]=useState(EMPTY_ADD);useEffect(()=>{const e=e=>{const s=e.detail,t=s?.assetType??"",o=s?.location??"";t&&m({...EMPTY_ADD,open:!0,assetType:t,roleSelection:o,location:o})};return window.addEventListener("ams:prefill-add",e),()=>window.removeEventListener("ams:prefill-add",e)},[]);const p=useMemo(()=>Object.keys(e).map(s=>({label:e[s]?.label??s,value:s})),[e]),y=useMemo(()=>u.assetType?s[u.assetType]??[]:[],[u.assetType,s]),_=y.length>0,h=useMemo(()=>{const e=y.map(e=>({label:roleLabel(e),value:e.location}));return e.push({label:"Other (advanced — type a custom role)",value:ROLE_OTHER}),e},[y]),b=useMemo(()=>u.roleSelection===ROLE_OTHER?null:y.find(e=>e.location===u.roleSelection)??null,[u.roleSelection,y]),f=useMemo(()=>t.filter(e=>(!i||e.asset_type===i)&&(!c||e.status===c)),[t,i,c]),x=useMemo(()=>fieldsFor(e,u.assetType),[e,u.assetType]),g=useMemo(()=>subLocationsFor(e,u.assetType),[e,u.assetType]),j=!u.assetType||_&&(""===u.roleSelection||u.roleSelection===ROLE_OTHER&&!u.location.trim())||x.some(e=>e.required&&!u.customFields[e.name]?.toString().trim())||(g?.keys.some(e=>g.fields.some(s=>s.required&&!u.subLocationFields[e]?.[s.name]?.toString().trim()))??!1);return _jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"0.5rem"},children:[_jsxs("div",{style:{display:"flex",gap:"0.75rem",alignItems:"center"},children:[_jsx(Dropdown,{value:i,options:[{label:"All Types",value:null},...p],onChange:e=>n(e.value),placeholder:"Filter by type"}),_jsx(Dropdown,{value:c,options:[{label:"All Statuses",value:null},{label:"Active",value:"active"},{label:"Out for Service",value:"out_for_service"},{label:"Retired",value:"retired"}],onChange:e=>d(e.value),placeholder:"Filter by status"}),_jsx("span",{style:{marginLeft:"auto"},children:_jsx(Button,{icon:"pi pi-plus",label:"Add Asset",onClick:()=>m(e=>({...e,open:!0})),disabled:0===p.length})})]}),_jsxs(DataTable,{value:f,selectionMode:"single",selection:f.find(e=>e.asset_id===a.assetId)??null,onSelectionChange:e=>{const s=e.value;s&&l({assetType:s.asset_type,assetId:s.asset_id})},dataKey:"asset_id",emptyMessage:0===p.length?"AMS not enabled in this project (no asset_types declared).":"No assets registered yet.",size:"small",stripedRows:!0,children:[_jsx(Column,{field:"asset_id",header:"Asset ID"}),_jsx(Column,{field:"asset_type",header:"Type",body:s=>e[s.asset_type]?.label??s.asset_type}),_jsx(Column,{field:"serial",header:"Serial"}),_jsx(Column,{field:"location",header:"Role",body:e=>e.location?((e,t)=>{const o=(s[e]??[]).find(e=>e.location===t);return o?roleLabel(o):t})(e.asset_type,e.location):_jsx("span",{style:{color:"#9ca3af"},children:"—"})}),_jsx(Column,{field:"status",header:"Status"}),_jsx(Column,{header:"Calibration",body:e=>e.current_calibration_id?_jsx("span",{title:e.current_calibration_id,children:"✓"}):_jsx("span",{style:{color:"#f59e0b"},children:"none"})})]}),_jsxs(Dialog,{header:"Add New Asset",visible:u.open,style:{width:"32rem"},onHide:()=>m(EMPTY_ADD),footer:_jsxs(_Fragment,{children:[_jsx(Button,{label:"Cancel",severity:"secondary",onClick:()=>m(EMPTY_ADD)}),_jsx(Button,{label:"Create",icon:"pi pi-check",onClick:async()=>{if(!u.assetType)return;const e={};for(const s of x){const t=u.customFields[s.name];if(void 0!==t&&""!==t)switch(s.type){case"f32":case"f64":case"i8":case"i16":case"i32":case"i64":case"u8":case"u16":case"u32":case"u64":{const o=Number(t);Number.isFinite(o)&&(e[s.name]=o);break}case"bool":e[s.name]="true"===t||"1"===t;break;default:e[s.name]=t}}const s={};if(g)for(const e of g.keys){const t={};for(const s of g.fields){const o=coerceField(s,u.subLocationFields[e]?.[s.name]??"");void 0!==o&&(t[s.name]=o)}s[e]=t}const t={asset_type:u.assetType,serial:u.serial,location:u.location,custom:e};g&&(t.sub_locations=s);try{const e=await r("ams.create_asset",MessageType.Request,t);e?.success&&(m(EMPTY_ADD),await o(),e.data?.asset_id&&l({assetType:u.assetType,assetId:e.data.asset_id}))}catch(e){}},disabled:j})]}),children:[_jsxs("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.5rem 1rem",alignItems:"center"},children:[_jsx("label",{children:"Type *"}),_jsx(Dropdown,{value:u.assetType,options:p,onChange:e=>(e=>{const t=s[e]??[],o=1===t.length?{roleSelection:t[0].location,location:t[0].location}:{roleSelection:"",location:""};m(s=>({...s,assetType:e,...o,customFields:{},subLocationFields:{}}))})(e.value),placeholder:"Choose asset type"}),_jsx("label",{children:"Serial"}),_jsx(InputText,{value:u.serial,onChange:e=>m(s=>({...s,serial:e.target.value}))}),_&&_jsxs(_Fragment,{children:[_jsx("label",{children:"Role *"}),_jsx(Dropdown,{value:u.roleSelection,options:h,onChange:e=>{return s=e.value,void m(s===ROLE_OTHER?e=>({...e,roleSelection:ROLE_OTHER,location:""}):e=>({...e,roleSelection:s,location:s}));var s},placeholder:"Choose where this asset is mounted"}),u.roleSelection===ROLE_OTHER&&_jsxs(_Fragment,{children:[_jsx("label",{children:"Custom role"}),_jsx(InputText,{value:u.location,placeholder:"e.g. tsdr_secondary",onChange:e=>m(s=>({...s,location:e.target.value}))})]})]}),x.map(e=>{const s=e.label??e.name,t=e.units?`${s} [${e.units}]${e.required?" *":""}`:`${s}${e.required?" *":""}`,o="string"!==e.type&&"bool"!==e.type;return _jsxs(React.Fragment,{children:[_jsx("label",{title:e.description??void 0,children:t}),"bool"===e.type?_jsx(Dropdown,{value:u.customFields[e.name]??"",options:[{label:"true",value:"true"},{label:"false",value:"false"}],onChange:s=>m(t=>({...t,customFields:{...t.customFields,[e.name]:s.value}})),placeholder:"—"}):_jsx(InputText,{value:u.customFields[e.name]??"",keyfilter:o?"num":void 0,placeholder:e.description??void 0,onChange:s=>m(t=>({...t,customFields:{...t.customFields,[e.name]:s.target.value}}))})]},e.name)})]}),g&&_jsxs("div",{style:{marginTop:"1.5rem"},children:[_jsx("h4",{style:{margin:"0 0 0.5rem 0"},children:g.label??"Sub-locations"}),_jsx("div",{style:{overflowX:"auto"},children:_jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.875rem"},children:[_jsx("thead",{children:_jsxs("tr",{children:[_jsx("th",{style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:g.key_label??"Key"}),g.fields.map(e=>_jsxs("th",{title:e.description??void 0,style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:[e.label??e.name,e.units?` [${e.units}]`:"",e.required?" *":""]},e.name))]})}),_jsx("tbody",{children:g.keys.map(e=>_jsxs("tr",{children:[_jsx("td",{style:{padding:"0.25rem 0.5rem",fontWeight:600},children:e}),g.fields.map(s=>{const t=u.subLocationFields[e]?.[s.name]??"",o="string"!==s.type&&"bool"!==s.type;return _jsx("td",{style:{padding:"0.25rem 0.5rem"},children:_jsx(InputText,{value:t,keyfilter:o?"num":void 0,onChange:t=>{const o=t.target.value;m(t=>({...t,subLocationFields:{...t.subLocationFields,[e]:{...t.subLocationFields[e]??{},[s.name]:o}}}))},style:{width:"100%"}})},s.name)})]},e))})]})})]}),_jsxs("div",{style:{fontSize:"0.875rem",color:"#9ca3af",marginTop:"1rem"},children:[_&&b&&_jsxs(_Fragment,{children:[b.description&&_jsx("p",{style:{margin:"0 0 0.5rem 0"},children:b.description}),_jsxs("p",{style:{margin:"0 0 0.5rem 0",color:"#34d399"},children:["✓ ",roleUsageSummary(b)]})]}),_&&u.roleSelection===ROLE_OTHER&&_jsx("p",{style:{margin:"0 0 0.5rem 0",color:"#f59e0b"},children:"⚠ No test method on this machine references this custom role yet. The asset will be registered but won't be picked up at start_test unless you add an asset_ref to a test method's project.json."}),!_&&u.assetType&&_jsx("p",{style:{margin:"0 0 0.5rem 0"},children:"This asset type isn't selected by physical role on this machine — test methods reference it by ID instead. Just register the asset and pick it by ID on the Test Setup form when running a test."}),_jsxs("p",{style:{margin:0},children:["The asset_id is generated by the server (format:"," ",_jsxs("code",{children:[u.assetType?e[u.assetType]?.id_prefix??"A-":"A-","YYYYMMDDTHHMMSS"]}),"). Manufacturer serial is recorded for traceability but is not used as the unique key."]})]})]})]})};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CalibrationEntryDialog.d.ts","sourceRoot":"","sources":["../../../src/components/ams/CalibrationEntryDialog.tsx"],"names":[],"mappings":"AAUA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAW/D,MAAM,WAAW,2BAA2B;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;
|
|
1
|
+
{"version":3,"file":"CalibrationEntryDialog.d.ts","sourceRoot":"","sources":["../../../src/components/ams/CalibrationEntryDialog.tsx"],"names":[],"mappings":"AAUA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAW/D,MAAM,WAAW,2BAA2B;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAwBD,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,2BAA2B,CAsRxE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useContext,useEffect,useState}from"react";import{Button}from"primereact/button";import{Dialog}from"primereact/dialog";import{InputText}from"primereact/inputtext";import{InputNumber}from"primereact/inputnumber";import{Calendar}from"primereact/calendar";import{Dropdown}from"primereact/dropdown";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useAmsSchemas}from"./AmsProvider";export const CalibrationEntryDialog=({visible:e,assetId:
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useContext,useEffect,useState}from"react";import{Button}from"primereact/button";import{Dialog}from"primereact/dialog";import{InputText}from"primereact/inputtext";import{InputNumber}from"primereact/inputnumber";import{Calendar}from"primereact/calendar";import{Dropdown}from"primereact/dropdown";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useAmsSchemas}from"./AmsProvider";export const CalibrationEntryDialog=({visible:e,assetId:t,assetType:a,onHide:r,onAdded:n})=>{const l=useAmsSchemas(),{invoke:s}=useContext(EventEmitterContext),i=l[a]?.calibration_fields??[],o=(()=>{const e=l[a]?.sub_locations;return e&&Array.isArray(e.keys)?e:null})(),u=o?.calibration_fields??[],d=u.length>0,[m,c]=useState({}),[p,x]=useState({}),[h,g]=useState(""),[_,f]=useState(null),[v,b]=useState(""),[j,y]=useState(""),[C,I]=useState(!1),[S,T]=useState(null);useEffect(()=>{e&&(c({}),x({}),g(""),f(null),b(""),y(""),T(null))},[e]);return _jsxs(Dialog,{header:`Add Calibration — ${t}`,visible:e,onHide:r,style:{width:"40rem"},footer:_jsxs(_Fragment,{children:[_jsx(Button,{label:"Cancel",severity:"secondary",onClick:r,disabled:C}),_jsx(Button,{label:"Save",icon:"pi pi-check",onClick:async()=>{if(d&&o)for(const e of o.keys)for(const t of u){if(!t.required)continue;const a=p[e]?.[t.name];if(null==a||""===a)return void T(`Field "${t.label??t.name}" on axis "${e}" is required.`)}else for(const e of i)if(e.required&&(void 0===m[e.name]||null===m[e.name]||""===m[e.name]))return void T(`Field "${e.label??e.name}" is required.`);const e=d?p:m;I(!0),T(null);try{const a=await s("ams.add_calibration",MessageType.Request,{asset_id:t,performed_by:h,expires_at:_?_.toISOString():null,cert_ref:v,notes:j,values:e});a?.success?(n?.(a.data.cal_id),r()):T(a?.error_message??"add_calibration failed")}catch(e){T(String(e?.message??e))}finally{I(!1)}},loading:C})]}),children:[_jsxs("div",d&&o?{children:[_jsx("h4",{style:{margin:"0 0 0.5rem 0"},children:o.label??"Per-axis calibration"}),_jsx("div",{style:{overflowX:"auto",marginBottom:"1rem"},children:_jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.875rem"},children:[_jsx("thead",{children:_jsxs("tr",{children:[_jsx("th",{style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:o.key_label??"Key"}),u.map(e=>_jsxs("th",{title:e.description??void 0,style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:[e.label??e.name,e.units?` [${e.units}]`:"",e.required?" *":""]},e.name))]})}),_jsx("tbody",{children:o.keys.map(e=>_jsxs("tr",{children:[_jsx("td",{style:{padding:"0.25rem 0.5rem",fontWeight:600},children:e}),u.map(t=>{const a=p[e]?.[t.name],r="string"!==t.type&&"bool"!==t.type;return _jsx("td",{style:{padding:"0.25rem 0.5rem"},children:r?_jsx(InputNumber,{value:a??null,onValueChange:a=>{x(r=>({...r,[e]:{...r[e]??{},[t.name]:a.value}}))},useGrouping:!1,maxFractionDigits:t.type.startsWith("f")?9:0,inputStyle:{width:"100%"}}):_jsx(InputText,{value:a??"",onChange:a=>{x(r=>({...r,[e]:{...r[e]??{},[t.name]:a.target.value}}))},style:{width:"100%"}})},t.name)})]},e))})]})}),_jsxs("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.5rem 1rem",alignItems:"center"},children:[_jsx("label",{children:"Performed by"}),_jsx(InputText,{value:h,onChange:e=>g(e.target.value)}),_jsx("label",{children:"Expires at"}),_jsx(Calendar,{value:_,onChange:e=>f(e.value??null),showIcon:!0,dateFormat:"yy-mm-dd"}),_jsx("label",{children:"Certificate ref"}),_jsx(InputText,{value:v,onChange:e=>b(e.target.value)}),_jsx("label",{children:"Notes"}),_jsx(InputText,{value:j,onChange:e=>y(e.target.value)})]})]}:{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.5rem 1rem",alignItems:"center"},children:[i.flatMap((e,t)=>{const[a,r]=(e=>{const t=`${e.label??e.name}${e.units?` [${e.units}]`:""}${e.required?" *":""}`,a=_jsx("label",{title:e.description??"",children:t}),r=t=>c(a=>({...a,[e.name]:t}));let n;switch(e.type){case"string":default:n=_jsx(InputText,{value:m[e.name]??"",onChange:e=>r(e.target.value)});break;case"enum":n=_jsx(Dropdown,{value:m[e.name]??null,options:(e.values??[]).map(e=>({label:e,value:e})),onChange:e=>r(e.value),placeholder:"Choose…"});break;case"bool":n=_jsx(Dropdown,{value:m[e.name]??null,options:[{label:"true",value:!0},{label:"false",value:!1}],onChange:e=>r(e.value)});break;case"u8":case"u16":case"u32":case"u64":case"i8":case"i16":case"i32":case"i64":case"f32":case"f64":n=_jsx(InputNumber,{value:m[e.name]??null,onValueChange:e=>r(e.value),useGrouping:!1,maxFractionDigits:e.type.startsWith("f")?9:0})}return[a,n]})(e);return[_jsx(React.Fragment,{children:a},`l-${t}`),_jsx(React.Fragment,{children:r},`i-${t}`)]}),_jsx("hr",{style:{gridColumn:"1 / span 2",width:"100%"}}),_jsx("label",{children:"Performed by"}),_jsx(InputText,{value:h,onChange:e=>g(e.target.value)}),_jsx("label",{children:"Expires at"}),_jsx(Calendar,{value:_,onChange:e=>f(e.value??null),showIcon:!0,dateFormat:"yy-mm-dd"}),_jsx("label",{children:"Certificate ref"}),_jsx(InputText,{value:v,onChange:e=>b(e.target.value)}),_jsx("label",{children:"Notes"}),_jsx(InputText,{value:j,onChange:e=>y(e.target.value)})]}),S&&_jsx("div",{style:{marginTop:"1rem",color:"#ef4444"},children:S})]})};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/** Custom event the banner emits; <AssetRegistryTable> listens for it
|
|
3
|
+
* and opens its Add dialog pre-populated. Decouples the two so the
|
|
4
|
+
* banner can sit anywhere relative to the table in the layout. */
|
|
5
|
+
export declare const PREFILL_ADD_EVENT = "ams:prefill-add";
|
|
6
|
+
export interface PrefillAddDetail {
|
|
7
|
+
assetType: string;
|
|
8
|
+
location: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const MissingAssetsBanner: React.FC;
|
|
11
|
+
//# sourceMappingURL=MissingAssetsBanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MissingAssetsBanner.d.ts","sourceRoot":"","sources":["../../../src/components/ams/MissingAssetsBanner.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAIvC;;mEAEmE;AACnE,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AACnD,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAG,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAiGvC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useMemo}from"react";import{Button}from"primereact/button";import{useAms}from"./AmsProvider";export const PREFILL_ADD_EVENT="ams:prefill-add";export const MissingAssetsBanner=()=>{const{roles:e,assets:s,rolesLoaded:t}=useAms(),o=useMemo(()=>{const t=[];for(const[o,r]of Object.entries(e))for(const e of r){s.some(s=>s.asset_type===o&&s.location===e.location&&"active"===s.status)||t.push({assetType:o,role:e})}return t},[e,s]);if(!t)return null;if(0===o.length)return null;const r=(e,s,t)=>1===e?s:t;return _jsxs("div",{role:"alert",style:{borderLeft:"4px solid #f59e0b",background:"rgba(245, 158, 11, 0.08)",padding:"0.75rem 1rem",marginBottom:"1rem",borderRadius:"4px"},children:[_jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",marginBottom:"0.5rem"},children:[_jsx("i",{className:"pi pi-exclamation-triangle",style:{color:"#f59e0b"}}),_jsxs("strong",{children:[o.length," ",r(o.length,"role has","roles have")," no active asset registered."]}),_jsxs("span",{style:{color:"var(--text-secondary-color)",fontSize:"0.875rem"},children:["Modules and tests depending on ",r(o.length,"it","them")," will refuse to start."]})]}),_jsx("ul",{style:{margin:0,paddingLeft:"1.5rem"},children:o.map(({assetType:e,role:s})=>{const t=s.label??s.location,o=[s.used_by.length>0?`methods: ${s.used_by.join(", ")}`:null,s.used_by_modules.length>0?`modules: ${s.used_by_modules.join(", ")}`:null].filter(Boolean).join(" • ");return _jsxs("li",{style:{marginBottom:"0.25rem",display:"flex",alignItems:"center",gap:"0.5rem"},children:[_jsxs("span",{children:[_jsx("strong",{children:t}),_jsxs("span",{style:{color:"var(--text-secondary-color)"},children:[" ","(",e," at ",_jsx("code",{children:s.location}),")"]}),o&&_jsxs("span",{style:{color:"var(--text-secondary-color)",fontSize:"0.85em",marginLeft:"0.5rem"},children:["— ",o]})]}),_jsx(Button,{label:"Register",icon:"pi pi-plus",size:"small",outlined:!0,onClick:()=>((e,s)=>{const t={assetType:e,location:s};window.dispatchEvent(new CustomEvent("ams:prefill-add",{detail:t}))})(e,s.location)})]},`${e}/${s.location}`)})})]})};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlaceholderHealthPanel.d.ts","sourceRoot":"","sources":["../../../src/components/ams/PlaceholderHealthPanel.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAuD,MAAM,OAAO,CAAC;AA+B5E,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EA+I1C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useCallback,useContext,useEffect,useState}from"react";import{Button}from"primereact/button";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useAms}from"./AmsProvider";export const PlaceholderHealthPanel=()=>{const{invoke:e}=useContext(EventEmitterContext),{assets:s,refreshAssets:l}=useAms(),[t,o]=useState(null),[r,a]=useState(null),[n,i]=useState(!1),[d,c]=useState(null),m=useCallback(async()=>{i(!0),c(null);try{const s=await e("ams.diagnose_placeholders",MessageType.Request,{});s?.success?(o(s.data?.placeholders??[]),a(s.data?.summary??null)):c(s?.error_message??"diagnose_placeholders failed")}catch(e){c(String(e?.message??e))}finally{i(!1)}},[e]);useEffect(()=>{m()},[m,s]);const u=r&&_jsx("span",{children:0===r.total?_jsxs("span",{style:{color:"#9ca3af"},children:["No ",_jsx("code",{children:"${ams.*}"})," placeholders in any enabled module's config."]}):0===r.unresolved?_jsxs("span",{style:{color:"#34d399"},children:["✓ All ",r.total," placeholder",1===r.total?"":"s"," resolved. Modules will start cleanly."]}):_jsxs("span",{style:{color:"#f59e0b"},children:[r.unresolved," of ",r.total," placeholder",1===r.total?"":"s"," can't be resolved. Register the missing asset",1===r.unresolved?"":"s"," before starting the affected module",1===r.unresolved?"":"s","."]})});return _jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"0.75rem"},children:[_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[_jsx("h4",{style:{margin:0},children:"Module Placeholder Health"}),_jsx(Button,{icon:"pi pi-refresh",label:"Refresh",onClick:()=>{l(),m()},loading:n,severity:"secondary",outlined:!0})]}),d&&_jsxs("div",{style:{color:"#ef4444",fontSize:"0.875rem"},children:["Couldn't fetch placeholder diagnostic: ",d]}),_jsx("div",{style:{fontSize:"0.875rem"},children:u}),t&&t.length>0&&_jsxs(DataTable,{value:t,size:"small",stripedRows:!0,sortField:"status",sortOrder:-1,emptyMessage:"No placeholders to report.",children:[_jsx(Column,{header:"",body:e=>"ok"===e.status?_jsx("span",{style:{color:"#34d399",display:"inline-flex",alignItems:"center",gap:"0.25rem"},children:_jsx("i",{className:"pi pi-check-circle"})}):_jsx("span",{style:{color:"#f59e0b",display:"inline-flex",alignItems:"center",gap:"0.25rem"},children:_jsx("i",{className:"pi pi-exclamation-triangle"})}),style:{width:"2rem"}}),_jsx(Column,{field:"module",header:"Module",style:{width:"8rem"}}),_jsx(Column,{field:"location",header:"Role",style:{width:"10rem"}}),_jsx(Column,{header:"Value / Reason",body:e=>{if("unresolved"===e.status)return _jsx("span",{style:{color:"#f59e0b"},children:e.reason??"unresolved"});const s=e.resolved_value;let l;return l="string"==typeof s?_jsxs("code",{children:['"',s,'"']}):"number"==typeof s?_jsx("code",{children:s}):null==s?_jsx("em",{style:{color:"#9ca3af"},children:"null"}):_jsx("code",{children:JSON.stringify(s)}),l}}),_jsx(Column,{header:"Asset",body:e=>"ok"===e.status&&e.asset_id?_jsx("code",{style:{fontSize:"0.85em"},children:e.asset_id}):_jsx("span",{style:{color:"#9ca3af"},children:"—"}),style:{width:"14rem"}}),_jsx(Column,{field:"path",header:"Config path",body:e=>_jsx("code",{style:{fontSize:"0.8em"},children:e.path})})]})]})};
|
|
@@ -4,4 +4,6 @@ export { AssetRegistryTable } from './AssetRegistryTable';
|
|
|
4
4
|
export { AssetDetailView } from './AssetDetailView';
|
|
5
5
|
export { CalibrationEntryDialog } from './CalibrationEntryDialog';
|
|
6
6
|
export { SubLocationPicker } from './SubLocationPicker';
|
|
7
|
+
export { PlaceholderHealthPanel } from './PlaceholderHealthPanel';
|
|
8
|
+
export { MissingAssetsBanner } from './MissingAssetsBanner';
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ams/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7H,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/ams/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7H,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{AmsProvider,useAms,useAmsSchemas,useAmsRoles,useAmsAlerts,useAmsAssets,useAmsSelection}from"./AmsProvider";export{AssetRegistryTable}from"./AssetRegistryTable";export{AssetDetailView}from"./AssetDetailView";export{CalibrationEntryDialog}from"./CalibrationEntryDialog";export{SubLocationPicker}from"./SubLocationPicker";
|
|
1
|
+
export{AmsProvider,useAms,useAmsSchemas,useAmsRoles,useAmsAlerts,useAmsAssets,useAmsSelection}from"./AmsProvider";export{AssetRegistryTable}from"./AssetRegistryTable";export{AssetDetailView}from"./AssetDetailView";export{CalibrationEntryDialog}from"./CalibrationEntryDialog";export{SubLocationPicker}from"./SubLocationPicker";export{PlaceholderHealthPanel}from"./PlaceholderHealthPanel";export{MissingAssetsBanner}from"./MissingAssetsBanner";
|
|
@@ -14,6 +14,8 @@ export { TestDataView } from './tis/TestDataView';
|
|
|
14
14
|
export type { TestDataViewProps, ChartAxis, ChartSeries, ChartView, RawDataShape } from './tis/TestDataView';
|
|
15
15
|
export { TestRawDataView } from './tis/TestRawDataView';
|
|
16
16
|
export type { TestRawDataViewProps } from './tis/TestRawDataView';
|
|
17
|
+
export { ProjectManager } from './tis/ProjectManager';
|
|
18
|
+
export type { ProjectManagerProps } from './tis/ProjectManager';
|
|
17
19
|
export { AmsProvider, useAms, useAmsSchemas, useAmsAlerts, useAmsAssets, useAmsSelection, } from './ams/AmsProvider';
|
|
18
20
|
export type { AmsProviderProps, AmsContextValue, AmsAlerts, AmsAssetEntry, AmsSelection, AmsSchemaRegistry, AmsTypeSchema, } from './ams/AmsProvider';
|
|
19
21
|
export { AssetRegistryTable } from './ams/AssetRegistryTable';
|
|
@@ -21,4 +23,10 @@ export { AssetDetailView } from './ams/AssetDetailView';
|
|
|
21
23
|
export { CalibrationEntryDialog } from './ams/CalibrationEntryDialog';
|
|
22
24
|
export type { CalibrationEntryDialogProps } from './ams/CalibrationEntryDialog';
|
|
23
25
|
export { SubLocationPicker } from './ams/SubLocationPicker';
|
|
26
|
+
export { NetworkProvider, useNetwork } from './network/NetworkProvider';
|
|
27
|
+
export type { NetworkProviderProps, NetworkContextValue, NetworkStatus, NetworkInterface, NetworkConnection, NetworkDeviceIp4, WifiAp, StagedChange, } from './network/NetworkProvider';
|
|
28
|
+
export { NetworkPanel } from './network/NetworkPanel';
|
|
29
|
+
export type { NetworkPanelProps } from './network/NetworkPanel';
|
|
30
|
+
export { StagedChangeBanner } from './network/StagedChangeBanner';
|
|
31
|
+
export type { StagedChangeBannerProps } from './network/StagedChangeBanner';
|
|
24
32
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACH,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,EACb,WAAW,EACX,eAAe,EACf,UAAU,EACV,SAAS,GACZ,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACR,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAU,uBAAuB,CAAC;AAC5D,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,MAAY,qBAAqB,CAAC;AAC1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,iBAAiB,EAAE,MAAQ,yBAAyB,CAAC;AAC9D,YAAY,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEvF,OAAO,EAAE,gBAAgB,EAAE,MAAS,wBAAwB,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,MAAO,0BAA0B,CAAC;AAC/D,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,MAAa,oBAAoB,CAAC;AACzD,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7G,OAAO,EAAE,eAAe,EAAE,MAAU,uBAAuB,CAAC;AAC5D,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACH,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,EACb,WAAW,EACX,eAAe,EACf,UAAU,EACV,SAAS,GACZ,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACR,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAU,uBAAuB,CAAC;AAC5D,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,MAAY,qBAAqB,CAAC;AAC1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,iBAAiB,EAAE,MAAQ,yBAAyB,CAAC;AAC9D,YAAY,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEvF,OAAO,EAAE,gBAAgB,EAAE,MAAS,wBAAwB,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,MAAO,0BAA0B,CAAC;AAC/D,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,MAAa,oBAAoB,CAAC;AACzD,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7G,OAAO,EAAE,eAAe,EAAE,MAAU,uBAAuB,CAAC;AAC5D,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,MAAW,sBAAsB,CAAC;AAC3D,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAMhE,OAAO,EACH,WAAW,EACX,MAAM,EACN,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,eAAe,GAClB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACR,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,aAAa,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAS,0BAA0B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAY,uBAAuB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,YAAY,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAU,yBAAyB,CAAC;AAShE,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACxE,YAAY,EACR,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,MAAM,EACN,YAAY,GACf,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,YAAY,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC"}
|
package/dist/components/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{TisProvider,TisContext,useTis,useTisSchemas,useTisState,useTisSelection,useTisRuns,useTisRun}from"./tis/TisProvider";export{ProjectSelector}from"./tis/ProjectSelector";export{TestSetupForm}from"./tis/TestSetupForm";export{ProjectInfoDialog}from"./tis/ProjectInfoDialog";export{TestMethodDialog}from"./tis/TestMethodDialog";export{ResultHistoryTable}from"./tis/ResultHistoryTable";export{TestDataView}from"./tis/TestDataView";export{TestRawDataView}from"./tis/TestRawDataView";export{AmsProvider,useAms,useAmsSchemas,useAmsAlerts,useAmsAssets,useAmsSelection}from"./ams/AmsProvider";export{AssetRegistryTable}from"./ams/AssetRegistryTable";export{AssetDetailView}from"./ams/AssetDetailView";export{CalibrationEntryDialog}from"./ams/CalibrationEntryDialog";export{SubLocationPicker}from"./ams/SubLocationPicker";
|
|
1
|
+
export{TisProvider,TisContext,useTis,useTisSchemas,useTisState,useTisSelection,useTisRuns,useTisRun}from"./tis/TisProvider";export{ProjectSelector}from"./tis/ProjectSelector";export{TestSetupForm}from"./tis/TestSetupForm";export{ProjectInfoDialog}from"./tis/ProjectInfoDialog";export{TestMethodDialog}from"./tis/TestMethodDialog";export{ResultHistoryTable}from"./tis/ResultHistoryTable";export{TestDataView}from"./tis/TestDataView";export{TestRawDataView}from"./tis/TestRawDataView";export{ProjectManager}from"./tis/ProjectManager";export{AmsProvider,useAms,useAmsSchemas,useAmsAlerts,useAmsAssets,useAmsSelection}from"./ams/AmsProvider";export{AssetRegistryTable}from"./ams/AssetRegistryTable";export{AssetDetailView}from"./ams/AssetDetailView";export{CalibrationEntryDialog}from"./ams/CalibrationEntryDialog";export{SubLocationPicker}from"./ams/SubLocationPicker";export{NetworkProvider,useNetwork}from"./network/NetworkProvider";export{NetworkPanel}from"./network/NetworkPanel";export{StagedChangeBanner}from"./network/StagedChangeBanner";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface NetworkPanelProps {
|
|
3
|
+
/** Optional CSS class on the outer container. */
|
|
4
|
+
className?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const NetworkPanel: React.FC<NetworkPanelProps>;
|
|
7
|
+
export default NetworkPanel;
|
|
8
|
+
//# sourceMappingURL=NetworkPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NetworkPanel.d.ts","sourceRoot":"","sources":["../../../src/components/network/NetworkPanel.tsx"],"names":[],"mappings":"AAeA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAuBnD,MAAM,WAAW,iBAAiB;IAC9B,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA6TpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useEffect,useState}from"react";import{Button}from"primereact/button";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Dialog}from"primereact/dialog";import{Password}from"primereact/password";import{InputSwitch}from"primereact/inputswitch";import{ConfirmDialog,confirmDialog}from"primereact/confirmdialog";import{useNetwork}from"./NetworkProvider";const signalBars=e=>e>=75?"▰▰▰▰":e>=50?"▰▰▰▱":e>=25?"▰▰▱▱":e>0?"▰▱▱▱":"▱▱▱▱",isSecured=e=>{const i=(e??"").trim();return i.length>0&&"--"!==i};export const NetworkPanel=({className:e})=>{const i=useNetwork(),[s,t]=useState(null),[r,n]=useState(""),[a,l]=useState(!1);useEffect(()=>{0!==i.aps.length||i.scanning||i.scanWifi()},[]);const o=i.status.interfaces.filter(e=>"ethernet"===e.type),d=i.status.interfaces.filter(e=>"wifi"===e.type),c=d.find(e=>"connected"===e.state)??d[0];return _jsxs("div",{className:e,style:{width:"100%",maxWidth:"100%",boxSizing:"border-box"},children:[_jsx(ConfirmDialog,{}),_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1rem",gap:"0.5rem",flexWrap:"wrap"},children:[_jsxs("div",{children:[_jsx("h3",{style:{margin:0},children:"Network"}),c?_jsxs("div",{style:{fontSize:"0.875rem",color:"#9ca3af",marginTop:"0.25rem"},children:["connected"===c.state?_jsxs(_Fragment,{children:["Connected to ",_jsx("code",{children:c.connection||"(unnamed)"})," on ",_jsx("code",{children:c.device})]}):_jsxs(_Fragment,{children:["WiFi: ",c.state]}),c.ip4.addresses.length>0&&_jsxs(_Fragment,{children:[" · ",c.ip4.addresses[0]]})]}):_jsx("div",{style:{fontSize:"0.875rem",color:"#9ca3af",marginTop:"0.25rem"},children:"No WiFi device detected."})]}),_jsxs("div",{style:{display:"flex",gap:"0.75rem",alignItems:"center",flexWrap:"wrap"},children:[_jsxs("label",{style:{display:"inline-flex",alignItems:"center",gap:"0.4rem"},children:[_jsx("span",{style:{fontSize:"0.875rem"},children:"WiFi radio"}),_jsx(InputSwitch,{checked:!!i.status.wifi_radio,onChange:e=>{i.setRadio(!!e.value)},disabled:null===i.status.wifi_radio})]}),_jsx(Button,{icon:"pi pi-refresh",label:"Refresh",size:"small",onClick:()=>{i.refreshStatus()}})]})]}),i.lastError&&_jsx("div",{style:{background:"#7f1d1d",color:"white",padding:"0.5rem 0.75rem",borderRadius:4,marginBottom:"1rem",fontSize:"0.875rem"},children:i.lastError}),_jsxs("div",{style:{marginBottom:"1.5rem",padding:"0.75rem 1rem",border:"1px solid #2a2a2a",borderRadius:4,background:"#161616"},children:[_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"0.75rem"},children:[_jsx("strong",{children:"WiFi Networks"}),_jsx(Button,{icon:i.scanning?"pi pi-spin pi-spinner":"pi pi-search",label:i.scanning?"Scanning…":"Scan",size:"small",outlined:!0,disabled:i.scanning||!1===i.status.wifi_radio,onClick:()=>{i.scanWifi()}})]}),_jsxs(DataTable,{value:i.aps,emptyMessage:!1===i.status.wifi_radio?"WiFi radio is off.":"No networks found yet. Click Scan to refresh.",scrollable:!0,scrollHeight:"20rem",tableStyle:{minWidth:0},style:{width:"100%"},children:[_jsx(Column,{header:"SSID",body:e=>_jsxs("span",{children:[e.in_use&&_jsx("i",{className:"pi pi-check",style:{marginRight:"0.4rem",color:"#22c55e"}}),e.ssid]}),style:{minWidth:"10rem"}}),_jsx(Column,{header:"Signal",body:e=>_jsxs("span",{style:{fontFamily:"monospace"},children:[signalBars(e.signal)," ",_jsxs("span",{style:{color:"#9ca3af"},children:[e.signal,"%"]})]}),style:{width:"10rem"},sortable:!0,sortField:"signal"}),_jsx(Column,{header:"Security",body:e=>_jsx("span",{children:isSecured(e.security)?e.security:"Open"}),style:{width:"8rem"}}),_jsx(Column,{header:"Action",style:{width:"9rem"},body:e=>_jsx(Button,{icon:"pi pi-link",label:e.in_use?"Reconnect":"Connect",size:"small",outlined:!0,disabled:!!i.staged,onClick:()=>(e=>{t(e),n("")})(e)})})]})]}),i.status.connections.length>0&&_jsxs("div",{style:{marginBottom:"1.5rem",padding:"0.75rem 1rem",border:"1px solid #2a2a2a",borderRadius:4,background:"#161616"},children:[_jsx("strong",{style:{display:"block",marginBottom:"0.75rem"},children:"Saved Connections"}),_jsxs(DataTable,{value:i.status.connections,emptyMessage:"No saved profiles.",tableStyle:{minWidth:0},style:{width:"100%"},children:[_jsx(Column,{field:"name",header:"Name",style:{minWidth:"10rem"}}),_jsx(Column,{field:"type",header:"Type",style:{width:"8rem"}}),_jsx(Column,{field:"device",header:"Device",style:{minWidth:"8rem"}}),_jsx(Column,{header:"Active",style:{width:"6rem"},body:e=>e.active?_jsx("i",{className:"pi pi-check",style:{color:"#22c55e"}}):null}),_jsx(Column,{header:"Action",style:{width:"8rem"},body:e=>"wifi"===e.type?_jsx(Button,{icon:"pi pi-trash",label:"Forget",size:"small",severity:"danger",outlined:!0,onClick:()=>{var s;confirmDialog({header:"Forget network",icon:"pi pi-exclamation-triangle",acceptLabel:"Forget",rejectLabel:"Cancel",acceptClassName:"p-button-danger",message:_jsxs("div",{children:[_jsxs("p",{style:{marginTop:0},children:["Remove saved profile ",_jsx("code",{children:(s=e).name}),"?"]}),_jsx("p",{style:{marginBottom:0,fontSize:"0.875rem",color:"#9ca3af"},children:"The password is deleted. You'll need to re-enter it next time you connect to this network."})]}),accept:()=>{i.forgetConnection(s.uuid)}})}}):null})]})]}),_jsxs("div",{style:{padding:"0.75rem 1rem",border:"1px solid #2a2a2a",borderRadius:4,background:"#161616"},children:[_jsx("strong",{style:{display:"block",marginBottom:"0.25rem"},children:"Wired Interfaces"}),_jsx("div",{style:{fontSize:"0.75rem",color:"#6b7280",marginBottom:"0.75rem"},children:"Wired configuration is managed by netplan and is read-only here."}),_jsxs(DataTable,{value:o,emptyMessage:"No wired interfaces.",tableStyle:{minWidth:0},style:{width:"100%"},children:[_jsx(Column,{field:"device",header:"Device",style:{minWidth:"8rem"}}),_jsx(Column,{field:"state",header:"State",style:{width:"8rem"}}),_jsx(Column,{header:"IP Address",body:e=>e.ip4.addresses.length>0?e.ip4.addresses.join(", "):_jsx("span",{style:{color:"#6b7280"},children:"—"}),style:{minWidth:"10rem"}}),_jsx(Column,{header:"Gateway",body:e=>e.ip4.gateway||_jsx("span",{style:{color:"#6b7280"},children:"—"}),style:{minWidth:"8rem"}}),_jsx(Column,{header:"DNS",body:e=>e.ip4.dns.length>0?e.ip4.dns.join(", "):_jsx("span",{style:{color:"#6b7280"},children:"—"}),style:{minWidth:"8rem"}})]})]}),_jsx(Dialog,{header:s?`Connect to ${s.ssid}`:"Connect",visible:!!s,style:{width:"24rem"},onHide:()=>{a||t(null)},modal:!0,draggable:!1,children:s&&_jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"0.75rem"},children:[_jsxs("div",{style:{fontSize:"0.875rem",color:"#9ca3af"},children:[_jsxs("div",{children:["Signal: ",s.signal,"%"]}),_jsxs("div",{children:["Security: ",isSecured(s.security)?s.security:"Open"]})]}),isSecured(s.security)?_jsxs(_Fragment,{children:[_jsx("label",{htmlFor:"nw-pw",style:{fontSize:"0.875rem"},children:"Password"}),_jsx(Password,{inputId:"nw-pw",value:r,onChange:e=>n(e.target.value),feedback:!1,toggleMask:!0,autoFocus:!0})]}):_jsx("div",{style:{fontSize:"0.875rem"},children:"This is an open network. No password required."}),_jsx("div",{style:{background:"#78350f",color:"white",padding:"0.5rem 0.75rem",borderRadius:4,fontSize:"0.875rem"},children:"After connecting, you have 60 seconds to confirm the change. If you don't, the server will auto-revert to the previous network — that way a bad password from a remote session can't lock you out."}),_jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.4rem"},children:[_jsx(Button,{label:"Cancel",outlined:!0,onClick:()=>t(null),disabled:a}),_jsx(Button,{label:a?"Connecting…":"Connect",icon:a?"pi pi-spin pi-spinner":"pi pi-link",onClick:()=>{(async()=>{if(s){l(!0);try{const e=isSecured(s.security)?r:void 0;await i.wifiConnect(s.ssid,e)&&(t(null),n(""))}finally{l(!1)}}})()},disabled:a||isSecured(s.security)&&0===r.length})]})]})})]})};export default NetworkPanel;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React, { type ReactNode } from 'react';
|
|
2
|
+
export interface NetworkDeviceIp4 {
|
|
3
|
+
addresses: string[];
|
|
4
|
+
gateway: string;
|
|
5
|
+
dns: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface NetworkInterface {
|
|
8
|
+
device: string;
|
|
9
|
+
type: string;
|
|
10
|
+
state: string;
|
|
11
|
+
connection: string;
|
|
12
|
+
ip4: NetworkDeviceIp4;
|
|
13
|
+
}
|
|
14
|
+
export interface NetworkConnection {
|
|
15
|
+
name: string;
|
|
16
|
+
uuid: string;
|
|
17
|
+
type: string;
|
|
18
|
+
device: string;
|
|
19
|
+
active: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface WifiAp {
|
|
22
|
+
ssid: string;
|
|
23
|
+
bssid: string;
|
|
24
|
+
signal: number;
|
|
25
|
+
security: string;
|
|
26
|
+
in_use: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface StagedChange {
|
|
29
|
+
staged_id: string;
|
|
30
|
+
device: string;
|
|
31
|
+
ssid: string;
|
|
32
|
+
prev_connection_uuid: string;
|
|
33
|
+
new_connection_uuid: string;
|
|
34
|
+
new_profile_created: boolean;
|
|
35
|
+
revert_in_seconds: number;
|
|
36
|
+
/**
|
|
37
|
+
* Absolute deadline (ms since epoch) computed when the staged
|
|
38
|
+
* change was received. The banner uses this to render a
|
|
39
|
+
* monotonically-decreasing countdown that doesn't depend on
|
|
40
|
+
* `revert_in_seconds` staying fresh in React state.
|
|
41
|
+
*/
|
|
42
|
+
deadline_ms: number;
|
|
43
|
+
}
|
|
44
|
+
export interface NetworkStatus {
|
|
45
|
+
interfaces: NetworkInterface[];
|
|
46
|
+
connections: NetworkConnection[];
|
|
47
|
+
wifi_radio: boolean | null;
|
|
48
|
+
}
|
|
49
|
+
export interface NetworkContextValue {
|
|
50
|
+
status: NetworkStatus;
|
|
51
|
+
statusLoaded: boolean;
|
|
52
|
+
refreshStatus: () => Promise<void>;
|
|
53
|
+
aps: WifiAp[];
|
|
54
|
+
scanning: boolean;
|
|
55
|
+
scanWifi: (device?: string) => Promise<void>;
|
|
56
|
+
/** Latest pending stage, or null when none in flight. */
|
|
57
|
+
staged: StagedChange | null;
|
|
58
|
+
/** Connect to an SSID; returns the staged change record on success. */
|
|
59
|
+
wifiConnect: (ssid: string, password?: string, device?: string) => Promise<StagedChange | null>;
|
|
60
|
+
confirmConnection: (stagedId: string) => Promise<boolean>;
|
|
61
|
+
cancelStaged: (stagedId: string) => Promise<boolean>;
|
|
62
|
+
forgetConnection: (uuid: string) => Promise<boolean>;
|
|
63
|
+
setRadio: (enabled: boolean) => Promise<boolean>;
|
|
64
|
+
/** Most recent error from any network action, or empty string. */
|
|
65
|
+
lastError: string;
|
|
66
|
+
}
|
|
67
|
+
export interface NetworkProviderProps {
|
|
68
|
+
children: ReactNode;
|
|
69
|
+
}
|
|
70
|
+
export declare const NetworkProvider: React.FC<NetworkProviderProps>;
|
|
71
|
+
export declare const useNetwork: () => NetworkContextValue;
|
|
72
|
+
//# sourceMappingURL=NetworkProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NetworkProvider.d.ts","sourceRoot":"","sources":["../../../src/components/network/NetworkProvider.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,EAOV,KAAK,SAAS,EACjB,MAAM,OAAO,CAAC;AAQf,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,gBAAgB,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,MAAM;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC1B,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAChC,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,yDAAyD;IACzD,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAE5B,uEAAuE;IACvE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAChG,iBAAiB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACrD,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACrD,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjD,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;CACrB;AA4BD,MAAM,WAAW,oBAAoB;IACjC,QAAQ,EAAE,SAAS,CAAC;CACvB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA0M1D,CAAC;AAMF,eAAO,MAAM,UAAU,2BAAmC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx}from"react/jsx-runtime";import React,{createContext,useCallback,useContext,useEffect,useMemo,useState}from"react";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";const EMPTY_STATUS={interfaces:[],connections:[],wifi_radio:null},NetworkContext=createContext({status:EMPTY_STATUS,statusLoaded:!1,refreshStatus:async()=>{},aps:[],scanning:!1,scanWifi:async()=>{},staged:null,wifiConnect:async()=>null,confirmConnection:async()=>!1,cancelStaged:async()=>!1,forgetConnection:async()=>!1,setRadio:async()=>!1,lastError:""});export const NetworkProvider=({children:e})=>{const{invoke:t,subscribe:s,unsubscribe:n}=useContext(EventEmitterContext),[a,r]=useState(EMPTY_STATUS),[c,i]=useState(!1),[o,d]=useState([]),[u,_]=useState(!1),[g,l]=useState(null),[f,w]=useState(""),m=useCallback(async()=>{try{const[e,s]=await Promise.all([t("nw.list_interfaces",MessageType.Request,{}),t("nw.status",MessageType.Request,{})]),n=e?.success?e.data?.interfaces??[]:[],a=s?.success?s.data?.connections??[]:[],c=s?.success&&"boolean"==typeof s.data?.wifi_radio?s.data.wifi_radio:null;r({interfaces:n,connections:a,wifi_radio:c}),i(!0),w(e?.success?s?.success?"":s?.error_message??"":e?.error_message??"")}catch(e){w(e instanceof Error?e.message:String(e))}},[t]);useEffect(()=>{m()},[m]),useEffect(()=>{const e=[s("nw.staged_change",e=>{if(!e||"object"!=typeof e)return;const t=Number(e.revert_in_seconds??0);l({staged_id:String(e.staged_id??""),device:String(e.device??""),ssid:String(e.ssid??""),prev_connection_uuid:String(e.prev_connection_uuid??""),new_connection_uuid:String(e.new_connection_uuid??""),new_profile_created:!!e.new_profile_created,revert_in_seconds:t,deadline_ms:Date.now()+1e3*t})}),s("nw.confirmed",e=>{const t=String(e?.staged_id??"");l(e=>e&&e.staged_id===t?null:e),m()}),s("nw.revert_fired",e=>{const t=String(e?.staged_id??"");l(e=>e&&e.staged_id===t?null:e),m()}),s("nw.connection_deleted",()=>{m()})];return()=>{e.forEach(n)}},[s,n,m]);const S=useCallback(async e=>{_(!0),w("");try{const s={};e&&(s.device=e);const n=await t("nw.scan_wifi",MessageType.Request,s);n?.success?d(n.data?.access_points??[]):w(n?.error_message??"scan_wifi failed")}catch(e){w(e instanceof Error?e.message:String(e))}finally{_(!1)}},[t]),y=useCallback(async(e,s,n)=>{w("");try{const a={ssid:e};s&&(a.password=s),n&&(a.device=n);const r=await t("nw.wifi_connect",MessageType.Request,a);if(!r?.success)return w(r?.error_message??"wifi_connect failed"),null;const c=Number(r.data?.revert_in_seconds??0),i={staged_id:String(r.data?.staged_id??""),device:String(r.data?.device??""),ssid:String(r.data?.ssid??e),prev_connection_uuid:String(r.data?.prev_connection_uuid??""),new_connection_uuid:String(r.data?.new_connection_uuid??""),new_profile_created:!!r.data?.new_profile_created,revert_in_seconds:c,deadline_ms:Date.now()+1e3*c};return l(i),i}catch(e){return w(e instanceof Error?e.message:String(e)),null}},[t]),p=useCallback(async e=>{try{const s=await t("nw.confirm_connection",MessageType.Request,{staged_id:e});return s?.success?(l(t=>t&&t.staged_id===e?null:t),!0):(w(s?.error_message??"confirm_connection failed"),!1)}catch(e){return w(e instanceof Error?e.message:String(e)),!1}},[t]),C=useCallback(async e=>{try{const s=await t("nw.cancel_staged",MessageType.Request,{staged_id:e});return!!s?.success}catch(e){return w(e instanceof Error?e.message:String(e)),!1}},[t]),v=useCallback(async e=>{try{const s=await t("nw.forget_connection",MessageType.Request,{uuid:e});return s?.success?(m(),!0):(w(s?.error_message??"forget_connection failed"),!1)}catch(e){return w(e instanceof Error?e.message:String(e)),!1}},[t,m]),E=useCallback(async e=>{try{const s=await t("nw.set_radio",MessageType.Request,{enabled:e});return s?.success?(r(t=>({...t,wifi_radio:e})),!0):(w(s?.error_message??"set_radio failed"),!1)}catch(e){return w(e instanceof Error?e.message:String(e)),!1}},[t]),b=useMemo(()=>({status:a,statusLoaded:c,refreshStatus:m,aps:o,scanning:u,scanWifi:S,staged:g,wifiConnect:y,confirmConnection:p,cancelStaged:C,forgetConnection:v,setRadio:E,lastError:f}),[a,c,m,o,u,S,g,y,p,C,v,E,f]);return _jsx(NetworkContext.Provider,{value:b,children:e})};export const useNetwork=()=>useContext(NetworkContext);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface StagedChangeBannerProps {
|
|
3
|
+
/** Override the banner placement. Defaults to a fixed top bar. */
|
|
4
|
+
style?: React.CSSProperties;
|
|
5
|
+
}
|
|
6
|
+
export declare const StagedChangeBanner: React.FC<StagedChangeBannerProps>;
|
|
7
|
+
export default StagedChangeBanner;
|
|
8
|
+
//# sourceMappingURL=StagedChangeBanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StagedChangeBanner.d.ts","sourceRoot":"","sources":["../../../src/components/network/StagedChangeBanner.tsx"],"names":[],"mappings":"AAYA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,MAAM,WAAW,uBAAuB;IACpC,kEAAkE;IAClE,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC/B;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA6EhE,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useEffect,useState}from"react";import{Button}from"primereact/button";import{useNetwork}from"./NetworkProvider";export const StagedChangeBanner=({style:e})=>{const{staged:t,confirmConnection:i,cancelStaged:n}=useNetwork(),[r,s]=useState(()=>Date.now());if(useEffect(()=>{if(!t)return;const e=window.setInterval(()=>s(Date.now()),250);return()=>window.clearInterval(e)},[t]),!t)return null;const o=Math.max(0,Math.ceil((t.deadline_ms-r)/1e3)),a=Math.max(1,t.revert_in_seconds),d=Math.max(0,Math.min(100,o/a*100)),l={position:"sticky",top:0,zIndex:1e3,padding:"0.75rem 1rem",background:o<=10?"#7f1d1d":"#78350f",color:"white",borderBottom:"1px solid #1f2937",boxShadow:"0 2px 4px rgba(0, 0, 0, 0.3)",...e};return _jsxs("div",{style:l,role:"alertdialog","aria-live":"polite",children:[_jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:"1rem",flexWrap:"wrap"},children:[_jsxs("div",{style:{minWidth:0},children:[_jsx("strong",{children:"WiFi change pending:"})," ","connected to ",_jsx("code",{children:t.ssid})," on ",_jsx("code",{children:t.device})]}),_jsxs("div",{style:{fontVariantNumeric:"tabular-nums",fontSize:"1.1rem"},children:["Reverting in ",_jsxs("strong",{children:[o,"s"]})]}),_jsxs("div",{style:{display:"flex",gap:"0.4rem"},children:[_jsx(Button,{label:"Confirm",icon:"pi pi-check",size:"small",severity:"success",onClick:()=>{i(t.staged_id)}}),_jsx(Button,{label:"Cancel & Revert",icon:"pi pi-undo",size:"small",severity:"danger",outlined:!0,onClick:()=>{n(t.staged_id)}})]})]}),_jsx("div",{style:{marginTop:"0.5rem",height:"0.25rem",background:"rgba(255, 255, 255, 0.2)",borderRadius:0,overflow:"hidden"},children:_jsx("div",{style:{width:`${d}%`,height:"100%",background:"white",transition:"width 0.25s linear"}})})]})};export default StagedChangeBanner;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { NetworkProvider, useNetwork } from './NetworkProvider';
|
|
2
|
+
export type { NetworkProviderProps, NetworkContextValue, NetworkStatus, NetworkInterface, NetworkConnection, NetworkDeviceIp4, WifiAp, StagedChange, } from './NetworkProvider';
|
|
3
|
+
export { NetworkPanel } from './NetworkPanel';
|
|
4
|
+
export type { NetworkPanelProps } from './NetworkPanel';
|
|
5
|
+
export { StagedChangeBanner } from './StagedChangeBanner';
|
|
6
|
+
export type { StagedChangeBannerProps } from './StagedChangeBanner';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/network/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAChE,YAAY,EACR,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,MAAM,EACN,YAAY,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{NetworkProvider,useNetwork}from"./NetworkProvider";export{NetworkPanel}from"./NetworkPanel";export{StagedChangeBanner}from"./StagedChangeBanner";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface ProjectManagerProps {
|
|
3
|
+
/** Override the project scope. Defaults to `useTis().selection.projectId`. */
|
|
4
|
+
projectId?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const ProjectManager: React.FC<ProjectManagerProps>;
|
|
7
|
+
//# sourceMappingURL=ProjectManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProjectManager.d.ts","sourceRoot":"","sources":["../../../src/components/tis/ProjectManager.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAuD,MAAM,OAAO,CAAC;AAU5E,MAAM,WAAW,mBAAmB;IAChC,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAyBD,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAgVxD,CAAC"}
|