@adcops/autocore-react 3.5.7 → 3.5.11

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 (95) hide show
  1. package/dist/components/forms/useEditDraft.d.ts +49 -0
  2. package/dist/components/forms/useEditDraft.d.ts.map +1 -0
  3. package/dist/components/forms/useEditDraft.js +1 -0
  4. package/dist/components/index.d.ts +6 -0
  5. package/dist/components/index.d.ts.map +1 -1
  6. package/dist/components/index.js +1 -1
  7. package/dist/components/tis/TestDataView.d.ts +8 -0
  8. package/dist/components/tis/TestDataView.d.ts.map +1 -1
  9. package/dist/components/tis/TestDataView.js +1 -1
  10. package/dist/components/tis/TestRawDataView.d.ts.map +1 -1
  11. package/dist/components/tis/TestRawDataView.js +1 -1
  12. package/dist/components/tis/chartViews.d.ts +57 -0
  13. package/dist/components/tis/chartViews.d.ts.map +1 -0
  14. package/dist/components/tis/chartViews.js +1 -0
  15. package/dist/components/tis-editor/TisConfigEditor.css +11 -0
  16. package/dist/components/tis-editor/TisConfigEditor.d.ts.map +1 -1
  17. package/dist/components/tis-editor/TisConfigEditor.js +1 -1
  18. package/dist/components/tis-editor/editor/AuthoringContext.d.ts +37 -0
  19. package/dist/components/tis-editor/editor/AuthoringContext.d.ts.map +1 -0
  20. package/dist/components/tis-editor/editor/AuthoringContext.js +1 -0
  21. package/dist/components/tis-editor/editor/ChartViewDialog.d.ts +11 -0
  22. package/dist/components/tis-editor/editor/ChartViewDialog.d.ts.map +1 -1
  23. package/dist/components/tis-editor/editor/ChartViewDialog.js +1 -1
  24. package/dist/components/tis-editor/editor/FieldArrayEditor.d.ts.map +1 -1
  25. package/dist/components/tis-editor/editor/FieldArrayEditor.js +1 -1
  26. package/dist/components/tis-editor/editor/RawDataEditor.d.ts.map +1 -1
  27. package/dist/components/tis-editor/editor/RawDataEditor.js +1 -1
  28. package/dist/components/tis-editor/editor/TestFieldDialog.d.ts +7 -0
  29. package/dist/components/tis-editor/editor/TestFieldDialog.d.ts.map +1 -1
  30. package/dist/components/tis-editor/editor/TestFieldDialog.js +1 -1
  31. package/dist/components/tis-editor/editor/ViewsEditor.d.ts.map +1 -1
  32. package/dist/components/tis-editor/editor/ViewsEditor.js +1 -1
  33. package/dist/components/tis-editor/types.d.ts +6 -0
  34. package/dist/components/tis-editor/types.d.ts.map +1 -1
  35. package/dist/components/varpick/VariableInput.d.ts +41 -0
  36. package/dist/components/varpick/VariableInput.d.ts.map +1 -0
  37. package/dist/components/varpick/VariableInput.js +1 -0
  38. package/dist/components/varpick/VariablePicker.d.ts +45 -0
  39. package/dist/components/varpick/VariablePicker.d.ts.map +1 -0
  40. package/dist/components/varpick/VariablePicker.js +1 -0
  41. package/dist/components/varpick/index.d.ts +16 -0
  42. package/dist/components/varpick/index.d.ts.map +1 -0
  43. package/dist/components/varpick/index.js +1 -0
  44. package/dist/components/varpick/tisCatalogs.d.ts +85 -0
  45. package/dist/components/varpick/tisCatalogs.d.ts.map +1 -0
  46. package/dist/components/varpick/tisCatalogs.js +1 -0
  47. package/dist/components/varpick/varpick.css +167 -0
  48. package/dist/core/AutoCoreTagContext.d.ts.map +1 -1
  49. package/dist/core/AutoCoreTagContext.js +1 -1
  50. package/dist/core/AutoCoreTagTypes.d.ts +13 -0
  51. package/dist/core/AutoCoreTagTypes.d.ts.map +1 -1
  52. package/dist/hooks/index.d.ts +4 -0
  53. package/dist/hooks/index.d.ts.map +1 -1
  54. package/dist/hooks/index.js +1 -1
  55. package/dist/hooks/useGmVariables.d.ts +57 -0
  56. package/dist/hooks/useGmVariables.d.ts.map +1 -0
  57. package/dist/hooks/useGmVariables.js +1 -0
  58. package/dist/hooks/useSequenceProducers.d.ts +38 -0
  59. package/dist/hooks/useSequenceProducers.d.ts.map +1 -0
  60. package/dist/hooks/useSequenceProducers.js +1 -0
  61. package/package.json +7 -2
  62. package/src/components/forms/useEditDraft.ts +0 -0
  63. package/src/components/index.ts +20 -0
  64. package/src/components/tis/TestDataView.tsx +16 -10
  65. package/src/components/tis/TestRawDataView.tsx +6 -7
  66. package/src/components/tis/chartViews.ts +104 -0
  67. package/src/components/tis-editor/TisConfigEditor.css +11 -0
  68. package/src/components/tis-editor/TisConfigEditor.tsx +31 -0
  69. package/src/components/tis-editor/editor/AuthoringContext.tsx +43 -0
  70. package/src/components/tis-editor/editor/ChartViewDialog.tsx +48 -17
  71. package/src/components/tis-editor/editor/FieldArrayEditor.tsx +1 -0
  72. package/src/components/tis-editor/editor/RawDataEditor.tsx +7 -2
  73. package/src/components/tis-editor/editor/TestFieldDialog.tsx +90 -23
  74. package/src/components/tis-editor/editor/ViewsEditor.tsx +56 -5
  75. package/src/components/tis-editor/types.ts +6 -0
  76. package/src/components/varpick/VariableInput.tsx +126 -0
  77. package/src/components/varpick/VariablePicker.tsx +168 -0
  78. package/src/components/varpick/index.ts +22 -0
  79. package/src/components/varpick/tisCatalogs.ts +235 -0
  80. package/src/components/varpick/varpick.css +167 -0
  81. package/src/core/AutoCoreTagContext.tsx +3 -1
  82. package/src/core/AutoCoreTagTypes.ts +14 -0
  83. package/src/hooks/index.ts +11 -0
  84. package/src/hooks/useGmVariables.ts +142 -0
  85. package/src/hooks/useSequenceProducers.ts +104 -0
  86. package/tools/tests/dist/TestFieldDialog-C4mKVh7q.js +32817 -0
  87. package/tools/tests/dist/autocore-react.css +257 -0
  88. package/tools/tests/dist/tis-editor.entry.js +9295 -0
  89. package/tools/tests/dist/varpick.entry.js +113 -0
  90. package/tools/tests/live-server.probe.mjs +172 -0
  91. package/tools/tests/tis-editor.entry.tsx +46 -0
  92. package/tools/tests/tis-editor.test.mjs +133 -0
  93. package/tools/tests/varpick.entry.tsx +81 -0
  94. package/tools/tests/varpick.test.mjs +208 -0
  95. package/tools/tests/vite.config.mjs +35 -0
@@ -0,0 +1,49 @@
1
+ /**
2
+ * useEditDraft — draft state for a dialog that edits one record.
3
+ *
4
+ * A dialog seeds its draft from the record it was opened on, then owns that
5
+ * draft until it closes. Written the obvious way — a `useEffect` keyed on the
6
+ * `initial` prop — the reseed fires whenever the prop's OBJECT IDENTITY
7
+ * changes, which is not the same event as "the operator opened a different
8
+ * record":
9
+ *
10
+ * - a parent that builds `initial={{ id, record }}` inline hands over a new
11
+ * object on every render of its own, and
12
+ * - these editors sit under `AutoCoreTagProvider` / `TisProvider`, whose
13
+ * consumers re-render on live tag and broadcast traffic — many times a
14
+ * second on a running machine.
15
+ *
16
+ * Together those reseeded the draft within a frame of every keystroke, so the
17
+ * TIS chart-view dialog was effectively read-only: type a character, watch the
18
+ * original value come back. (gen4_ac, 2026-08-29.)
19
+ *
20
+ * The reseed here is keyed on an explicit EDIT TOKEN instead — closed, or open
21
+ * on a named record — so upstream identity churn cannot reach it. Two
22
+ * transitions reseed, and nothing else does:
23
+ *
24
+ * closed → open:<key> dialog opened on a record → seed
25
+ * open:<key A> → open:<key B> swapped to another record → seed
26
+ * open:<key> → closed dialog closed → draft kept as-is
27
+ */
28
+ import type { Dispatch, SetStateAction } from 'react';
29
+ export interface EditDraft<T> {
30
+ /** The working copy. Edits survive any re-render of the tree above. */
31
+ draft: T;
32
+ setDraft: Dispatch<SetStateAction<T>>;
33
+ /**
34
+ * The current edit token. Stable for as long as one record stays open, so
35
+ * it is safe as a `useEffect` dependency for companion state that has to
36
+ * be cleared alongside a reseed (a validation error, say).
37
+ */
38
+ token: string;
39
+ }
40
+ /**
41
+ * @param visible Whether the dialog is open.
42
+ * @param editKey Stable identity of the record being edited — a view id, a
43
+ * field name. Empty string for "new record".
44
+ * @param seed Builds the initial draft. Called only on a reseed, so it may
45
+ * read the current props directly.
46
+ */
47
+ export declare function useEditDraft<T>(visible: boolean, editKey: string, seed: () => T): EditDraft<T>;
48
+ export default useEditDraft;
49
+ //# sourceMappingURL=useEditDraft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEditDraft.d.ts","sourceRoot":"","sources":["../../../src/components/forms/useEditDraft.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAKtD,MAAM,WAAW,SAAS,CAAC,CAAC;IACxB,uEAAuE;IACvE,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC1B,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,CAAC,GACd,SAAS,CAAC,CAAC,CAAC,CAed;AAED,eAAe,YAAY,CAAC"}
@@ -0,0 +1 @@
1
+ import{useState}from"react";const CLOSED="\0closed";export function useEditDraft(t,e,r){const o=t?`open:${e}`:CLOSED,[a,s]=useState(r),[u,f]=useState(o);return u!==o&&(f(o),t&&s(r())),{draft:a,setDraft:s,token:o}}export default useEditDraft;
@@ -6,6 +6,8 @@ export { TestSetupForm } from './tis/TestSetupForm';
6
6
  export type { TestSetupFormProps } from './tis/TestSetupForm';
7
7
  export { TestSetupView } from './tis/TestSetupView';
8
8
  export type { TestSetupViewProps } from './tis/TestSetupView';
9
+ export { orderedViews, renumberViews, moveView } from './tis/chartViews';
10
+ export type { NamedView, OrderableView } from './tis/chartViews';
9
11
  export { TestFieldRow } from './tis/TestFieldRow';
10
12
  export type { TestFieldRowProps, CycleConfigScope } from './tis/TestFieldRow';
11
13
  export { CycleConfigForm, cycleConfigSummary } from './tis/CycleConfigForm';
@@ -45,4 +47,8 @@ export { NetworkPanel } from './network/NetworkPanel';
45
47
  export type { NetworkPanelProps } from './network/NetworkPanel';
46
48
  export { StagedChangeBanner } from './network/StagedChangeBanner';
47
49
  export type { StagedChangeBannerProps } from './network/StagedChangeBanner';
50
+ export { VariablePicker, VariableInput } from './varpick';
51
+ export type { VariablePickerProps, VariableInputProps } from './varpick';
52
+ export { boundCatalog, chartFieldCatalog, configSourceCatalog, cycleSourceCatalog, rawSourceCatalog, } from './varpick';
53
+ export type { TisCatalogContext } from './varpick';
48
54
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- export{TisProvider,TisContext,useTis,useTisSchemas,useTisState,useTisSelection,useTisRuns,useTisRun,useTisCycleConfig}from"./tis/TisProvider";export{ProjectSelector}from"./tis/ProjectSelector";export{TestSetupForm}from"./tis/TestSetupForm";export{TestSetupView}from"./tis/TestSetupView";export{TestFieldRow}from"./tis/TestFieldRow";export{CycleConfigForm,cycleConfigSummary}from"./tis/CycleConfigForm";export{CycleConfigDialog,useCycleConfigGate}from"./tis/CycleConfigDialog";export{CycleStatusStrip}from"./tis/CycleStatusStrip";export{ProjectInfoDialog}from"./tis/ProjectInfoDialog";export{TestMethodDialog}from"./tis/TestMethodDialog";export{ResultHistoryTable}from"./tis/ResultHistoryTable";export{SampleSummaryPanel}from"./tis/SampleSummaryPanel";export{TestDataView,DEFAULT_X_DECIMALS}from"./tis/TestDataView";export{UnitSystemSelector}from"./UnitSystemSelector";export{UnitsEditor}from"./UnitsEditor";export{TestRawDataView}from"./tis/TestRawDataView";export{ProjectManager}from"./tis/ProjectManager";export{AmsProvider,useAms,useAmsSchemas,useAmsAlerts,useAmsAssets,useAmsSelection}from"./ams/AmsProvider";export{AssetRegistryTable}from"./ams/AssetRegistryTable";export{AssetDetailView}from"./ams/AssetDetailView";export{CalibrationEntryDialog}from"./ams/CalibrationEntryDialog";export{SubLocationPicker}from"./ams/SubLocationPicker";export{NetworkProvider,useNetwork}from"./network/NetworkProvider";export{NetworkPanel}from"./network/NetworkPanel";export{StagedChangeBanner}from"./network/StagedChangeBanner";
1
+ export{TisProvider,TisContext,useTis,useTisSchemas,useTisState,useTisSelection,useTisRuns,useTisRun,useTisCycleConfig}from"./tis/TisProvider";export{ProjectSelector}from"./tis/ProjectSelector";export{TestSetupForm}from"./tis/TestSetupForm";export{TestSetupView}from"./tis/TestSetupView";export{orderedViews,renumberViews,moveView}from"./tis/chartViews";export{TestFieldRow}from"./tis/TestFieldRow";export{CycleConfigForm,cycleConfigSummary}from"./tis/CycleConfigForm";export{CycleConfigDialog,useCycleConfigGate}from"./tis/CycleConfigDialog";export{CycleStatusStrip}from"./tis/CycleStatusStrip";export{ProjectInfoDialog}from"./tis/ProjectInfoDialog";export{TestMethodDialog}from"./tis/TestMethodDialog";export{ResultHistoryTable}from"./tis/ResultHistoryTable";export{SampleSummaryPanel}from"./tis/SampleSummaryPanel";export{TestDataView,DEFAULT_X_DECIMALS}from"./tis/TestDataView";export{UnitSystemSelector}from"./UnitSystemSelector";export{UnitsEditor}from"./UnitsEditor";export{TestRawDataView}from"./tis/TestRawDataView";export{ProjectManager}from"./tis/ProjectManager";export{AmsProvider,useAms,useAmsSchemas,useAmsAlerts,useAmsAssets,useAmsSelection}from"./ams/AmsProvider";export{AssetRegistryTable}from"./ams/AssetRegistryTable";export{AssetDetailView}from"./ams/AssetDetailView";export{CalibrationEntryDialog}from"./ams/CalibrationEntryDialog";export{SubLocationPicker}from"./ams/SubLocationPicker";export{NetworkProvider,useNetwork}from"./network/NetworkProvider";export{NetworkPanel}from"./network/NetworkPanel";export{StagedChangeBanner}from"./network/StagedChangeBanner";export{VariablePicker,VariableInput}from"./varpick";export{boundCatalog,chartFieldCatalog,configSourceCatalog,cycleSourceCatalog,rawSourceCatalog}from"./varpick";
@@ -121,6 +121,14 @@ export interface ChartView {
121
121
  * table, CSV export and every calculation still see the full value.
122
122
  */
123
123
  x_decimals?: number;
124
+ /**
125
+ * Position in the view picker, ascending — the view with the lowest
126
+ * `order` is the one this panel opens on. Written by the TIS editor's
127
+ * Move up / Move down. See `chartViews.ts`: the keys of `views` arrive
128
+ * sorted by id, so the order an author chose has to be carried
129
+ * explicitly.
130
+ */
131
+ order?: number;
124
132
  /**
125
133
  * Optional shaded X-range bands drawn over the plot, declared per view
126
134
  * in project.json (static). These are drawn on every cycle.
@@ -1 +1 @@
1
- {"version":3,"file":"TestDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestDataView.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TestDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestDataView.tsx"],"names":[],"mappings":"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"}
@@ -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 annotationPlugin from"chartjs-plugin-annotation";import{Line}from"react-chartjs-2";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";import{formatScaled}from"../../core/formatScaled";import{useRawCycleData}from"./useRawCycleData";import{ScienceTable}from"./ScienceTable";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin,annotationPlugin);export const TestDataView=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,n=e.methodId??t.selection.methodId,a=e.runId??t.selection.runId,o=e.schema??(n?t.schemas[n]:void 0),{throttleMs:l=100,cycleTableHeight:i="400px",chartHeight:s="320px"}=e,{invoke:c,subscribe:d,unsubscribe:u}=useContext(EventEmitterContext),{scales:m}=useContext(AutoCoreTagContext),[p,y]=useState(null),[f,h]=useState([]),[g,_]=useState({}),[x,b]=useState({}),[j,v]=useState(!1),[w,C]=useState(!1),S=useCallback(async(e,t,o)=>{const l=e?.cycle_index;if(r&&n&&a&&l)try{const e=await c("tis.update_cycle",MessageType.Request,{project_id:r,method_id:n,run_id:a,cycle_index:l,fields:{[t]:o}});if(!1===e?.success)return;h(e=>e.map(e=>e?.cycle_index===l?{...e,[t]:o}:e))}catch(e){}},[c,r,n,a]),T=useRef(null),[R,O]=useState(null),[A,D]=useState(null),[M,E]=useState(!1),[L,I]=useState(null),[N,F]=useState(null),[k,q]=useState(!1),[H,P]=useState([]),[V,z]=useState(null),$=useMemo(()=>{const e=[];for(const[t,r]of Object.entries(o?.views??{}))e.push({name:t,view:r});return e},[o]),[B,G]=useState($.length>0?$[0].name:null);useEffect(()=>{if(0===$.length)return;null!==B&&$.some(e=>e.name===B)||G($[0].name)},[$,B]);const W=$.find(e=>e.name===B)?.view,U="raw_trace"===W?.type,J=useRef([]),X=useRef(null),Y=useRef(null),Z=()=>{Y.current||(Y.current=setTimeout(()=>{if(Y.current=null,J.current.length>0){const e=J.current;J.current=[],h(t=>[...e.slice().reverse(),...t])}X.current&&(_(X.current),X.current=null)},l))};useEffect(()=>{if(!r||!n||!a)return y(null),h([]),void _({});let e=!1;return(async()=>{try{const t=await c("tis.read_test",MessageType.Request,{project_id:r,method_id:n,run_id:a});!e&&t?.success&&(y(t.data),_(t.data.results??{}));const o=await c("tis.read_cycles",MessageType.Request,{project_id:r,method_id:n,run_id:a,offset:0,limit:200,order:"desc"});!e&&o?.success&&h(o.data.cycles??[])}catch(e){}})(),()=>{e=!0}},[r,n,a,c]),useEffect(()=>{const e=e=>e?.project_id===r&&e?.method_id===n&&e?.run_id===a,t=d("tis.cycle_added",t=>{e(t)&&t.cycle&&(J.current.push(t.cycle),Z())}),o=d("tis.results_updated",t=>{e(t)&&(X.current=t.results??{},Z())});return()=>{u(t),u(o),Y.current&&(clearTimeout(Y.current),Y.current=null)}},[r,n,a,l]);const K="string"==typeof p?.sample_id&&p.sample_id?p.sample_id:"string"==typeof p?.config?.sample_id?p.config.sample_id:"";useEffect(()=>{if(!r||!n||!K)return void b({});let e=!1;const t=async()=>{try{const t=await c("tis.sample_summary",MessageType.Request,{project_id:r,method_id:n,sample_id:K,run_id:a});!e&&t?.success&&b(t.data?.summary??{})}catch(e){}};t();const o=[d("tis.sample_summary_updated",e=>{e?.project_id===r&&e?.method_id===n&&e?.sample_id===K&&t()}),d("tis.cycle_added",e=>{e?.project_id===r&&e?.method_id===n&&t()})];return()=>{e=!0,o.forEach(u)}},[r,n,K,a,c,d,u]);const Q=useRawCycleData({projectId:r,methodId:n,runId:a,blobName:o?.raw_data?.blob_name??"trace",source:W?.source??"raw",enabled:U}),ee=useMemo(()=>{if(!W)return null;if("cycle_scatter"===W.type){const e=W.x.field;if(!e)return null;const t=[...f].reverse(),r=m?.[quantityOfField(o,e)??""],n=W.x_decimals??r?.precision??DEFAULT_X_DECIMALS;return{labels:t.map(t=>formatAxisTick(toDisplayValue(t[e],r),n)),datasets:W.y.map((e,r)=>({label:e.label??e.field,data:t.map(t=>toDisplayValue(t[e.field],m?.[quantityOfField(o,e.field)??""])),yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(r),backgroundColor:palette(r),tension:.1,pointRadius:2}))}}if("raw_trace"===W.type){if(!Q.raw)return null;const e=W.x.column;if(!e)return null;const t=m?.[quantityOfColumn(o,e)??""],r=Q.raw[e]??[],n=t?r.map(e=>toDisplayValue(e,t)):r,a=!1!==W.smooth;return{datasets:W.y.map((e,t)=>{const r=m?.[quantityOfColumn(o,e.column)??""],l=Q.raw[e.column]??[],i=r?l.map(e=>toDisplayValue(e,r)):l,s=a?smoothTraceForDisplay(n,i,W.smoothWindow):i.map((e,t)=>({x:n[t],y:e}));return{label:e.label??e.column,data:s,yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(t),backgroundColor:palette(t),pointRadius:0,borderWidth:1.5,showLine:!0,...a?{cubicInterpolationMode:"monotone"}:{}}})}}return null},[W,f,Q.raw,m,o]),te=W?.y.some(e=>"right"===e.y_axis)??!1,re=useMemo(()=>{if(!U)return[];const e=Q.envelope,t=e?.regions??e?.context?.regions;return Array.isArray(t)?t:[]},[U,Q.envelope]),ne=useMemo(()=>[...W?.regions??[],...re],[W,re]),ae=useMemo(()=>{const e="raw_trace"===W?.type,t=t=>{const r=e?quantityOfColumn(o,t.column):quantityOfField(o,t.field);return r?m?.[r]?.label:void 0},r=e?quantityOfColumn(o,W?.x.column):quantityOfField(o,W?.x.field),n=r?m?.[r]?.label:void 0,a=W?.x.label?n?`${W.x.label} [${n}]`:W.x.label:void 0,l=W?.x_decimals??(r?m?.[r]?.precision:void 0)??DEFAULT_X_DECIMALS,i={callback(t){const r=e?t:this?.getLabelForValue?.(t)??t;return formatAxisTick(r,l)}};return{responsive:!0,maintainAspectRatio:!1,parsing:!e&&void 0,scales:{x:e?{type:"linear",ticks:i,title:{display:!!a,text:a}}:{ticks:i,title:{display:!!a,text:a}},y:{position:"left",title:{display:!0,text:axisLabel(W,"left",t)}},...te?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:axisLabel(W,"right",t)}}}:{}},plugins:{legend:{display:!0},zoom:{pan:{enabled:!0,mode:"xy"},zoom:{wheel:{enabled:!0},pinch:{enabled:!0},mode:"xy"}},annotation:{annotations:buildRegionAnnotations(ne)}}}},[W,te,ne,m,o]),oe=o?.raw_data?.blob_name??"trace",le=useRef(""),ie=useCallback(async()=>{if(!r||!n||!a)return[];try{const e=await c("tis.list_raw",MessageType.Request,{project_id:r,method_id:n,run_id:a});if(!e?.success)return[];const t=e.data?.cycles??[];return t.filter(e=>e?.name===oe&&"number"==typeof e?.cycle_index).map(e=>e.cycle_index).sort((e,t)=>e-t)}catch{return[]}},[r,n,a,oe,c]),se=useCallback(async e=>{if(!r||!n||!a)return;const t=`${r}|${n}|${a}|${oe}|${e??"latest"}`;if(le.current===t)return;le.current=t;const o={project_id:r,method_id:n,run_id:a,name:oe};null!=e&&(o.cycle_index=e),E(!0),D(null),O(null);try{const e=await c("tis.read_raw",MessageType.Request,o);e?.success?O(e.data??{}):D(e?.error_message??"No raw data on disk for this run.")}catch(e){D(String(e?.message??e))}finally{E(!1)}q(!0),F(null),I(null);try{const e=await c("tis.read_filtered",MessageType.Request,o);e?.success?I(e.data??{}):F(e?.error_message??"No filtered data on disk for this run.")}catch(e){F(String(e?.message??e))}finally{q(!1)}},[r,n,a,oe,c]);useEffect(()=>{le.current="",P([]),z(null)},[r,n,a,oe]);return useEffect(()=>{j&&null!=V&&se(V)},[j,V,se]),r&&n&&a&&o?_jsxs("div",{className:"vblock",style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[_jsx(Header,{meta:p,config:p?.config,runId:a,projectId:r,methodId:n,canViewRaw:!!o.raw_data,onViewRaw:async()=>{v(!0);let e=H;0===e.length&&(e=await ie(),P(e));const t=e.length>0?e[e.length-1]:null,r=V??t;V!==r&&z(r),await se(r)},onShowConfig:()=>C(!0)}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("div",{className:"flex",style:{gap:"1rem",alignItems:"center",marginBottom:"0.5rem",flexWrap:"wrap"},children:[_jsx(Dropdown,{value:B,options:$.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>G(e.value),placeholder:0===$.length?"No view defined":"Select a view",disabled:0===$.length}),_jsx("h3",{style:{margin:0},children:W?.title??""}),U&&Q.cycles.length>1&&_jsxs(_Fragment,{children:[_jsx("label",{htmlFor:"chart-cycle-picker",style:{color:"var(--text-secondary-color)"},children:"Cycle:"}),_jsx(Dropdown,{inputId:"chart-cycle-picker",value:Q.selectedCycle,options:Q.cycles.map(e=>({label:`Cycle ${e}`,value:e})),onChange:e=>Q.setSelectedCycle(Number(e.value)),style:{minWidth:"8rem"}}),_jsxs("span",{style:{color:"var(--text-secondary-color)"},children:["of ",Q.cycles.length]})]}),_jsx("div",{style:{flex:1}}),_jsx(Button,{icon:"pi pi-th-large",outlined:!0,rounded:!0,size:"small",onClick:()=>T.current?.resetZoom?.(),disabled:!ee,tooltip:"Reset chart zoom",tooltipOptions:{position:"left"},"aria-label":"Reset chart zoom"})]}),_jsxs("div",{style:{height:s,position:"relative"},children:[U&&Q.loading&&_jsx(ChartOverlay,{children:"Loading raw data…"}),U&&Q.error&&_jsx(ChartOverlay,{children:Q.error}),ee&&_jsx(Line,{ref:T,data:ee,options:ae})]})]}),(()=>{const e=f.length>CYCLE_VIRTUAL_THRESHOLD,t=[...(o.cycle_config_fields??[]).map(e=>toScienceColumn(e,!0,m)),...(o.cycle_fields??[]).map(e=>toScienceColumn(e,!!e.editable,m))];return _jsx(ScienceTable,{title:`Cycle Data (${f.length})`,columns:t,rows:f,indexOrder:"descending",scrollable:e,scrollHeight:e?i:void 0,emptyMessage:"No cycles yet.",onCellEdit:S})})(),(()=>{const e={...g,...x},t=Object.keys(e).length>0,r=o.results_fields??[],n=r.map(e=>toScienceColumn(e,!1,m)),a=r.some(isProjectScoped);return _jsxs(_Fragment,{children:[_jsx(ScienceTable,{title:"Results",columns:n,rows:t?[e]:[],emptyMessage:"No results yet."}),a&&_jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-secondary-color)",margin:"0.25rem 0 0.75rem"},children:"* across every test of this sample in the project. All other values describe this test."})]})})(),o.raw_data&&_jsxs(Dialog,{visible:j,onHide:()=>v(!1),header:`Run Data — ${a}`,style:{width:"90vw",height:"80vh"},maximizable:!0,children:[_jsx(CyclePickerBar,{cycles:H,selected:V,onChange:z}),_jsx(RawEnvelopeHeader,{envelope:R}),_jsxs(TabView,{style:{height:"100%"},children:[_jsx(TabPanel,{header:"Raw Data",children:_jsx(DataBlobTable,{blob:unwrapEnvelope(R),loading:M,error:A,rawData:o.raw_data})}),_jsx(TabPanel,{header:"Filtered Data",children:_jsx(DataBlobTable,{blob:unwrapEnvelope(L),loading:k,error:N,rawData:o.raw_data,emptyMessage:"Filtered data is written by post-processing — none on disk for this run yet."})})]})]}),_jsx(Dialog,{visible:w,onHide:()=>C(!1),header:"Test Configuration",style:{width:"min(640px, 90vw)"},modal:!0,children:_jsx(ConfigList,{config:p?.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:n,methodId:a,canViewRaw:o,onViewRaw:l,onShowConfig:i})=>{const s="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:[s||r,c&&_jsx(Button,{icon:"pi pi-info-circle",type:"button",rounded:!0,text:!0,onClick:i,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: ",n," · method: ",a," · run: ",r,e?.start_time&&_jsxs(_Fragment,{children:[" · started: ",new Date(e.start_time).toLocaleString()]})]})]}),o&&_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))})},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,n=e.context;if(null==t&&!r&&!n)return null;const a=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:a(r)}),n&&_jsx("div",{style:{marginTop:"0.25rem"},children:a(n)})]})},DataBlobTable=({blob:e,loading:t,error:r,rawData:n,emptyMessage:a})=>{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:a??r});if(!e||"object"!=typeof e)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:"No data."});const o=Object.keys(n.columns??{}),l=Object.keys(e).filter(t=>Array.isArray(e[t])),i=[];for(const t of o)Array.isArray(e[t])&&i.push(t);for(const e of l)i.includes(e)||i.push(e);if(0===i.length)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:a??"No columnar data in this blob."});const s=i.reduce((t,r)=>Math.min(t,e[r].length),Number.POSITIVE_INFINITY),c=Number.isFinite(s)?s:0,d=Array.from({length:c},(t,r)=>{const n={__i:r};for(const t of i)n[t]=e[t][r];return n}),u=e=>{const t=n.units?.[e];return t?`${e} [${t}]`:e};return _jsxs(DataTable,{value:d,scrollable:!0,scrollHeight:"60vh",virtualScrollerOptions:{itemSize:32},emptyMessage:a??"No data.",size:"small",stripedRows:!0,children:[_jsx(Column,{field:"__i",header:"#",style:{width:"5rem",textAlign:"right"},bodyStyle:{fontVariantNumeric:"tabular-nums",textAlign:"right"}}),i.map(e=>_jsx(Column,{field:e,header:u(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),CYCLE_VIRTUAL_THRESHOLD=30,CHART_COLORS=["#4ea8de","#f59e0b","#22c55e","#a855f7","#ef4444","#14b8a6","#eab308","#ec4899"],palette=e=>CHART_COLORS[e%CHART_COLORS.length],SG_ORDER=3,SMOOTH_TARGET_POINTS=800;function invertMatrix(e){const t=e.length,r=e.map((e,r)=>[...e,...Array.from({length:t},(e,t)=>r===t?1:0)]);for(let e=0;e<t;e++){let n=e;for(let a=e+1;a<t;a++)Math.abs(r[a][e])>Math.abs(r[n][e])&&(n=a);if(Math.abs(r[n][e])<1e-12)return null;[r[e],r[n]]=[r[n],r[e]];const a=r[e][e];for(let n=0;n<2*t;n++)r[e][n]/=a;for(let n=0;n<t;n++){if(n===e)continue;const a=r[n][e];if(0!==a)for(let o=0;o<2*t;o++)r[n][o]-=a*r[e][o]}}return r.map(e=>e.slice(t))}function sgWeights(e,t){const r=2*e+1,n=Math.min(t,r-1),a=[];for(let t=-e;t<=e;t++){const e=[];let r=1;for(let a=0;a<=n;a++)e.push(r),r*=t;a.push(e)}const o=n+1,l=Array.from({length:o},()=>new Array(o).fill(0));for(let e=0;e<o;e++)for(let t=0;t<o;t++){let n=0;for(let o=0;o<r;o++)n+=a[o][e]*a[o][t];l[e][t]=n}const i=invertMatrix(l);if(!i)return new Array(r).fill(1/r);const s=new Array(r);for(let e=0;e<r;e++){let t=0;for(let r=0;r<o;r++)t+=i[0][r]*a[e][r];s[e]=t}return s}function savitzkyGolay(e,t){const r=e.length;if(0===r||t<1)return e.slice();const n=new Map,a=e=>{let t=n.get(e);return t||(t=sgWeights(e,3),n.set(e,t)),t},o=new Array(r);for(let n=0;n<r;n++){const l=Math.min(t,n,r-1-n);if(l<1){o[n]=e[n];continue}const i=a(l);let s=0;for(let t=-l;t<=l;t++)s+=i[t+l]*e[n+t];o[n]=s}return o}function smoothTraceForDisplay(e,t,r){const n=Math.min(e.length,t.length);if(0===n)return[];const a=r&&r>1?Math.max(1,Math.floor((Math.min(r,n)-1)/2)):Math.max(2,Math.min(40,Math.round(n/250))),o=savitzkyGolay(t.slice(0,n),a),l=Math.max(1,Math.ceil(n/SMOOTH_TARGET_POINTS)),i=[];for(let t=0;t<n;t+=l)i.push({x:e[t],y:o[t]});return(n-1)%l!=0&&i.push({x:e[n-1],y:o[n-1]}),i}const DEFAULT_REGION_FILL="rgba(78, 168, 222, 0.15)",REGION_LABEL_COLOR="rgba(226, 232, 240, 0.85)";function buildRegionAnnotations(e){if(!e||0===e.length)return{};const t={};return e.forEach((e,r)=>{const n=!!e.borderColor;t[`region-${r}`]={type:"box",xScaleID:"x",xMin:e.xMin,xMax:e.xMax,backgroundColor:e.color??DEFAULT_REGION_FILL,borderColor:n?e.borderColor:"transparent",borderWidth:n?1:0,drawTime:"beforeDatasetsDraw",...e.label?{label:{display:!0,content:e.label,position:{x:"center",y:"start"},color:REGION_LABEL_COLOR,font:{size:11}}}:{}}}),t}const ChartOverlay=({children:e})=>_jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",color:"var(--text-secondary-color)",pointerEvents:"none"},children:e});export const DEFAULT_X_DECIMALS=2;const formatAxisTick=(e,t)=>{const r="number"==typeof e?e:Number(e);return Number.isFinite(r)?Number.parseFloat(r.toFixed(t)).toString():null==e?"":String(e)},quantityOfField=(e,t)=>{if(e&&t)for(const r of[e.cycle_config_fields,e.cycle_fields,e.results_fields]){const e=(r??[]).find(e=>e.name===t);if(e?.quantity)return e.quantity}},quantityOfColumn=(e,t)=>{if(e&&t)return e.raw_data?.columns?.[t]?.quantity},toDisplayValue=(e,t)=>t&&"number"==typeof e&&Number.isFinite(e)?e*t.scale+(t.offset??0):e,seriesLabel=e=>e.label??e.field??e.column??"",axisLabel=(e,t,r)=>{const n=e?.y.filter(e=>"right"===e.y_axis==("right"===t))??[],a=n.map(seriesLabel).join(" / "),o=Array.from(new Set(n.map(r).filter(Boolean)));return 1===o.length?`${a} [${o[0]}]`:a},isProjectScoped=e=>"project"===e.aggregate?.scope,toScienceColumn=(e,t=!1,r)=>{const n=e.quantity?r?.[e.quantity]:void 0;return{field:e.name,label:(e.label&&e.label.length>0?e.label:e.name)+(isProjectScoped(e)?" *":""),units:n?n.label:e.units,editable:t,body:t=>formatCell(t[e.name],e.type,e.scale,n)}},formatCell=(e,t,r,n)=>null==e?"":n&&"number"==typeof e&&Number.isFinite(e)?formatScaled(e*n.scale+(n.offset??0),n):(r&&1!==r&&"number"==typeof e&&Number.isFinite(e)&&(e*=r),"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 annotationPlugin from"chartjs-plugin-annotation";import{Line}from"react-chartjs-2";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";import{formatScaled}from"../../core/formatScaled";import{useRawCycleData}from"./useRawCycleData";import{orderedViews}from"./chartViews";import{ScienceTable}from"./ScienceTable";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin,annotationPlugin);export const TestDataView=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,a=e.methodId??t.selection.methodId,n=e.runId??t.selection.runId,o=e.schema??(a?t.schemas[a]:void 0),{throttleMs:l=100,cycleTableHeight:i="400px",chartHeight:s="320px"}=e,{invoke:c,subscribe:d,unsubscribe:u}=useContext(EventEmitterContext),{scales:m}=useContext(AutoCoreTagContext),[p,y]=useState(null),[f,h]=useState([]),[g,_]=useState({}),[x,b]=useState({}),[j,v]=useState(!1),[w,C]=useState(!1),S=useCallback(async(e,t,o)=>{const l=e?.cycle_index;if(r&&a&&n&&l)try{const e=await c("tis.update_cycle",MessageType.Request,{project_id:r,method_id:a,run_id:n,cycle_index:l,fields:{[t]:o}});if(!1===e?.success)return;h(e=>e.map(e=>e?.cycle_index===l?{...e,[t]:o}:e))}catch(e){}},[c,r,a,n]),T=useRef(null),[R,O]=useState(null),[A,D]=useState(null),[M,E]=useState(!1),[L,I]=useState(null),[N,F]=useState(null),[k,q]=useState(!1),[V,H]=useState([]),[P,z]=useState(null),$=useMemo(()=>orderedViews(o?.views),[o]),[B,G]=useState($.length>0?$[0].name:null);useEffect(()=>{if(0===$.length)return;null!==B&&$.some(e=>e.name===B)||G($[0].name)},[$,B]);const W=$.find(e=>e.name===B)?.view,U="raw_trace"===W?.type,J=useRef([]),X=useRef(null),Y=useRef(null),Z=()=>{Y.current||(Y.current=setTimeout(()=>{if(Y.current=null,J.current.length>0){const e=J.current;J.current=[],h(t=>[...e.slice().reverse(),...t])}X.current&&(_(X.current),X.current=null)},l))};useEffect(()=>{if(!r||!a||!n)return y(null),h([]),void _({});let e=!1;return(async()=>{try{const t=await c("tis.read_test",MessageType.Request,{project_id:r,method_id:a,run_id:n});!e&&t?.success&&(y(t.data),_(t.data.results??{}));const o=await c("tis.read_cycles",MessageType.Request,{project_id:r,method_id:a,run_id:n,offset:0,limit:200,order:"desc"});!e&&o?.success&&h(o.data.cycles??[])}catch(e){}})(),()=>{e=!0}},[r,a,n,c]),useEffect(()=>{const e=e=>e?.project_id===r&&e?.method_id===a&&e?.run_id===n,t=d("tis.cycle_added",t=>{e(t)&&t.cycle&&(J.current.push(t.cycle),Z())}),o=d("tis.results_updated",t=>{e(t)&&(X.current=t.results??{},Z())});return()=>{u(t),u(o),Y.current&&(clearTimeout(Y.current),Y.current=null)}},[r,a,n,l]);const K="string"==typeof p?.sample_id&&p.sample_id?p.sample_id:"string"==typeof p?.config?.sample_id?p.config.sample_id:"";useEffect(()=>{if(!r||!a||!K)return void b({});let e=!1;const t=async()=>{try{const t=await c("tis.sample_summary",MessageType.Request,{project_id:r,method_id:a,sample_id:K,run_id:n});!e&&t?.success&&b(t.data?.summary??{})}catch(e){}};t();const o=[d("tis.sample_summary_updated",e=>{e?.project_id===r&&e?.method_id===a&&e?.sample_id===K&&t()}),d("tis.cycle_added",e=>{e?.project_id===r&&e?.method_id===a&&t()})];return()=>{e=!0,o.forEach(u)}},[r,a,K,n,c,d,u]);const Q=useRawCycleData({projectId:r,methodId:a,runId:n,blobName:o?.raw_data?.blob_name??"trace",source:W?.source??"raw",enabled:U}),ee=useMemo(()=>{if(!W)return null;if("cycle_scatter"===W.type){const e=W.x.field;if(!e)return null;const t=[...f].reverse(),r=m?.[quantityOfField(o,e)??""],a=W.x_decimals??r?.precision??DEFAULT_X_DECIMALS;return{labels:t.map(t=>formatAxisTick(toDisplayValue(t[e],r),a)),datasets:W.y.map((e,r)=>({label:e.label??e.field,data:t.map(t=>toDisplayValue(t[e.field],m?.[quantityOfField(o,e.field)??""])),yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(r),backgroundColor:palette(r),tension:.1,pointRadius:2}))}}if("raw_trace"===W.type){if(!Q.raw)return null;const e=W.x.column;if(!e)return null;const t=m?.[quantityOfColumn(o,e)??""],r=Q.raw[e]??[],a=t?r.map(e=>toDisplayValue(e,t)):r,n=!1!==W.smooth;return{datasets:W.y.map((e,t)=>{const r=m?.[quantityOfColumn(o,e.column)??""],l=Q.raw[e.column]??[],i=r?l.map(e=>toDisplayValue(e,r)):l,s=n?smoothTraceForDisplay(a,i,W.smoothWindow):i.map((e,t)=>({x:a[t],y:e}));return{label:e.label??e.column,data:s,yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(t),backgroundColor:palette(t),pointRadius:0,borderWidth:1.5,showLine:!0,...n?{cubicInterpolationMode:"monotone"}:{}}})}}return null},[W,f,Q.raw,m,o]),te=W?.y.some(e=>"right"===e.y_axis)??!1,re=useMemo(()=>{if(!U)return[];const e=Q.envelope,t=e?.regions??e?.context?.regions;return Array.isArray(t)?t:[]},[U,Q.envelope]),ae=useMemo(()=>[...W?.regions??[],...re],[W,re]),ne=useMemo(()=>{const e="raw_trace"===W?.type,t=t=>{const r=e?quantityOfColumn(o,t.column):quantityOfField(o,t.field);return r?m?.[r]?.label:void 0},r=e?quantityOfColumn(o,W?.x.column):quantityOfField(o,W?.x.field),a=r?m?.[r]?.label:void 0,n=W?.x.label?a?`${W.x.label} [${a}]`:W.x.label:void 0,l=W?.x_decimals??(r?m?.[r]?.precision:void 0)??DEFAULT_X_DECIMALS,i={callback(t){const r=e?t:this?.getLabelForValue?.(t)??t;return formatAxisTick(r,l)}};return{responsive:!0,maintainAspectRatio:!1,parsing:!e&&void 0,scales:{x:e?{type:"linear",ticks:i,title:{display:!!n,text:n}}:{ticks:i,title:{display:!!n,text:n}},y:{position:"left",title:{display:!0,text:axisLabel(W,"left",t)}},...te?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:axisLabel(W,"right",t)}}}:{}},plugins:{legend:{display:!0},zoom:{pan:{enabled:!0,mode:"xy"},zoom:{wheel:{enabled:!0},pinch:{enabled:!0},mode:"xy"}},annotation:{annotations:buildRegionAnnotations(ae)}}}},[W,te,ae,m,o]),oe=o?.raw_data?.blob_name??"trace",le=useRef(""),ie=useCallback(async()=>{if(!r||!a||!n)return[];try{const e=await c("tis.list_raw",MessageType.Request,{project_id:r,method_id:a,run_id:n});if(!e?.success)return[];const t=e.data?.cycles??[];return t.filter(e=>e?.name===oe&&"number"==typeof e?.cycle_index).map(e=>e.cycle_index).sort((e,t)=>e-t)}catch{return[]}},[r,a,n,oe,c]),se=useCallback(async e=>{if(!r||!a||!n)return;const t=`${r}|${a}|${n}|${oe}|${e??"latest"}`;if(le.current===t)return;le.current=t;const o={project_id:r,method_id:a,run_id:n,name:oe};null!=e&&(o.cycle_index=e),E(!0),D(null),O(null);try{const e=await c("tis.read_raw",MessageType.Request,o);e?.success?O(e.data??{}):D(e?.error_message??"No raw data on disk for this run.")}catch(e){D(String(e?.message??e))}finally{E(!1)}q(!0),F(null),I(null);try{const e=await c("tis.read_filtered",MessageType.Request,o);e?.success?I(e.data??{}):F(e?.error_message??"No filtered data on disk for this run.")}catch(e){F(String(e?.message??e))}finally{q(!1)}},[r,a,n,oe,c]);useEffect(()=>{le.current="",H([]),z(null)},[r,a,n,oe]);return useEffect(()=>{j&&null!=P&&se(P)},[j,P,se]),r&&a&&n&&o?_jsxs("div",{className:"vblock",style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[_jsx(Header,{meta:p,config:p?.config,runId:n,projectId:r,methodId:a,canViewRaw:!!o.raw_data,onViewRaw:async()=>{v(!0);let e=V;0===e.length&&(e=await ie(),H(e));const t=e.length>0?e[e.length-1]:null,r=P??t;P!==r&&z(r),await se(r)},onShowConfig:()=>C(!0)}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("div",{className:"flex",style:{gap:"1rem",alignItems:"center",marginBottom:"0.5rem",flexWrap:"wrap"},children:[_jsx(Dropdown,{value:B,options:$.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>G(e.value),placeholder:0===$.length?"No view defined":"Select a view",disabled:0===$.length}),_jsx("h3",{style:{margin:0},children:W?.title??""}),U&&Q.cycles.length>1&&_jsxs(_Fragment,{children:[_jsx("label",{htmlFor:"chart-cycle-picker",style:{color:"var(--text-secondary-color)"},children:"Cycle:"}),_jsx(Dropdown,{inputId:"chart-cycle-picker",value:Q.selectedCycle,options:Q.cycles.map(e=>({label:`Cycle ${e}`,value:e})),onChange:e=>Q.setSelectedCycle(Number(e.value)),style:{minWidth:"8rem"}}),_jsxs("span",{style:{color:"var(--text-secondary-color)"},children:["of ",Q.cycles.length]})]}),_jsx("div",{style:{flex:1}}),_jsx(Button,{icon:"pi pi-th-large",outlined:!0,rounded:!0,size:"small",onClick:()=>T.current?.resetZoom?.(),disabled:!ee,tooltip:"Reset chart zoom",tooltipOptions:{position:"left"},"aria-label":"Reset chart zoom"})]}),_jsxs("div",{style:{height:s,position:"relative"},children:[U&&Q.loading&&_jsx(ChartOverlay,{children:"Loading raw data…"}),U&&Q.error&&_jsx(ChartOverlay,{children:Q.error}),ee&&_jsx(Line,{ref:T,data:ee,options:ne})]})]}),(()=>{const e=f.length>CYCLE_VIRTUAL_THRESHOLD,t=[...(o.cycle_config_fields??[]).map(e=>toScienceColumn(e,!0,m)),...(o.cycle_fields??[]).map(e=>toScienceColumn(e,!!e.editable,m))];return _jsx(ScienceTable,{title:`Cycle Data (${f.length})`,columns:t,rows:f,indexOrder:"descending",scrollable:e,scrollHeight:e?i:void 0,emptyMessage:"No cycles yet.",onCellEdit:S})})(),(()=>{const e={...g,...x},t=Object.keys(e).length>0,r=o.results_fields??[],a=r.map(e=>toScienceColumn(e,!1,m)),n=r.some(isProjectScoped);return _jsxs(_Fragment,{children:[_jsx(ScienceTable,{title:"Results",columns:a,rows:t?[e]:[],emptyMessage:"No results yet."}),n&&_jsx("div",{style:{fontSize:"0.8rem",color:"var(--text-secondary-color)",margin:"0.25rem 0 0.75rem"},children:"* across every test of this sample in the project. All other values describe this test."})]})})(),o.raw_data&&_jsxs(Dialog,{visible:j,onHide:()=>v(!1),header:`Run Data — ${n}`,style:{width:"90vw",height:"80vh"},maximizable:!0,children:[_jsx(CyclePickerBar,{cycles:V,selected:P,onChange:z}),_jsx(RawEnvelopeHeader,{envelope:R}),_jsxs(TabView,{style:{height:"100%"},children:[_jsx(TabPanel,{header:"Raw Data",children:_jsx(DataBlobTable,{blob:unwrapEnvelope(R),loading:M,error:A,rawData:o.raw_data})}),_jsx(TabPanel,{header:"Filtered Data",children:_jsx(DataBlobTable,{blob:unwrapEnvelope(L),loading:k,error:N,rawData:o.raw_data,emptyMessage:"Filtered data is written by post-processing — none on disk for this run yet."})})]})]}),_jsx(Dialog,{visible:w,onHide:()=>C(!1),header:"Test Configuration",style:{width:"min(640px, 90vw)"},modal:!0,children:_jsx(ConfigList,{config:p?.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:n,canViewRaw:o,onViewRaw:l,onShowConfig:i})=>{const s="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:[s||r,c&&_jsx(Button,{icon:"pi pi-info-circle",type:"button",rounded:!0,text:!0,onClick:i,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: ",n," · run: ",r,e?.start_time&&_jsxs(_Fragment,{children:[" · started: ",new Date(e.start_time).toLocaleString()]})]})]}),o&&_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))})},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 n=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:n(r)}),a&&_jsx("div",{style:{marginTop:"0.25rem"},children:n(a)})]})},DataBlobTable=({blob:e,loading:t,error:r,rawData:a,emptyMessage:n})=>{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:n??r});if(!e||"object"!=typeof e)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:"No data."});const o=Object.keys(a.columns??{}),l=Object.keys(e).filter(t=>Array.isArray(e[t])),i=[];for(const t of o)Array.isArray(e[t])&&i.push(t);for(const e of l)i.includes(e)||i.push(e);if(0===i.length)return _jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:n??"No columnar data in this blob."});const s=i.reduce((t,r)=>Math.min(t,e[r].length),Number.POSITIVE_INFINITY),c=Number.isFinite(s)?s:0,d=Array.from({length:c},(t,r)=>{const a={__i:r};for(const t of i)a[t]=e[t][r];return a}),u=e=>{const t=a.units?.[e];return t?`${e} [${t}]`:e};return _jsxs(DataTable,{value:d,scrollable:!0,scrollHeight:"60vh",virtualScrollerOptions:{itemSize:32},emptyMessage:n??"No data.",size:"small",stripedRows:!0,children:[_jsx(Column,{field:"__i",header:"#",style:{width:"5rem",textAlign:"right"},bodyStyle:{fontVariantNumeric:"tabular-nums",textAlign:"right"}}),i.map(e=>_jsx(Column,{field:e,header:u(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),CYCLE_VIRTUAL_THRESHOLD=30,CHART_COLORS=["#4ea8de","#f59e0b","#22c55e","#a855f7","#ef4444","#14b8a6","#eab308","#ec4899"],palette=e=>CHART_COLORS[e%CHART_COLORS.length],SG_ORDER=3,SMOOTH_TARGET_POINTS=800;function invertMatrix(e){const t=e.length,r=e.map((e,r)=>[...e,...Array.from({length:t},(e,t)=>r===t?1:0)]);for(let e=0;e<t;e++){let a=e;for(let n=e+1;n<t;n++)Math.abs(r[n][e])>Math.abs(r[a][e])&&(a=n);if(Math.abs(r[a][e])<1e-12)return null;[r[e],r[a]]=[r[a],r[e]];const n=r[e][e];for(let a=0;a<2*t;a++)r[e][a]/=n;for(let a=0;a<t;a++){if(a===e)continue;const n=r[a][e];if(0!==n)for(let o=0;o<2*t;o++)r[a][o]-=n*r[e][o]}}return r.map(e=>e.slice(t))}function sgWeights(e,t){const r=2*e+1,a=Math.min(t,r-1),n=[];for(let t=-e;t<=e;t++){const e=[];let r=1;for(let n=0;n<=a;n++)e.push(r),r*=t;n.push(e)}const o=a+1,l=Array.from({length:o},()=>new Array(o).fill(0));for(let e=0;e<o;e++)for(let t=0;t<o;t++){let a=0;for(let o=0;o<r;o++)a+=n[o][e]*n[o][t];l[e][t]=a}const i=invertMatrix(l);if(!i)return new Array(r).fill(1/r);const s=new Array(r);for(let e=0;e<r;e++){let t=0;for(let r=0;r<o;r++)t+=i[0][r]*n[e][r];s[e]=t}return s}function savitzkyGolay(e,t){const r=e.length;if(0===r||t<1)return e.slice();const a=new Map,n=e=>{let t=a.get(e);return t||(t=sgWeights(e,3),a.set(e,t)),t},o=new Array(r);for(let a=0;a<r;a++){const l=Math.min(t,a,r-1-a);if(l<1){o[a]=e[a];continue}const i=n(l);let s=0;for(let t=-l;t<=l;t++)s+=i[t+l]*e[a+t];o[a]=s}return o}function smoothTraceForDisplay(e,t,r){const a=Math.min(e.length,t.length);if(0===a)return[];const n=r&&r>1?Math.max(1,Math.floor((Math.min(r,a)-1)/2)):Math.max(2,Math.min(40,Math.round(a/250))),o=savitzkyGolay(t.slice(0,a),n),l=Math.max(1,Math.ceil(a/SMOOTH_TARGET_POINTS)),i=[];for(let t=0;t<a;t+=l)i.push({x:e[t],y:o[t]});return(a-1)%l!=0&&i.push({x:e[a-1],y:o[a-1]}),i}const DEFAULT_REGION_FILL="rgba(78, 168, 222, 0.15)",REGION_LABEL_COLOR="rgba(226, 232, 240, 0.85)";function buildRegionAnnotations(e){if(!e||0===e.length)return{};const t={};return e.forEach((e,r)=>{const a=!!e.borderColor;t[`region-${r}`]={type:"box",xScaleID:"x",xMin:e.xMin,xMax:e.xMax,backgroundColor:e.color??DEFAULT_REGION_FILL,borderColor:a?e.borderColor:"transparent",borderWidth:a?1:0,drawTime:"beforeDatasetsDraw",...e.label?{label:{display:!0,content:e.label,position:{x:"center",y:"start"},color:REGION_LABEL_COLOR,font:{size:11}}}:{}}}),t}const ChartOverlay=({children:e})=>_jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",color:"var(--text-secondary-color)",pointerEvents:"none"},children:e});export const DEFAULT_X_DECIMALS=2;const formatAxisTick=(e,t)=>{const r="number"==typeof e?e:Number(e);return Number.isFinite(r)?Number.parseFloat(r.toFixed(t)).toString():null==e?"":String(e)},quantityOfField=(e,t)=>{if(e&&t)for(const r of[e.cycle_config_fields,e.cycle_fields,e.results_fields]){const e=(r??[]).find(e=>e.name===t);if(e?.quantity)return e.quantity}},quantityOfColumn=(e,t)=>{if(e&&t)return e.raw_data?.columns?.[t]?.quantity},toDisplayValue=(e,t)=>t&&"number"==typeof e&&Number.isFinite(e)?e*t.scale+(t.offset??0):e,seriesLabel=e=>e.label??e.field??e.column??"",axisLabel=(e,t,r)=>{const a=e?.y.filter(e=>"right"===e.y_axis==("right"===t))??[],n=a.map(seriesLabel).join(" / "),o=Array.from(new Set(a.map(r).filter(Boolean)));return 1===o.length?`${n} [${o[0]}]`:n},isProjectScoped=e=>"project"===e.aggregate?.scope,toScienceColumn=(e,t=!1,r)=>{const a=e.quantity?r?.[e.quantity]:void 0;return{field:e.name,label:(e.label&&e.label.length>0?e.label:e.name)+(isProjectScoped(e)?" *":""),units:a?a.label:e.units,editable:t,body:t=>formatCell(t[e.name],e.type,e.scale,a)}},formatCell=(e,t,r,a)=>null==e?"":a&&"number"==typeof e&&Number.isFinite(e)?formatScaled(e*a.scale+(a.offset??0),a):(r&&1!==r&&"number"==typeof e&&Number.isFinite(e)&&(e*=r),"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,KAAoC,MAAM,OAAO,CAAC;AAWzD,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAS5D,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,CAqJ1D,CAAC"}
1
+ {"version":3,"file":"TestRawDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestRawDataView.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAoC,MAAM,OAAO,CAAC;AAWzD,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAU5D,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,CAmJ1D,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{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{useTis}from"./TisProvider";import{useRawCycleData}from"./useRawCycleData";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin);export const TestRawDataView=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,l=e.methodId??t.selection.methodId,a=e.runId??t.selection.runId,o=e.schema??(l?t.schemas[l]:void 0),{blobName:s,chartHeight:n="60vh"}=e,i=useRef(null),c=useMemo(()=>{const e=[];for(const[t,r]of Object.entries(o?.views??{}))"raw_trace"===r.type&&e.push({name:t,view:r});return e},[o]),[d,m]=useState(c.length>0?c[0].name:null),p=s??o?.raw_data?.blob_name??"trace",y=c.find(e=>e.name===d)?.view,{cycles:x,selectedCycle:h,setSelectedCycle:u,raw:g,envelope:j,loading:f,error:v}=useRawCycleData({projectId:r,methodId:l,runId:a,blobName:p,source:y?.source??"raw",enabled:!!r&&!!l&&!!a}),_=useMemo(()=>{if(!g||!d)return null;const e=c.find(e=>e.name===d)?.view;if(!e)return null;const t=e.x.column,r=g[t]??[];return{datasets:e.y.map((e,t)=>({label:e.label??e.column,data:(g[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}))}},[g,d,c]),b=y?.y.some(e=>"right"===e.y_axis)??!1,w=useMemo(()=>({responsive:!0,maintainAspectRatio:!1,parsing:!1,scales:{x:{type:"linear",title:{display:!!y?.x.label,text:y?.x.label}},y:{position:"left",title:{display:!0,text:axisLabel(y,"left")}},...b?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:axisLabel(y,"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"}}}}),[y,b]);return r&&l&&a?o?o.raw_data?0===c.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:d,options:c.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>m(e.value),placeholder:"Select a view"}),_jsx("h3",{style:{margin:0},children:y?.title??""}),x.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:h,options:x.map(e=>({label:`Cycle ${e}`,value:e})),onChange:e=>u(Number(e.value)),style:{minWidth:"8rem"}}),_jsxs("span",{style:{color:"var(--text-secondary-color)"},children:["of ",x.length]})]}),_jsx("div",{style:{flex:1}}),_jsx(Button,{icon:"pi pi-refresh",label:"Reset Zoom",outlined:!0,onClick:()=>i.current?.resetZoom?.()})]}),_jsx(EnvelopeMetaStrip,{envelope:j}),_jsxs("div",{style:{flex:1,minHeight:0,height:n,position:"relative"},children:[f&&_jsx(Overlay,{children:"Loading raw data…"}),v&&_jsx(Overlay,{children:v}),_&&!f&&!v&&_jsx(Line,{ref:i,data:_,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}),EnvelopeMetaStrip=({envelope:e})=>{if(!e||"object"!=typeof e)return null;const t=e.cycle_index,r=e.cycle_fields,l=e.context;if(null==t&&!r&&!l)return null;const a=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:a(r)}),l&&_jsx("div",{style:{marginTop:"0.25rem"},children:a(l)})]})},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,{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{useTis}from"./TisProvider";import{useRawCycleData}from"./useRawCycleData";import{orderedViews}from"./chartViews";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin);export const TestRawDataView=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,l=e.methodId??t.selection.methodId,a=e.runId??t.selection.runId,o=e.schema??(l?t.schemas[l]:void 0),{blobName:s,chartHeight:i="60vh"}=e,n=useRef(null),c=useMemo(()=>orderedViews(o?.views,"raw_trace"),[o]),[d,m]=useState(c.length>0?c[0].name:null),p=s??o?.raw_data?.blob_name??"trace",y=c.find(e=>e.name===d)?.view,{cycles:x,selectedCycle:h,setSelectedCycle:u,raw:g,envelope:j,loading:f,error:v}=useRawCycleData({projectId:r,methodId:l,runId:a,blobName:p,source:y?.source??"raw",enabled:!!r&&!!l&&!!a}),_=useMemo(()=>{if(!g||!d)return null;const e=c.find(e=>e.name===d)?.view;if(!e)return null;const t=e.x.column,r=g[t]??[];return{datasets:e.y.map((e,t)=>({label:e.label??e.column,data:(g[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}))}},[g,d,c]),b=y?.y.some(e=>"right"===e.y_axis)??!1,w=useMemo(()=>({responsive:!0,maintainAspectRatio:!1,parsing:!1,scales:{x:{type:"linear",title:{display:!!y?.x.label,text:y?.x.label}},y:{position:"left",title:{display:!0,text:axisLabel(y,"left")}},...b?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:axisLabel(y,"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"}}}}),[y,b]);return r&&l&&a?o?o.raw_data?0===c.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:d,options:c.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>m(e.value),placeholder:"Select a view"}),_jsx("h3",{style:{margin:0},children:y?.title??""}),x.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:h,options:x.map(e=>({label:`Cycle ${e}`,value:e})),onChange:e=>u(Number(e.value)),style:{minWidth:"8rem"}}),_jsxs("span",{style:{color:"var(--text-secondary-color)"},children:["of ",x.length]})]}),_jsx("div",{style:{flex:1}}),_jsx(Button,{icon:"pi pi-refresh",label:"Reset Zoom",outlined:!0,onClick:()=>n.current?.resetZoom?.()})]}),_jsx(EnvelopeMetaStrip,{envelope:j}),_jsxs("div",{style:{flex:1,minHeight:0,height:i,position:"relative"},children:[f&&_jsx(Overlay,{children:"Loading raw data…"}),v&&_jsx(Overlay,{children:v}),_&&!f&&!v&&_jsx(Line,{ref:n,data:_,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}),EnvelopeMetaStrip=({envelope:e})=>{if(!e||"object"!=typeof e)return null;const t=e.cycle_index,r=e.cycle_fields,l=e.context;if(null==t&&!r&&!l)return null;const a=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:a(r)}),l&&_jsx("div",{style:{marginTop:"0.25rem"},children:a(l)})]})},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(" / ")??"";
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Chart-view ordering.
3
+ *
4
+ * `views` is a JSON object and the server holds it in a `BTreeMap`, so what
5
+ * reaches the HMI is sorted by view id — never by the order anyone chose. That
6
+ * order is a real setting: the Data tab opens on the FIRST view, so whichever
7
+ * id happens to sort first becomes the default chart. Renaming views to spell
8
+ * an order is not an option (the id is the wire key, and codegen emits it).
9
+ *
10
+ * So the order is carried explicitly, per view, as `order`: an integer,
11
+ * ascending, renumbered densely by the editor's Move up / Move down.
12
+ *
13
+ * `order` is deliberately NOT modelled by the Rust `ChartView`. It rides in
14
+ * that struct's flattened `extra` map, the way `x_decimals`, `smooth` and
15
+ * `regions` already do, so a `tis.put_method` → `tis.save_config` round-trip
16
+ * preserves it with no server-side change to deploy.
17
+ *
18
+ * A view with no `order` sorts after every ordered one, by id — so a method
19
+ * that has never been through the editor keeps exactly the order it shows
20
+ * today, and a newly added view lands last instead of jumping to the front.
21
+ */
22
+ /** Minimal shape this module needs; both the editor's and the runtime's
23
+ * `ChartView` satisfy it. */
24
+ export interface OrderableView {
25
+ order?: number;
26
+ type?: string;
27
+ }
28
+ /** A view together with its id — the id is the wire key, not a field. */
29
+ export interface NamedView<V> {
30
+ name: string;
31
+ view: V;
32
+ }
33
+ /**
34
+ * The method's views in display order: by `order` ascending, then by id.
35
+ *
36
+ * @param views The method's `views` map, as received from the server.
37
+ * @param ofType Optional `type` filter (e.g. `'raw_trace'`).
38
+ */
39
+ export declare function orderedViews<V extends OrderableView>(views?: Record<string, V> | null, ofType?: string): NamedView<V>[];
40
+ /**
41
+ * Stamp `order` 0..n-1 onto `views` following `orderedIds`.
42
+ *
43
+ * Every view is renumbered, not just the moved one: dense integers mean the
44
+ * next move is a swap of two adjacent numbers, and a method that was
45
+ * previously unordered comes out fully ordered after one Move rather than
46
+ * half-and-half.
47
+ *
48
+ * Ids in `views` but missing from `orderedIds` keep their existing `order`
49
+ * and land after the renumbered ones.
50
+ */
51
+ export declare function renumberViews<V extends OrderableView>(views: Record<string, V>, orderedIds: string[]): Record<string, V>;
52
+ /**
53
+ * Move the view at `index` by `dir` (-1 up, +1 down) and renumber.
54
+ * Out-of-range moves return the map unchanged.
55
+ */
56
+ export declare function moveView<V extends OrderableView>(views: Record<string, V>, index: number, dir: -1 | 1): Record<string, V>;
57
+ //# sourceMappingURL=chartViews.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chartViews.d.ts","sourceRoot":"","sources":["../../../src/components/tis/chartViews.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;8BAC8B;AAC9B,MAAM,WAAW,aAAa;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,yEAAyE;AACzE,MAAM,WAAW,SAAS,CAAC,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,CAAC;CACX;AAQD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,aAAa,EAChD,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,IAAI,EAChC,MAAM,CAAC,EAAE,MAAM,GAChB,SAAS,CAAC,CAAC,CAAC,EAAE,CAWhB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,aAAa,EACjD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EACxB,UAAU,EAAE,MAAM,EAAE,GACrB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAUnB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,aAAa,EAC5C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EACxB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,GACZ,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAMnB"}
@@ -0,0 +1 @@
1
+ const UNORDERED=Number.MAX_SAFE_INTEGER,orderOf=e=>"number"==typeof e?.order&&Number.isFinite(e.order)?e.order:UNORDERED;export function orderedViews(e,r){const o=[];for(const[n,t]of Object.entries(e??{}))r&&t?.type!==r||o.push({name:n,view:t});return o.sort((e,r)=>{const o=orderOf(e.view)-orderOf(r.view);return 0!==o?o:e.name.localeCompare(r.name)}),o}export function renumberViews(e,r){const o={};r.forEach((r,n)=>{const t=e[r];t&&(o[r]={...t,order:n})});for(const[r,n]of Object.entries(e))r in o||(o[r]=n);return o}export function moveView(e,r,o){const n=orderedViews(e).map(e=>e.name),t=r+o;return r<0||r>=n.length||t<0||t>=n.length?e:([n[r],n[t]]=[n[t],n[r]],renumberViews(e,n))}
@@ -105,6 +105,17 @@
105
105
  font-size: 0.8rem;
106
106
  }
107
107
 
108
+ /* A degradation, not a failure: the editor works, it just knows less. Amber
109
+ * rather than the red used for a real error. */
110
+ .tis-editor__notice {
111
+ background: #fffbeb;
112
+ color: #92400e;
113
+ border-left: 3px solid #d97706;
114
+ padding: 0.5rem 1rem;
115
+ margin: 0.5rem 1rem;
116
+ font-size: 0.875rem;
117
+ }
118
+
108
119
  .tis-editor__empty {
109
120
  flex: 1;
110
121
  display: flex;
@@ -1 +1 @@
1
- {"version":3,"file":"TisConfigEditor.d.ts","sourceRoot":"","sources":["../../../src/components/tis-editor/TisConfigEditor.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAM5E,OAAO,uBAAuB,CAAC;AAE/B,MAAM,WAAW,oBAAoB;IACjC;+EAC2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,OAAO,CAAC,EAAE,aAAa,CAAC;CAC3B;AAmBD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAyQ1D,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"TisConfigEditor.d.ts","sourceRoot":"","sources":["../../../src/components/tis-editor/TisConfigEditor.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAM5E,OAAO,uBAAuB,CAAC;AAM/B,MAAM,WAAW,oBAAoB;IACjC;+EAC2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,OAAO,CAAC,EAAE,aAAa,CAAC;CAC3B;AAmBD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAoS1D,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import{useEffect,useMemo,useState}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Button}from"primereact/button";import{InputText}from"primereact/inputtext";import{Dialog}from"primereact/dialog";import{useContext}from"react";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTisConfig}from"../../hooks/useTisConfig";import{useAmsAssetTypes}from"../../hooks/useAmsAssetTypes";import{MethodFormEditor}from"./editor/MethodFormEditor";import{SaveDiffDialog}from"./editor/SaveDiffDialog";import"./TisConfigEditor.css";const EMPTY_METHOD={label:"",description:"",project_fields:[],config_fields:[],cycle_config_fields:[],cycle_fields:[],results_fields:[],views:{},asset_refs:[]};export const TisConfigEditor=({projectId:e,invoker:t})=>{const s=useContext(EventEmitterContext),i=useMemo(()=>t??(async(e,t)=>await s.invoke(e,MessageType.Request,t)),[t,s]),o=useTisConfig(e,{invoker:i}),a=useAmsAssetTypes({invoker:i}),[n,r]=useState(null),[l,d]=useState(null),[c,m]=useState(!1),[f,p]=useState(!1),[h,u]=useState(!1),[_,g]=useState(""),x=useMemo(()=>o.config?Object.entries(o.config.methods).map(([e,t])=>({id:e,label:t?.label??""})):[],[o.config]);useEffect(()=>{if(!n&&o.config){const e=o.config.defaultMethodId||Object.keys(o.config.methods)[0]||null;r(e)}},[o.config,n]),useEffect(()=>{d(null)},[n]);return _jsxs("div",{className:"tis-editor",children:[_jsxs("header",{className:"tis-editor__header",children:[_jsxs("h2",{children:["Test Methods"," ",o.config?.dirty&&_jsx("span",{className:"tis-editor__dirty-pill",children:"unsaved"})]}),_jsxs("div",{className:"tis-editor__header-actions",children:[_jsx(Button,{label:"Save…",icon:"pi pi-save",disabled:c||!o.config?.dirty,onClick:()=>p(!0)}),_jsx(Button,{label:"Revert",icon:"pi pi-undo",className:"p-button-secondary",disabled:c||!o.config?.dirty,onClick:async()=>{if(window.confirm("Discard all in-progress edits? This cannot be undone.")){m(!0);try{await o.revert()}catch(e){d(String(e?.message??e))}finally{m(!1)}}}})]})]}),o.error&&_jsxs("div",{className:"tis-editor__error",children:[_jsx("strong",{children:"Error:"})," ",_jsx("pre",{children:o.error})]}),_jsxs("div",{className:"tis-editor__body",children:[_jsxs("aside",{className:"tis-editor__sidebar",children:[_jsxs("div",{className:"tis-editor__sidebar-actions",children:[_jsx(Button,{label:"New",icon:"pi pi-plus",disabled:c,onClick:()=>u(!0)}),_jsx(Button,{label:"Duplicate",icon:"pi pi-clone",className:"p-button-secondary",disabled:c||!n,onClick:async()=>{if(!n||!o.config)return;const e=o.config.methods[n];if(!e)return;let t=`${n}_copy`,s=2;for(;o.config.methods[t];)t=`${n}_copy_${s++}`;m(!0);try{await o.putMethod(t,JSON.parse(JSON.stringify(e))),r(t)}catch(e){d(String(e?.message??e))}finally{m(!1)}}}),_jsx(Button,{label:"Delete",icon:"pi pi-trash",className:"p-button-danger",disabled:c||!n,onClick:async()=>{if(n&&window.confirm(`Remove method "${n}"? This is staged — Save persists it.`)){m(!0);try{await o.removeMethod(n),r(null)}catch(e){d(String(e?.message??e))}finally{m(!1)}}}})]}),_jsxs(DataTable,{value:x,selection:x.find(e=>e.id===n)??null,onSelectionChange:e=>r(e.value?.id??null),selectionMode:"single",dataKey:"id",scrollable:!0,scrollHeight:"flex",emptyMessage:o.loading?"Loading…":"No test methods defined.",children:[_jsx(Column,{field:"id",header:"Method ID"}),_jsx(Column,{field:"label",header:"Label"})]})]}),_jsx("section",{className:"tis-editor__detail",children:n&&o.config?.methods[n]?_jsxs(_Fragment,{children:[l&&_jsx("div",{className:"tis-editor__error",children:_jsx("pre",{children:l})}),_jsx(MethodFormEditor,{methodId:n,method:o.config.methods[n],onApply:async e=>{if(n){m(!0);try{await o.putMethod(n,e),d(null)}catch(e){d(String(e?.message??e))}finally{m(!1)}}},busy:c,knownAssetTypes:a.types})]}):_jsx("div",{className:"tis-editor__empty",children:"Select a test method on the left, or create a new one."})})]}),_jsxs(Dialog,{header:"New Test Method",visible:h,onHide:()=>u(!1),style:{width:"24rem"},children:[_jsxs("label",{className:"tis-editor__new-method-label",children:["Method ID",_jsx(InputText,{value:_,onChange:e=>g(e.target.value),placeholder:"e.g. translational_traction",autoFocus:!0})]}),_jsx("small",{children:"Canonical key — appears in wire payloads, on-disk paths, and generated code."}),_jsxs("div",{style:{display:"flex",gap:"0.5rem",justifyContent:"flex-end",marginTop:"1rem"},children:[_jsx(Button,{label:"Cancel",className:"p-button-text",onClick:()=>u(!1)}),_jsx(Button,{label:"Create",disabled:!_.trim()||c,onClick:async()=>{const e=_.trim();if(e)if(o.config?.methods[e])d(`A method named "${e}" already exists.`);else{m(!0);try{await o.putMethod(e,EMPTY_METHOD),r(e),u(!1),g("")}catch(e){d(String(e?.message??e))}finally{m(!1)}}}})]})]}),_jsx(SaveDiffDialog,{visible:f,staged:o.config?.methods??{},invoker:i,onConfirm:async()=>{m(!0);try{await o.save(),p(!1)}catch(e){d(String(e?.message??e))}finally{m(!1)}},onCancel:()=>p(!1)})]})};export default TisConfigEditor;
1
+ import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import{useEffect,useMemo,useState}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Button}from"primereact/button";import{InputText}from"primereact/inputtext";import{Dialog}from"primereact/dialog";import{useContext}from"react";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTisConfig}from"../../hooks/useTisConfig";import{useAmsAssetTypes}from"../../hooks/useAmsAssetTypes";import{MethodFormEditor}from"./editor/MethodFormEditor";import{SaveDiffDialog}from"./editor/SaveDiffDialog";import"./TisConfigEditor.css";import{useGmVariables}from"../../hooks/useGmVariables";import{useSequenceProducers}from"../../hooks/useSequenceProducers";import{AuthoringContext}from"./editor/AuthoringContext";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";const EMPTY_METHOD={label:"",description:"",project_fields:[],config_fields:[],cycle_config_fields:[],cycle_fields:[],results_fields:[],views:{},asset_refs:[]};export const TisConfigEditor=({projectId:e,invoker:t})=>{const s=useContext(EventEmitterContext),i=useMemo(()=>t??(async(e,t)=>await s.invoke(e,MessageType.Request,t)),[t,s]),o=useTisConfig(e,{invoker:i}),{tags:a}=useContext(AutoCoreTagContext),r=useGmVariables({invoker:i,fallbackTags:a}),n=useAmsAssetTypes({invoker:i}),[l,d]=useState(null),[c,m]=useState(null),[u,f]=useState(!1),[p,h]=useState(!1),[g,_]=useState(!1),[x,y]=useState(""),b=useMemo(()=>o.config?Object.entries(o.config.methods).map(([e,t])=>({id:e,label:t?.label??""})):[],[o.config]);useEffect(()=>{if(!l&&o.config){const e=o.config.defaultMethodId||Object.keys(o.config.methods)[0]||null;d(e)}},[o.config,l]),useEffect(()=>{m(null)},[l]);const{producedNames:v}=useSequenceProducers(l),j=useMemo(()=>({variables:r.variables,producedNames:v,partial:r.partial}),[r.variables,v,r.partial]);return _jsx(AuthoringContext.Provider,{value:j,children:_jsxs("div",{className:"tis-editor",children:[_jsxs("header",{className:"tis-editor__header",children:[_jsxs("h2",{children:["Test Methods"," ",o.config?.dirty&&_jsx("span",{className:"tis-editor__dirty-pill",children:"unsaved"})]}),_jsxs("div",{className:"tis-editor__header-actions",children:[_jsx(Button,{label:"Save…",icon:"pi pi-save",disabled:u||!o.config?.dirty,onClick:()=>h(!0)}),_jsx(Button,{label:"Revert",icon:"pi pi-undo",className:"p-button-secondary",disabled:u||!o.config?.dirty,onClick:async()=>{if(window.confirm("Discard all in-progress edits? This cannot be undone.")){f(!0);try{await o.revert()}catch(e){m(String(e?.message??e))}finally{f(!1)}}}})]})]}),o.error&&_jsxs("div",{className:"tis-editor__error",children:[_jsx("strong",{children:"Error:"})," ",_jsx("pre",{children:o.error})]}),r.partial&&_jsx("div",{className:"tis-editor__notice",children:"This server cannot describe its own variables, so the pickers are listing only the variables published to this HMI, without descriptions. Update autocore_server to get the full list."}),_jsxs("div",{className:"tis-editor__body",children:[_jsxs("aside",{className:"tis-editor__sidebar",children:[_jsxs("div",{className:"tis-editor__sidebar-actions",children:[_jsx(Button,{label:"New",icon:"pi pi-plus",disabled:u,onClick:()=>_(!0)}),_jsx(Button,{label:"Duplicate",icon:"pi pi-clone",className:"p-button-secondary",disabled:u||!l,onClick:async()=>{if(!l||!o.config)return;const e=o.config.methods[l];if(!e)return;let t=`${l}_copy`,s=2;for(;o.config.methods[t];)t=`${l}_copy_${s++}`;f(!0);try{await o.putMethod(t,JSON.parse(JSON.stringify(e))),d(t)}catch(e){m(String(e?.message??e))}finally{f(!1)}}}),_jsx(Button,{label:"Delete",icon:"pi pi-trash",className:"p-button-danger",disabled:u||!l,onClick:async()=>{if(l&&window.confirm(`Remove method "${l}"? This is staged — Save persists it.`)){f(!0);try{await o.removeMethod(l),d(null)}catch(e){m(String(e?.message??e))}finally{f(!1)}}}})]}),_jsxs(DataTable,{value:b,selection:b.find(e=>e.id===l)??null,onSelectionChange:e=>d(e.value?.id??null),selectionMode:"single",dataKey:"id",scrollable:!0,scrollHeight:"flex",emptyMessage:o.loading?"Loading…":"No test methods defined.",children:[_jsx(Column,{field:"id",header:"Method ID"}),_jsx(Column,{field:"label",header:"Label"})]})]}),_jsx("section",{className:"tis-editor__detail",children:l&&o.config?.methods[l]?_jsxs(_Fragment,{children:[c&&_jsx("div",{className:"tis-editor__error",children:_jsx("pre",{children:c})}),_jsx(MethodFormEditor,{methodId:l,method:o.config.methods[l],onApply:async e=>{if(l){f(!0);try{await o.putMethod(l,e),m(null)}catch(e){m(String(e?.message??e))}finally{f(!1)}}},busy:u,knownAssetTypes:n.types})]}):_jsx("div",{className:"tis-editor__empty",children:"Select a test method on the left, or create a new one."})})]}),_jsxs(Dialog,{header:"New Test Method",visible:g,onHide:()=>_(!1),style:{width:"24rem"},children:[_jsxs("label",{className:"tis-editor__new-method-label",children:["Method ID",_jsx(InputText,{value:x,onChange:e=>y(e.target.value),placeholder:"e.g. translational_traction",autoFocus:!0})]}),_jsx("small",{children:"Canonical key — appears in wire payloads, on-disk paths, and generated code."}),_jsxs("div",{style:{display:"flex",gap:"0.5rem",justifyContent:"flex-end",marginTop:"1rem"},children:[_jsx(Button,{label:"Cancel",className:"p-button-text",onClick:()=>_(!1)}),_jsx(Button,{label:"Create",disabled:!x.trim()||u,onClick:async()=>{const e=x.trim();if(e)if(o.config?.methods[e])m(`A method named "${e}" already exists.`);else{f(!0);try{await o.putMethod(e,EMPTY_METHOD),d(e),_(!1),y("")}catch(e){m(String(e?.message??e))}finally{f(!1)}}}})]})]}),_jsx(SaveDiffDialog,{visible:p,staged:o.config?.methods??{},invoker:i,onConfirm:async()=>{f(!0);try{await o.save(),h(!1)}catch(e){m(String(e?.message??e))}finally{f(!1)}},onCancel:()=>h(!1)})]})})};export default TisConfigEditor;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * What the method editor's pickers can offer.
3
+ *
4
+ * A context rather than props because the fields that need it — a field
5
+ * dialog's Source, a bound, a chart axis, a raw column — sit three and four
6
+ * levels below the editor that fetches it, and threading the same two values
7
+ * through every intermediate component is how a prop list becomes noise.
8
+ *
9
+ * Everything here is optional. With none of it the pickers still open; they just
10
+ * have nothing to list, which is exactly the state the editor was in before they
11
+ * existed.
12
+ */
13
+ import type { GmVariable } from '@adcops/autocore-varpick';
14
+ export interface AuthoringCatalogs {
15
+ /** The machine's GM variable table, from `gm.get_variables`. */
16
+ variables: GmVariable[];
17
+ /**
18
+ * `store_value` names in the selected method's sequence.
19
+ *
20
+ * `undefined` means "not looked up" — the host could not read the
21
+ * `.seq.json`, or this product has no sequencer. That is deliberately
22
+ * different from `[]`, which means "read it, and it stores nothing": the
23
+ * first must not claim a cycle field has no producer.
24
+ */
25
+ producedNames?: string[];
26
+ /**
27
+ * True when `variables` came from the generated tag spec rather than the
28
+ * server — names and types, no descriptions, `ux: true` only.
29
+ *
30
+ * Worth surfacing: a picker that silently lists two thirds of the machine
31
+ * is worse than one that says it is listing two thirds of the machine.
32
+ */
33
+ partial?: boolean;
34
+ }
35
+ export declare const AuthoringContext: import("react").Context<AuthoringCatalogs>;
36
+ export declare const useAuthoringCatalogs: () => AuthoringCatalogs;
37
+ //# sourceMappingURL=AuthoringContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthoringContext.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/AuthoringContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D,MAAM,WAAW,iBAAiB;IAC9B,gEAAgE;IAChE,SAAS,EAAE,UAAU,EAAE,CAAC;IAExB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,gBAAgB,4CAAsD,CAAC;AAEpF,eAAO,MAAM,oBAAoB,QAAO,iBAAiD,CAAC"}
@@ -0,0 +1 @@
1
+ import{createContext,useContext}from"react";export const AuthoringContext=createContext({variables:[]});export const useAuthoringCatalogs=()=>useContext(AuthoringContext);
@@ -1,4 +1,5 @@
1
1
  import type { ChartView } from '../types';
2
+ import type { Catalog } from '@adcops/autocore-varpick';
2
3
  export interface ChartViewDialogProps {
3
4
  visible: boolean;
4
5
  initial: {
@@ -9,6 +10,16 @@ export interface ChartViewDialogProps {
9
10
  onSave: (viewId: string, view: ChartView) => void;
10
11
  /** Known field/column names; offered as datalist suggestions. */
11
12
  knownKeys: string[];
13
+ /**
14
+ * The same names, grouped and described, for the picker button.
15
+ *
16
+ * Takes the view TYPE because it decides which list is the likely answer:
17
+ * a `raw_trace` plots trace columns, a `cycle_scatter` plots cycle fields.
18
+ * A datalist alone was not enough — it only appears once you start typing,
19
+ * which is no help when you do not know what to type, and it does not open
20
+ * at all on a touchscreen.
21
+ */
22
+ fieldCatalog?: (viewType: string) => Catalog;
12
23
  /** Other view ids already in use — for uniqueness validation. */
13
24
  siblingIds: string[];
14
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ChartViewDialog.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/ChartViewDialog.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAA0B,SAAS,EAAE,MAAM,UAAU,CAAC;AAiBlE,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAClD,iEAAiE;IACjE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,iEAAiE;IACjE,UAAU,EAAE,MAAM,EAAE,CAAC;CACxB;AAQD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA0J1D,CAAC"}
1
+ {"version":3,"file":"ChartViewDialog.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/ChartViewDialog.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAA0B,SAAS,EAAE,MAAM,UAAU,CAAC;AAElE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAiBxD,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAClD,iEAAiE;IACjE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,iEAAiE;IACjE,UAAU,EAAE,MAAM,EAAE,CAAC;CACxB;AAQD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA4K1D,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{useEffect,useState}from"react";import{Dialog}from"primereact/dialog";import{Button}from"primereact/button";import{InputText}from"primereact/inputtext";import{Dropdown}from"primereact/dropdown";import{InputNumber}from"primereact/inputnumber";import{FormRow}from"../../forms/FormRow";import{DEFAULT_X_DECIMALS}from"../../tis/TestDataView";const MAX_X_DECIMALS=8,VIEW_TYPES=[{label:"Cycle scatter",value:"cycle_scatter"},{label:"Raw trace",value:"raw_trace"}],Y_AXES=[{label:"Left",value:"left"},{label:"Right",value:"right"}],blank=()=>({title:"",type:"cycle_scatter",x:{field:"",label:""},y:[]});export const ChartViewDialog=({visible:e,initial:l,onCancel:t,onSave:a,knownKeys:i,siblingIds:n})=>{const[s,r]=useState(""),[o,u]=useState(blank()),[m,c]=useState(null);useEffect(()=>{e&&(r(l?.viewId??""),u(l?JSON.parse(JSON.stringify(l.view)):blank()),c(null))},[e,l]);const d="raw_trace"===o.type,p=d?"column":"field",x=e=>{u({...o,x:{...o.x,...e}})},_=(e,l)=>{const t=[...o.y];t[e]={...t[e],...l},u({...o,y:t})};return _jsxs(Dialog,{header:l?`Edit view: ${l.viewId}`:"New chart view",visible:e,onHide:t,style:{width:"42rem"},children:[m&&_jsx("div",{style:{color:"#dc2626",marginBottom:"0.5rem"},children:m}),_jsx(FormRow,{label:"View ID",required:!0,hint:"Stable key (e.g. cof_scatter). Cannot collide with other views.",children:_jsx(InputText,{value:s,onChange:e=>r(e.target.value)})}),_jsx(FormRow,{label:"Title",children:_jsx(InputText,{value:o.title??"",onChange:e=>u({...o,title:e.target.value})})}),_jsx(FormRow,{label:"Type",required:!0,children:_jsx(Dropdown,{value:o.type,options:VIEW_TYPES,onChange:e=>u({...o,type:e.value})})}),_jsx(FormRow,{label:d?"X column":"X field",required:!0,children:_jsx(InputText,{value:o.x[p]??"",onChange:e=>x({[p]:e.target.value}),list:"known-keys"})}),_jsx(FormRow,{label:"X label",children:_jsx(InputText,{value:o.x.label??"",onChange:e=>x({label:e.target.value})})}),_jsx(FormRow,{label:"X decimals",hint:`Decimal places on X-axis tick labels. Blank uses the default (${DEFAULT_X_DECIMALS}). Display only — stored data keeps full precision.`,children:_jsx(InputNumber,{value:o.x_decimals??null,onValueChange:e=>{const l={...o};null==e.value?delete l.x_decimals:l.x_decimals=e.value,u(l)},min:0,max:8,placeholder:String(DEFAULT_X_DECIMALS),showButtons:!0})}),_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",margin:"1rem 0 0.5rem"},children:[_jsx("strong",{children:"Y series"}),_jsx(Button,{label:"Add series",icon:"pi pi-plus",size:"small",onClick:()=>{u({...o,y:[...o.y,{[p]:"",label:"",y_axis:"left"}]})}})]}),0===o.y.length&&_jsx("small",{children:"No series — add at least one."}),o.y.map((e,l)=>_jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr 6rem 2rem",gap:"0.5rem",marginBottom:"0.25rem",alignItems:"center"},children:[_jsx(InputText,{placeholder:d?"column":"field",value:e[p]??"",onChange:e=>_(l,{[p]:e.target.value}),list:"known-keys"}),_jsx(InputText,{placeholder:"label",value:e.label??"",onChange:e=>_(l,{label:e.target.value})}),_jsx(Dropdown,{value:e.y_axis??"left",options:Y_AXES,onChange:e=>_(l,{y_axis:e.value})}),_jsx(Button,{icon:"pi pi-trash",className:"p-button-text p-button-danger p-button-sm",onClick:()=>(e=>{u({...o,y:o.y.filter((l,t)=>t!==e)})})(l),"aria-label":"Remove series"})]},l)),_jsx("datalist",{id:"known-keys",children:i.map(e=>_jsx("option",{value:e},e))}),_jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem",marginTop:"1rem"},children:[_jsx(Button,{label:"Cancel",className:"p-button-text",onClick:t}),_jsx(Button,{label:"Save",onClick:()=>{const e=s.trim()?n.includes(s)&&s!==l?.viewId?`A view named "${s}" already exists.`:null:"View ID is required.";e?c(e):a(s,o)}})]})]})};
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{useEffect,useState}from"react";import{Dialog}from"primereact/dialog";import{Button}from"primereact/button";import{InputText}from"primereact/inputtext";import{Dropdown}from"primereact/dropdown";import{InputNumber}from"primereact/inputnumber";import{FormRow}from"../../forms/FormRow";import{useEditDraft}from"../../forms/useEditDraft";import{DEFAULT_X_DECIMALS}from"../../tis/TestDataView";import{VariableInput}from"../../varpick";const MAX_X_DECIMALS=8,VIEW_TYPES=[{label:"Cycle scatter",value:"cycle_scatter"},{label:"Raw trace",value:"raw_trace"}],Y_AXES=[{label:"Left",value:"left"},{label:"Right",value:"right"}],blank=()=>({title:"",type:"cycle_scatter",x:{field:"",label:""},y:[]});export const ChartViewDialog=({visible:e,initial:t,onCancel:l,onSave:a,knownKeys:i,siblingIds:r,fieldCatalog:n})=>{const{draft:o,setDraft:s,token:c}=useEditDraft(e,t?.viewId??"",()=>({viewId:t?.viewId??"",view:t?JSON.parse(JSON.stringify(t.view)):blank()})),m=o.viewId,d=o.view,u=e=>s(t=>({...t,view:e})),[p,x]=useState(null);useEffect(()=>{x(null)},[c]);const _="raw_trace"===d.type,h=_?"column":"field",v=e=>{u({...d,x:{...d.x,...e}})},f=(e,t)=>{const l=[...d.y];l[e]={...l[e],...t},u({...d,y:l})};return _jsxs(Dialog,{header:t?`Edit view: ${t.viewId}`:"New chart view",visible:e,onHide:l,style:{width:"42rem"},children:[p&&_jsx("div",{style:{color:"#dc2626",marginBottom:"0.5rem"},children:p}),_jsx(FormRow,{label:"View ID",required:!0,hint:"Stable key (e.g. cof_scatter). Cannot collide with other views.",children:_jsx(InputText,{value:m,onChange:e=>{return t=e.target.value,s(e=>({...e,viewId:t}));var t}})}),_jsx(FormRow,{label:"Title",children:_jsx(InputText,{value:d.title??"",onChange:e=>u({...d,title:e.target.value})})}),_jsx(FormRow,{label:"Type",required:!0,children:_jsx(Dropdown,{value:d.type,options:VIEW_TYPES,onChange:e=>u({...d,type:e.value})})}),_jsx(FormRow,{label:_?"X column":"X field",required:!0,children:_jsx(VariableInput,{value:d.x[h]??"",onChange:e=>v({[h]:e}),catalog:()=>n?.(d.type)??[],ariaLabel:"Choose the X axis column",pickerTitle:"X axis",pickerHint:"A chart naming a column that does not exist draws an empty plot with no error, which reads as “the machine recorded nothing”."})}),_jsx(FormRow,{label:"X label",children:_jsx(InputText,{value:d.x.label??"",onChange:e=>v({label:e.target.value})})}),_jsx(FormRow,{label:"X decimals",hint:`Decimal places on X-axis tick labels. Blank uses the default (${DEFAULT_X_DECIMALS}). Display only — stored data keeps full precision.`,children:_jsx(InputNumber,{value:d.x_decimals??null,onValueChange:e=>{const t={...d};null==e.value?delete t.x_decimals:t.x_decimals=e.value,u(t)},min:0,max:8,placeholder:String(DEFAULT_X_DECIMALS),showButtons:!0})}),_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",margin:"1rem 0 0.5rem"},children:[_jsx("strong",{children:"Y series"}),_jsx(Button,{label:"Add series",icon:"pi pi-plus",size:"small",onClick:()=>{u({...d,y:[...d.y,{[h]:"",label:"",y_axis:"left"}]})}})]}),0===d.y.length&&_jsx("small",{children:"No series — add at least one."}),d.y.map((e,t)=>_jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr 6rem 2rem",gap:"0.5rem",marginBottom:"0.25rem",alignItems:"center"},children:[_jsx(VariableInput,{placeholder:_?"column":"field",value:e[h]??"",onChange:e=>f(t,{[h]:e}),catalog:()=>n?.(d.type)??[],ariaLabel:`Choose the column for series ${t+1}`,pickerTitle:"Y series"}),_jsx(InputText,{placeholder:"label",value:e.label??"",onChange:e=>f(t,{label:e.target.value})}),_jsx(Dropdown,{value:e.y_axis??"left",options:Y_AXES,onChange:e=>f(t,{y_axis:e.value})}),_jsx(Button,{icon:"pi pi-trash",className:"p-button-text p-button-danger p-button-sm",onClick:()=>(e=>{u({...d,y:d.y.filter((t,l)=>l!==e)})})(t),"aria-label":"Remove series"})]},t)),_jsx("datalist",{id:"known-keys",children:i.map(e=>_jsx("option",{value:e},e))}),_jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem",marginTop:"1rem"},children:[_jsx(Button,{label:"Cancel",className:"p-button-text",onClick:l}),_jsx(Button,{label:"Save",onClick:()=>{const e=m.trim()?r.includes(m)&&m!==t?.viewId?`A view named "${m}" already exists.`:null:"View ID is required.";e?x(e):a(m,d)}})]})]})};
@@ -1 +1 @@
1
- {"version":3,"file":"FieldArrayEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/FieldArrayEditor.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAa,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAyBrE,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CACxC;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAwH5D,CAAC"}
1
+ {"version":3,"file":"FieldArrayEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/FieldArrayEditor.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAa,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAyBrE,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CACxC;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAyH5D,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import{useState}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Button}from"primereact/button";import{FormSection}from"../../forms/FormSection";import{TestFieldDialog}from"./TestFieldDialog";const TITLES={project_fields:"Project Fields",config_fields:"Config Fields",cycle_config_fields:"Cycle Configuration Fields",cycle_fields:"Cycle Fields",results_fields:"Results Fields"},DESCRIPTIONS={project_fields:"System-level fields (operator, station). Filled by the HMI but not cycled.",config_fields:"Operator-input config (speeds, loads). Snapshotted into test.json on start.",cycle_config_fields:"Operator-entered annotation recorded onto every cycle row (e.g. which of six positions this is). Shown on the HMI Cycle tab and written as the first Cycle Data columns after the row index. Mark them Required so the machine cannot start unannotated, and Autoclear so the next row cannot inherit a stale value.",cycle_fields:"Per-cycle capture. One row appended to cycles.jsonl per cycle.",results_fields:"Post-test summary (min/max/avg, pass/fail). Written once at finish. A field can also be a cross-test Aggregate (avg/min/max/stddev/count over tests sharing a sample_id)."},aggregateLabel=e=>{const t=e.aggregate;return t?"count"===t.fn?"count":`${t.fn}(${t.of??"?"})`:""};export const FieldArrayEditor=({arrayKey:e,method:t,onChange:s})=>{const l=t[e]??[],[o,i]=useState(!1),[n,a]=useState(null),r=(o,i)=>{const n=o+i;if(n<0||n>=l.length)return;const a=[...l];[a[o],a[n]]=[a[n],a[o]],s({...t,[e]:a})};return _jsxs(_Fragment,{children:[_jsx(FormSection,{title:TITLES[e],description:DESCRIPTIONS[e],actions:_jsx(Button,{label:"Add field",icon:"pi pi-plus",size:"small",onClick:()=>{a(null),i(!0)}}),children:_jsxs(DataTable,{value:l,dataKey:"name",emptyMessage:"No fields defined.",children:[_jsx(Column,{field:"name",header:"Name"}),_jsx(Column,{field:"type",header:"Type",style:{width:"6rem"}}),_jsx(Column,{field:"units",header:"Units",style:{width:"6rem"}}),_jsx(Column,{header:"Req",body:e=>e.required?"✓":"",style:{width:"4rem"}}),_jsx(Column,{field:"label",header:"Label"}),"results_fields"===e&&_jsx(Column,{header:"Aggregate",body:e=>aggregateLabel(e),style:{width:"8rem"}}),"cycle_config_fields"===e&&_jsx(Column,{header:"Autoclear",body:e=>e.autoclear?"✓":"",style:{width:"6rem"}}),_jsx(Column,{header:"",body:(o,n)=>_jsxs("div",{style:{display:"flex",gap:"0.25rem"},children:[_jsx(Button,{icon:"pi pi-arrow-up",className:"p-button-text p-button-sm",disabled:0===n.rowIndex,onClick:()=>r(n.rowIndex,-1),"aria-label":"Move up"}),_jsx(Button,{icon:"pi pi-arrow-down",className:"p-button-text p-button-sm",disabled:n.rowIndex===l.length-1,onClick:()=>r(n.rowIndex,1),"aria-label":"Move down"}),_jsx(Button,{icon:"pi pi-pencil",className:"p-button-text p-button-sm",onClick:()=>{return e=n.rowIndex,a(e),void i(!0);var e},"aria-label":"Edit"}),_jsx(Button,{icon:"pi pi-trash",className:"p-button-text p-button-danger p-button-sm",onClick:()=>(o=>{const i=l[o];if(!i)return;if(!window.confirm(`Remove field "${i.name}"?`))return;const n=l.filter((e,t)=>t!==o);s({...t,[e]:n})})(n.rowIndex),"aria-label":"Remove"})]}),style:{width:"10rem"}})]})}),_jsx(TestFieldDialog,{visible:o,initial:null!==n?l[n]??null:null,siblingNames:l.map(e=>e.name),isResultsField:"results_fields"===e,isCycleConfigField:"cycle_config_fields"===e,cycleFieldNames:(t.cycle_fields??[]).map(e=>e.name).filter(Boolean),resultsFieldNames:(t.results_fields??[]).map(e=>e.name).filter(Boolean),onCancel:()=>i(!1),onSave:o=>{const a=[...l];null===n?a.push(o):a[n]=o,s({...t,[e]:a}),i(!1)}})]})};
1
+ import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import{useState}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Button}from"primereact/button";import{FormSection}from"../../forms/FormSection";import{TestFieldDialog}from"./TestFieldDialog";const TITLES={project_fields:"Project Fields",config_fields:"Config Fields",cycle_config_fields:"Cycle Configuration Fields",cycle_fields:"Cycle Fields",results_fields:"Results Fields"},DESCRIPTIONS={project_fields:"System-level fields (operator, station). Filled by the HMI but not cycled.",config_fields:"Operator-input config (speeds, loads). Snapshotted into test.json on start.",cycle_config_fields:"Operator-entered annotation recorded onto every cycle row (e.g. which of six positions this is). Shown on the HMI Cycle tab and written as the first Cycle Data columns after the row index. Mark them Required so the machine cannot start unannotated, and Autoclear so the next row cannot inherit a stale value.",cycle_fields:"Per-cycle capture. One row appended to cycles.jsonl per cycle.",results_fields:"Post-test summary (min/max/avg, pass/fail). Written once at finish. A field can also be a cross-test Aggregate (avg/min/max/stddev/count over tests sharing a sample_id)."},aggregateLabel=e=>{const t=e.aggregate;return t?"count"===t.fn?"count":`${t.fn}(${t.of??"?"})`:""};export const FieldArrayEditor=({arrayKey:e,method:t,onChange:l})=>{const s=t[e]??[],[i,o]=useState(!1),[n,a]=useState(null),r=(i,o)=>{const n=i+o;if(n<0||n>=s.length)return;const a=[...s];[a[i],a[n]]=[a[n],a[i]],l({...t,[e]:a})};return _jsxs(_Fragment,{children:[_jsx(FormSection,{title:TITLES[e],description:DESCRIPTIONS[e],actions:_jsx(Button,{label:"Add field",icon:"pi pi-plus",size:"small",onClick:()=>{a(null),o(!0)}}),children:_jsxs(DataTable,{value:s,dataKey:"name",emptyMessage:"No fields defined.",children:[_jsx(Column,{field:"name",header:"Name"}),_jsx(Column,{field:"type",header:"Type",style:{width:"6rem"}}),_jsx(Column,{field:"units",header:"Units",style:{width:"6rem"}}),_jsx(Column,{header:"Req",body:e=>e.required?"✓":"",style:{width:"4rem"}}),_jsx(Column,{field:"label",header:"Label"}),"results_fields"===e&&_jsx(Column,{header:"Aggregate",body:e=>aggregateLabel(e),style:{width:"8rem"}}),"cycle_config_fields"===e&&_jsx(Column,{header:"Autoclear",body:e=>e.autoclear?"✓":"",style:{width:"6rem"}}),_jsx(Column,{header:"",body:(i,n)=>_jsxs("div",{style:{display:"flex",gap:"0.25rem"},children:[_jsx(Button,{icon:"pi pi-arrow-up",className:"p-button-text p-button-sm",disabled:0===n.rowIndex,onClick:()=>r(n.rowIndex,-1),"aria-label":"Move up"}),_jsx(Button,{icon:"pi pi-arrow-down",className:"p-button-text p-button-sm",disabled:n.rowIndex===s.length-1,onClick:()=>r(n.rowIndex,1),"aria-label":"Move down"}),_jsx(Button,{icon:"pi pi-pencil",className:"p-button-text p-button-sm",onClick:()=>{return e=n.rowIndex,a(e),void o(!0);var e},"aria-label":"Edit"}),_jsx(Button,{icon:"pi pi-trash",className:"p-button-text p-button-danger p-button-sm",onClick:()=>(i=>{const o=s[i];if(!o)return;if(!window.confirm(`Remove field "${o.name}"?`))return;const n=s.filter((e,t)=>t!==i);l({...t,[e]:n})})(n.rowIndex),"aria-label":"Remove"})]}),style:{width:"10rem"}})]})}),_jsx(TestFieldDialog,{visible:i,initial:null!==n?s[n]??null:null,siblingNames:s.map(e=>e.name),isResultsField:"results_fields"===e,isCycleConfigField:"cycle_config_fields"===e,isCycleField:"cycle_fields"===e,cycleFieldNames:(t.cycle_fields??[]).map(e=>e.name).filter(Boolean),resultsFieldNames:(t.results_fields??[]).map(e=>e.name).filter(Boolean),onCancel:()=>o(!1),onSave:i=>{const a=[...s];null===n?a.push(i):a[n]=i,l({...t,[e]:a}),o(!1)}})]})};
@@ -1 +1 @@
1
- {"version":3,"file":"RawDataEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/RawDataEditor.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAA2B,UAAU,EAAE,MAAM,UAAU,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CACxC;AAID,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAsGtD,CAAC"}
1
+ {"version":3,"file":"RawDataEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/RawDataEditor.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAA2B,UAAU,EAAE,MAAM,UAAU,CAAC;AAGpE,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CACxC;AAID,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA0GtD,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import{InputText}from"primereact/inputtext";import{Button}from"primereact/button";import{Checkbox}from"primereact/checkbox";import{FormSection}from"../../forms/FormSection";import{FormRow}from"../../forms/FormRow";const emptyRawData=()=>({blob_name:"trace",columns:{}});export const RawDataEditor=({method:e,onChange:t})=>{const n=e.raw_data,o=!!n,r=n=>{t({...e,raw_data:n})},a=(e,t)=>{n&&r({...n,columns:{...n.columns,[e]:t}})};return _jsxs(FormSection,{title:"Raw Data",description:"Columnar blob shape captured per cycle under raw_data/. Required only when the method records DAQ traces.",actions:_jsx(Checkbox,{checked:o,onChange:e=>r(e.checked?emptyRawData():null)}),children:[!o&&_jsx("small",{children:"Raw data capture disabled. Tick the box above to enable."}),o&&n&&_jsxs(_Fragment,{children:[_jsx(FormRow,{label:"Blob name",required:!0,hint:"Base filename under raw_data/, no extension.",children:_jsx(InputText,{value:n.blob_name,onChange:e=>r({...n,blob_name:e.target.value})})}),_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginTop:"0.75rem"},children:[_jsx("strong",{children:"Columns"}),_jsx(Button,{label:"Add column",icon:"pi pi-plus",size:"small",onClick:()=>{if(!n)return;let e="column",t=1;for(;n.columns[`${e}${t}`];)t++;r({...n,columns:{...n.columns,[`${e}${t}`]:{source:"time"}}})}})]}),0===Object.keys(n.columns).length&&_jsx("small",{children:"No columns defined."}),Object.entries(n.columns).map(([e,t])=>_jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1.5fr 1.5fr 2rem",gap:"0.5rem",marginTop:"0.25rem",alignItems:"center"},children:[_jsx(InputText,{placeholder:"column name",defaultValue:e,onBlur:t=>((e,t)=>{if(!n||!t.trim()||t===e)return;if(n.columns[t])return;const o={...n.columns};o[t]=o[e],delete o[e],r({...n,columns:o})})(e,t.target.value.trim())}),_jsx(InputText,{placeholder:"source (time / ni.<daq>.channels.<name> / derived)",value:t.source,onChange:n=>a(e,{...t,source:n.target.value})}),_jsx(InputText,{placeholder:"formula (only when source=derived)",value:t.formula??"",onChange:n=>a(e,{...t,formula:n.target.value||void 0}),disabled:"derived"!==t.source}),_jsx(Button,{icon:"pi pi-trash",className:"p-button-text p-button-danger p-button-sm",onClick:()=>(e=>{if(!n)return;if(!window.confirm(`Remove column "${e}"?`))return;const t={...n.columns};delete t[e],r({...n,columns:t})})(e),"aria-label":"Remove column"})]},e))]})]})};
1
+ import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import{InputText}from"primereact/inputtext";import{Button}from"primereact/button";import{Checkbox}from"primereact/checkbox";import{FormSection}from"../../forms/FormSection";import{FormRow}from"../../forms/FormRow";import{VariableInput,rawSourceCatalog}from"../../varpick";const emptyRawData=()=>({blob_name:"trace",columns:{}});export const RawDataEditor=({method:e,onChange:o})=>{const n=e.raw_data,t=!!n,r=n=>{o({...e,raw_data:n})},a=(e,o)=>{n&&r({...n,columns:{...n.columns,[e]:o}})};return _jsxs(FormSection,{title:"Raw Data",description:"Columnar blob shape captured per cycle under raw_data/. Required only when the method records DAQ traces.",actions:_jsx(Checkbox,{checked:t,onChange:e=>r(e.checked?emptyRawData():null)}),children:[!t&&_jsx("small",{children:"Raw data capture disabled. Tick the box above to enable."}),t&&n&&_jsxs(_Fragment,{children:[_jsx(FormRow,{label:"Blob name",required:!0,hint:"Base filename under raw_data/, no extension.",children:_jsx(InputText,{value:n.blob_name,onChange:e=>r({...n,blob_name:e.target.value})})}),_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginTop:"0.75rem"},children:[_jsx("strong",{children:"Columns"}),_jsx(Button,{label:"Add column",icon:"pi pi-plus",size:"small",onClick:()=>{if(!n)return;let e="column",o=1;for(;n.columns[`${e}${o}`];)o++;r({...n,columns:{...n.columns,[`${e}${o}`]:{source:"time"}}})}})]}),0===Object.keys(n.columns).length&&_jsx("small",{children:"No columns defined."}),Object.entries(n.columns).map(([e,o])=>_jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1.5fr 1.5fr 2rem",gap:"0.5rem",marginTop:"0.25rem",alignItems:"center"},children:[_jsx(InputText,{placeholder:"column name",defaultValue:e,onBlur:o=>((e,o)=>{if(!n||!o.trim()||o===e)return;if(n.columns[o])return;const t={...n.columns};t[o]=t[e],delete t[e],r({...n,columns:t})})(e,o.target.value.trim())}),_jsx(VariableInput,{placeholder:"source (time / ni.<daq>.channels.<name> / derived)",value:o.source,onChange:n=>a(e,{...o,source:n}),catalog:()=>rawSourceCatalog(),ariaLabel:`Choose the source for column ${e}`,pickerTitle:"Column source",pickerHint:"A DAQ channel is named ni.<daq>.channels.<name> and is not listed here — the editor has no channel catalog, so type it."}),_jsx(InputText,{placeholder:"formula (only when source=derived)",value:o.formula??"",onChange:n=>a(e,{...o,formula:n.target.value||void 0}),disabled:"derived"!==o.source}),_jsx(Button,{icon:"pi pi-trash",className:"p-button-text p-button-danger p-button-sm",onClick:()=>(e=>{if(!n)return;if(!window.confirm(`Remove column "${e}"?`))return;const o={...n.columns};delete o[e],r({...n,columns:o})})(e),"aria-label":"Remove column"})]},e))]})]})};
@@ -15,6 +15,13 @@ export interface TestFieldDialogProps {
15
15
  /** Candidate target field names for an aggregate's `of`, by source. */
16
16
  cycleFieldNames?: string[];
17
17
  resultsFieldNames?: string[];
18
+ /**
19
+ * True when this field belongs to `cycle_fields`. Only there does Source
20
+ * have two possible producers — a GM tag read at record time, or the
21
+ * sequence storing a value under this column's NAME — so only there is the
22
+ * picker a producer picker rather than a variable list.
23
+ */
24
+ isCycleField?: boolean;
18
25
  }
19
26
  export declare const TestFieldDialog: React.FC<TestFieldDialogProps>;
20
27
  //# sourceMappingURL=TestFieldDialog.d.ts.map