@adcops/autocore-react 3.3.73 → 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.
Files changed (75) hide show
  1. package/dist/assets/HomeMotor.d.ts +4 -0
  2. package/dist/assets/HomeMotor.d.ts.map +1 -0
  3. package/dist/assets/HomeMotor.js +1 -0
  4. package/dist/assets/svg/home_motor.svg +57 -0
  5. package/dist/components/Indicator.d.ts +29 -52
  6. package/dist/components/Indicator.d.ts.map +1 -1
  7. package/dist/components/Indicator.js +1 -1
  8. package/dist/components/ValueInput.d.ts +1 -1
  9. package/dist/components/ValueInput.d.ts.map +1 -1
  10. package/dist/components/ams/AmsProvider.d.ts +7 -0
  11. package/dist/components/ams/AmsProvider.d.ts.map +1 -1
  12. package/dist/components/ams/AssetDetailView.d.ts.map +1 -1
  13. package/dist/components/ams/AssetDetailView.js +1 -1
  14. package/dist/components/ams/AssetRegistryTable.d.ts.map +1 -1
  15. package/dist/components/ams/AssetRegistryTable.js +1 -1
  16. package/dist/components/ams/CalibrationEntryDialog.d.ts.map +1 -1
  17. package/dist/components/ams/CalibrationEntryDialog.js +1 -1
  18. package/dist/components/ams/MissingAssetsBanner.d.ts +11 -0
  19. package/dist/components/ams/MissingAssetsBanner.d.ts.map +1 -0
  20. package/dist/components/ams/MissingAssetsBanner.js +1 -0
  21. package/dist/components/ams/PlaceholderHealthPanel.d.ts +3 -0
  22. package/dist/components/ams/PlaceholderHealthPanel.d.ts.map +1 -0
  23. package/dist/components/ams/PlaceholderHealthPanel.js +1 -0
  24. package/dist/components/ams/index.d.ts +2 -0
  25. package/dist/components/ams/index.d.ts.map +1 -1
  26. package/dist/components/ams/index.js +1 -1
  27. package/dist/components/index.d.ts +8 -0
  28. package/dist/components/index.d.ts.map +1 -1
  29. package/dist/components/index.js +1 -1
  30. package/dist/components/network/NetworkPanel.d.ts +8 -0
  31. package/dist/components/network/NetworkPanel.d.ts.map +1 -0
  32. package/dist/components/network/NetworkPanel.js +1 -0
  33. package/dist/components/network/NetworkProvider.d.ts +72 -0
  34. package/dist/components/network/NetworkProvider.d.ts.map +1 -0
  35. package/dist/components/network/NetworkProvider.js +1 -0
  36. package/dist/components/network/StagedChangeBanner.d.ts +8 -0
  37. package/dist/components/network/StagedChangeBanner.d.ts.map +1 -0
  38. package/dist/components/network/StagedChangeBanner.js +1 -0
  39. package/dist/components/network/index.d.ts +7 -0
  40. package/dist/components/network/index.d.ts.map +1 -0
  41. package/dist/components/network/index.js +1 -0
  42. package/dist/components/tis/ProjectManager.d.ts +7 -0
  43. package/dist/components/tis/ProjectManager.d.ts.map +1 -0
  44. package/dist/components/tis/ProjectManager.js +1 -0
  45. package/dist/components/tis/ResultHistoryTable.d.ts.map +1 -1
  46. package/dist/components/tis/ResultHistoryTable.js +1 -1
  47. package/dist/components/tis/TestDataView.d.ts.map +1 -1
  48. package/dist/components/tis/TestDataView.js +1 -1
  49. package/dist/components/tis/TestRawDataView.d.ts.map +1 -1
  50. package/dist/components/tis/TestRawDataView.js +1 -1
  51. package/dist/components/tis/TestSetupForm.d.ts +7 -0
  52. package/dist/components/tis/TestSetupForm.d.ts.map +1 -1
  53. package/dist/components/tis/TestSetupForm.js +1 -1
  54. package/package.json +5 -1
  55. package/src/assets/HomeMotor.tsx +37 -0
  56. package/src/assets/svg/home_motor.svg +57 -0
  57. package/src/components/Indicator.tsx +166 -162
  58. package/src/components/ValueInput.tsx +2 -2
  59. package/src/components/ams/AmsProvider.tsx +7 -0
  60. package/src/components/ams/AssetDetailView.tsx +287 -4
  61. package/src/components/ams/AssetRegistryTable.tsx +325 -21
  62. package/src/components/ams/CalibrationEntryDialog.tsx +163 -30
  63. package/src/components/ams/MissingAssetsBanner.tsx +124 -0
  64. package/src/components/ams/PlaceholderHealthPanel.tsx +188 -0
  65. package/src/components/ams/index.ts +2 -0
  66. package/src/components/index.ts +26 -0
  67. package/src/components/network/NetworkPanel.tsx +363 -0
  68. package/src/components/network/NetworkProvider.tsx +349 -0
  69. package/src/components/network/StagedChangeBanner.tsx +101 -0
  70. package/src/components/network/index.ts +17 -0
  71. package/src/components/tis/ProjectManager.tsx +392 -0
  72. package/src/components/tis/ResultHistoryTable.tsx +125 -74
  73. package/src/components/tis/TestDataView.tsx +160 -14
  74. package/src/components/tis/TestRawDataView.tsx +118 -8
  75. package/src/components/tis/TestSetupForm.tsx +42 -1
@@ -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"}
@@ -0,0 +1 @@
1
+ import{jsx as _jsx,Fragment as _Fragment,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{ConfirmDialog,confirmDialog}from"primereact/confirmdialog";import{ProgressBar}from"primereact/progressbar";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";const formatBytes=e=>{if(!Number.isFinite(e)||e<=0)return"0 B";const t=["B","KiB","MiB","GiB","TiB","PiB"];let r=0,s=e;for(;s>=1024&&r<t.length-1;)s/=1024,r++;return`${s.toFixed(s>=100?0:s>=10?1:2)} ${t[r]}`},formatDate=e=>{if(!e)return"";const t=new Date(e);return Number.isNaN(t.getTime())?e:t.toLocaleString()};export const ProjectManager=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,{invoke:s}=useContext(EventEmitterContext),[i,a]=useState([]),[o,n]=useState(!1),[l,c]=useState(null),[d,m]=useState(!1),[p,u]=useState(!1),[f,h]=useState(null),[g,_]=useState(""),y=useCallback(async()=>{if(r){n(!0);try{const e=await s("tis.list_tests",MessageType.Request,{project_id:r});e?.success&&e.data?.tests?a(e.data.tests):a([])}catch(e){a([])}finally{n(!1)}}else a([])},[r,s]),j=useCallback(async()=>{try{const e=await s("tis.disk_usage",MessageType.Request,{});e?.success&&e.data?(h(e.data),_("")):(h(null),_(e?.error_message??"disk_usage failed"))}catch(e){h(null),_(e instanceof Error?e.message:String(e))}},[s]);useEffect(()=>{y()},[y,t.state.activeRunId]),useEffect(()=>{j()},[j]);const b=e=>{const i=e?.run_id??"",a=e?.sample_id??"";confirmDialog({header:"Delete test",icon:"pi pi-exclamation-triangle",acceptLabel:"Delete",rejectLabel:"Cancel",acceptClassName:"p-button-danger",message:_jsxs("div",{children:[_jsxs("p",{style:{marginTop:0},children:["Permanently delete run ",_jsx("code",{children:i}),a?_jsxs(_Fragment,{children:[" (sample ",_jsx("code",{children:a}),")"]}):null,"?"]}),_jsxs("p",{style:{marginBottom:0,fontSize:"0.875rem",color:"#9ca3af"},children:["Removes ",_jsx("code",{children:"test.json"}),", cycles, raw and filtered data for this run. This action cannot be undone."]})]}),accept:()=>{(async e=>{const i=e?.run_id,a=e?.method_id;if(r&&a&&i){c(i);try{const e=await s("tis.delete_test",MessageType.Request,{project_id:r,method_id:a,run_id:i});if(!e?.success)return void alert(`Failed to delete test ${i}`+(e?.error_message?`: ${e.error_message}`:""));await y(),t.selection.runId===i&&t.setSelection({runId:null})}catch(e){alert(`Delete failed: ${e instanceof Error?e.message:String(e)}`)}finally{c(null)}}})(e)}})},x=e=>{const t="string"==typeof e?.sample_id?e.sample_id:"";if(t)return t;const r=e?.config;return r&&"object"==typeof r&&"string"==typeof r.sample_id?r.sample_id:""},v=f&&f.total_bytes>0?Math.min(100,Math.round(f.used_bytes/f.total_bytes*100)):0;return _jsxs("div",{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:[_jsx("h3",{style:{margin:0},children:r?`Project Manager: ${r}`:"Project Manager (no project selected)"}),_jsxs("div",{style:{display:"flex",gap:"0.4rem",alignItems:"center",flexWrap:"wrap"},children:[_jsx(Button,{icon:p?"pi pi-spin pi-spinner":"pi pi-box",label:"Download Archive",size:"small",outlined:!0,disabled:!r||p||d,onClick:async()=>{if(r){u(!0);try{const e=await s("tis.export_project_zip",MessageType.Request,{project_id:r});if(!e?.success)return void alert("Failed to build project archive"+(e?.error_message?`: ${e.error_message}`:""));const t="string"==typeof e.data?.download_url?e.data.download_url:"";if(!t)return void alert("Server did not return a download URL for the archive.");const i=document.createElement("a");i.href=t,i.download="string"==typeof e.data?.filename?e.data.filename:`${r}_project_archive.zip`,document.body.appendChild(i),i.click(),i.remove()}catch(e){alert(`Download failed: ${e instanceof Error?e.message:String(e)}`)}finally{u(!1)}}},tooltip:"Download a ZIP of the entire project directory",tooltipOptions:{position:"bottom"}}),_jsx(Button,{icon:d?"pi pi-spin pi-spinner":"pi pi-trash",label:"Delete Project",size:"small",severity:"danger",disabled:!r||d||p,onClick:()=>{if(!r)return;const e=i.length;confirmDialog({header:"Delete project",icon:"pi pi-exclamation-triangle",acceptLabel:"Delete Project",rejectLabel:"Cancel",acceptClassName:"p-button-danger",message:_jsxs("div",{children:[_jsxs("p",{style:{marginTop:0},children:["Permanently delete project ",_jsx("code",{children:r})," and all ",_jsx("strong",{children:e})," test",1===e?"":"s"," inside it?"]}),_jsx("p",{style:{marginBottom:0,fontSize:"0.875rem",color:"#9ca3af"},children:"This removes every method, run, cycle, and raw/filtered blob under the project. Consider downloading the archive first. This action cannot be undone."})]}),accept:()=>{(async()=>{if(r){m(!0);try{const e=await s("tis.delete_project",MessageType.Request,{project_id:r});if(!e?.success)return void alert(`Failed to delete project ${r}`+(e?.error_message?`: ${e.error_message}`:""));t.setSelection({projectId:null,methodId:null,sampleId:null,runId:null}),await t.refreshProjects(),await j(),a([])}catch(e){alert(`Delete failed: ${e instanceof Error?e.message:String(e)}`)}finally{m(!1)}}})()}})},tooltip:"Permanently delete the project and every test inside it",tooltipOptions:{position:"bottom"}}),_jsx(Button,{icon:"pi pi-refresh",label:"Refresh",size:"small",onClick:()=>{y(),j()},disabled:o})]})]}),_jsxs("div",{style:{marginBottom:"1rem",padding:"0.75rem 1rem",border:"1px solid #2a2a2a",borderRadius:4,background:"#161616"},children:[_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"baseline",flexWrap:"wrap",gap:"0.5rem"},children:[_jsx("strong",{children:"Server Disk Space"}),f?_jsxs("span",{style:{fontSize:"0.875rem",color:"#9ca3af"},children:[formatBytes(f.available_bytes)," free of ",formatBytes(f.total_bytes)," ","(",100-v,"% available)"]}):_jsx("span",g?{style:{fontSize:"0.875rem",color:"#f87171"},children:g}:{style:{fontSize:"0.875rem",color:"#9ca3af"},children:"Loading…"})]}),f&&_jsxs(_Fragment,{children:[_jsx(ProgressBar,{value:v,showValue:!1,style:{height:"0.5rem",marginTop:"0.5rem"},color:v>=90?"#dc2626":v>=75?"#f59e0b":void 0}),_jsx("div",{style:{fontSize:"0.75rem",color:"#6b7280",marginTop:"0.4rem"},children:_jsx("code",{children:f.base_directory})})]})]}),_jsxs(DataTable,{value:i,loading:o,paginator:!0,rows:10,emptyMessage:r?"No tests in this project.":"Select a project to manage.",scrollable:!0,scrollHeight:"flex",tableStyle:{minWidth:0},style:{width:"100%"},children:[_jsx(Column,{header:"Sample ID",body:x,sortable:!0,sortFunction:e=>{const t=[...e.data];return t.sort((t,r)=>x(t).localeCompare(x(r))*(e.order??1)),t},style:{minWidth:"8rem"}}),_jsx(Column,{field:"start_time",header:"Date/Time",sortable:!0,body:e=>formatDate(e.start_time),style:{minWidth:"12rem"}}),_jsx(Column,{field:"method_id",header:"Test Method",sortable:!0,style:{minWidth:"10rem"}}),_jsx(Column,{field:"run_id",header:"Run ID",sortable:!0,style:{minWidth:"12rem"}}),_jsx(Column,{header:"Action",style:{width:"8rem"},body:e=>{const t=l===e.run_id;return _jsx(Button,{icon:t?"pi pi-spin pi-spinner":"pi pi-trash",label:"Delete",size:"small",severity:"danger",outlined:!0,disabled:null!==l||d,onClick:()=>b(e),tooltip:"Permanently delete this test",tooltipOptions:{position:"left"}})}})]})]})};
@@ -1 +1 @@
1
- {"version":3,"file":"ResultHistoryTable.d.ts","sourceRoot":"","sources":["../../../src/components/tis/ResultHistoryTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAQ/D,MAAM,WAAW,uBAAuB;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAwDD,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAqMhE,CAAC"}
1
+ {"version":3,"file":"ResultHistoryTable.d.ts","sourceRoot":"","sources":["../../../src/components/tis/ResultHistoryTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAQ/D,MAAM,WAAW,uBAAuB;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAwBD,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAwRhE,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useEffect,useContext}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Button}from"primereact/button";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";const rawBlobToCsv=e=>{if(!e||"object"!=typeof e)return"";const t=Object.entries(e).filter(([,e])=>Array.isArray(e));if(0===t.length)return"";t.sort(([e],[t])=>"t"===e?-1:"t"===t?1:0);const r=t.map(([e])=>e),o=t.reduce((e,[,t])=>Math.min(e,t.length),1/0),s=e=>{if(null==e)return"";const t=String(e);return/[",\n\r]/.test(t)?`"${t.replace(/"/g,'""')}"`:t},i=[r.join(",")];for(let e=0;e<o;e++)i.push(t.map(([,t])=>s(t[e])).join(","));return i.join("\n")},downloadCsv=(e,t)=>{const r=new Blob([t],{type:"text/csv;charset=utf-8;"}),o=URL.createObjectURL(r),s=document.createElement("a");s.href=o,s.download=e,document.body.appendChild(s),s.click(),s.remove(),URL.revokeObjectURL(o)};export const ResultHistoryTable=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,o=e.methodId,[s,i]=useState([]),[n,a]=useState(!1),[l,d]=useState(null),{invoke:c}=useContext(EventEmitterContext),m=async()=>{if(r){a(!0);try{const e={project_id:r};o&&(e.method_id=o);const t=await c("tis.list_tests",MessageType.Request,e);t.success&&t.data&&t.data.tests&&i(t.data.tests)}catch(e){}a(!1)}else i([])};useEffect(()=>{m()},[r,o,t.state.activeRunId]);const u=async(e,t)=>{const s=e?.run_id,i=e?.method_id??o;if(!s||!i)return;const n="raw"===t?"tis.read_raw":"tis.read_filtered",a="raw"===t?"raw trace":"filtered trace",l="raw"===t?"raw":"filtered";d({runId:s,kind:t});try{const e=await c(n,MessageType.Request,{project_id:r,method_id:i,run_id:s,name:"trace"});if(!e?.success||!e.data)return void alert(`No ${a} available for ${s}`+(e?.error_message?`: ${e.error_message}`:""));const t=rawBlobToCsv(e.data);if(!t)return void alert(`${a} for ${s} is empty or has no array columns.`);downloadCsv(`${r}_${i}_${s}_${l}.csv`,t)}catch(e){alert(`Download failed: ${e instanceof Error?e.message:String(e)}`)}finally{d(null)}},p=e=>{const t="string"==typeof e?.sample_id?e.sample_id:"";if(t)return t;const r=e?.config;return r&&"object"==typeof r&&"string"==typeof r.sample_id?r.sample_id:""};return _jsxs("div",{style:{width:"100%",maxWidth:"100%",overflow:"hidden",boxSizing:"border-box"},children:[_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1rem"},children:[_jsx("h3",{style:{margin:0},children:r?`Test History: ${r}${o?` / ${o}`:""}`:"Test History (no project selected)"}),_jsx(Button,{icon:"pi pi-refresh",label:"Refresh",onClick:m,disabled:n})]}),_jsxs(DataTable,{value:s,loading:n,paginator:!0,rows:10,emptyMessage:"No tests found.",scrollable:!0,scrollHeight:"flex",tableStyle:{minWidth:0},style:{width:"100%"},selectionMode:"single",onSelectionChange:e=>{const r=e.value;r?.run_id&&t.setSelection({projectId:r.project_id??null,methodId:r.method_id??null,runId:r.run_id})},children:[_jsx(Column,{header:"Sample ID",sortable:!0,body:p,sortFunction:e=>{const t=[...e.data];return t.sort((t,r)=>p(t).localeCompare(p(r))*(e.order??1)),t},style:{minWidth:"8rem"}}),_jsx(Column,{field:"start_time",header:"Date/Time",sortable:!0,body:e=>{return(t=e.start_time)?new Date(t).toLocaleString():"";var t},style:{minWidth:"12rem"}}),_jsx(Column,{field:"method_id",header:"Test Method",sortable:!0,style:{minWidth:"10rem"}}),_jsx(Column,{field:"run_id",header:"Run ID",sortable:!0,style:{minWidth:"12rem"}}),_jsx(Column,{header:"Download",style:{width:"14rem"},body:e=>{const t=l?.runId===e.run_id&&"raw"===l?.kind,r=l?.runId===e.run_id&&"filtered"===l?.kind,o=null!==l;return _jsxs("div",{style:{display:"flex",gap:"0.4rem"},children:[_jsx(Button,{icon:t?"pi pi-spin pi-spinner":"pi pi-download",label:"Raw",size:"small",outlined:!0,disabled:o,onClick:()=>u(e,"raw"),tooltip:"Download raw_data/trace.json as CSV",tooltipOptions:{position:"left"}}),_jsx(Button,{icon:r?"pi pi-spin pi-spinner":"pi pi-download",label:"Filtered",size:"small",outlined:!0,disabled:o,onClick:()=>u(e,"filtered"),tooltip:"Download filtered_data/trace.json as CSV",tooltipOptions:{position:"left"}})]})}})]})]})};
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useEffect,useContext}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Button}from"primereact/button";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";const downloadCsvBlob=(e,t)=>{const o=new Blob([t],{type:"text/csv;charset=utf-8;"}),r=URL.createObjectURL(o),i=document.createElement("a");i.href=r,i.download=e,document.body.appendChild(i),i.click(),i.remove(),URL.revokeObjectURL(r)};export const ResultHistoryTable=e=>{const t=useTis(),o=e.projectId??t.selection.projectId,r=e.methodId,[i,s]=useState([]),[a,n]=useState(!1),[l,d]=useState(null),[c,p]=useState(null),{invoke:m}=useContext(EventEmitterContext),u=async()=>{if(o){n(!0);try{const e={project_id:o};r&&(e.method_id=r);const t=await m("tis.list_tests",MessageType.Request,e);t.success&&t.data&&t.data.tests&&s(t.data.tests)}catch(e){}n(!1)}else s([])};useEffect(()=>{u()},[o,r,t.state.activeRunId]);const f=async(e,t)=>{const i=e?.run_id,s=e?.method_id??r;if(!i||!s||!o)return;const a="report"===t?"tis.export_test_csv":"tis.export_test_data_csv",n="report"===t?"test report":"test data";d({runId:i,kind:t});try{const e=await m(a,MessageType.Request,{project_id:o,method_id:s,run_id:i});if(!e?.success)return void alert(`Failed to build ${n} for ${i}`+(e?.error_message?`: ${e.error_message}`:""));const r="string"==typeof e.data?.csv?e.data.csv:"";if(!r)return void alert(`${n} for ${i} is empty.`);const l="string"==typeof e.data?.filename&&e.data.filename?e.data.filename:`${o}_${s}_${i}_${t}.csv`;downloadCsvBlob(l,r)}catch(e){alert(`Download failed: ${e instanceof Error?e.message:String(e)}`)}finally{d(null)}},_=async e=>{if(!o)return;const t="report"===e?"tis.export_project_csv":"tis.export_project_zip",r="report"===e?"project report":"project archive";p(e);try{const i=await m(t,MessageType.Request,{project_id:o});if(!i?.success)return void alert(`Failed to build ${r}`+(i?.error_message?`: ${i.error_message}`:""));if("report"===e){const e="string"==typeof i.data?.csv?i.data.csv:"";if(!e)return void alert(`Project ${o} has no tests to report.`);const t="string"==typeof i.data?.filename&&i.data.filename?i.data.filename:`${o}_project_report.csv`;downloadCsvBlob(t,e)}else{const e="string"==typeof i.data?.download_url?i.data.download_url:"";if(!e)return void alert(`Server did not return a download URL for ${r}.`);const t=document.createElement("a");t.href=e,t.download="string"==typeof i.data?.filename?i.data.filename:`${o}_project_archive.zip`,document.body.appendChild(t),t.click(),t.remove()}}catch(e){alert(`Download failed: ${e instanceof Error?e.message:String(e)}`)}finally{p(null)}},h=e=>{const t="string"==typeof e?.sample_id?e.sample_id:"";if(t)return t;const o=e?.config;return o&&"object"==typeof o&&"string"==typeof o.sample_id?o.sample_id:""};return _jsxs("div",{style:{width:"100%",maxWidth:"100%",overflow:"hidden",boxSizing:"border-box"},children:[_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1rem",gap:"0.5rem",flexWrap:"wrap"},children:[_jsx("h3",{style:{margin:0},children:o?`Test History: ${o}${r?` / ${r}`:""}`:"Test History (no project selected)"}),_jsxs("div",{style:{display:"flex",gap:"0.4rem",alignItems:"center"},children:[_jsx(Button,{icon:"report"===c?"pi pi-spin pi-spinner":"pi pi-file",label:"Download Report",size:"small",outlined:!0,disabled:!o||null!==c,onClick:()=>_("report"),tooltip:"Download a CSV report of every test in this project",tooltipOptions:{position:"bottom"}}),_jsx(Button,{icon:"archive"===c?"pi pi-spin pi-spinner":"pi pi-box",label:"Download Archive",size:"small",outlined:!0,disabled:!o||null!==c,onClick:()=>_("archive"),tooltip:"Download a ZIP of the entire project directory (all tests, raw data, configs)",tooltipOptions:{position:"bottom"}}),_jsx(Button,{icon:"pi pi-refresh",label:"Refresh",size:"small",onClick:u,disabled:a})]})]}),_jsxs(DataTable,{value:i,loading:a,paginator:!0,rows:10,emptyMessage:"No tests found.",scrollable:!0,scrollHeight:"flex",tableStyle:{minWidth:0},style:{width:"100%"},selectionMode:"single",onSelectionChange:e=>{const o=e.value;o?.run_id&&t.setSelection({projectId:o.project_id??null,methodId:o.method_id??null,runId:o.run_id})},children:[_jsx(Column,{header:"Sample ID",sortable:!0,body:h,sortFunction:e=>{const t=[...e.data];return t.sort((t,o)=>h(t).localeCompare(h(o))*(e.order??1)),t},style:{minWidth:"8rem"}}),_jsx(Column,{field:"start_time",header:"Date/Time",sortable:!0,body:e=>{return(t=e.start_time)?new Date(t).toLocaleString():"";var t},style:{minWidth:"12rem"}}),_jsx(Column,{field:"method_id",header:"Test Method",sortable:!0,style:{minWidth:"10rem"}}),_jsx(Column,{field:"run_id",header:"Run ID",sortable:!0,style:{minWidth:"12rem"}}),_jsx(Column,{header:"Download",style:{width:"14rem"},body:e=>{const t=l?.runId===e.run_id&&"data"===l?.kind,o=l?.runId===e.run_id&&"report"===l?.kind,r=null!==l;return _jsxs("div",{style:{display:"flex",gap:"0.4rem"},children:[_jsx(Button,{icon:t?"pi pi-spin pi-spinner":"pi pi-download",label:"Data",size:"small",outlined:!0,disabled:r,onClick:()=>f(e,"data"),tooltip:"Download raw + filtered trace data as one CSV",tooltipOptions:{position:"left"}}),_jsx(Button,{icon:o?"pi pi-spin pi-spinner":"pi pi-file",label:"Report",size:"small",outlined:!0,disabled:r,onClick:()=>f(e,"report"),tooltip:"Download a CSV report (metadata + cycles + results) for this test",tooltipOptions:{position:"left"}})]})}})]})]})};
@@ -1 +1 @@
1
- {"version":3,"file":"TestDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestDataView.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAwE,MAAM,OAAO,CAAC;AA6B7F,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IAAI,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CAAE;AAChF,MAAM,WAAW,WAAW;IAAG,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAAE;AAC5G,MAAM,WAAW,SAAS;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,eAAe,GAAG,WAAW,CAAC;IACpC,CAAC,EAAE,SAAS,CAAC;IACb,CAAC,EAAE,WAAW,EAAE,CAAC;CACpB;AACD,MAAM,WAAW,SAAS;IAAG,MAAM,EAAE,MAAM,CAAC;CAAE;AAC9C,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB;;8CAE0C;IAC1C,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACtC,KAAK,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACrC;AACD,MAAM,WAAW,UAAU;IACvB,cAAc,EAAG,YAAY,EAAE,CAAC;IAChC,aAAa,EAAI,YAAY,EAAE,CAAC;IAChC,YAAY,EAAK,YAAY,EAAE,CAAC;IAChC,cAAc,EAAG,YAAY,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAQ,YAAY,GAAG,IAAI,CAAC;IACrC,KAAK,CAAC,EAAW;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC/C,wDAAwD;IACxD,KAAK,CAAC,EAAW,MAAM,CAAC;IACxB,qDAAqD;IACrD,WAAW,CAAC,EAAK,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAC9B,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,CAAC,EAAG,MAAM,CAAC;IACnB,gEAAgE;IAChE,KAAK,CAAC,EAAM,MAAM,CAAC;IACnB,kEAAkE;IAClE,MAAM,CAAC,EAAK,UAAU,CAAC;IACvB,8EAA8E;IAC9E,UAAU,CAAC,EAAG,MAAM,CAAC;IACrB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAID,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAkYpD,CAAC"}
1
+ {"version":3,"file":"TestDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestDataView.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAwE,MAAM,OAAO,CAAC;AA6B7F,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IAAI,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CAAE;AAChF,MAAM,WAAW,WAAW;IAAG,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAAE;AAC5G,MAAM,WAAW,SAAS;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,eAAe,GAAG,WAAW,CAAC;IACpC,CAAC,EAAE,SAAS,CAAC;IACb,CAAC,EAAE,WAAW,EAAE,CAAC;CACpB;AACD,MAAM,WAAW,SAAS;IAAG,MAAM,EAAE,MAAM,CAAC;CAAE;AAC9C,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB;;8CAE0C;IAC1C,OAAO,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACtC,KAAK,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACrC;AACD,MAAM,WAAW,UAAU;IACvB,cAAc,EAAG,YAAY,EAAE,CAAC;IAChC,aAAa,EAAI,YAAY,EAAE,CAAC;IAChC,YAAY,EAAK,YAAY,EAAE,CAAC;IAChC,cAAc,EAAG,YAAY,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAQ,YAAY,GAAG,IAAI,CAAC;IACrC,KAAK,CAAC,EAAW;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC/C,wDAAwD;IACxD,KAAK,CAAC,EAAW,MAAM,CAAC;IACxB,qDAAqD;IACrD,WAAW,CAAC,EAAK,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAC9B,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,CAAC,EAAG,MAAM,CAAC;IACnB,gEAAgE;IAChE,KAAK,CAAC,EAAM,MAAM,CAAC;IACnB,kEAAkE;IAClE,MAAM,CAAC,EAAK,UAAU,CAAC;IACvB,8EAA8E;IAC9E,UAAU,CAAC,EAAG,MAAM,CAAC;IACrB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAID,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgcpD,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useCallback,useContext,useEffect,useMemo,useRef,useState}from"react";import{Button}from"primereact/button";import{Column}from"primereact/column";import{DataTable}from"primereact/datatable";import{Dialog}from"primereact/dialog";import{Dropdown}from"primereact/dropdown";import{TabView,TabPanel}from"primereact/tabview";import{Chart as ChartJS,CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend}from"chart.js";import zoomPlugin from"chartjs-plugin-zoom";import{Line}from"react-chartjs-2";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin);export const TestDataView=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,a=e.methodId??t.selection.methodId,i=e.runId??t.selection.runId,s=e.schema??(a?t.schemas[a]:void 0),{throttleMs:l=100,cycleTableHeight:n="400px"}=e,{invoke:o,subscribe:c,unsubscribe:d}=useContext(EventEmitterContext),[m,u]=useState(null),[p,h]=useState([]),[f,g]=useState({}),[y,_]=useState(!1),[x,b]=useState(!1),[j,v]=useState(null),[w,S]=useState(null),[C,T]=useState(!1),[R,N]=useState(null),[D,I]=useState(null),[L,A]=useState(!1),O=useMemo(()=>{const e=[];for(const[t,r]of Object.entries(s?.views??{}))"cycle_scatter"===r.type&&e.push({name:t,view:r});return e},[s]),[E,M]=useState(O.length>0?O[0].name:null);useEffect(()=>{if(0===O.length)return;null!==E&&O.some(e=>e.name===E)||M(O[0].name)},[O,E]);const k=useRef([]),z=useRef(null),F=useRef(null),H=()=>{F.current||(F.current=setTimeout(()=>{if(F.current=null,k.current.length>0){const e=k.current;k.current=[],h(t=>[...e.slice().reverse(),...t])}z.current&&(g(z.current),z.current=null)},l))};useEffect(()=>{if(!r||!a||!i)return u(null),h([]),void g({});let e=!1;return(async()=>{try{const t=await o("tis.read_test",MessageType.Request,{project_id:r,method_id:a,run_id:i});!e&&t?.success&&(u(t.data),g(t.data.results??{}));const s=await o("tis.read_cycles",MessageType.Request,{project_id:r,method_id:a,run_id:i,offset:0,limit:200,order:"desc"});!e&&s?.success&&h(s.data.cycles??[])}catch(e){}})(),()=>{e=!0}},[r,a,i,o]),useEffect(()=>{const e=e=>e?.project_id===r&&e?.method_id===a&&e?.run_id===i,t=c("tis.cycle_added",t=>{e(t)&&t.cycle&&(k.current.push(t.cycle),H())}),s=c("tis.results_updated",t=>{e(t)&&(z.current=t.results??{},H())});return()=>{d(t),d(s),F.current&&(clearTimeout(F.current),F.current=null)}},[r,a,i,l]);const P=useMemo(()=>{if(!E||0===O.length)return null;const e=O.find(e=>e.name===E)?.view;if(!e)return null;const t=e.x.field,r=[...p].reverse();return{labels:r.map(e=>e[t]),datasets:e.y.map((e,t)=>({label:e.label??e.field,data:r.map(t=>t[e.field]),yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(t),backgroundColor:palette(t),tension:.1,pointRadius:2}))}},[p,E,O]),V=O.find(e=>e.name===E)?.view,$=V?.y.some(e=>"right"===e.y_axis)??!1,B=useMemo(()=>({responsive:!0,maintainAspectRatio:!1,scales:{x:{title:{display:!!V?.x.label,text:V?.x.label}},y:{position:"left",title:{display:!0,text:leftAxisLabel(V)}},...$?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:rightAxisLabel(V)}}}:{}},plugins:{legend:{display:!0},zoom:{pan:{enabled:!0,mode:"xy"},zoom:{wheel:{enabled:!0},pinch:{enabled:!0},mode:"xy"}}}}),[V,$]),q=s?.raw_data?.blob_name??"trace",J=useRef(""),G=useCallback(async()=>{if(!r||!a||!i)return;const e=`${r}|${a}|${i}|${q}`;if(J.current!==e){J.current=e,T(!0),S(null),v(null);try{const e=await o("tis.read_raw",MessageType.Request,{project_id:r,method_id:a,run_id:i,name:q});e?.success?v(e.data??{}):S(e?.error_message??"No raw data on disk for this run.")}catch(e){S(String(e?.message??e))}finally{T(!1)}A(!0),I(null),N(null);try{const e=await o("tis.read_filtered",MessageType.Request,{project_id:r,method_id:a,run_id:i,name:q});e?.success?N(e.data??{}):I(e?.error_message??"No filtered data on disk for this run.")}catch(e){I(String(e?.message??e))}finally{A(!1)}}},[r,a,i,q,o]);useEffect(()=>{J.current=""},[r,a,i,q]);return r&&a&&i&&s?_jsxs("div",{className:"vblock",style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[_jsx(Header,{meta:m,config:m?.config,runId:i,projectId:r,methodId:a,canViewRaw:!!s.raw_data,onViewRaw:()=>{_(!0),G()},onShowConfig:()=>b(!0)}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("div",{className:"flex",style:{gap:"1rem",alignItems:"center",marginBottom:"0.5rem"},children:[_jsx(Dropdown,{value:E,options:O.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>M(e.value),placeholder:0===O.length?"No view defined":"Select a view",disabled:0===O.length}),_jsx("h3",{style:{margin:0},children:V?.title??""})]}),_jsx("div",{style:{height:320},children:P&&_jsx(Line,{data:P,options:B})})]}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("h3",{style:{marginTop:0},children:["Cycle Data (",p.length,")"]}),_jsx(DataTable,{value:p,scrollable:!0,scrollHeight:n,virtualScrollerOptions:{itemSize:38},emptyMessage:"No cycles yet.",children:s.cycle_fields.map(e=>_jsx(Column,{field:e.name,header:e.units?`${e.name} (${e.units})`:e.name,body:t=>formatCell(t[e.name],e.type)},e.name))})]}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsx("h3",{style:{marginTop:0},children:"Results"}),_jsx(ResultsGrid,{schema:s.results_fields,values:f})]}),s.raw_data&&_jsx(Dialog,{visible:y,onHide:()=>_(!1),header:`Run Data — ${i}`,style:{width:"90vw",height:"80vh"},maximizable:!0,children:_jsxs(TabView,{style:{height:"100%"},children:[_jsx(TabPanel,{header:"Raw Data",children:_jsx(DataBlobTable,{blob:j,loading:C,error:w,rawData:s.raw_data})}),_jsx(TabPanel,{header:"Filtered Data",children:_jsx(DataBlobTable,{blob:R,loading:L,error:D,rawData:s.raw_data,emptyMessage:"Filtered data is written by post-processing — none on disk for this run yet."})})]})}),_jsx(Dialog,{visible:x,onHide:()=>b(!1),header:"Test Configuration",style:{width:"min(640px, 90vw)"},modal:!0,children:_jsx(ConfigList,{config:m?.config})})]}):_jsx("div",{className:"p-card",style:{padding:"1rem",color:"var(--text-secondary-color)"},children:"No test selected. Pick a row from the History tab or start a run."})};const Header=({meta:e,config:t,runId:r,projectId:a,methodId:i,canViewRaw:s,onViewRaw:l,onShowConfig:n})=>{const o="string"==typeof e?.sample_id&&e.sample_id||"string"==typeof e?.config?.sample_id&&e.config.sample_id||"",c=t&&"object"==typeof t&&Object.entries(t).some(([e])=>"sample_id"!==e);return _jsx("div",{className:"p-card",style:{padding:"1rem"},children:_jsxs("div",{className:"flex",style:{justifyContent:"space-between",alignItems:"flex-start",gap:"1rem"},children:[_jsxs("div",{children:[_jsxs("h2",{style:{margin:0,display:"flex",alignItems:"center",gap:"0.5rem"},children:[o||r,c&&_jsx(Button,{icon:"pi pi-info-circle",type:"button",rounded:!0,text:!0,onClick:n,tooltip:"Show test configuration",tooltipOptions:{position:"top"},style:{width:"2rem",height:"2rem",padding:0},"aria-label":"Show test configuration"})]}),_jsxs("div",{style:{color:"var(--text-secondary-color)",fontSize:"0.85em"},children:["project: ",a," · method: ",i," · run: ",r,e?.start_time&&_jsxs(_Fragment,{children:[" · started: ",new Date(e.start_time).toLocaleString()]})]})]}),s&&_jsx(Button,{icon:"pi pi-table",label:"View Raw Data",onClick:l,outlined:!0})]})})},ConfigList=({config:e})=>{const t=e&&"object"==typeof e?Object.entries(e).filter(([e])=>"sample_id"!==e):[];return 0===t.length?_jsx("div",{style:{color:"var(--text-secondary-color)"},children:"No configuration recorded for this run."}):_jsx("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.5rem 1rem",fontSize:"0.95em"},children:t.map(([e,t])=>_jsxs(React.Fragment,{children:[_jsx("div",{style:{color:"var(--text-secondary-color)"},children:e}),_jsx("div",{children:formatCell(t,"string")})]},e))})},DataBlobTable=({blob:e,loading:t,error:r,rawData:a,emptyMessage:i})=>{if(t)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:"Loading…"});if(r)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:i??r});if(!e||"object"!=typeof e)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:"No data."});const s=Object.keys(a.columns??{}),l=Object.keys(e).filter(t=>Array.isArray(e[t])),n=[];for(const t of s)Array.isArray(e[t])&&n.push(t);for(const e of l)n.includes(e)||n.push(e);if(0===n.length)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:i??"No columnar data in this blob."});const o=n.reduce((t,r)=>Math.min(t,e[r].length),Number.POSITIVE_INFINITY),c=Number.isFinite(o)?o:0,d=Array.from({length:c},(t,r)=>{const a={__i:r};for(const t of n)a[t]=e[t][r];return a}),m=e=>{const t=a.units?.[e];return t?`${e} [${t}]`:e};return _jsxs(DataTable,{value:d,scrollable:!0,scrollHeight:"60vh",virtualScrollerOptions:{itemSize:32},emptyMessage:i??"No data.",size:"small",stripedRows:!0,children:[_jsx(Column,{field:"__i",header:"#",style:{width:"5rem",textAlign:"right"},bodyStyle:{fontVariantNumeric:"tabular-nums",textAlign:"right"}}),n.map(e=>_jsx(Column,{field:e,header:m(e),style:{minWidth:"8rem"},bodyStyle:{fontVariantNumeric:"tabular-nums",textAlign:"right"},body:t=>formatNumeric(t[e])},e))]})},formatNumeric=e=>null==e?"":"number"==typeof e&&Number.isFinite(e)?Number.parseFloat(e.toPrecision(6)).toString():String(e),ResultsGrid=({schema:e,values:t})=>t&&0!==Object.keys(t).length?_jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(220px, 1fr))",gap:"0.5rem 1rem"},children:e.map(e=>_jsxs("div",{children:[_jsxs("div",{style:{fontSize:"0.8em",color:"var(--text-secondary-color)"},children:[e.name,e.units?` (${e.units})`:""]}),_jsx("div",{children:formatCell(t[e.name],e.type)})]},e.name))}):_jsx("div",{style:{color:"var(--text-secondary-color)"},children:"No results yet."}),CHART_COLORS=["#4ea8de","#f59e0b","#22c55e","#a855f7","#ef4444","#14b8a6","#eab308","#ec4899"],palette=e=>CHART_COLORS[e%CHART_COLORS.length],leftAxisLabel=e=>e?.y.filter(e=>"right"!==e.y_axis).map(e=>e.label??e.field).join(" / ")??"",rightAxisLabel=e=>e?.y.filter(e=>"right"===e.y_axis).map(e=>e.label??e.field).join(" / ")??"",formatCell=(e,t)=>null==e?"":"f32"===t||"f64"===t?"number"==typeof e?e.toFixed(4):String(e):"object"==typeof e?JSON.stringify(e):String(e);
1
+ import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useCallback,useContext,useEffect,useMemo,useRef,useState}from"react";import{Button}from"primereact/button";import{Column}from"primereact/column";import{DataTable}from"primereact/datatable";import{Dialog}from"primereact/dialog";import{Dropdown}from"primereact/dropdown";import{TabView,TabPanel}from"primereact/tabview";import{Chart as ChartJS,CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend}from"chart.js";import zoomPlugin from"chartjs-plugin-zoom";import{Line}from"react-chartjs-2";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin);export const TestDataView=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,a=e.methodId??t.selection.methodId,s=e.runId??t.selection.runId,l=e.schema??(a?t.schemas[a]:void 0),{throttleMs:i=100,cycleTableHeight:n="400px"}=e,{invoke:o,subscribe:c,unsubscribe:d}=useContext(EventEmitterContext),[m,u]=useState(null),[p,y]=useState([]),[h,f]=useState({}),[g,x]=useState(!1),[_,b]=useState(!1),[j,v]=useState(null),[w,C]=useState(null),[S,T]=useState(!1),[R,N]=useState(null),[D,I]=useState(null),[E,A]=useState(!1),[O,k]=useState([]),[L,M]=useState(null),z=useMemo(()=>{const e=[];for(const[t,r]of Object.entries(l?.views??{}))"cycle_scatter"===r.type&&e.push({name:t,view:r});return e},[l]),[H,P]=useState(z.length>0?z[0].name:null);useEffect(()=>{if(0===z.length)return;null!==H&&z.some(e=>e.name===H)||P(z[0].name)},[z,H]);const F=useRef([]),$=useRef(null),V=useRef(null),B=()=>{V.current||(V.current=setTimeout(()=>{if(V.current=null,F.current.length>0){const e=F.current;F.current=[],y(t=>[...e.slice().reverse(),...t])}$.current&&(f($.current),$.current=null)},i))};useEffect(()=>{if(!r||!a||!s)return u(null),y([]),void f({});let e=!1;return(async()=>{try{const t=await o("tis.read_test",MessageType.Request,{project_id:r,method_id:a,run_id:s});!e&&t?.success&&(u(t.data),f(t.data.results??{}));const l=await o("tis.read_cycles",MessageType.Request,{project_id:r,method_id:a,run_id:s,offset:0,limit:200,order:"desc"});!e&&l?.success&&y(l.data.cycles??[])}catch(e){}})(),()=>{e=!0}},[r,a,s,o]),useEffect(()=>{const e=e=>e?.project_id===r&&e?.method_id===a&&e?.run_id===s,t=c("tis.cycle_added",t=>{e(t)&&t.cycle&&(F.current.push(t.cycle),B())}),l=c("tis.results_updated",t=>{e(t)&&($.current=t.results??{},B())});return()=>{d(t),d(l),V.current&&(clearTimeout(V.current),V.current=null)}},[r,a,s,i]);const q=useMemo(()=>{if(!H||0===z.length)return null;const e=z.find(e=>e.name===H)?.view;if(!e)return null;const t=e.x.field,r=[...p].reverse();return{labels:r.map(e=>e[t]),datasets:e.y.map((e,t)=>({label:e.label??e.field,data:r.map(t=>t[e.field]),yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(t),backgroundColor:palette(t),tension:.1,pointRadius:2}))}},[p,H,z]),J=z.find(e=>e.name===H)?.view,G=J?.y.some(e=>"right"===e.y_axis)??!1,W=useMemo(()=>({responsive:!0,maintainAspectRatio:!1,scales:{x:{title:{display:!!J?.x.label,text:J?.x.label}},y:{position:"left",title:{display:!0,text:leftAxisLabel(J)}},...G?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:rightAxisLabel(J)}}}:{}},plugins:{legend:{display:!0},zoom:{pan:{enabled:!0,mode:"xy"},zoom:{wheel:{enabled:!0},pinch:{enabled:!0},mode:"xy"}}}}),[J,G]),Y=l?.raw_data?.blob_name??"trace",K=useRef(""),Q=useCallback(async()=>{if(!r||!a||!s)return[];try{const e=await o("tis.list_raw",MessageType.Request,{project_id:r,method_id:a,run_id:s});if(!e?.success)return[];const t=e.data?.cycles??[];return t.filter(e=>e?.name===Y&&"number"==typeof e?.cycle_index).map(e=>e.cycle_index).sort((e,t)=>e-t)}catch{return[]}},[r,a,s,Y,o]),U=useCallback(async e=>{if(!r||!a||!s)return;const t=`${r}|${a}|${s}|${Y}|${e??"latest"}`;if(K.current===t)return;K.current=t;const l={project_id:r,method_id:a,run_id:s,name:Y};null!=e&&(l.cycle_index=e),T(!0),C(null),v(null);try{const e=await o("tis.read_raw",MessageType.Request,l);e?.success?v(e.data??{}):C(e?.error_message??"No raw data on disk for this run.")}catch(e){C(String(e?.message??e))}finally{T(!1)}A(!0),I(null),N(null);try{const e=await o("tis.read_filtered",MessageType.Request,{project_id:r,method_id:a,run_id:s,name:Y});e?.success?N(e.data??{}):I(e?.error_message??"No filtered data on disk for this run.")}catch(e){I(String(e?.message??e))}finally{A(!1)}},[r,a,s,Y,o]);useEffect(()=>{K.current="",k([]),M(null)},[r,a,s,Y]);return useEffect(()=>{g&&null!=L&&U(L)},[g,L,U]),r&&a&&s&&l?_jsxs("div",{className:"vblock",style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[_jsx(Header,{meta:m,config:m?.config,runId:s,projectId:r,methodId:a,canViewRaw:!!l.raw_data,onViewRaw:async()=>{x(!0);let e=O;0===e.length&&(e=await Q(),k(e));const t=e.length>0?e[e.length-1]:null,r=L??t;L!==r&&M(r),await U(r)},onShowConfig:()=>b(!0)}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("div",{className:"flex",style:{gap:"1rem",alignItems:"center",marginBottom:"0.5rem"},children:[_jsx(Dropdown,{value:H,options:z.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>P(e.value),placeholder:0===z.length?"No view defined":"Select a view",disabled:0===z.length}),_jsx("h3",{style:{margin:0},children:J?.title??""})]}),_jsx("div",{style:{height:320},children:q&&_jsx(Line,{data:q,options:W})})]}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("h3",{style:{marginTop:0},children:["Cycle Data (",p.length,")"]}),_jsx(DataTable,{value:p,scrollable:!0,scrollHeight:n,virtualScrollerOptions:{itemSize:38},emptyMessage:"No cycles yet.",children:l.cycle_fields.map(e=>_jsx(Column,{field:e.name,header:e.units?`${e.name} (${e.units})`:e.name,body:t=>formatCell(t[e.name],e.type)},e.name))})]}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsx("h3",{style:{marginTop:0},children:"Results"}),_jsx(ResultsGrid,{schema:l.results_fields,values:h})]}),l.raw_data&&_jsxs(Dialog,{visible:g,onHide:()=>x(!1),header:`Run Data — ${s}`,style:{width:"90vw",height:"80vh"},maximizable:!0,children:[_jsx(CyclePickerBar,{cycles:O,selected:L,onChange:M}),_jsx(RawEnvelopeHeader,{envelope:j}),_jsxs(TabView,{style:{height:"100%"},children:[_jsx(TabPanel,{header:"Raw Data",children:_jsx(DataBlobTable,{blob:unwrapEnvelope(j),loading:S,error:w,rawData:l.raw_data})}),_jsx(TabPanel,{header:"Filtered Data",children:_jsx(DataBlobTable,{blob:unwrapEnvelope(R),loading:E,error:D,rawData:l.raw_data,emptyMessage:"Filtered data is written by post-processing — none on disk for this run yet."})})]})]}),_jsx(Dialog,{visible:_,onHide:()=>b(!1),header:"Test Configuration",style:{width:"min(640px, 90vw)"},modal:!0,children:_jsx(ConfigList,{config:m?.config})})]}):_jsx("div",{className:"p-card",style:{padding:"1rem",color:"var(--text-secondary-color)"},children:"No test selected. Pick a row from the History tab or start a run."})};const Header=({meta:e,config:t,runId:r,projectId:a,methodId:s,canViewRaw:l,onViewRaw:i,onShowConfig:n})=>{const o="string"==typeof e?.sample_id&&e.sample_id||"string"==typeof e?.config?.sample_id&&e.config.sample_id||"",c=t&&"object"==typeof t&&Object.entries(t).some(([e])=>"sample_id"!==e);return _jsx("div",{className:"p-card",style:{padding:"1rem"},children:_jsxs("div",{className:"flex",style:{justifyContent:"space-between",alignItems:"flex-start",gap:"1rem"},children:[_jsxs("div",{children:[_jsxs("h2",{style:{margin:0,display:"flex",alignItems:"center",gap:"0.5rem"},children:[o||r,c&&_jsx(Button,{icon:"pi pi-info-circle",type:"button",rounded:!0,text:!0,onClick:n,tooltip:"Show test configuration",tooltipOptions:{position:"top"},style:{width:"2rem",height:"2rem",padding:0},"aria-label":"Show test configuration"})]}),_jsxs("div",{style:{color:"var(--text-secondary-color)",fontSize:"0.85em"},children:["project: ",a," · method: ",s," · run: ",r,e?.start_time&&_jsxs(_Fragment,{children:[" · started: ",new Date(e.start_time).toLocaleString()]})]})]}),l&&_jsx(Button,{icon:"pi pi-table",label:"View Raw Data",onClick:i,outlined:!0})]})})},ConfigList=({config:e})=>{const t=e&&"object"==typeof e?Object.entries(e).filter(([e])=>"sample_id"!==e):[];return 0===t.length?_jsx("div",{style:{color:"var(--text-secondary-color)"},children:"No configuration recorded for this run."}):_jsx("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.5rem 1rem",fontSize:"0.95em"},children:t.map(([e,t])=>_jsxs(React.Fragment,{children:[_jsx("div",{style:{color:"var(--text-secondary-color)"},children:e}),_jsx("div",{children:formatCell(t,"string")})]},e))})},unwrapEnvelope=e=>e&&"object"==typeof e&&"data"in e&&e.data&&"object"==typeof e.data&&Object.values(e.data).some(e=>Array.isArray(e))?e.data:e,CyclePickerBar=({cycles:e,selected:t,onChange:r})=>e.length<=1?null:_jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.5rem",padding:"0.25rem 0.5rem 0.5rem"},children:[_jsx("label",{htmlFor:"raw-cycle-picker",style:{color:"var(--text-secondary-color)"},children:"Cycle:"}),_jsx(Dropdown,{inputId:"raw-cycle-picker",value:t,options:e.map(e=>({label:`Cycle ${e}`,value:e})),onChange:e=>r(Number(e.value)),style:{minWidth:"8rem"}}),_jsxs("span",{style:{color:"var(--text-secondary-color)"},children:["(",e.length," cycles recorded)"]})]}),RawEnvelopeHeader=({envelope:e})=>{if(!e||"object"!=typeof e)return null;const t=e.cycle_index,r=e.cycle_fields,a=e.context;if(null==t&&!r&&!a)return null;const s=e=>{if(!e||"object"!=typeof e)return null;const t=Object.entries(e).filter(([,e])=>null!==e&&"object"!=typeof e);return 0===t.length?null:t.map(([e,t])=>_jsxs("span",{style:{marginRight:"1rem"},children:[_jsxs("span",{style:{color:"var(--text-secondary-color)"},children:[e,": "]}),_jsx("span",{children:String(t)})]},e))};return _jsxs("div",{style:{padding:"0.5rem",borderBottom:"1px solid var(--surface-border)",fontSize:"0.9rem"},children:[null!=t&&_jsx("div",{children:_jsxs("strong",{children:["Cycle ",t]})}),r&&_jsx("div",{style:{marginTop:"0.25rem"},children:s(r)}),a&&_jsx("div",{style:{marginTop:"0.25rem"},children:s(a)})]})},DataBlobTable=({blob:e,loading:t,error:r,rawData:a,emptyMessage:s})=>{if(t)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:"Loading…"});if(r)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:s??r});if(!e||"object"!=typeof e)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:"No data."});const l=Object.keys(a.columns??{}),i=Object.keys(e).filter(t=>Array.isArray(e[t])),n=[];for(const t of l)Array.isArray(e[t])&&n.push(t);for(const e of i)n.includes(e)||n.push(e);if(0===n.length)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:s??"No columnar data in this blob."});const o=n.reduce((t,r)=>Math.min(t,e[r].length),Number.POSITIVE_INFINITY),c=Number.isFinite(o)?o:0,d=Array.from({length:c},(t,r)=>{const a={__i:r};for(const t of n)a[t]=e[t][r];return a}),m=e=>{const t=a.units?.[e];return t?`${e} [${t}]`:e};return _jsxs(DataTable,{value:d,scrollable:!0,scrollHeight:"60vh",virtualScrollerOptions:{itemSize:32},emptyMessage:s??"No data.",size:"small",stripedRows:!0,children:[_jsx(Column,{field:"__i",header:"#",style:{width:"5rem",textAlign:"right"},bodyStyle:{fontVariantNumeric:"tabular-nums",textAlign:"right"}}),n.map(e=>_jsx(Column,{field:e,header:m(e),style:{minWidth:"8rem"},bodyStyle:{fontVariantNumeric:"tabular-nums",textAlign:"right"},body:t=>formatNumeric(t[e])},e))]})},formatNumeric=e=>null==e?"":"number"==typeof e&&Number.isFinite(e)?Number.parseFloat(e.toPrecision(6)).toString():String(e),ResultsGrid=({schema:e,values:t})=>t&&0!==Object.keys(t).length?_jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(220px, 1fr))",gap:"0.5rem 1rem"},children:e.map(e=>_jsxs("div",{children:[_jsxs("div",{style:{fontSize:"0.8em",color:"var(--text-secondary-color)"},children:[e.name,e.units?` (${e.units})`:""]}),_jsx("div",{children:formatCell(t[e.name],e.type)})]},e.name))}):_jsx("div",{style:{color:"var(--text-secondary-color)"},children:"No results yet."}),CHART_COLORS=["#4ea8de","#f59e0b","#22c55e","#a855f7","#ef4444","#14b8a6","#eab308","#ec4899"],palette=e=>CHART_COLORS[e%CHART_COLORS.length],leftAxisLabel=e=>e?.y.filter(e=>"right"!==e.y_axis).map(e=>e.label??e.field).join(" / ")??"",rightAxisLabel=e=>e?.y.filter(e=>"right"===e.y_axis).map(e=>e.label??e.field).join(" / ")??"",formatCell=(e,t)=>null==e?"":"f32"===t||"f64"===t?"number"==typeof e?e.toFixed(4):String(e):"object"==typeof e?JSON.stringify(e):String(e);
@@ -1 +1 @@
1
- {"version":3,"file":"TestRawDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestRawDataView.tsx"],"names":[],"mappings":"AAYA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAahF,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAQ5D,MAAM,WAAW,oBAAoB;IACjC,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,CAAC,EAAG,MAAM,CAAC;IACnB,gEAAgE;IAChE,KAAK,CAAC,EAAM,MAAM,CAAC;IACnB,kEAAkE;IAClE,MAAM,CAAC,EAAK,UAAU,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAuJ1D,CAAC"}
1
+ {"version":3,"file":"TestRawDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestRawDataView.tsx"],"names":[],"mappings":"AAYA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAahF,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAQ5D,MAAM,WAAW,oBAAoB;IACjC,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,CAAC,EAAG,MAAM,CAAC;IACnB,gEAAgE;IAChE,KAAK,CAAC,EAAM,MAAM,CAAC;IACnB,kEAAkE;IAClE,MAAM,CAAC,EAAK,UAAU,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAuN1D,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useContext,useEffect,useMemo,useRef,useState}from"react";import{Button}from"primereact/button";import{Dropdown}from"primereact/dropdown";import{Chart as ChartJS,CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend}from"chart.js";import zoomPlugin from"chartjs-plugin-zoom";import{Line}from"react-chartjs-2";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin);export const TestRawDataView=e=>{const t=useTis(),a=e.projectId??t.selection.projectId,s=e.methodId??t.selection.methodId,o=e.runId??t.selection.runId,i=e.schema??(s?t.schemas[s]:void 0),{blobName:r,chartHeight:n="60vh"}=e,{invoke:l}=useContext(EventEmitterContext),[m,d]=useState(null),[c,p]=useState(!0),[u,h]=useState(null),x=useRef(null),y=useMemo(()=>{const e=[];for(const[t,a]of Object.entries(i?.views??{}))"raw_trace"===a.type&&e.push({name:t,view:a});return e},[i]),[f,g]=useState(y.length>0?y[0].name:null),_=r??i?.raw_data?.blob_name??"trace";useEffect(()=>{if(!a||!s||!o)return d(null),p(!1),void h(null);let e=!1;return p(!0),h(null),(async()=>{try{const t=await l("tis.read_raw",MessageType.Request,{project_id:a,method_id:s,run_id:o,name:_});if(e)return;t?.success?d(t.data??{}):h(t?.error_message??"Failed to read raw data")}catch(t){e||h(String(t?.message??t))}finally{e||p(!1)}})(),()=>{e=!0}},[a,s,o,_,l]);const v=useMemo(()=>{if(!m||!f)return null;const e=y.find(e=>e.name===f)?.view;if(!e)return null;const t=e.x.column,a=m[t]??[];return{datasets:e.y.map((e,t)=>({label:e.label??e.column,data:(m[e.column]??[]).map((e,t)=>({x:a[t],y:e})),yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(t),backgroundColor:palette(t),pointRadius:0,borderWidth:1.5,showLine:!0}))}},[m,f,y]),j=y.find(e=>e.name===f)?.view,b=j?.y.some(e=>"right"===e.y_axis)??!1,w=useMemo(()=>({responsive:!0,maintainAspectRatio:!1,parsing:!1,scales:{x:{type:"linear",title:{display:!!j?.x.label,text:j?.x.label}},y:{position:"left",title:{display:!0,text:axisLabel(j,"left")}},...b?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:axisLabel(j,"right")}}}:{}},plugins:{legend:{display:!0},zoom:{pan:{enabled:!0,mode:"xy"},zoom:{wheel:{enabled:!0},pinch:{enabled:!0},drag:{enabled:!0,modifierKey:"shift"},mode:"xy"}}}}),[j,b]);return a&&s&&o?i?i.raw_data?0===y.length?_jsx(EmptyState,{message:"No raw_trace views declared. Add one to schema.views in project.json."}):_jsxs("div",{className:"vblock",style:{display:"flex",flexDirection:"column",gap:"1rem",height:"100%"},children:[_jsxs("div",{className:"flex",style:{gap:"1rem",alignItems:"center"},children:[_jsx(Dropdown,{value:f,options:y.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>g(e.value),placeholder:"Select a view"}),_jsx("h3",{style:{margin:0},children:j?.title??""}),_jsx("div",{style:{flex:1}}),_jsx(Button,{icon:"pi pi-refresh",label:"Reset Zoom",outlined:!0,onClick:()=>x.current?.resetZoom?.()})]}),_jsxs("div",{style:{flex:1,minHeight:0,height:n,position:"relative"},children:[c&&_jsx(Overlay,{children:"Loading raw data…"}),u&&_jsx(Overlay,{children:u}),v&&!c&&!u&&_jsx(Line,{ref:x,data:v,options:w})]})]}):_jsx(EmptyState,{message:"No raw_data is declared for this test method."}):_jsx(EmptyState,{message:"Schema not loaded yet."}):_jsx(EmptyState,{message:"No test selected."})};const Overlay=({children:e})=>_jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",color:"var(--text-secondary-color)",pointerEvents:"none"},children:e}),EmptyState=({message:e})=>_jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:e}),CHART_COLORS=["#4ea8de","#f59e0b","#22c55e","#a855f7","#ef4444","#14b8a6","#eab308","#ec4899"],palette=e=>CHART_COLORS[e%CHART_COLORS.length],axisLabel=(e,t)=>e?.y.filter(e=>(e.y_axis??"left")===t).map(e=>e.label??e.column).join(" / ")??"";
1
+ import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useContext,useEffect,useMemo,useRef,useState}from"react";import{Button}from"primereact/button";import{Dropdown}from"primereact/dropdown";import{Chart as ChartJS,CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend}from"chart.js";import zoomPlugin from"chartjs-plugin-zoom";import{Line}from"react-chartjs-2";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin);export const TestRawDataView=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,a=e.methodId??t.selection.methodId,l=e.runId??t.selection.runId,n=e.schema??(a?t.schemas[a]:void 0),{blobName:s,chartHeight:o="60vh"}=e,{invoke:i}=useContext(EventEmitterContext),[c,d]=useState(null),[m,p]=useState(null),[u,y]=useState(!0),[x,h]=useState(null),f=useRef(null),[g,_]=useState([]),[v,j]=useState(null),b=useMemo(()=>{const e=[];for(const[t,r]of Object.entries(n?.views??{}))"raw_trace"===r.type&&e.push({name:t,view:r});return e},[n]),[w,S]=useState(b.length>0?b[0].name:null),C=s??n?.raw_data?.blob_name??"trace";useEffect(()=>{_([]),j(null)},[r,a,l,C]),useEffect(()=>{if(!r||!a||!l)return;let e=!1;return(async()=>{try{const t=await i("tis.list_raw",MessageType.Request,{project_id:r,method_id:a,run_id:l});if(e||!t?.success)return;const n=(t.data?.cycles??[]).filter(e=>e?.name===C&&"number"==typeof e?.cycle_index).map(e=>e.cycle_index).sort((e,t)=>e-t);_(n),n.length>0&&j(e=>e??n[n.length-1])}catch{}})(),()=>{e=!0}},[r,a,l,C,i]),useEffect(()=>{if(!r||!a||!l)return d(null),p(null),y(!1),void h(null);let e=!1;return y(!0),h(null),(async()=>{try{const t={project_id:r,method_id:a,run_id:l,name:C};null!=v&&(t.cycle_index=v);const n=await i("tis.read_raw",MessageType.Request,t);if(e)return;if(n?.success){const e=n.data??{};p(e),d(unwrapEnvelope(e))}else h(n?.error_message??"Failed to read raw data")}catch(t){e||h(String(t?.message??t))}finally{e||y(!1)}})(),()=>{e=!0}},[r,a,l,C,v,i]);const E=useMemo(()=>{if(!c||!w)return null;const e=b.find(e=>e.name===w)?.view;if(!e)return null;const t=e.x.column,r=c[t]??[];return{datasets:e.y.map((e,t)=>({label:e.label??e.column,data:(c[e.column]??[]).map((e,t)=>({x:r[t],y:e})),yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(t),backgroundColor:palette(t),pointRadius:0,borderWidth:1.5,showLine:!0}))}},[c,w,b]),T=b.find(e=>e.name===w)?.view,L=T?.y.some(e=>"right"===e.y_axis)??!1,R=useMemo(()=>({responsive:!0,maintainAspectRatio:!1,parsing:!1,scales:{x:{type:"linear",title:{display:!!T?.x.label,text:T?.x.label}},y:{position:"left",title:{display:!0,text:axisLabel(T,"left")}},...L?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:axisLabel(T,"right")}}}:{}},plugins:{legend:{display:!0},zoom:{pan:{enabled:!0,mode:"xy"},zoom:{wheel:{enabled:!0},pinch:{enabled:!0},drag:{enabled:!0,modifierKey:"shift"},mode:"xy"}}}}),[T,L]);return r&&a&&l?n?n.raw_data?0===b.length?_jsx(EmptyState,{message:"No raw_trace views declared. Add one to schema.views in project.json."}):_jsxs("div",{className:"vblock",style:{display:"flex",flexDirection:"column",gap:"1rem",height:"100%"},children:[_jsxs("div",{className:"flex",style:{gap:"1rem",alignItems:"center",flexWrap:"wrap"},children:[_jsx(Dropdown,{value:w,options:b.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>S(e.value),placeholder:"Select a view"}),_jsx("h3",{style:{margin:0},children:T?.title??""}),g.length>1&&_jsxs(_Fragment,{children:[_jsx("label",{htmlFor:"rawview-cycle-picker",style:{color:"var(--text-secondary-color)"},children:"Cycle:"}),_jsx(Dropdown,{inputId:"rawview-cycle-picker",value:v,options:g.map(e=>({label:`Cycle ${e}`,value:e})),onChange:e=>j(Number(e.value)),style:{minWidth:"8rem"}}),_jsxs("span",{style:{color:"var(--text-secondary-color)"},children:["of ",g.length]})]}),_jsx("div",{style:{flex:1}}),_jsx(Button,{icon:"pi pi-refresh",label:"Reset Zoom",outlined:!0,onClick:()=>f.current?.resetZoom?.()})]}),_jsx(EnvelopeMetaStrip,{envelope:m}),_jsxs("div",{style:{flex:1,minHeight:0,height:o,position:"relative"},children:[u&&_jsx(Overlay,{children:"Loading raw data…"}),x&&_jsx(Overlay,{children:x}),E&&!u&&!x&&_jsx(Line,{ref:f,data:E,options:R})]})]}):_jsx(EmptyState,{message:"No raw_data is declared for this test method."}):_jsx(EmptyState,{message:"Schema not loaded yet."}):_jsx(EmptyState,{message:"No test selected."})};const Overlay=({children:e})=>_jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",color:"var(--text-secondary-color)",pointerEvents:"none"},children:e}),EmptyState=({message:e})=>_jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:e}),unwrapEnvelope=e=>e&&"object"==typeof e?"data"in e&&e.data&&"object"==typeof e.data&&Object.values(e.data).some(e=>Array.isArray(e))?e.data:e:{},EnvelopeMetaStrip=({envelope:e})=>{if(!e||"object"!=typeof e)return null;const t=e.cycle_index,r=e.cycle_fields,a=e.context;if(null==t&&!r&&!a)return null;const l=e=>e&&"object"==typeof e?Object.entries(e).filter(([,e])=>null!==e&&"object"!=typeof e).map(([e,t])=>_jsxs("span",{style:{marginRight:"1rem"},children:[_jsxs("span",{style:{color:"var(--text-secondary-color)"},children:[e,": "]}),_jsx("span",{children:String(t)})]},e)):null;return _jsxs("div",{style:{padding:"0.5rem 0.25rem",fontSize:"0.9rem",borderTop:"1px solid var(--surface-border)",borderBottom:"1px solid var(--surface-border)"},children:[null!=t&&_jsx("div",{children:_jsxs("strong",{children:["Cycle ",t]})}),r&&_jsx("div",{style:{marginTop:"0.25rem"},children:l(r)}),a&&_jsx("div",{style:{marginTop:"0.25rem"},children:l(a)})]})},CHART_COLORS=["#4ea8de","#f59e0b","#22c55e","#a855f7","#ef4444","#14b8a6","#eab308","#ec4899"],palette=e=>CHART_COLORS[e%CHART_COLORS.length],axisLabel=(e,t)=>e?.y.filter(e=>(e.y_axis??"left")===t).map(e=>e.label??e.column).join(" / ")??"";
@@ -24,6 +24,13 @@ export interface TestFieldDef {
24
24
  label?: string;
25
25
  /** Long-form guidance surfaced as a hover tooltip on an info icon. */
26
26
  description?: string;
27
+ /** Seed value applied when the operator selects this test method.
28
+ * For source-bound fields the default is written to the GM tag so
29
+ * the control program sees it; for non-source fields it's stashed
30
+ * straight into stagedConfig. Operator edits override per-stage,
31
+ * but the schema default never mutates — re-selecting the method
32
+ * re-applies the default. */
33
+ default?: any;
27
34
  }
28
35
  export interface TestMethod {
29
36
  project_fields: TestFieldDef[];
@@ -1 +1 @@
1
- {"version":3,"file":"TestSetupForm.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestSetupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAcxE;;;;;GAKG;AACH,UAAU,WAAW;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,aAAa,GAAG,aAAa,CAAC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IACzB,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;0EACsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACvB,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;IAC3B;0CACsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;2CACuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;gEAG4D;IAC5D,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf;;sDAEkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IAC/B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAChE;AAyED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAobtD,CAAC"}
1
+ {"version":3,"file":"TestSetupForm.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestSetupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAchF;;;;;GAKG;AACH,UAAU,WAAW;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,aAAa,GAAG,aAAa,CAAC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IACzB,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;0EACsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;kCAK8B;IAC9B,OAAO,CAAC,EAAE,GAAG,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACvB,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;IAC3B;0CACsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;2CACuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;gEAG4D;IAC5D,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf;;sDAEkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IAC/B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAChE;AAyED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAsdtD,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useState,useEffect,useContext,useMemo}from"react";import{Button}from"primereact/button";import{InputText}from"primereact/inputtext";import{Dropdown}from"primereact/dropdown";import{Dialog}from"primereact/dialog";import{EventEmitterContext}from"../../core/EventEmitterContext";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";import{MessageType}from"../../hub/CommandMessage";import{ValueInput}from"../ValueInput";import{TextInput}from"../TextInput";import{useTis}from"./TisProvider";import{useAmsAssets,useAmsRoles}from"../ams/AmsProvider";import{TestMethodDialog}from"./TestMethodDialog";const labelOf=e=>{const t=e.label&&e.label.length>0?e.label:e.name;return e.units?`${t} [${e.units}]`:t},hasDescription=e=>"string"==typeof e.description&&e.description.length>0,methodLabelOf=(e,t)=>t?.label&&t.label.length>0?t.label:e,AssetIdPicker=({assetType:e,value:t,onChange:s,invalid:i})=>{const a=useAmsAssets(),n=useAmsRoles(),o=useMemo(()=>a.filter(t=>t.asset_type===e&&"active"===t.status).map(e=>{const t=n[e.asset_type]?.find(t=>t.location===e.location)?.label,s=[e.asset_id];return t?s.push(`— ${t}`):e.location&&s.push(`— ${e.location}`),e.serial&&s.push(`(s/n ${e.serial})`),{label:s.join(" "),value:e.asset_id}}),[a,n,e]);return _jsx(Dropdown,{value:t,options:o,onChange:e=>s(e.value??""),placeholder:0===o.length?`No active ${e} assets registered — add one in Settings → Assets`:`Select ${e}…`,className:i?"p-invalid":"",filter:!0,showClear:!0,disabled:0===o.length})};export const TestSetupForm=({schema:e,defaultMethodId:t,onMethodChange:s,onValidationChange:i})=>{const a=useTis(),{invoke:n,write:o}=useContext(EventEmitterContext),{rawValues:r,findTagByFqdn:l}=useContext(AutoCoreTagContext),d=useMemo(()=>Object.keys(a.schemas),[a.schemas]),c=a.selection.projectId,m=""!==c.trim()&&a.projectKnown(c.trim()),[p,u]=useState(a.selection.methodId||t||a.defaultMethodId||""),[h,f]=useState(a.selection.sampleId||""),g=a.stagedConfig,x=e=>{const t="function"==typeof e?e(a.stagedConfig):e;t!==a.stagedConfig&&a.setStagedConfig(t)},_=e??(p?a.schemas[p]:void 0);useEffect(()=>{a.selection.methodId!==p&&p&&a.setSelection({methodId:p}),s&&s(p)},[p]),useEffect(()=>{a.selection.sampleId!==h&&a.setSelection({sampleId:h})},[h]),useEffect(()=>{a.state.stagedSampleId&&a.state.stagedSampleId!==h&&f(a.state.stagedSampleId)},[a.state.stagedSampleId]),useEffect(()=>{a.selection.methodId&&a.selection.methodId!==p&&u(a.selection.methodId)},[a.selection.methodId]);const[j,y]=useState(!1),[v,b]=useState(!1),[I,C]=useState({open:!1,title:"",body:null});useEffect(()=>{_&&x(e=>{let t=e;for(const s of _.config_fields){if("sample_id"===s.name)continue;if(!s.source)continue;const i=l(s.source);if(!i)continue;const a=r[i.tagName];null!=a&&(t[s.name]!==a&&(t===e&&(t={...e}),t[s.name]=a))}return t})},[_,r,l]),useEffect(()=>{if(!_)return void y(!1);let e=!0;m||(e=!1),p.trim()||(e=!1),h.trim()||(e=!1),e&&!a.projectFieldsLoaded&&(e=!1);for(const t of _.config_fields)if("sample_id"!==t.name&&t.required){const s=g[t.name];if(void 0===s||""===s||null===s){e=!1;break}}if(y(e),i&&i(e,g),e){const{sample_id:e,...t}=g??{},s={...a.projectFields,...t};n("tis.stage_test",MessageType.Request,{project_id:c,method_id:p,sample_id:h,config:s}).catch(e=>{})}},[g,_,c,p,h,m,a.projectFields,a.projectFieldsLoaded,i,n]);const S=async(e,t)=>{if(x({...g,[e.name]:t}),e.source)try{await o(e.source,t)}catch(e){}};if(!_)return _jsx("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:_jsx("h3",{className:"ac-form-section",children:a.schemasLoaded?"No Test Method Selected":"Loading test methods…"})});if(!m)return _jsxs("div",{style:{padding:"1.25rem",maxWidth:"600px"},children:[_jsx("h3",{className:"ac-form-section",children:"No project selected"}),_jsxs("p",{style:{color:"var(--text-secondary-color)",marginTop:"0.5rem"},children:["Pick a project on the ",_jsx("strong",{children:"Project"})," tab first",""!==c.trim()&&` (or click + there to create "${c.trim()}")`,"."]})]});const T=j&&!a.state.lastStartError;return _jsxs("div",{className:"ac-form-grid",style:{padding:"1.25rem",gridTemplateColumns:"auto 1fr 1.75rem 1.75rem"},children:[_jsxs("h3",{className:"ac-form-section",style:{display:"flex",alignItems:"center",gap:"10px"},children:["Test Setup",_jsx(Button,{icon:T?"pi pi-check-circle":"pi pi-exclamation-circle",severity:T?"success":"danger",text:!0,rounded:!0,"aria-label":"Test Setup status",onClick:()=>{const e=(()=>{const e=[];if(m||e.push("No project is selected. Pick or create one on the Project tab."),a.projectFieldsLoaded||e.push("Project fields are still loading."),p.trim()||e.push("No test method selected."),h.trim()||e.push("Sample ID is required."),_)for(const t of _.config_fields){if("sample_id"===t.name)continue;if(!t.required)continue;const s=g[t.name];void 0!==s&&""!==s&&null!==s||e.push(`Required field "${labelOf(t)}" is empty.`)}return e})(),t=a.state.lastStartError?.trim()??"";let s;s=0!==e.length||t?_jsxs("div",{children:[e.length>0&&_jsxs(_Fragment,{children:[_jsx("p",{style:{margin:"0 0 0.5rem 0"},children:"The form is incomplete:"}),_jsx("ul",{style:{margin:"0 0 1rem 1.25rem"},children:e.map((e,t)=>_jsx("li",{children:e},t))})]}),t&&_jsxs(_Fragment,{children:[_jsx("p",{style:{margin:"0 0 0.25rem 0",fontWeight:600},children:"Last start_test error from the server:"}),_jsx("pre",{style:{margin:0,padding:"0.5rem",background:"rgba(0,0,0,0.25)",borderRadius:"4px",whiteSpace:"pre-wrap",fontSize:"0.875rem"},children:t})]})]}):_jsx("p",{style:{margin:0},children:"All required fields are complete. The test is staged and ready to start."}),C({open:!0,title:"Test Setup Status",body:s})}}),_jsxs("span",{style:{fontSize:"0.85em",color:"var(--text-secondary-color)",fontWeight:"normal",marginLeft:"0.25rem"},children:["project: ",_jsx("strong",{children:c})]})]}),_jsx("span",{className:"ac-form-label",children:"Sample ID"}),_jsx(TextInput,{label:void 0,value:h,onValueChanged:e=>{f(e)},className:h.trim()?"":"p-invalid"}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:h.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:h.trim()?"pi pi-check":"pi pi-times"})}),d.length>0&&_jsxs(_Fragment,{children:[_jsx("span",{className:"ac-form-label",children:"Test Method"}),_jsxs("div",{className:"p-inputgroup",style:{flex:1},children:[_jsx(InputText,{value:methodLabelOf(p,_),readOnly:!0,style:{flex:1},tabIndex:-1}),_jsx(Button,{icon:"pi pi-pencil",type:"button",onClick:()=>b(!0),tooltip:d.length>1?"Change test method":"View test method details",tooltipOptions:{position:"top"}})]}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:p?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:p?"pi pi-check":"pi pi-times"})})]}),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Test Configuration"}),_.config_fields.map(e=>{if("sample_id"===e.name)return null;const t=(e=>{if(!e.required)return!0;const t=g[e.name];return void 0!==t&&""!==t&&null!==t})(e),s=(e=>{const t=_?.asset_refs??[],s=`config.${e.name}`,i=t.find(e=>"by_id_field"===e.select&&e.from===s);return i?i.asset_type:null})(e),i=!s&&"string"!==e.type&&"bool"!==e.type;return _jsxs(React.Fragment,{children:[_jsx("span",{className:"ac-form-label",children:labelOf(e)}),s?_jsx(AssetIdPicker,{assetType:s,value:null!=g[e.name]?String(g[e.name]):"",onChange:t=>S(e,t),invalid:!t}):i?_jsx(ValueInput,{label:void 0,value:null!=g[e.name]?Number(g[e.name]):null,onValueChanged:t=>S(e,t),className:t?"":"p-invalid"}):_jsx(TextInput,{label:void 0,value:null!=g[e.name]?String(g[e.name]):"",onValueChanged:t=>S(e,t),className:t?"":"p-invalid"}),hasDescription(e)?_jsx(Button,{icon:"pi pi-info-circle",text:!0,rounded:!0,"aria-label":`About ${labelOf(e)}`,onClick:()=>C({open:!0,title:labelOf(e),body:_jsx("p",{style:{margin:0,whiteSpace:"pre-wrap"},children:e.description})})}):_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:t?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:t?"pi pi-check":"pi pi-times"})})]},e.name)}),_jsx(TestMethodDialog,{visible:v,onHide:()=>b(!1),currentMethodId:p,onSelected:e=>u(e)}),_jsx(Dialog,{header:I.title,visible:I.open,onHide:()=>C({open:!1,title:"",body:null}),style:{width:"32rem",maxWidth:"90vw"},modal:!0,dismissableMask:!0,children:I.body})]})};
1
+ import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useState,useEffect,useContext,useMemo,useRef}from"react";import{Button}from"primereact/button";import{InputText}from"primereact/inputtext";import{Dropdown}from"primereact/dropdown";import{Dialog}from"primereact/dialog";import{EventEmitterContext}from"../../core/EventEmitterContext";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";import{MessageType}from"../../hub/CommandMessage";import{ValueInput}from"../ValueInput";import{TextInput}from"../TextInput";import{useTis}from"./TisProvider";import{useAmsAssets,useAmsRoles}from"../ams/AmsProvider";import{TestMethodDialog}from"./TestMethodDialog";const labelOf=e=>{const t=e.label&&e.label.length>0?e.label:e.name;return e.units?`${t} [${e.units}]`:t},hasDescription=e=>"string"==typeof e.description&&e.description.length>0,methodLabelOf=(e,t)=>t?.label&&t.label.length>0?t.label:e,AssetIdPicker=({assetType:e,value:t,onChange:s,invalid:i})=>{const a=useAmsAssets(),n=useAmsRoles(),o=useMemo(()=>a.filter(t=>t.asset_type===e&&"active"===t.status).map(e=>{const t=n[e.asset_type]?.find(t=>t.location===e.location)?.label,s=[e.asset_id];return t?s.push(`— ${t}`):e.location&&s.push(`— ${e.location}`),e.serial&&s.push(`(s/n ${e.serial})`),{label:s.join(" "),value:e.asset_id}}),[a,n,e]);return _jsx(Dropdown,{value:t,options:o,onChange:e=>s(e.value??""),placeholder:0===o.length?`No active ${e} assets registered — add one in Settings → Assets`:`Select ${e}…`,className:i?"p-invalid":"",filter:!0,showClear:!0,disabled:0===o.length})};export const TestSetupForm=({schema:e,defaultMethodId:t,onMethodChange:s,onValidationChange:i})=>{const a=useTis(),{invoke:n,write:o}=useContext(EventEmitterContext),{rawValues:r,findTagByFqdn:l}=useContext(AutoCoreTagContext),c=useMemo(()=>Object.keys(a.schemas),[a.schemas]),d=a.selection.projectId,m=""!==d.trim()&&a.projectKnown(d.trim()),[p,u]=useState(a.selection.methodId||t||a.defaultMethodId||""),[f,h]=useState(a.selection.sampleId||""),g=a.stagedConfig,x=e=>{const t="function"==typeof e?e(a.stagedConfig):e;t!==a.stagedConfig&&a.setStagedConfig(t)},_=e??(p?a.schemas[p]:void 0);useEffect(()=>{a.selection.methodId!==p&&p&&a.setSelection({methodId:p}),s&&s(p)},[p]),useEffect(()=>{a.selection.sampleId!==f&&a.setSelection({sampleId:f})},[f]),useEffect(()=>{a.state.stagedSampleId&&a.state.stagedSampleId!==f&&h(a.state.stagedSampleId)},[a.state.stagedSampleId]),useEffect(()=>{a.selection.methodId&&a.selection.methodId!==p&&u(a.selection.methodId)},[a.selection.methodId]);const[j,v]=useState(!1),[y,b]=useState(!1),[I,C]=useState({open:!1,title:"",body:null}),S=useRef("");useEffect(()=>{_&&p&&S.current!==p&&(S.current=p,x(e=>{let t=e;for(const s of _.config_fields)"sample_id"!==s.name&&void 0!==s.default&&null!==s.default&&(t===e&&(t={...e}),t[s.name]=s.default,s.source&&Promise.resolve().then(()=>o(s.source,s.default)).catch(e=>{}));return t}))},[_,p,o]),useEffect(()=>{_&&x(e=>{let t=e;for(const s of _.config_fields){if("sample_id"===s.name)continue;if(!s.source)continue;const i=l(s.source);if(!i)continue;const a=r[i.tagName];null!=a&&(t[s.name]!==a&&(t===e&&(t={...e}),t[s.name]=a))}return t})},[_,r,l]),useEffect(()=>{if(!_)return void v(!1);let e=!0;m||(e=!1),p.trim()||(e=!1),f.trim()||(e=!1),e&&!a.projectFieldsLoaded&&(e=!1);for(const t of _.config_fields)if("sample_id"!==t.name&&t.required){const s=g[t.name];if(void 0===s||""===s||null===s){e=!1;break}}if(v(e),i&&i(e,g),e){const{sample_id:e,...t}=g??{},s={...a.projectFields,...t};n("tis.stage_test",MessageType.Request,{project_id:d,method_id:p,sample_id:f,config:s}).catch(e=>{})}},[g,_,d,p,f,m,a.projectFields,a.projectFieldsLoaded,i,n]);const T=async(e,t)=>{if(x({...g,[e.name]:t}),e.source)try{await o(e.source,t)}catch(e){}};if(!_)return _jsx("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:_jsx("h3",{className:"ac-form-section",children:a.schemasLoaded?"No Test Method Selected":"Loading test methods…"})});if(!m)return _jsxs("div",{style:{padding:"1.25rem",maxWidth:"600px"},children:[_jsx("h3",{className:"ac-form-section",children:"No project selected"}),_jsxs("p",{style:{color:"var(--text-secondary-color)",marginTop:"0.5rem"},children:["Pick a project on the ",_jsx("strong",{children:"Project"})," tab first",""!==d.trim()&&` (or click + there to create "${d.trim()}")`,"."]})]});const N=j&&!a.state.lastStartError;return _jsxs("div",{className:"ac-form-grid",style:{padding:"1.25rem",gridTemplateColumns:"auto 1fr 1.75rem 1.75rem"},children:[_jsxs("h3",{className:"ac-form-section",style:{display:"flex",alignItems:"center",gap:"10px"},children:["Test Setup",_jsx(Button,{icon:N?"pi pi-check-circle":"pi pi-exclamation-circle",severity:N?"success":"danger",text:!0,rounded:!0,"aria-label":"Test Setup status",onClick:()=>{const e=(()=>{const e=[];if(m||e.push("No project is selected. Pick or create one on the Project tab."),a.projectFieldsLoaded||e.push("Project fields are still loading."),p.trim()||e.push("No test method selected."),f.trim()||e.push("Sample ID is required."),_)for(const t of _.config_fields){if("sample_id"===t.name)continue;if(!t.required)continue;const s=g[t.name];void 0!==s&&""!==s&&null!==s||e.push(`Required field "${labelOf(t)}" is empty.`)}return e})(),t=a.state.lastStartError?.trim()??"";let s;s=0!==e.length||t?_jsxs("div",{children:[e.length>0&&_jsxs(_Fragment,{children:[_jsx("p",{style:{margin:"0 0 0.5rem 0"},children:"The form is incomplete:"}),_jsx("ul",{style:{margin:"0 0 1rem 1.25rem"},children:e.map((e,t)=>_jsx("li",{children:e},t))})]}),t&&_jsxs(_Fragment,{children:[_jsx("p",{style:{margin:"0 0 0.25rem 0",fontWeight:600},children:"Last start_test error from the server:"}),_jsx("pre",{style:{margin:0,padding:"0.5rem",background:"rgba(0,0,0,0.25)",borderRadius:"4px",whiteSpace:"pre-wrap",fontSize:"0.875rem"},children:t})]})]}):_jsx("p",{style:{margin:0},children:"All required fields are complete. The test is staged and ready to start."}),C({open:!0,title:"Test Setup Status",body:s})}}),_jsxs("span",{style:{fontSize:"0.85em",color:"var(--text-secondary-color)",fontWeight:"normal",marginLeft:"0.25rem"},children:["project: ",_jsx("strong",{children:d})]})]}),_jsx("span",{className:"ac-form-label",children:"Sample ID"}),_jsx(TextInput,{label:void 0,value:f,onValueChanged:e=>{h(e)},className:f.trim()?"":"p-invalid"}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:f.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:f.trim()?"pi pi-check":"pi pi-times"})}),c.length>0&&_jsxs(_Fragment,{children:[_jsx("span",{className:"ac-form-label",children:"Test Method"}),_jsxs("div",{className:"p-inputgroup",style:{flex:1},children:[_jsx(InputText,{value:methodLabelOf(p,_),readOnly:!0,style:{flex:1},tabIndex:-1}),_jsx(Button,{icon:"pi pi-pencil",type:"button",onClick:()=>b(!0),tooltip:c.length>1?"Change test method":"View test method details",tooltipOptions:{position:"top"}})]}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:p?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:p?"pi pi-check":"pi pi-times"})})]}),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Test Configuration"}),_.config_fields.map(e=>{if("sample_id"===e.name)return null;const t=(e=>{if(!e.required)return!0;const t=g[e.name];return void 0!==t&&""!==t&&null!==t})(e),s=(e=>{const t=_?.asset_refs??[],s=`config.${e.name}`,i=t.find(e=>"by_id_field"===e.select&&e.from===s);return i?i.asset_type:null})(e),i=!s&&"string"!==e.type&&"bool"!==e.type;return _jsxs(React.Fragment,{children:[_jsx("span",{className:"ac-form-label",children:labelOf(e)}),s?_jsx(AssetIdPicker,{assetType:s,value:null!=g[e.name]?String(g[e.name]):"",onChange:t=>T(e,t),invalid:!t}):i?_jsx(ValueInput,{label:void 0,value:null!=g[e.name]?Number(g[e.name]):null,onValueChanged:t=>T(e,t),className:t?"":"p-invalid"}):_jsx(TextInput,{label:void 0,value:null!=g[e.name]?String(g[e.name]):"",onValueChanged:t=>T(e,t),className:t?"":"p-invalid"}),hasDescription(e)?_jsx(Button,{icon:"pi pi-info-circle",text:!0,rounded:!0,"aria-label":`About ${labelOf(e)}`,onClick:()=>C({open:!0,title:labelOf(e),body:_jsx("p",{style:{margin:0,whiteSpace:"pre-wrap"},children:e.description})})}):_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:t?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:t?"pi pi-check":"pi pi-times"})})]},e.name)}),_jsx(TestMethodDialog,{visible:y,onHide:()=>b(!1),currentMethodId:p,onSelected:e=>u(e)}),_jsx(Dialog,{header:I.title,visible:I.open,onHide:()=>C({open:!1,title:"",body:null}),style:{width:"32rem",maxWidth:"90vw"},modal:!0,dismissableMask:!0,children:I.body})]})};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adcops/autocore-react",
3
- "version": "3.3.73",
3
+ "version": "3.3.77",
4
4
  "description": "A React component library for industrial user interfaces.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -91,6 +91,10 @@
91
91
  "import": "./dist/components/*",
92
92
  "types": "./dist/components/*.d.ts"
93
93
  },
94
+ "./assets/*": {
95
+ "import": "./dist/assets/*",
96
+ "types": "./dist/assets/*.d.ts"
97
+ },
94
98
  "./hooks/*": {
95
99
  "import": "./dist/hooks/*",
96
100
  "types": "./dist/hooks/*.d.ts"
@@ -0,0 +1,37 @@
1
+ import type { SVGProps } from "react";
2
+
3
+ export const HomeMotor = (props: SVGProps<SVGSVGElement>) => (
4
+ <svg
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ width="24"
7
+ height="24"
8
+ viewBox="0 0 24 24"
9
+ fill="none"
10
+ stroke="currentColor"
11
+ strokeWidth="2"
12
+ strokeLinecap="round"
13
+ strokeLinejoin="round"
14
+ {...props}
15
+ >
16
+ {/* The House Outline */}
17
+ <path d="M8.5 21H5a2 2 0 0 1-2-2v-9a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2v-2" />
18
+
19
+ {/* The Motor Outer Casing */}
20
+ <circle
21
+ cx="12"
22
+ cy="12.5"
23
+ r="4"
24
+ />
25
+
26
+ {/* The Motor Shaft / Center Point */}
27
+ <circle
28
+ cx="12"
29
+ cy="12.5"
30
+ r="1"
31
+ fill="currentColor"
32
+ stroke="none"
33
+ />
34
+ </svg>
35
+ );
36
+
37
+ export default HomeMotor;
@@ -0,0 +1,57 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <svg
3
+ width="24"
4
+ height="24"
5
+ viewBox="0 0 24 24"
6
+ fill="none"
7
+ stroke="currentColor"
8
+ stroke-width="2"
9
+ stroke-linecap="round"
10
+ stroke-linejoin="round"
11
+ class="lucide lucide-house-plug-icon lucide-house-plug"
12
+ version="1.1"
13
+ id="svg4"
14
+ sodipodi:docname="home-motor.svg"
15
+ inkscape:version="1.4.3 (0d15f75, 2025-12-25)"
16
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
17
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
18
+ xmlns="http://www.w3.org/2000/svg"
19
+ xmlns:svg="http://www.w3.org/2000/svg">
20
+ <defs
21
+ id="defs4" />
22
+ <sodipodi:namedview
23
+ id="namedview4"
24
+ pagecolor="#ffffff"
25
+ bordercolor="#000000"
26
+ borderopacity="0.25"
27
+ inkscape:showpageshadow="2"
28
+ inkscape:pageopacity="0.0"
29
+ inkscape:pagecheckerboard="0"
30
+ inkscape:deskcolor="#d1d1d1"
31
+ inkscape:zoom="50.541667"
32
+ inkscape:cx="12"
33
+ inkscape:cy="12"
34
+ inkscape:window-width="2560"
35
+ inkscape:window-height="1494"
36
+ inkscape:window-x="-11"
37
+ inkscape:window-y="-11"
38
+ inkscape:window-maximized="1"
39
+ inkscape:current-layer="svg4" />
40
+ <path
41
+ d="M8.5 21H5a2 2 0 0 1-2-2v-9a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2v-2"
42
+ id="path4" />
43
+ <ellipse
44
+ style="fill:none;stroke-width:2.08003;stroke-dasharray:none"
45
+ id="path5"
46
+ cx="11.970321"
47
+ cy="12.366035"
48
+ rx="3.9292588"
49
+ ry="3.9292586" />
50
+ <ellipse
51
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:4.98654;stroke-dasharray:none;stroke-opacity:1"
52
+ id="path6"
53
+ cx="11.970321"
54
+ cy="12.366035"
55
+ rx="0.89035445"
56
+ ry="0.89035451" />
57
+ </svg>