@adcops/autocore-react 3.3.85 → 3.3.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/AxisC.d.ts +4 -0
- package/dist/assets/AxisC.d.ts.map +1 -0
- package/dist/assets/AxisC.js +1 -0
- package/dist/assets/AxisX.js +1 -1
- package/dist/assets/AxisY.js +1 -1
- package/dist/assets/AxisZ.js +1 -1
- package/dist/components/ValueInput.css +9 -12
- package/dist/components/ValueInput.d.ts +45 -154
- package/dist/components/ValueInput.d.ts.map +1 -1
- package/dist/components/ValueInput.js +1 -1
- package/dist/components/ams/AmsProvider.d.ts +10 -0
- package/dist/components/ams/AmsProvider.d.ts.map +1 -1
- package/dist/components/ams/AssetRegistryTable.d.ts.map +1 -1
- package/dist/components/ams/AssetRegistryTable.js +1 -1
- package/dist/components/forms/FormRow.d.ts +20 -0
- package/dist/components/forms/FormRow.d.ts.map +1 -0
- package/dist/components/forms/FormRow.js +1 -0
- package/dist/components/forms/FormSection.d.ts +19 -0
- package/dist/components/forms/FormSection.d.ts.map +1 -0
- package/dist/components/forms/FormSection.js +1 -0
- package/dist/components/forms/forms.css +89 -0
- package/dist/components/forms/index.d.ts +3 -0
- package/dist/components/forms/index.d.ts.map +1 -0
- package/dist/components/forms/index.js +1 -0
- package/dist/components/tis-editor/TisConfigEditor.css +121 -0
- package/dist/components/tis-editor/TisConfigEditor.d.ts +28 -0
- package/dist/components/tis-editor/TisConfigEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/TisConfigEditor.js +1 -0
- package/dist/components/tis-editor/editor/AnalysisEditor.d.ts +7 -0
- package/dist/components/tis-editor/editor/AnalysisEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/AnalysisEditor.js +1 -0
- package/dist/components/tis-editor/editor/AssetRefsEditor.d.ts +10 -0
- package/dist/components/tis-editor/editor/AssetRefsEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/AssetRefsEditor.js +1 -0
- package/dist/components/tis-editor/editor/ChartViewDialog.d.ts +16 -0
- package/dist/components/tis-editor/editor/ChartViewDialog.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/ChartViewDialog.js +1 -0
- package/dist/components/tis-editor/editor/FieldArrayEditor.d.ts +8 -0
- package/dist/components/tis-editor/editor/FieldArrayEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/FieldArrayEditor.js +1 -0
- package/dist/components/tis-editor/editor/IdentitySection.d.ts +7 -0
- package/dist/components/tis-editor/editor/IdentitySection.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/IdentitySection.js +1 -0
- package/dist/components/tis-editor/editor/MethodFormEditor.d.ts +20 -0
- package/dist/components/tis-editor/editor/MethodFormEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/MethodFormEditor.js +1 -0
- package/dist/components/tis-editor/editor/RawDataEditor.d.ts +7 -0
- package/dist/components/tis-editor/editor/RawDataEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/RawDataEditor.js +1 -0
- package/dist/components/tis-editor/editor/SaveDiffDialog.d.ts +22 -0
- package/dist/components/tis-editor/editor/SaveDiffDialog.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/SaveDiffDialog.js +1 -0
- package/dist/components/tis-editor/editor/TestFieldDialog.d.ts +11 -0
- package/dist/components/tis-editor/editor/TestFieldDialog.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/TestFieldDialog.js +1 -0
- package/dist/components/tis-editor/editor/ViewsEditor.d.ts +7 -0
- package/dist/components/tis-editor/editor/ViewsEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/ViewsEditor.js +1 -0
- package/dist/components/tis-editor/types.d.ts +78 -0
- package/dist/components/tis-editor/types.d.ts.map +1 -0
- package/dist/components/tis-editor/types.js +1 -0
- package/dist/components/tis-editor/validation.d.ts +20 -0
- package/dist/components/tis-editor/validation.d.ts.map +1 -0
- package/dist/components/tis-editor/validation.js +1 -0
- package/dist/hooks/useAmsAssetTypes.d.ts +23 -0
- package/dist/hooks/useAmsAssetTypes.d.ts.map +1 -0
- package/dist/hooks/useAmsAssetTypes.js +1 -0
- package/dist/hooks/useTisConfig.d.ts +51 -0
- package/dist/hooks/useTisConfig.d.ts.map +1 -0
- package/dist/hooks/useTisConfig.js +1 -0
- package/package.json +9 -3
- package/src/assets/AxisC.tsx +38 -0
- package/src/assets/AxisX.tsx +32 -32
- package/src/assets/AxisY.tsx +34 -34
- package/src/assets/AxisZ.tsx +31 -31
- package/src/components/ValueInput.css +9 -12
- package/src/components/ValueInput.tsx +132 -317
- package/src/components/ams/AmsProvider.tsx +10 -0
- package/src/components/ams/AssetRegistryTable.tsx +53 -8
- package/src/components/forms/FormRow.tsx +37 -0
- package/src/components/forms/FormSection.tsx +39 -0
- package/src/components/forms/forms.css +89 -0
- package/src/components/forms/index.ts +2 -0
- package/src/components/tis-editor/TisConfigEditor.css +121 -0
- package/src/components/tis-editor/TisConfigEditor.tsx +321 -0
- package/src/components/tis-editor/editor/AnalysisEditor.tsx +54 -0
- package/src/components/tis-editor/editor/AssetRefsEditor.tsx +187 -0
- package/src/components/tis-editor/editor/ChartViewDialog.tsx +170 -0
- package/src/components/tis-editor/editor/FieldArrayEditor.tsx +131 -0
- package/src/components/tis-editor/editor/IdentitySection.tsx +36 -0
- package/src/components/tis-editor/editor/MethodFormEditor.tsx +176 -0
- package/src/components/tis-editor/editor/RawDataEditor.tsx +117 -0
- package/src/components/tis-editor/editor/SaveDiffDialog.tsx +160 -0
- package/src/components/tis-editor/editor/TestFieldDialog.tsx +134 -0
- package/src/components/tis-editor/editor/ViewsEditor.tsx +101 -0
- package/src/components/tis-editor/types.ts +95 -0
- package/src/components/tis-editor/validation.ts +104 -0
- package/src/hooks/useAmsAssetTypes.ts +70 -0
- package/src/hooks/useTisConfig.ts +164 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
.tis-editor {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
height: 100%;
|
|
5
|
+
min-height: 0;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.tis-editor__header {
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
justify-content: space-between;
|
|
12
|
+
padding: 0.75rem 1rem;
|
|
13
|
+
border-bottom: 1px solid var(--surface-d, #e2e8f0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.tis-editor__header h2 {
|
|
17
|
+
margin: 0;
|
|
18
|
+
font-size: 1.125rem;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.tis-editor__header-actions {
|
|
22
|
+
display: flex;
|
|
23
|
+
gap: 0.5rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.tis-editor__dirty-pill {
|
|
27
|
+
display: inline-block;
|
|
28
|
+
background: #ea580c;
|
|
29
|
+
color: white;
|
|
30
|
+
font-size: 0.7rem;
|
|
31
|
+
font-weight: 600;
|
|
32
|
+
text-transform: uppercase;
|
|
33
|
+
letter-spacing: 0.05em;
|
|
34
|
+
padding: 0.15rem 0.5rem;
|
|
35
|
+
border-radius: 999px;
|
|
36
|
+
margin-left: 0.5rem;
|
|
37
|
+
vertical-align: middle;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.tis-editor__body {
|
|
41
|
+
flex: 1;
|
|
42
|
+
display: flex;
|
|
43
|
+
min-height: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.tis-editor__sidebar {
|
|
47
|
+
flex: 0 0 320px;
|
|
48
|
+
border-right: 1px solid var(--surface-d, #e2e8f0);
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-direction: column;
|
|
51
|
+
min-height: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.tis-editor__sidebar-actions {
|
|
55
|
+
display: flex;
|
|
56
|
+
gap: 0.25rem;
|
|
57
|
+
padding: 0.5rem;
|
|
58
|
+
border-bottom: 1px solid var(--surface-d, #e2e8f0);
|
|
59
|
+
flex-wrap: wrap;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.tis-editor__sidebar-actions .p-button {
|
|
63
|
+
flex: 1 1 auto;
|
|
64
|
+
min-width: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.tis-editor__detail {
|
|
68
|
+
flex: 1;
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
min-height: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.tis-editor__detail-header {
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: space-between;
|
|
78
|
+
padding: 0.5rem 1rem;
|
|
79
|
+
border-bottom: 1px solid var(--surface-d, #e2e8f0);
|
|
80
|
+
background: var(--surface-b, #f8fafc);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.tis-editor__editor-wrap {
|
|
84
|
+
flex: 1;
|
|
85
|
+
min-height: 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.tis-editor__editor-wrap > * {
|
|
89
|
+
height: 100%;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.tis-editor__error {
|
|
93
|
+
background: #fef2f2;
|
|
94
|
+
color: #991b1b;
|
|
95
|
+
border-left: 3px solid #dc2626;
|
|
96
|
+
padding: 0.5rem 1rem;
|
|
97
|
+
margin: 0.5rem 1rem;
|
|
98
|
+
font-size: 0.875rem;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.tis-editor__error pre {
|
|
102
|
+
white-space: pre-wrap;
|
|
103
|
+
margin: 0.25rem 0 0 0;
|
|
104
|
+
font-family: ui-monospace, monospace;
|
|
105
|
+
font-size: 0.8rem;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.tis-editor__empty {
|
|
109
|
+
flex: 1;
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: center;
|
|
113
|
+
color: var(--text-color-secondary, #64748b);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.tis-editor__new-method-label {
|
|
117
|
+
display: flex;
|
|
118
|
+
flex-direction: column;
|
|
119
|
+
gap: 0.25rem;
|
|
120
|
+
margin-bottom: 0.25rem;
|
|
121
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TisConfigEditor — master-detail UI for editing TIS test_methods.
|
|
3
|
+
*
|
|
4
|
+
* Left: PrimeReact DataTable listing methods (method_id + label).
|
|
5
|
+
* Right: tabbed editor for the selected method. Phase 1 ships a single
|
|
6
|
+
* JSON-via-Monaco tab; Phase 2 layers form editors on top of it.
|
|
7
|
+
* Action bar: New / Duplicate / Delete / Apply / Save / Revert.
|
|
8
|
+
*
|
|
9
|
+
* "Apply" pushes the local Monaco buffer to the server-side stage
|
|
10
|
+
* (`tis.put_method`). "Save" persists the entire stage to project.json
|
|
11
|
+
* (`tis.save_config`). "Revert" drops the stage (`tis.discard_config_changes`).
|
|
12
|
+
*
|
|
13
|
+
* Save is disabled (with a tooltip) when active tests are open against
|
|
14
|
+
* any method — the server enforces the same gate, but disabling on the
|
|
15
|
+
* client gives clearer UX.
|
|
16
|
+
*/
|
|
17
|
+
import { type TisIpcInvoker } from '../../hooks/useTisConfig';
|
|
18
|
+
import './TisConfigEditor.css';
|
|
19
|
+
export interface TisConfigEditorProps {
|
|
20
|
+
/** Project ID. Today this is informational (the server hosts one
|
|
21
|
+
* project) but the wire contract carries it for forward compatibility. */
|
|
22
|
+
projectId: string;
|
|
23
|
+
/** Optional invoker override — primarily for the playground / tests. */
|
|
24
|
+
invoker?: TisIpcInvoker;
|
|
25
|
+
}
|
|
26
|
+
export declare const TisConfigEditor: React.FC<TisConfigEditorProps>;
|
|
27
|
+
export default TisConfigEditor;
|
|
28
|
+
//# sourceMappingURL=TisConfigEditor.d.ts.map
|
|
@@ -0,0 +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;AAkBD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAoQ1D,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +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_fields:[],results_fields:[],views:{},asset_refs:[]};export const TisConfigEditor=({projectId:e,invoker:t})=>{const s=useContext(EventEmitterContext),i=t??(async(e,t)=>await s.invoke(e,MessageType.Request,t)),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;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnalysisEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/AnalysisEditor.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAiB,UAAU,EAAE,MAAM,UAAU,CAAC;AAE1D,MAAM,WAAW,mBAAmB;IAChC,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CACxC;AAID,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAwCxD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";import{InputText}from"primereact/inputtext";import{Checkbox}from"primereact/checkbox";import{FormSection}from"../../forms/FormSection";import{FormRow}from"../../forms/FormRow";const empty=()=>({script:"",function:""});export const AnalysisEditor=({method:e,onChange:t})=>{const o=e.analysis,n=!!o,r=o=>{t({...e,analysis:o})};return _jsxs(FormSection,{title:"Analysis Hook",description:"Optional post-cycle Python entry point. Codegen wires this into the method's TestManager.",actions:_jsx(Checkbox,{checked:n,onChange:e=>r(e.checked?empty():null)}),children:[!n&&_jsx("small",{children:"Analysis hook disabled. Tick the box to enable."}),n&&o&&_jsxs(_Fragment,{children:[_jsx(FormRow,{label:"Script",required:!0,hint:"Path under autocore-python's scripts directory.",children:_jsx(InputText,{value:o.script,onChange:e=>r({...o,script:e.target.value}),placeholder:"e.g. analysis/traction_v1.py"})}),_jsx(FormRow,{label:"Function",required:!0,hint:"Entry-point name within the script.",children:_jsx(InputText,{value:o.function,onChange:e=>r({...o,function:e.target.value}),placeholder:"e.g. analyze_cycle"})})]})]})};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TestMethod } from '../types';
|
|
2
|
+
export interface AssetRefsEditorProps {
|
|
3
|
+
method: TestMethod;
|
|
4
|
+
onChange: (next: TestMethod) => void;
|
|
5
|
+
/** Asset types known to AMS, supplied by the host. Empty array = use a
|
|
6
|
+
* free-form text field. Phase 3 wires this up to ams.list_schemas. */
|
|
7
|
+
knownAssetTypes?: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare const AssetRefsEditor: React.FC<AssetRefsEditorProps>;
|
|
10
|
+
//# sourceMappingURL=AssetRefsEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssetRefsEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/AssetRefsEditor.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAY,UAAU,EAAE,MAAM,UAAU,CAAC;AAarD,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC;2EACuE;IACvE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC9B;AAOD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAsJ1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import{useState}from"react";import{Dialog}from"primereact/dialog";import{Button}from"primereact/button";import{InputText}from"primereact/inputtext";import{InputTextarea}from"primereact/inputtextarea";import{Dropdown}from"primereact/dropdown";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{FormSection}from"../../forms/FormSection";import{FormRow}from"../../forms/FormRow";const SELECT_OPTIONS=[{label:"By location",value:"by_location"},{label:"By id field",value:"by_id_field"}],CALIBRATION_OPTIONS=[{label:"Ignore",value:"ignore"},{label:"Warn (default)",value:"warn"},{label:"Require",value:"require"}],blank=()=>({field:"",asset_type:"",select:"by_location",calibration_required:"warn"});export const AssetRefsEditor=({method:e,onChange:t,knownAssetTypes:l=[]})=>{const o=e.asset_refs??[],[a,r]=useState(!1),[i,s]=useState(null),[n,d]=useState(blank()),[u,c]=useState(null),m=l.length>0?l.map(e=>({label:e,value:e})):null;return _jsxs(_Fragment,{children:[_jsx(FormSection,{title:"Asset References",description:"AMS dependencies resolved at start_test time and snapshotted into test.json.",actions:_jsx(Button,{label:"Add asset_ref",icon:"pi pi-plus",size:"small",onClick:()=>{s(null),d(blank()),c(null),r(!0)}}),children:_jsxs(DataTable,{value:o,dataKey:"field",emptyMessage:"No asset_refs declared.",children:[_jsx(Column,{field:"field",header:"Field"}),_jsx(Column,{field:"asset_type",header:"Asset type"}),_jsx(Column,{field:"select",header:"Select",style:{width:"7rem"}}),_jsx(Column,{header:"Locator",body:e=>"by_location"===e.select?e.location:e.from}),_jsx(Column,{field:"calibration_required",header:"Calibration",style:{width:"7rem"}}),_jsx(Column,{header:"",body:(l,a)=>_jsxs("div",{style:{display:"flex",gap:"0.25rem"},children:[_jsx(Button,{icon:"pi pi-pencil",className:"p-button-text p-button-sm",onClick:()=>{return e=a.rowIndex,s(e),d({...o[e]}),c(null),void r(!0);var e}}),_jsx(Button,{icon:"pi pi-trash",className:"p-button-text p-button-danger p-button-sm",onClick:()=>{return l=a.rowIndex,void(window.confirm(`Remove asset_ref "${o[l].field}"?`)&&t({...e,asset_refs:o.filter((e,t)=>t!==l)}));var l}})]}),style:{width:"6rem"}})]})}),_jsxs(Dialog,{header:null===i?"New asset_ref":`Edit asset_ref: ${o[i??0]?.field}`,visible:a,onHide:()=>r(!1),style:{width:"40rem"},children:[u&&_jsx("div",{style:{color:"#dc2626",marginBottom:"0.5rem"},children:u}),_jsx(FormRow,{label:"Field",required:!0,hint:"Key under test.json::asset_snapshot.",children:_jsx(InputText,{value:n.field,onChange:e=>d({...n,field:e.target.value})})}),_jsx(FormRow,{label:"Asset type",required:!0,children:m?_jsx(Dropdown,{value:n.asset_type,options:m,onChange:e=>d({...n,asset_type:e.value}),editable:!0}):_jsx(InputText,{value:n.asset_type,onChange:e=>d({...n,asset_type:e.target.value}),placeholder:"e.g. load_cell"})}),_jsx(FormRow,{label:"Select",required:!0,children:_jsx(Dropdown,{value:n.select,options:SELECT_OPTIONS,onChange:e=>d({...n,select:e.value})})}),"by_location"===n.select&&_jsx(FormRow,{label:"Location",required:!0,hint:"AMS location key (e.g. tsdr).",children:_jsx(InputText,{value:n.location??"",onChange:e=>d({...n,location:e.target.value})})}),"by_id_field"===n.select&&_jsx(FormRow,{label:"From",required:!0,hint:"Dotted config path (e.g. config.surface_asset_id).",children:_jsx(InputText,{value:n.from??"",onChange:e=>d({...n,from:e.target.value})})}),_jsx(FormRow,{label:"Calibration policy",children:_jsx(Dropdown,{value:n.calibration_required??"warn",options:CALIBRATION_OPTIONS,onChange:e=>d({...n,calibration_required:e.value})})}),_jsx(FormRow,{label:"Label",children:_jsx(InputText,{value:n.label??"",onChange:e=>d({...n,label:e.target.value||void 0})})}),_jsx(FormRow,{label:"Description",children:_jsx(InputTextarea,{rows:2,value:n.description??"",onChange:e=>d({...n,description:e.target.value||void 0})})}),_jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem",marginTop:"1rem"},children:[_jsx(Button,{label:"Cancel",className:"p-button-text",onClick:()=>r(!1)}),_jsx(Button,{label:"Save",onClick:()=>{const l=(a=n).field.trim()?a.asset_type.trim()?"by_location"!==a.select||a.location?.trim()?"by_id_field"!==a.select||a.from?.trim()?o.some((e,t)=>e.field===a.field&&t!==i)?`An asset_ref for field "${a.field}" already exists.`:null:"From-path is required when select=by_id_field.":"Location is required when select=by_location.":"Asset type is required.":"Field name is required.";var a;if(l)return void c(l);const s=[...o];null===i?s.push(n):s[i]=n,t({...e,asset_refs:s}),r(!1)}})]})]})]})};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ChartView } from '../types';
|
|
2
|
+
export interface ChartViewDialogProps {
|
|
3
|
+
visible: boolean;
|
|
4
|
+
initial: {
|
|
5
|
+
viewId: string;
|
|
6
|
+
view: ChartView;
|
|
7
|
+
} | null;
|
|
8
|
+
onCancel: () => void;
|
|
9
|
+
onSave: (viewId: string, view: ChartView) => void;
|
|
10
|
+
/** Known field/column names; offered as datalist suggestions. */
|
|
11
|
+
knownKeys: string[];
|
|
12
|
+
/** Other view ids already in use — for uniqueness validation. */
|
|
13
|
+
siblingIds: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare const ChartViewDialog: React.FC<ChartViewDialogProps>;
|
|
16
|
+
//# sourceMappingURL=ChartViewDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChartViewDialog.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/ChartViewDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA0B,SAAS,EAAE,MAAM,UAAU,CAAC;AAYlE,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,CAsI1D,CAAC"}
|
|
@@ -0,0 +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{FormRow}from"../../forms/FormRow";const 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:n})=>{const[r,s]=useState(""),[o,c]=useState(blank()),[u,m]=useState(null);useEffect(()=>{e&&(s(t?.viewId??""),c(t?JSON.parse(JSON.stringify(t.view)):blank()),m(null))},[e,t]);const d="raw_trace"===o.type,p=d?"column":"field",x=e=>{c({...o,x:{...o.x,...e}})},_=(e,t)=>{const l=[...o.y];l[e]={...l[e],...t},c({...o,y:l})};return _jsxs(Dialog,{header:t?`Edit view: ${t.viewId}`:"New chart view",visible:e,onHide:l,style:{width:"42rem"},children:[u&&_jsx("div",{style:{color:"#dc2626",marginBottom:"0.5rem"},children:u}),_jsx(FormRow,{label:"View ID",required:!0,hint:"Stable key (e.g. cof_scatter). Cannot collide with other views.",children:_jsx(InputText,{value:r,onChange:e=>s(e.target.value)})}),_jsx(FormRow,{label:"Title",children:_jsx(InputText,{value:o.title??"",onChange:e=>c({...o,title:e.target.value})})}),_jsx(FormRow,{label:"Type",required:!0,children:_jsx(Dropdown,{value:o.type,options:VIEW_TYPES,onChange:e=>c({...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})})}),_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:()=>{c({...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,t)=>_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=>_(t,{[p]:e.target.value}),list:"known-keys"}),_jsx(InputText,{placeholder:"label",value:e.label??"",onChange:e=>_(t,{label:e.target.value})}),_jsx(Dropdown,{value:e.y_axis??"left",options:Y_AXES,onChange:e=>_(t,{y_axis:e.value})}),_jsx(Button,{icon:"pi pi-trash",className:"p-button-text p-button-danger p-button-sm",onClick:()=>(e=>{c({...o,y:o.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=r.trim()?n.includes(r)&&r!==t?.viewId?`A view named "${r}" already exists.`:null:"View ID is required.";e?m(e):a(r,o)}})]})]})};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TestMethod, FieldArrayKey } from '../types';
|
|
2
|
+
export interface FieldArrayEditorProps {
|
|
3
|
+
arrayKey: FieldArrayKey;
|
|
4
|
+
method: TestMethod;
|
|
5
|
+
onChange: (next: TestMethod) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare const FieldArrayEditor: React.FC<FieldArrayEditorProps>;
|
|
8
|
+
//# sourceMappingURL=FieldArrayEditor.d.ts.map
|
|
@@ -0,0 +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;AAgBrE,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,CAsG5D,CAAC"}
|
|
@@ -0,0 +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_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_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."};export const FieldArrayEditor=({arrayKey:e,method:t,onChange:i})=>{const o=t[e]??[],[l,s]=useState(!1),[n,r]=useState(null),a=(l,s)=>{const n=l+s;if(n<0||n>=o.length)return;const r=[...o];[r[l],r[n]]=[r[n],r[l]],i({...t,[e]:r})};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:()=>{r(null),s(!0)}}),children:_jsxs(DataTable,{value:o,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"}),_jsx(Column,{header:"",body:(l,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:()=>a(n.rowIndex,-1),"aria-label":"Move up"}),_jsx(Button,{icon:"pi pi-arrow-down",className:"p-button-text p-button-sm",disabled:n.rowIndex===o.length-1,onClick:()=>a(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,r(e),void s(!0);var e},"aria-label":"Edit"}),_jsx(Button,{icon:"pi pi-trash",className:"p-button-text p-button-danger p-button-sm",onClick:()=>(l=>{const s=o[l];if(!s)return;if(!window.confirm(`Remove field "${s.name}"?`))return;const n=o.filter((e,t)=>t!==l);i({...t,[e]:n})})(n.rowIndex),"aria-label":"Remove"})]}),style:{width:"10rem"}})]})}),_jsx(TestFieldDialog,{visible:l,initial:null!==n?o[n]??null:null,siblingNames:o.map(e=>e.name),onCancel:()=>s(!1),onSave:l=>{const r=[...o];null===n?r.push(l):r[n]=l,i({...t,[e]:r}),s(!1)}})]})};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TestMethod } from '../types';
|
|
2
|
+
export interface IdentitySectionProps {
|
|
3
|
+
method: TestMethod;
|
|
4
|
+
onChange: (next: TestMethod) => void;
|
|
5
|
+
}
|
|
6
|
+
export declare const IdentitySection: React.FC<IdentitySectionProps>;
|
|
7
|
+
//# sourceMappingURL=IdentitySection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IdentitySection.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/IdentitySection.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CACxC;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAwB1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{InputText}from"primereact/inputtext";import{InputTextarea}from"primereact/inputtextarea";import{FormSection}from"../../forms/FormSection";import{FormRow}from"../../forms/FormRow";export const IdentitySection=({method:e,onChange:t})=>_jsxs(FormSection,{title:"Identity",description:"Display label and operator-facing description for this method.",children:[_jsx(FormRow,{label:"Label",hint:"Pretty name shown in the Test Method picker.",children:_jsx(InputText,{value:e.label??"",onChange:o=>t({...e,label:o.target.value})})}),_jsx(FormRow,{label:"Description",hint:"Long-form guidance shown beneath the picker when this method is selected.",children:_jsx(InputTextarea,{rows:3,value:e.description??"",onChange:o=>t({...e,description:o.target.value})})})]});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MethodFormEditor — tabbed shell that composes the per-section subforms
|
|
3
|
+
* for a single TestMethod. The JSON tab is always available as an escape
|
|
4
|
+
* hatch for power users.
|
|
5
|
+
*
|
|
6
|
+
* Owns the local working copy of the method. Hands the changed copy back
|
|
7
|
+
* to the parent via onChange — the parent decides when to call put_method.
|
|
8
|
+
*/
|
|
9
|
+
import type { TestMethod } from '../types';
|
|
10
|
+
export interface MethodFormEditorProps {
|
|
11
|
+
methodId: string;
|
|
12
|
+
method: TestMethod;
|
|
13
|
+
/** Called on Apply with the working copy — parent forwards to put_method. */
|
|
14
|
+
onApply: (next: TestMethod) => Promise<void> | void;
|
|
15
|
+
/** AMS asset types — passed through to AssetRefsEditor for the dropdown. */
|
|
16
|
+
knownAssetTypes?: string[];
|
|
17
|
+
busy?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare const MethodFormEditor: React.FC<MethodFormEditorProps>;
|
|
20
|
+
//# sourceMappingURL=MethodFormEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MethodFormEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/MethodFormEditor.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,6EAA6E;IAC7E,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpD,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA+I5D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import{useEffect,useMemo,useState}from"react";import{TabView,TabPanel}from"primereact/tabview";import{Button}from"primereact/button";import{CodeEditor}from"../../CodeEditor";import{IdentitySection}from"./IdentitySection";import{FieldArrayEditor}from"./FieldArrayEditor";import{ViewsEditor}from"./ViewsEditor";import{RawDataEditor}from"./RawDataEditor";import{AssetRefsEditor}from"./AssetRefsEditor";import{AnalysisEditor}from"./AnalysisEditor";import{validateMethod}from"../validation";export const MethodFormEditor=({methodId:e,method:t,onApply:r,knownAssetTypes:i=[],busy:s})=>{const[o,a]=useState(t),[n,d]=useState(""),[l,h]=useState(null),[m,c]=useState(0);useEffect(()=>{a(t),d(JSON.stringify(t,null,2)),h(null)},[t,e]);const y=useMemo(()=>{try{return JSON.stringify(o)!==JSON.stringify(t)}catch{return!0}},[o,t]),f=useMemo(()=>validateMethod(e,o),[o,e]),x=e=>{a(e),d(JSON.stringify(e,null,2))};return _jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%",minHeight:0},children:[_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:"0.5rem 1rem",borderBottom:"1px solid var(--surface-d, #e2e8f0)",background:"var(--surface-b, #f8fafc)"},children:[_jsxs("strong",{children:[e,y&&_jsx("span",{style:{marginLeft:"0.5rem",color:"#ea580c"},children:"•"}),f.length>0&&_jsxs("span",{title:f.map(e=>e.message).join("\n"),style:{marginLeft:"0.5rem",background:"#fef2f2",color:"#991b1b",padding:"0.1rem 0.5rem",borderRadius:4,fontSize:"0.75rem",fontWeight:600,cursor:"help"},children:[f.length," issue",1===f.length?"":"s"]})]}),_jsx("div",{style:{display:"flex",gap:"0.5rem"},children:_jsx(Button,{label:"Apply",icon:"pi pi-check",disabled:s||!y||!!l||f.length>0,onClick:async()=>{l||await r(o)}})})]}),_jsx("div",{style:{flex:1,minHeight:0,overflow:"auto"},children:_jsxs(TabView,{activeIndex:m,onTabChange:e=>c(e.index),children:[_jsx(TabPanel,{header:"Identity",children:_jsx(IdentitySection,{method:o,onChange:x})}),_jsxs(TabPanel,{header:"Fields",children:[_jsx(FieldArrayEditor,{arrayKey:"project_fields",method:o,onChange:x}),_jsx(FieldArrayEditor,{arrayKey:"config_fields",method:o,onChange:x}),_jsx(FieldArrayEditor,{arrayKey:"cycle_fields",method:o,onChange:x}),_jsx(FieldArrayEditor,{arrayKey:"results_fields",method:o,onChange:x})]}),_jsx(TabPanel,{header:"Views",children:_jsx(ViewsEditor,{method:o,onChange:x})}),_jsx(TabPanel,{header:"Raw Data",children:_jsx(RawDataEditor,{method:o,onChange:x})}),_jsx(TabPanel,{header:"Assets",children:_jsx(AssetRefsEditor,{method:o,onChange:x,knownAssetTypes:i})}),_jsx(TabPanel,{header:"Analysis",children:_jsx(AnalysisEditor,{method:o,onChange:x})}),_jsxs(TabPanel,{header:"JSON",children:[l&&_jsx("div",{style:{color:"#dc2626",marginBottom:"0.5rem",fontFamily:"monospace"},children:l}),_jsx("div",{style:{height:"60vh"},children:_jsx(CodeEditor,{code:n,language:"json",theme:"vs-dark",readOnly:!1,cursorStyle:"line",onCodeChanged:e=>{const t=e??"";d(t);try{const e=JSON.parse(t);a(e),h(null)}catch(e){h(String(e?.message??e))}}})})]})]})})]})};
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +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))]})]})};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SaveDiffDialog — shows what's about to land on disk before save_config.
|
|
3
|
+
*
|
|
4
|
+
* Fetches a fresh disk-state via `tis.list_schemas` (the existing read
|
|
5
|
+
* endpoint that bypasses staging) and diffs against the current staged
|
|
6
|
+
* methods. Operator confirms or cancels.
|
|
7
|
+
*
|
|
8
|
+
* The diff is intentionally simple: added / removed / modified method IDs,
|
|
9
|
+
* plus a JSON before/after for each modified method. Adding a full
|
|
10
|
+
* line-level differ would mean another dep — not worth it for an HMI.
|
|
11
|
+
*/
|
|
12
|
+
import type { TisIpcInvoker } from '../../../hooks/useTisConfig';
|
|
13
|
+
import type { TestMethod } from '../types';
|
|
14
|
+
export interface SaveDiffDialogProps {
|
|
15
|
+
visible: boolean;
|
|
16
|
+
staged: Record<string, TestMethod>;
|
|
17
|
+
invoker: TisIpcInvoker;
|
|
18
|
+
onConfirm: () => Promise<void> | void;
|
|
19
|
+
onCancel: () => void;
|
|
20
|
+
}
|
|
21
|
+
export declare const SaveDiffDialog: React.FC<SaveDiffDialogProps>;
|
|
22
|
+
//# sourceMappingURL=SaveDiffDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SaveDiffDialog.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/SaveDiffDialog.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC,OAAO,EAAE,aAAa,CAAC;IACvB,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAQD,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAgGxD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import{useEffect,useState}from"react";import{Dialog}from"primereact/dialog";import{Button}from"primereact/button";export const SaveDiffDialog=({visible:e,staged:i,invoker:r,onConfirm:t,onCancel:s})=>{const[d,o]=useState(null),[n,l]=useState(null),[a,c]=useState(!1);useEffect(()=>{if(!e)return;let t=!1;return(async()=>{l(null);try{const e=await r("tis.list_schemas",{});if(t)return;if(!e.success)return void l(e.error_message??"tis.list_schemas failed");const s=e.data?.test_methods??{};o(buildDiff(s,i))}catch(e){l(String(e?.message??e))}})(),()=>{t=!0}},[e,i,r]);return _jsxs(Dialog,{header:"Save Test Methods to Disk",visible:e,onHide:s,style:{width:"60rem",maxWidth:"90vw"},children:[n&&_jsx("div",{style:{color:"#dc2626",marginBottom:"0.5rem"},children:n}),!d&&!n&&_jsx("small",{children:"Computing diff…"}),d&&_jsxs("div",{children:[_jsxs("p",{children:["About to overwrite ",_jsx("code",{children:"project.json"}),". A backup of the previous file will be written to"," ",_jsx("code",{children:"project.json.bak"}),"."]}),0===d.added.length&&0===d.removed.length&&0===d.modified.length&&_jsx("p",{children:_jsx("em",{children:"No changes detected."})}),d.added.length>0&&_jsxs("p",{children:[_jsx("strong",{children:"Added:"})," ",d.added.join(", ")]}),d.removed.length>0&&_jsxs("p",{children:[_jsx("strong",{children:"Removed:"})," ",d.removed.join(", ")]}),d.modified.length>0&&_jsxs(_Fragment,{children:[_jsxs("p",{children:[_jsx("strong",{children:"Modified:"})," ",d.modified.map(e=>e.id).join(", ")]}),_jsxs("details",{children:[_jsx("summary",{children:"Show before / after"}),d.modified.map(e=>_jsxs("div",{style:{marginTop:"0.75rem"},children:[_jsx("strong",{children:e.id}),_jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"0.5rem",marginTop:"0.25rem"},children:[_jsx("pre",{style:preStyle("before"),children:JSON.stringify(e.before,null,2)}),_jsx("pre",{style:preStyle("after"),children:JSON.stringify(e.after,null,2)})]})]},e.id))]})]})]}),_jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem",marginTop:"1rem"},children:[_jsx(Button,{label:"Cancel",className:"p-button-text",onClick:s,disabled:a}),_jsx(Button,{label:"Save",icon:"pi pi-save",disabled:a||!d,onClick:async()=>{c(!0);try{await t()}finally{c(!1)}}})]})]})};function preStyle(e){return{background:"before"===e?"#fef2f2":"#f0fdf4",color:"#0f172a",padding:"0.5rem",fontSize:"0.75rem",margin:0,maxHeight:"20rem",overflow:"auto",border:"1px solid "+("before"===e?"#fecaca":"#bbf7d0"),borderRadius:4}}function buildDiff(e,i){const r={added:[],removed:[],modified:[]},t=new Set([...Object.keys(e),...Object.keys(i)]);for(const s of t){const t=e[s],d=i[s];void 0===t&&void 0!==d?r.added.push(s):void 0!==t&&void 0===d?r.removed.push(s):void 0!==t&&void 0!==d&&JSON.stringify(t)!==JSON.stringify(d)&&r.modified.push({id:s,before:t,after:d})}return r}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { TestField } from '../types';
|
|
2
|
+
export interface TestFieldDialogProps {
|
|
3
|
+
visible: boolean;
|
|
4
|
+
initial: TestField | null;
|
|
5
|
+
onCancel: () => void;
|
|
6
|
+
onSave: (field: TestField) => void;
|
|
7
|
+
/** Names already in use within the same array — for uniqueness validation. */
|
|
8
|
+
siblingNames: string[];
|
|
9
|
+
}
|
|
10
|
+
export declare const TestFieldDialog: React.FC<TestFieldDialogProps>;
|
|
11
|
+
//# sourceMappingURL=TestFieldDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestFieldDialog.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/TestFieldDialog.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAa1C,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,SAAS,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACnC,8EAA8E;IAC9E,YAAY,EAAE,MAAM,EAAE,CAAC;CAC1B;AAID,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAoG1D,CAAC"}
|
|
@@ -0,0 +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{InputTextarea}from"primereact/inputtextarea";import{Dropdown}from"primereact/dropdown";import{Checkbox}from"primereact/checkbox";import{InputNumber}from"primereact/inputnumber";import{FormRow}from"../../forms/FormRow";const FIELD_TYPES=[{label:"string",value:"string"},{label:"i32",value:"i32"},{label:"i64",value:"i64"},{label:"u32",value:"u32"},{label:"u64",value:"u64"},{label:"f32",value:"f32"},{label:"f64",value:"f64"},{label:"bool",value:"bool"}],blank={name:"",type:"f32"};export const TestFieldDialog=({visible:e,initial:a,onCancel:t,onSave:l,siblingNames:r})=>{const[i,o]=useState(blank),[n,s]=useState(null);useEffect(()=>{e&&(o(a?{...a}:{...blank}),s(null))},[e,a]);return _jsxs(Dialog,{header:a?`Edit field: ${a.name}`:"New field",visible:e,onHide:t,style:{width:"36rem"},children:[n&&_jsx("div",{style:{color:"#dc2626",marginBottom:"0.75rem"},children:n}),_jsx(FormRow,{label:"Name",required:!0,hint:"Wire-format key. Also the column name in CSV exports.",children:_jsx(InputText,{value:i.name,onChange:e=>o({...i,name:e.target.value})})}),_jsx(FormRow,{label:"Type",required:!0,children:_jsx(Dropdown,{value:i.type,options:FIELD_TYPES,onChange:e=>o({...i,type:e.value}),editable:!0})}),_jsx(FormRow,{label:"Units",hint:"Display label, appended to form labels (e.g. m/s).",children:_jsx(InputText,{value:i.units??"",onChange:e=>o({...i,units:e.target.value||void 0})})}),_jsx(FormRow,{label:"Label",hint:"Pretty form label. Falls back to name when empty.",children:_jsx(InputText,{value:i.label??"",onChange:e=>o({...i,label:e.target.value||void 0})})}),_jsx(FormRow,{label:"Required",children:_jsx(Checkbox,{checked:!!i.required,onChange:e=>o({...i,required:!!e.checked})})}),_jsx(FormRow,{label:"Source",hint:"Optional gm.* variable to bind this field to.",children:_jsx(InputText,{value:i.source??"",onChange:e=>o({...i,source:e.target.value||void 0}),placeholder:"gm.<variable_name>"})}),_jsx(FormRow,{label:"Scale",hint:"display = raw × scale. Leave blank for 1.0 (no conversion).",children:_jsx(InputNumber,{value:i.scale??null,onValueChange:e=>o({...i,scale:"number"==typeof e.value?e.value:void 0}),mode:"decimal",minFractionDigits:0,maxFractionDigits:9})}),_jsx(FormRow,{label:"Description",hint:"Hover tooltip in the form.",children:_jsx(InputTextarea,{rows:2,value:i.description??"",onChange:e=>o({...i,description:e.target.value||void 0})})}),_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=(t=i).name.trim()?/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t.name)?r.some(e=>e===t.name&&e!==a?.name)?`A field named "${t.name}" already exists in this array.`:null:"Name must be a valid identifier (letters, digits, underscore; cannot start with a digit).":"Field name is required.";var t;e?s(e):l(i)}})]})]})};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ViewsEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/tis-editor/editor/ViewsEditor.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAwB,UAAU,EAAE,MAAM,UAAU,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CACxC;AAQD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAiFlD,CAAC"}
|
|
@@ -0,0 +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{ChartViewDialog}from"./ChartViewDialog";export const ViewsEditor=({method:e,onChange:t})=>{const i=e.views??{},a=Object.entries(i).map(([e,t])=>({id:e,title:t.title??"",type:t.type??""})),[s,n]=useState(!1),[o,r]=useState(null),l=[...(e.project_fields??[]).map(e=>e.name),...(e.config_fields??[]).map(e=>e.name),...(e.cycle_fields??[]).map(e=>e.name),...(e.results_fields??[]).map(e=>e.name),...Object.keys(e.raw_data?.columns??{})];return _jsxs(_Fragment,{children:[_jsx(FormSection,{title:"Views",description:"Named chart definitions rendered by <TestDataView> (cycle_scatter) and <TestRawDataView> (raw_trace).",actions:_jsx(Button,{label:"Add view",icon:"pi pi-plus",size:"small",onClick:()=>{r(null),n(!0)}}),children:_jsxs(DataTable,{value:a,dataKey:"id",emptyMessage:"No views defined.",children:[_jsx(Column,{field:"id",header:"View ID"}),_jsx(Column,{field:"title",header:"Title"}),_jsx(Column,{field:"type",header:"Type",style:{width:"8rem"}}),_jsx(Column,{header:"",body:a=>_jsxs("div",{style:{display:"flex",gap:"0.25rem"},children:[_jsx(Button,{icon:"pi pi-pencil",className:"p-button-text p-button-sm",onClick:()=>{return e=a.id,r(e),void n(!0);var e},"aria-label":"Edit"}),_jsx(Button,{icon:"pi pi-trash",className:"p-button-text p-button-danger p-button-sm",onClick:()=>(a=>{if(!window.confirm(`Remove view "${a}"?`))return;const s={...i};delete s[a],t({...e,views:s})})(a.id),"aria-label":"Remove"})]}),style:{width:"6rem"}})]})}),_jsx(ChartViewDialog,{visible:s,initial:o?{viewId:o,view:i[o]}:null,knownKeys:l,siblingIds:Object.keys(i),onCancel:()=>n(!1),onSave:(a,s)=>{const r={...i};o&&o!==a&&delete r[o],r[a]=s,t({...e,views:r}),n(!1)}})]})};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side mirror of the autocore-server TestMethod schema.
|
|
3
|
+
* Source of truth is autocore-server/src/project.rs.
|
|
4
|
+
*
|
|
5
|
+
* Kept loose — `unknown` for default values and pass-through fields — so
|
|
6
|
+
* unknown server-side extensions don't trip the editor at parse time.
|
|
7
|
+
*/
|
|
8
|
+
export type FieldType = 'string' | 'i32' | 'i64' | 'u32' | 'u64' | 'f32' | 'f64' | 'bool';
|
|
9
|
+
export interface TestField {
|
|
10
|
+
name: string;
|
|
11
|
+
type: FieldType | string;
|
|
12
|
+
units?: string;
|
|
13
|
+
required?: boolean;
|
|
14
|
+
source?: string;
|
|
15
|
+
label?: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
default?: unknown;
|
|
18
|
+
scale?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface ChartAxis {
|
|
21
|
+
field?: string;
|
|
22
|
+
column?: string;
|
|
23
|
+
label?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ChartSeries {
|
|
26
|
+
field?: string;
|
|
27
|
+
column?: string;
|
|
28
|
+
label?: string;
|
|
29
|
+
y_axis?: 'left' | 'right';
|
|
30
|
+
}
|
|
31
|
+
export type ChartViewType = 'cycle_scatter' | 'raw_trace';
|
|
32
|
+
export interface ChartView {
|
|
33
|
+
title?: string;
|
|
34
|
+
type: ChartViewType | string;
|
|
35
|
+
x: ChartAxis;
|
|
36
|
+
y: ChartSeries[];
|
|
37
|
+
}
|
|
38
|
+
export type RawColumnSource = 'time' | 'derived' | string;
|
|
39
|
+
export interface RawColumn {
|
|
40
|
+
source: RawColumnSource;
|
|
41
|
+
formula?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface RawDataShape {
|
|
44
|
+
blob_name: string;
|
|
45
|
+
columns: Record<string, RawColumn>;
|
|
46
|
+
units?: Record<string, string>;
|
|
47
|
+
}
|
|
48
|
+
export type AssetRefSelect = 'by_location' | 'by_id_field';
|
|
49
|
+
export type CalibrationPolicy = 'ignore' | 'warn' | 'require';
|
|
50
|
+
export interface AssetRef {
|
|
51
|
+
field: string;
|
|
52
|
+
asset_type: string;
|
|
53
|
+
select: AssetRefSelect | string;
|
|
54
|
+
location?: string;
|
|
55
|
+
from?: string;
|
|
56
|
+
calibration_required?: CalibrationPolicy | string;
|
|
57
|
+
label?: string;
|
|
58
|
+
description?: string;
|
|
59
|
+
}
|
|
60
|
+
export interface AnalysisShape {
|
|
61
|
+
script: string;
|
|
62
|
+
function: string;
|
|
63
|
+
}
|
|
64
|
+
export interface TestMethod {
|
|
65
|
+
label?: string;
|
|
66
|
+
description?: string;
|
|
67
|
+
project_fields?: TestField[];
|
|
68
|
+
config_fields?: TestField[];
|
|
69
|
+
cycle_fields?: TestField[];
|
|
70
|
+
results_fields?: TestField[];
|
|
71
|
+
raw_data?: RawDataShape | null;
|
|
72
|
+
views?: Record<string, ChartView>;
|
|
73
|
+
asset_refs?: AssetRef[];
|
|
74
|
+
analysis?: AnalysisShape | null;
|
|
75
|
+
[key: string]: unknown;
|
|
76
|
+
}
|
|
77
|
+
export type FieldArrayKey = 'project_fields' | 'config_fields' | 'cycle_fields' | 'results_fields';
|
|
78
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/tis-editor/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,SAAS,GACf,QAAQ,GACR,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAC7B,KAAK,GAAG,KAAK,GACb,MAAM,CAAC;AAEb,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,WAAW,CAAC;AAE1D,MAAM,WAAW,SAAS;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,aAAa,GAAG,MAAM,CAAC;IAC7B,CAAC,EAAE,SAAS,CAAC;IACb,CAAC,EAAE,WAAW,EAAE,CAAC;CACpB;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,SAAS;IACtB,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,aAAa,CAAC;AAC3D,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAE9D,MAAM,WAAW,QAAQ;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,SAAS,EAAE,CAAC;IAC7B,aAAa,CAAC,EAAE,SAAS,EAAE,CAAC;IAC5B,YAAY,CAAC,EAAE,SAAS,EAAE,CAAC;IAC3B,cAAc,CAAC,EAAE,SAAS,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG,eAAe,GAAG,cAAc,GAAG,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side validation for TestMethod. Mirrors the cross-field checks
|
|
3
|
+
* in autocore-server/src/tis_servelet.rs `validate_method` so the operator
|
|
4
|
+
* sees the same errors instantly in the form, not only after Apply.
|
|
5
|
+
*
|
|
6
|
+
* Returns a flat array of error messages. Empty array = clean.
|
|
7
|
+
*/
|
|
8
|
+
import type { TestMethod } from './types';
|
|
9
|
+
export interface ValidationError {
|
|
10
|
+
/** Dotted path: "<arrayKey>.<index>.<sub>" or "views.<viewId>.x" etc. */
|
|
11
|
+
path: string;
|
|
12
|
+
message: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function validateMethod(methodId: string, m: TestMethod): ValidationError[];
|
|
15
|
+
/**
|
|
16
|
+
* Validate a whole methods map. Returns errors grouped by methodId.
|
|
17
|
+
* Useful for the master-detail sidebar (display an error count per row).
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateMethods(methods: Record<string, TestMethod>): Record<string, ValidationError[]>;
|
|
20
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/components/tis-editor/validation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACG,UAAU,EACxB,MAAM,SAAS,CAAC;AAIjB,MAAM,WAAW,eAAe;IAC5B,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,GAAG,eAAe,EAAE,CAsEjF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAOtG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const FIELD_ARRAY_KEYS=["project_fields","config_fields","cycle_fields","results_fields"];export function validateMethod(e,a){const t=[];for(const n of FIELD_ARRAY_KEYS){const o=a[n]??[],s=new Set;o.forEach((a,o)=>{a.name&&""!==a.name.trim()?s.has(a.name)?t.push({path:`${n}.${o}.name`,message:`${e}.${n}: duplicate field name "${a.name}"`}):s.add(a.name):t.push({path:`${n}.${o}.name`,message:`${e}.${n}: empty field name`})})}const n=new Set;for(const e of FIELD_ARRAY_KEYS){(a[e]??[]).forEach(e=>e.name&&n.add(e.name))}const o=new Set(Object.keys(a.raw_data?.columns??{})),s=e=>e.field&&e.field.trim()?{key:e.field,ok:n.has(e.field)}:e.column&&e.column.trim()?{key:e.column,ok:o.has(e.column)}:null,c=a.views??{};for(const[a,n]of Object.entries(c)){if(n?.x){const o=s(n.x);o&&!o.ok&&t.push({path:`views.${a}.x`,message:`${e}.views.${a}: x.field/column "${o.key}" does not match any field or raw_data column`})}(n?.y??[]).forEach((n,o)=>{const c=s(n);c&&!c.ok&&t.push({path:`views.${a}.y.${o}`,message:`${e}.views.${a}.y[${o}]: field/column "${c.key}" does not match any field or raw_data column`})})}const m=a.raw_data;return m&&(m.blob_name&&""!==String(m.blob_name).trim()||t.push({path:"raw_data.blob_name",message:`${e}.raw_data: blob_name is empty`})),t}export function validateMethods(e){const a={};for(const[t,n]of Object.entries(e)){const e=validateMethod(t,n);e.length>0&&(a[t]=e)}return a}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useAmsAssetTypes — fetch the AMS asset-type catalog.
|
|
3
|
+
*
|
|
4
|
+
* Used by the TIS editor's AssetRefsEditor to populate the asset_type
|
|
5
|
+
* dropdown with real values instead of free-form text. Falls back to
|
|
6
|
+
* an empty array on error (the dropdown degrades gracefully to a text
|
|
7
|
+
* field).
|
|
8
|
+
*
|
|
9
|
+
* Wraps `ams.list_schemas`, which returns the merged catalog of
|
|
10
|
+
* built-in + project-declared asset types. Accepts an `invoker` override
|
|
11
|
+
* for the playground / tests.
|
|
12
|
+
*/
|
|
13
|
+
import type { TisIpcInvoker } from './useTisConfig';
|
|
14
|
+
export interface UseAmsAssetTypesResult {
|
|
15
|
+
types: string[];
|
|
16
|
+
loading: boolean;
|
|
17
|
+
error: string | null;
|
|
18
|
+
refresh: () => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export declare function useAmsAssetTypes(options?: {
|
|
21
|
+
invoker?: TisIpcInvoker;
|
|
22
|
+
}): UseAmsAssetTypesResult;
|
|
23
|
+
//# sourceMappingURL=useAmsAssetTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAmsAssetTypes.d.ts","sourceRoot":"","sources":["../../src/hooks/useAmsAssetTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,aAAa,CAAA;CAAE,GAAG,sBAAsB,CA4C9F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useCallback,useContext,useEffect,useState}from"react";import{EventEmitterContext}from"../core/EventEmitterContext";import{MessageType}from"../hub/CommandMessage";export function useAmsAssetTypes(e){const t=useContext(EventEmitterContext),s=e?.invoker??(async(e,s)=>await t.invoke(e,MessageType.Request,s)),[a,o]=useState([]),[r,n]=useState(!0),[c,m]=useState(null),u=useCallback(async()=>{n(!0);try{const e=await s("ams.list_schemas",{});if(!e.success)return m(e.error_message??"ams.list_schemas failed"),void o([]);const t=e.data??{},a=t.asset_types&&"object"==typeof t.asset_types?t.asset_types:t.schemas&&"object"==typeof t.schemas?t.schemas:null;o(a?Object.keys(a):[]),m(null)}catch(e){m(String(e?.message??e)),o([])}finally{n(!1)}},[s]);return useEffect(()=>{u()},[u]),{types:a,loading:r,error:c,refresh:u}}
|