@adcops/autocore-react 3.3.123 → 3.5.3

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 (55) hide show
  1. package/dist/components/UnitSystemSelector.d.ts +17 -0
  2. package/dist/components/UnitSystemSelector.d.ts.map +1 -0
  3. package/dist/components/UnitSystemSelector.js +1 -0
  4. package/dist/components/UnitsEditor.d.ts +11 -0
  5. package/dist/components/UnitsEditor.d.ts.map +1 -0
  6. package/dist/components/UnitsEditor.js +1 -0
  7. package/dist/components/index.d.ts +5 -1
  8. package/dist/components/index.d.ts.map +1 -1
  9. package/dist/components/index.js +1 -1
  10. package/dist/components/tis/ResultHistoryTable.d.ts.map +1 -1
  11. package/dist/components/tis/ResultHistoryTable.js +1 -1
  12. package/dist/components/tis/ScienceTable.d.ts +14 -0
  13. package/dist/components/tis/ScienceTable.d.ts.map +1 -1
  14. package/dist/components/tis/ScienceTable.js +1 -1
  15. package/dist/components/tis/TestDataView.d.ts +33 -4
  16. package/dist/components/tis/TestDataView.d.ts.map +1 -1
  17. package/dist/components/tis/TestDataView.js +1 -1
  18. package/dist/components/tis/TestFieldRow.d.ts +69 -7
  19. package/dist/components/tis/TestFieldRow.d.ts.map +1 -1
  20. package/dist/components/tis/TestFieldRow.js +1 -1
  21. package/dist/components/tis/TestSetupForm.d.ts.map +1 -1
  22. package/dist/components/tis/TestSetupForm.js +1 -1
  23. package/dist/components/tis/TisProvider.d.ts.map +1 -1
  24. package/dist/components/tis/TisProvider.js +1 -1
  25. package/dist/components/tis-editor/editor/ChartViewDialog.d.ts.map +1 -1
  26. package/dist/components/tis-editor/editor/ChartViewDialog.js +1 -1
  27. package/dist/components/tis-editor/types.d.ts +6 -0
  28. package/dist/components/tis-editor/types.d.ts.map +1 -1
  29. package/dist/core/AutoCoreTagContext.d.ts.map +1 -1
  30. package/dist/core/AutoCoreTagContext.js +1 -1
  31. package/dist/core/AutoCoreTagTypes.d.ts +82 -7
  32. package/dist/core/AutoCoreTagTypes.d.ts.map +1 -1
  33. package/dist/core/formatScaled.d.ts +16 -0
  34. package/dist/core/formatScaled.d.ts.map +1 -0
  35. package/dist/core/formatScaled.js +1 -0
  36. package/dist/hooks/useAutoCoreTag.d.ts +11 -3
  37. package/dist/hooks/useAutoCoreTag.d.ts.map +1 -1
  38. package/dist/hooks/useAutoCoreTag.js +1 -1
  39. package/package.json +1 -1
  40. package/src/components/UnitSystemSelector.tsx +88 -0
  41. package/src/components/UnitsEditor.tsx +317 -0
  42. package/src/components/index.ts +5 -1
  43. package/src/components/tis/ResultHistoryTable.tsx +96 -6
  44. package/src/components/tis/ScienceTable.tsx +33 -1
  45. package/src/components/tis/TestDataView.tsx +203 -33
  46. package/src/components/tis/TestFieldRow.tsx +126 -19
  47. package/src/components/tis/TestSetupForm.tsx +35 -7
  48. package/src/components/tis/TisProvider.tsx +46 -3
  49. package/src/components/tis-editor/editor/ChartViewDialog.tsx +27 -0
  50. package/src/components/tis-editor/types.ts +6 -0
  51. package/src/core/AutoCoreTagContext.tsx +165 -16
  52. package/src/core/AutoCoreTagTypes.ts +91 -7
  53. package/src/core/formatScaled.ts +72 -0
  54. package/src/hooks/useAutoCoreTag.ts +51 -3
  55. package/todo.md +6 -0
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useState,useEffect,useContext,useMemo}from"react";import{Button}from"primereact/button";import{InputText}from"primereact/inputtext";import{Dropdown}from"primereact/dropdown";import{Dialog}from"primereact/dialog";import{EventEmitterContext}from"../../core/EventEmitterContext";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";import{MessageType}from"../../hub/CommandMessage";import{TextInput}from"../TextInput";import{useTis}from"./TisProvider";import{useAmsAssets,useAmsRoles}from"../ams/AmsProvider";import{TestMethodDialog}from"./TestMethodDialog";import{ConfigurationDialog,configLabelOf}from"./ConfigurationDialog";import{TestFieldRow,displayToRaw,fieldIsValid,fieldIssue,labelOf}from"./TestFieldRow";const DEFAULT_TOKEN_RE=/^\$\{\s*([^}]+?)\s*\}$/,resolveDefaultRaw=(e,t,s)=>{const o=e.default;if("string"==typeof o){const e=o.match(DEFAULT_TOKEN_RE);if(e){const o=t(e[1]),i=o?s[o.tagName]:void 0;return null==i?{raw:void 0,ok:!1}:{raw:i,ok:!0}}}return{raw:displayToRaw(o,e.scale),ok:!0}},methodLabelOf=(e,t)=>t?.label&&t.label.length>0?t.label:e,AssetIdPicker=({assetType:e,value:t,onChange:s,invalid:o})=>{const i=useAmsAssets(),a=useAmsRoles(),n=useMemo(()=>i.filter(t=>t.asset_type===e&&"active"===t.status).map(e=>{const t=a[e.asset_type]?.find(t=>t.location===e.location)?.label,s=[e.asset_id];return t?s.push(`— ${t}`):e.location&&s.push(`— ${e.location}`),e.serial&&s.push(`(s/n ${e.serial})`),{label:s.join(" "),value:e.asset_id}}),[i,a,e]);return _jsx(Dropdown,{value:t,options:n,onChange:e=>s(e.value??""),placeholder:0===n.length?`No active ${e} assets registered — add one in Settings → Assets`:`Select ${e}…`,className:"ac-dropdown-clearable"+(o?" p-invalid":""),filter:!0,showClear:!0,disabled:0===n.length})};export const TestSetupForm=({schema:e,defaultMethodId:t,onMethodChange:s,onValidationChange:o})=>{const i=useTis(),{invoke:a,write:n}=useContext(EventEmitterContext),{rawValues:r,findTagByFqdn:l}=useContext(AutoCoreTagContext),c=useMemo(()=>Object.keys(i.schemas),[i.schemas]),d=i.selection.projectId,m=""!==d.trim()&&i.projectKnown(d.trim()),[f,p]=useState(i.selection.methodId||t||i.defaultMethodId||""),[u,h]=useState(i.selection.sampleId||""),g=i.stagedConfig,_=e=>{const t="function"==typeof e?e(i.stagedConfig):e;t!==i.stagedConfig&&i.setStagedConfig(t)},x=e??(f?i.schemas[f]:void 0),j=(e,t)=>{for(const[s,o]of Object.entries(e.defaults??{})){if("sample_id"===s)continue;const e=x?.config_fields.find(e=>e.name===s),i=displayToRaw(o,e?.scale);t[s]=i,e?.source&&Promise.resolve().then(()=>n(e.source,i)).catch(e=>{})}return t};useEffect(()=>{i.selection.methodId!==f&&f&&i.setSelection({methodId:f}),s&&s(f)},[f]),useEffect(()=>{i.selection.sampleId!==u&&i.setSelection({sampleId:u})},[u]),useEffect(()=>{i.state.stagedSampleId&&i.state.stagedSampleId!==u&&h(i.state.stagedSampleId)},[i.state.stagedSampleId]),useEffect(()=>{i.selection.methodId&&i.selection.methodId!==f&&p(i.selection.methodId)},[i.selection.methodId]);const[y,v]=useState(!1),[b,T]=useState(!1),[C,I]=useState(!1),N=x?.configurations??[],S=N.find(e=>e.name===i.configurationName),[w,k]=useState({open:!1,title:"",body:null});useEffect(()=>{if(!x||!f)return;if(i.defaultsAppliedForMethod===f)return;i.markDefaultsAppliedForMethod(f);const e=x.configurations&&x.configurations.length>0?x.configurations[0]:void 0;_(t=>{let s=t;for(const e of x.config_fields){if("sample_id"===e.name)continue;if(void 0===e.default||null===e.default)continue;if(e.source){const t=l(e.source),s=t?r[t.tagName]:void 0;if(null!=s)continue}const{raw:o,ok:i}=resolveDefaultRaw(e,l,r);i&&(s===t&&(s={...t}),s[e.name]=o,e.source&&Promise.resolve().then(()=>n(e.source,o)).catch(e=>{}))}return e&&(s===t&&(s={...t}),s=j(e,s)),s}),i.setConfigurationName(e?e.name:"")},[x,f,n,r,l,i.defaultsAppliedForMethod,i.markDefaultsAppliedForMethod,i.setConfigurationName]),useEffect(()=>{x&&_(e=>{let t=e;for(const s of x.config_fields){if("sample_id"===s.name)continue;if(!s.source)continue;const o=l(s.source);if(!o)continue;const i=r[o.tagName];null!=i&&(t[s.name]!==i&&(t===e&&(t={...e}),t[s.name]=i))}return t})},[x,r,l]),useEffect(()=>{if(!x)return void v(!1);let e=!0;m||(e=!1),f.trim()||(e=!1),u.trim()||(e=!1),e&&!i.projectFieldsLoaded&&(e=!1);for(const t of x.config_fields)if("sample_id"!==t.name&&fieldIssue(t,g[t.name])){e=!1;break}if(v(e),o&&o(e,g),e){const{sample_id:e,...t}=g??{},s={...i.projectFields,...t};a("tis.stage_test",MessageType.Request,{project_id:d,method_id:f,sample_id:u,config:s}).catch(e=>{})}},[g,x,d,f,u,m,i.projectFields,i.projectFieldsLoaded,o,a]);const E=async(e,t)=>{if(_({...g,[e.name]:t}),e.source)try{await n(e.source,t)}catch(e){}};if(!x)return _jsx("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:_jsx("h3",{className:"ac-form-section",children:i.schemasLoaded?"No Test Method Selected":"Loading test methods…"})});if(!m)return _jsxs("div",{style:{padding:"1.25rem",maxWidth:"600px"},children:[_jsx("h3",{className:"ac-form-section",children:"No project selected"}),_jsxs("p",{style:{color:"var(--text-secondary-color)",marginTop:"0.5rem"},children:["Pick a project on the ",_jsx("strong",{children:"Project"})," tab first",""!==d.trim()&&` (or click + there to create "${d.trim()}")`,"."]})]});const F={padding:"1.25rem",gridTemplateColumns:"auto 1fr 1.75rem 1.75rem"},A=y&&!i.state.lastStartError;return _jsxs("div",{className:"ac-test-setup-form",children:[_jsxs("div",{className:"ac-form-grid ac-test-setup-form__head",style:F,children:[_jsxs("h3",{className:"ac-form-section",style:{display:"flex",alignItems:"center",gap:"10px"},children:["Test Setup",_jsx(Button,{icon:A?"pi pi-check-circle":"pi pi-exclamation-circle",severity:A?"success":"danger",text:!0,rounded:!0,"aria-label":"Test Setup status",onClick:()=>{const e=(()=>{const e=[];if(m||e.push("No project is selected. Pick or create one on the Project tab."),i.projectFieldsLoaded||e.push("Project fields are still loading."),f.trim()||e.push("No test method selected."),u.trim()||e.push("Sample ID is required."),x)for(const t of x.config_fields){if("sample_id"===t.name)continue;const s=fieldIssue(t,g[t.name]);s&&e.push(`"${labelOf(t)}" ${s}.`)}return e})(),t=i.state.lastStartError?.trim()??"";let s;s=0!==e.length||t?_jsxs("div",{children:[e.length>0&&_jsxs(_Fragment,{children:[_jsx("p",{style:{margin:"0 0 0.5rem 0"},children:"The form is incomplete:"}),_jsx("ul",{style:{margin:"0 0 1rem 1.25rem"},children:e.map((e,t)=>_jsx("li",{children:e},t))})]}),t&&_jsxs(_Fragment,{children:[_jsx("p",{style:{margin:"0 0 0.25rem 0",fontWeight:600},children:"Last start_test error from the server:"}),_jsx("pre",{style:{margin:0,padding:"0.5rem",background:"rgba(0,0,0,0.25)",borderRadius:"4px",whiteSpace:"pre-wrap",fontSize:"0.875rem"},children:t})]})]}):_jsx("p",{style:{margin:0},children:"All required fields are complete. The test is staged and ready to start."}),k({open:!0,title:"Test Setup Status",body:s})}}),_jsxs("span",{style:{fontSize:"0.85em",color:"var(--text-secondary-color)",fontWeight:"normal",marginLeft:"0.25rem"},children:["project: ",_jsx("strong",{children:d})]})]}),_jsx("span",{className:"ac-form-label",children:"Sample ID"}),_jsx(TextInput,{label:void 0,value:u,onValueChanged:e=>{h(e)},className:u.trim()?"":"p-invalid"}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:u.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:u.trim()?"pi pi-check":"pi pi-times"})}),c.length>0&&_jsxs(_Fragment,{children:[_jsx("span",{className:"ac-form-label",children:"Test Method"}),_jsxs("div",{className:"p-inputgroup",style:{flex:1},children:[_jsx(InputText,{value:methodLabelOf(f,x),readOnly:!0,style:{flex:1},tabIndex:-1}),_jsx(Button,{icon:"pi pi-folder",label:c.length>1?"Change":"Details",type:"button",onClick:()=>T(!0)})]}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:f?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:f?"pi pi-check":"pi pi-times"})})]}),N.length>0&&_jsxs(_Fragment,{children:[_jsx("span",{className:"ac-form-label",children:"Configuration"}),_jsxs("div",{className:"p-inputgroup",style:{flex:1},children:[_jsx(InputText,{value:S?configLabelOf(S):"",placeholder:"No configuration selected",readOnly:!0,style:{flex:1},tabIndex:-1}),_jsx(Button,{icon:"pi pi-folder",label:"Change",type:"button",onClick:()=>I(!0)})]}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:S?"var(--green-500)":"var(--text-secondary-color)",display:"flex",alignItems:"center"},children:_jsx("i",{className:S?"pi pi-check":"pi pi-minus"})})]})]}),_jsx("div",{className:"ac-test-setup-form__body",children:_jsxs("div",{className:"ac-form-grid",style:F,children:[_jsx("h3",{className:"ac-form-section",children:"Test Configuration"}),x.config_fields.map(e=>{if("sample_id"===e.name)return null;const t=(e=>fieldIsValid(e,g[e.name]))(e),s=(e=>{const t=x?.asset_refs??[],s=i.projectAssetRefs??[],o=`config.${e.name}`,a=t.find(e=>"by_id_field"===e.select&&e.from===o);if(a)return a.asset_type;const n=s.find(e=>"by_id_field"===e.select&&e.from===o);return n?n.asset_type:null})(e);return _jsx(TestFieldRow,{field:e,value:g[e.name],valid:t,onChange:t=>E(e,t),onInfo:e=>k({open:!0,title:labelOf(e),body:_jsx("p",{style:{margin:0,whiteSpace:"pre-wrap"},children:e.description})}),control:s?_jsx(AssetIdPicker,{assetType:s,value:null!=g[e.name]?String(g[e.name]):"",onChange:t=>E(e,t),invalid:!t}):void 0},e.name)})]})}),_jsx(TestMethodDialog,{visible:b,onHide:()=>T(!1),currentMethodId:f,onSelected:e=>p(e)}),_jsx(ConfigurationDialog,{visible:C,onHide:()=>I(!1),configurations:N,currentConfigName:i.configurationName,onSelected:e=>{const t=N.find(t=>t.name===e);t&&(_(e=>j(t,{...e})),i.setConfigurationName(e))}}),_jsx(Dialog,{header:w.title,visible:w.open,onHide:()=>k({open:!1,title:"",body:null}),style:{width:"32rem",maxWidth:"90vw"},modal:!0,dismissableMask:!0,children:w.body})]})};
1
+ import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useState,useEffect,useContext,useMemo}from"react";import{Button}from"primereact/button";import{InputText}from"primereact/inputtext";import{Dropdown}from"primereact/dropdown";import{Dialog}from"primereact/dialog";import{EventEmitterContext}from"../../core/EventEmitterContext";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";import{MessageType}from"../../hub/CommandMessage";import{TextInput}from"../TextInput";import{useTis}from"./TisProvider";import{useAmsAssets,useAmsRoles}from"../ams/AmsProvider";import{TestMethodDialog}from"./TestMethodDialog";import{ConfigurationDialog,configLabelOf}from"./ConfigurationDialog";import{TestFieldRow,displayToRaw,effectiveField,fieldIsValid,fieldIssue,labelOf}from"./TestFieldRow";const DEFAULT_TOKEN_RE=/^\$\{\s*([^}]+?)\s*\}$/,resolveDefaultRaw=(e,t,s)=>{const i=e.default;if("string"==typeof i){const e=i.match(DEFAULT_TOKEN_RE);if(e){const i=t(e[1]),o=i?s[i.tagName]:void 0;return null==o?{raw:void 0,ok:!1}:{raw:o,ok:!0}}}return{raw:displayToRaw(i,e.scale),ok:!0}},methodLabelOf=(e,t)=>t?.label&&t.label.length>0?t.label:e,AssetIdPicker=({assetType:e,value:t,onChange:s,invalid:i})=>{const o=useAmsAssets(),a=useAmsRoles(),n=useMemo(()=>o.filter(t=>t.asset_type===e&&"active"===t.status).map(e=>{const t=a[e.asset_type]?.find(t=>t.location===e.location)?.label,s=[e.asset_id];return t?s.push(`— ${t}`):e.location&&s.push(`— ${e.location}`),e.serial&&s.push(`(s/n ${e.serial})`),{label:s.join(" "),value:e.asset_id}}),[o,a,e]);return _jsx(Dropdown,{value:t,options:n,onChange:e=>s(e.value??""),placeholder:0===n.length?`No active ${e} assets registered — add one in Settings → Assets`:`Select ${e}…`,className:"ac-dropdown-clearable"+(i?" p-invalid":""),filter:!0,showClear:!0,disabled:0===n.length})};export const TestSetupForm=({schema:e,defaultMethodId:t,onMethodChange:s,onValidationChange:i})=>{const o=useTis(),{invoke:a,write:n}=useContext(EventEmitterContext),{rawValues:r,findTagByFqdn:l,scales:c}=useContext(AutoCoreTagContext),d=useMemo(()=>Object.keys(o.schemas),[o.schemas]),m=o.selection.projectId,f=""!==m.trim()&&o.projectKnown(m.trim()),[p,u]=useState(o.selection.methodId||t||o.defaultMethodId||""),[h,g]=useState(o.selection.sampleId||""),_=o.stagedConfig,x=e=>{const t="function"==typeof e?e(o.stagedConfig):e;t!==o.stagedConfig&&o.setStagedConfig(t)},j=e??(p?o.schemas[p]:void 0),v=(e,t)=>{for(const[s,i]of Object.entries(e.defaults??{})){if("sample_id"===s)continue;const e=j?.config_fields.find(e=>e.name===s),o=e?effectiveField(e,c,{findTagByFqdn:l,rawValues:r}):void 0,a=displayToRaw(i,o?.scale,o?.unitOffset??0);t[s]=a,o?.source&&Promise.resolve().then(()=>n(o.source,a)).catch(e=>{})}return t};useEffect(()=>{o.selection.methodId!==p&&p&&o.setSelection({methodId:p}),s&&s(p)},[p]),useEffect(()=>{o.selection.sampleId!==h&&o.setSelection({sampleId:h})},[h]),useEffect(()=>{o.state.stagedSampleId&&o.state.stagedSampleId!==h&&g(o.state.stagedSampleId)},[o.state.stagedSampleId]),useEffect(()=>{o.selection.methodId&&o.selection.methodId!==p&&u(o.selection.methodId)},[o.selection.methodId]);const[y,b]=useState(!1),[T,C]=useState(!1),[I,N]=useState(!1),S=j?.configurations??[],w=S.find(e=>e.name===o.configurationName),[F,k]=useState({open:!1,title:"",body:null});useEffect(()=>{if(!j||!p)return;if(o.defaultsAppliedForMethod===p)return;o.markDefaultsAppliedForMethod(p);const e=j.configurations&&j.configurations.length>0?j.configurations[0]:void 0;x(t=>{let s=t;for(const e of j.config_fields){if("sample_id"===e.name)continue;if(void 0===e.default||null===e.default)continue;if(e.source){const t=l(e.source),s=t?r[t.tagName]:void 0;if(null!=s)continue}const{raw:i,ok:o}=resolveDefaultRaw(e,l,r);o&&(s===t&&(s={...t}),s[e.name]=i,e.source&&Promise.resolve().then(()=>n(e.source,i)).catch(e=>{}))}return e&&(s===t&&(s={...t}),s=v(e,s)),s}),o.setConfigurationName(e?e.name:"")},[j,p,n,r,l,o.defaultsAppliedForMethod,o.markDefaultsAppliedForMethod,o.setConfigurationName]),useEffect(()=>{j&&x(e=>{let t=e;for(const s of j.config_fields){if("sample_id"===s.name)continue;if(!s.source)continue;const i=l(s.source);if(!i)continue;const o=r[i.tagName];null!=o&&(t[s.name]!==o&&(t===e&&(t={...e}),t[s.name]=o))}return t})},[j,r,l]),useEffect(()=>{if(!j)return void b(!1);let e=!0;f||(e=!1),p.trim()||(e=!1),h.trim()||(e=!1),e&&!o.projectFieldsLoaded&&(e=!1);for(const t of j.config_fields)if("sample_id"!==t.name&&fieldIssue(E(t),_[t.name])){e=!1;break}if(b(e),i&&i(e,_),e){const{sample_id:e,...t}=_??{},s={...o.projectFields,...t};a("tis.stage_test",MessageType.Request,{project_id:m,method_id:p,sample_id:h,config:s}).catch(e=>{})}},[_,j,m,p,h,f,o.projectFields,o.projectFieldsLoaded,i,a]);const E=e=>effectiveField(e,c,{findTagByFqdn:l,rawValues:r}),A=async(e,t)=>{if(x({..._,[e.name]:t}),e.source)try{await n(e.source,t)}catch(e){}};if(!j)return _jsx("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:_jsx("h3",{className:"ac-form-section",children:o.schemasLoaded?"No Test Method Selected":"Loading test methods…"})});if(!f)return _jsxs("div",{style:{padding:"1.25rem",maxWidth:"600px"},children:[_jsx("h3",{className:"ac-form-section",children:"No project selected"}),_jsxs("p",{style:{color:"var(--text-secondary-color)",marginTop:"0.5rem"},children:["Pick a project on the ",_jsx("strong",{children:"Project"})," tab first",""!==m.trim()&&` (or click + there to create "${m.trim()}")`,"."]})]});const M={padding:"1.25rem",gridTemplateColumns:"auto 1fr 1.75rem 1.75rem"},D=y&&!o.state.lastStartError;return _jsxs("div",{className:"ac-test-setup-form",children:[_jsxs("div",{className:"ac-form-grid ac-test-setup-form__head",style:M,children:[_jsxs("h3",{className:"ac-form-section",style:{display:"flex",alignItems:"center",gap:"10px"},children:["Test Setup",_jsx(Button,{icon:D?"pi pi-check-circle":"pi pi-exclamation-circle",severity:D?"success":"danger",text:!0,rounded:!0,"aria-label":"Test Setup status",onClick:()=>{const e=(()=>{const e=[];if(f||e.push("No project is selected. Pick or create one on the Project tab."),o.projectFieldsLoaded||e.push("Project fields are still loading."),p.trim()||e.push("No test method selected."),h.trim()||e.push("Sample ID is required."),j)for(const t of j.config_fields){if("sample_id"===t.name)continue;const s=fieldIssue(E(t),_[t.name]);s&&e.push(`"${labelOf(E(t))}" ${s}.`)}return e})(),t=o.state.lastStartError?.trim()??"";let s;s=0!==e.length||t?_jsxs("div",{children:[e.length>0&&_jsxs(_Fragment,{children:[_jsx("p",{style:{margin:"0 0 0.5rem 0"},children:"The form is incomplete:"}),_jsx("ul",{style:{margin:"0 0 1rem 1.25rem"},children:e.map((e,t)=>_jsx("li",{children:e},t))})]}),t&&_jsxs(_Fragment,{children:[_jsx("p",{style:{margin:"0 0 0.25rem 0",fontWeight:600},children:"Last start_test error from the server:"}),_jsx("pre",{style:{margin:0,padding:"0.5rem",background:"rgba(0,0,0,0.25)",borderRadius:"4px",whiteSpace:"pre-wrap",fontSize:"0.875rem"},children:t})]})]}):_jsx("p",{style:{margin:0},children:"All required fields are complete. The test is staged and ready to start."}),k({open:!0,title:"Test Setup Status",body:s})}}),_jsxs("span",{style:{fontSize:"0.85em",color:"var(--text-secondary-color)",fontWeight:"normal",marginLeft:"0.25rem"},children:["project: ",_jsx("strong",{children:m})]})]}),_jsx("span",{className:"ac-form-label",children:"Sample ID"}),_jsx(TextInput,{label:void 0,value:h,onValueChanged:e=>{g(e)},className:h.trim()?"":"p-invalid"}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:h.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:h.trim()?"pi pi-check":"pi pi-times"})}),d.length>0&&_jsxs(_Fragment,{children:[_jsx("span",{className:"ac-form-label",children:"Test Method"}),_jsxs("div",{className:"p-inputgroup",style:{flex:1},children:[_jsx(InputText,{value:methodLabelOf(p,j),readOnly:!0,style:{flex:1},tabIndex:-1}),_jsx(Button,{icon:"pi pi-folder",label:d.length>1?"Change":"Details",type:"button",onClick:()=>C(!0)})]}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:p?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:p?"pi pi-check":"pi pi-times"})})]}),S.length>0&&_jsxs(_Fragment,{children:[_jsx("span",{className:"ac-form-label",children:"Configuration"}),_jsxs("div",{className:"p-inputgroup",style:{flex:1},children:[_jsx(InputText,{value:w?configLabelOf(w):"",placeholder:"No configuration selected",readOnly:!0,style:{flex:1},tabIndex:-1}),_jsx(Button,{icon:"pi pi-folder",label:"Change",type:"button",onClick:()=>N(!0)})]}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:w?"var(--green-500)":"var(--text-secondary-color)",display:"flex",alignItems:"center"},children:_jsx("i",{className:w?"pi pi-check":"pi pi-minus"})})]})]}),_jsx("div",{className:"ac-test-setup-form__body",children:_jsxs("div",{className:"ac-form-grid",style:M,children:[_jsx("h3",{className:"ac-form-section",children:"Test Configuration"}),j.config_fields.map(e=>{if("sample_id"===e.name)return null;const t=(e=>fieldIsValid(E(e),_[e.name]))(e),s=(e=>{const t=j?.asset_refs??[],s=o.projectAssetRefs??[],i=`config.${e.name}`,a=t.find(e=>"by_id_field"===e.select&&e.from===i);if(a)return a.asset_type;const n=s.find(e=>"by_id_field"===e.select&&e.from===i);return n?n.asset_type:null})(e);return _jsx(TestFieldRow,{field:e,value:_[e.name],valid:t,onChange:t=>A(e,t),onInfo:e=>k({open:!0,title:labelOf(e),body:_jsx("p",{style:{margin:0,whiteSpace:"pre-wrap"},children:e.description})}),control:s?_jsx(AssetIdPicker,{assetType:s,value:null!=_[e.name]?String(_[e.name]):"",onChange:t=>A(e,t),invalid:!t}):void 0},e.name)})]})}),_jsx(TestMethodDialog,{visible:T,onHide:()=>C(!1),currentMethodId:p,onSelected:e=>u(e)}),_jsx(ConfigurationDialog,{visible:I,onHide:()=>N(!1),configurations:S,currentConfigName:o.configurationName,onSelected:e=>{const t=S.find(t=>t.name===e);t&&(x(e=>v(t,{...e})),o.setConfigurationName(e))}}),_jsx(Dialog,{header:F.title,visible:F.open,onHide:()=>k({open:!1,title:"",body:null}),style:{width:"32rem",maxWidth:"90vw"},modal:!0,dismissableMask:!0,children:F.body})]})};
@@ -1 +1 @@
1
- {"version":3,"file":"TisProvider.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TisProvider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TisProvider.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TisProvider.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- import{jsx as _jsx}from"react/jsx-runtime";import React,{createContext,useCallback,useContext,useEffect,useMemo,useReducer,useRef,useState}from"react";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";const EMPTY_STATE={staged:!1,stagedProjectId:"",stagedMethodId:"",stagedSampleId:"",active:!1,activeProjectId:"",activeMethodId:"",activeSampleId:"",activeRunId:"",lastStartError:""},EMPTY_SELECTION={projectId:"",methodId:"",sampleId:"",runId:""},EMPTY_CYCLE_CONFIG={projectId:"",methodId:"",scope:"run",promptBeforeCycle:!1,values:{},latched:null,ready:!0,missing:[],promptDue:!1},cycleConfigFromPayload=e=>({projectId:String(e?.project_id??""),methodId:String(e?.method_id??""),scope:"cycle"===e?.scope?"cycle":"run",promptBeforeCycle:!!e?.prompt_before_cycle,values:e?.values&&"object"==typeof e.values?e.values:{},latched:e?.latched&&"object"==typeof e.latched?e.latched:null,ready:!1!==e?.ready,missing:Array.isArray(e?.missing)?e.missing:[],promptDue:!!e?.prompt_due}),TisContext=createContext({schemas:{},projectAssetRefs:[],defaultMethodId:"",schemasLoaded:!1,state:EMPTY_STATE,selection:EMPTY_SELECTION,setSelection:()=>{},existingProjects:[],projectKnown:()=>!1,refreshProjects:async()=>{},markProjectJustCreated:()=>{},projectFields:{},projectFieldsLoaded:!1,loadProjectFields:async()=>null,setProjectFields:()=>{},stagedConfig:{},setStagedConfig:()=>{},clearStagedConfig:()=>{},defaultsAppliedForMethod:"",markDefaultsAppliedForMethod:()=>{},configurationName:"",setConfigurationName:()=>{},cycleConfig:EMPTY_CYCLE_CONFIG,cycleConfigFields:[],setCycleConfigValues:async()=>{},clearCycleConfig:async()=>{},refreshCycleConfig:async()=>{},fetchRuns:async()=>[],fetchRun:async()=>null,runCache:{}});function liveReducer(e,t){switch(t.kind){case"staged":return{...e,staged:t.value};case"staged_project_id":return{...e,stagedProjectId:t.value};case"staged_method_id":return{...e,stagedMethodId:t.value};case"staged_sample_id":return{...e,stagedSampleId:t.value};case"active":return{...e,active:t.value};case"active_project_id":return{...e,activeProjectId:t.value};case"active_method_id":return{...e,activeMethodId:t.value};case"active_sample_id":return{...e,activeSampleId:t.value};case"active_run_id":return{...e,activeRunId:t.value};case"last_start_error":return{...e,lastStartError:t.value}}}export const TisProvider=({children:e,defaultMethodId:t})=>{const{invoke:s,subscribe:c,unsubscribe:a}=useContext(EventEmitterContext),[r,d]=useState({}),[o,n]=useState([]),[i,u]=useState(t??""),[l,p]=useState(!1),[f,_]=useReducer(liveReducer,EMPTY_STATE),[m,C]=useState({projectId:null,methodId:null,sampleId:null,runId:null}),I=useCallback(async()=>{try{const e=await s("tis.list_schemas",MessageType.Request,{});if(e?.success&&e.data){const s=e.data.test_methods??{},c=e.data.default_method_id??"",a=Array.isArray(e.data.asset_refs)?e.data.asset_refs:[];d(s),n(a),!t&&c&&u(c),p(!0)}}catch(e){}},[s]);useEffect(()=>{I()},[I]),useEffect(()=>{const e=c("tis.schema_changed",()=>{I()});return()=>{a(e)}},[c,a,I]),useEffect(()=>{let e=!1;return(async()=>{try{const t=await s("gnv.ux.selected_project_id",MessageType.Read,{});if(e)return;const c=t?.success?t.data??"":"";"string"==typeof c&&c.length>0&&C(e=>null===e.projectId?{...e,projectId:c}:e)}catch{}})(),()=>{e=!0}},[]),useEffect(()=>{const e=[c("tis.staged",e=>_({kind:"staged",value:!!e})),c("tis.staged_project_id",e=>_({kind:"staged_project_id",value:String(e??"")})),c("tis.staged_method_id",e=>_({kind:"staged_method_id",value:String(e??"")})),c("tis.staged_sample_id",e=>_({kind:"staged_sample_id",value:String(e??"")})),c("tis.active",e=>_({kind:"active",value:!!e})),c("tis.active_project_id",e=>_({kind:"active_project_id",value:String(e??"")})),c("tis.active_method_id",e=>_({kind:"active_method_id",value:String(e??"")})),c("tis.active_sample_id",e=>_({kind:"active_sample_id",value:String(e??"")})),c("tis.active_run_id",e=>_({kind:"active_run_id",value:String(e??"")})),c("tis.last_start_error",e=>_({kind:"last_start_error",value:String(e??"")}))];return()=>{e.forEach(a)}},[c,a]);const h=useRef({}),[y,g]=useState(0),j=useCallback(()=>g(e=>e+1),[]),v=useCallback((e,t)=>{if(!e)return;const s=h.current[e]??{meta:null,cycles:[],results:{},rawData:{}};h.current[e]={...s,cycles:[...s.cycles,t]},j()},[j]),S=useCallback((e,t)=>{if(!e)return;const s=h.current[e]??{meta:null,cycles:[],results:{},rawData:{}};h.current[e]={...s,results:t},j()},[j]);useEffect(()=>{const e=c("tis.cycle_added",e=>{e?.run_id&&e.cycle&&v(e.run_id,e.cycle)}),t=c("tis.results_updated",e=>{e?.run_id&&S(e.run_id,e.results??{})});return()=>{a(e),a(t)}},[c,a,v,S]);const T=useMemo(()=>({projectId:m.projectId??f.activeProjectId,methodId:m.methodId??(f.activeMethodId||i),sampleId:m.sampleId??f.activeSampleId,runId:m.runId??f.activeRunId}),[m,f,i]),E=useCallback(e=>{C(t=>({projectId:void 0===e.projectId?t.projectId:e.projectId,methodId:void 0===e.methodId?t.methodId:e.methodId,sampleId:void 0===e.sampleId?t.sampleId:e.sampleId,runId:void 0===e.runId?t.runId:e.runId})),void 0!==e.projectId&&s("gnv.ux.selected_project_id",MessageType.Write,e.projectId??"").catch(e=>{})},[s]),x=useRef("");useEffect(()=>{const e=f.activeRunId;e&&e!==x.current&&(x.current=e,C({projectId:null,methodId:null,sampleId:null,runId:null}))},[f.activeRunId]);const M=useCallback(async(e,t)=>{if(!e)return[];const c={project_id:e};t&&(c.method_id=t);try{const e=await s("tis.list_tests",MessageType.Request,c);if(e?.success&&e.data?.tests)return e.data.tests}catch(e){}return[]},[s]),k=useCallback(async(e,t,c)=>{if(!e||!t||!c)return null;try{const a=await s("tis.read_test",MessageType.Request,{project_id:e,method_id:t,run_id:c}),r=await s("tis.read_cycles",MessageType.Request,{project_id:e,method_id:t,run_id:c,offset:0,limit:1e3,order:"asc"});if(!a?.success)return null;const d={meta:a.data??null,cycles:r?.success?r.data?.cycles??[]:[],results:a.data?.results??{},rawData:h.current[c]?.rawData??{}};return h.current[c]=d,j(),d}catch(e){return null}},[s,j]),R=useMemo(()=>({...h.current}),[y]),[P,b]=useState([]),F=useRef(new Set),[w,Y]=useState(0),[A,L]=useState({}),N=useCallback(async()=>{try{const e=await s("tis.list_projects",MessageType.Request,{});e?.success&&e.data?.projects&&b(e.data.projects)}catch(e){}},[s]),D=useCallback(e=>{e&&(F.current.has(e)||(F.current.add(e),Y(e=>e+1)))},[]),q=useCallback(e=>!!e&&(!!F.current.has(e)||P.includes(e)),[P,w]),O=useCallback((e,t)=>{e&&L(s=>({...s,[e]:t}))},[]),G=useCallback(async e=>{if(!e)return null;try{const t=await s("tis.read_project",MessageType.Request,{project_id:e});if(t?.success){const s=t.data?.project_fields??{};return L(t=>({...t,[e]:s})),s}}catch(e){}return L(t=>({...t,[e]:{}})),{}},[s]);useEffect(()=>{N()},[N]),useEffect(()=>{const e=c("tis.project_created",()=>{N()}),t=c("tis.project_updated",e=>{const t="string"==typeof e?.project_id?e.project_id:"";t&&G(t)});return()=>{a(e),a(t)}},[c,a,N,G]),useEffect(()=>{const e=T.projectId;e&&q(e)&&void 0===A[e]&&G(e)},[T.projectId,q,A,G]);const V=A[T.projectId]??{},B=void 0!==A[T.projectId],[J,K]=useState({}),W=useCallback(e=>{K(t=>({...t,...e}))},[]),[z,H]=useState(""),Q=useCallback(e=>{H(e)},[]),[U,X]=useState(""),Z=useCallback(()=>{K({}),H(""),X("")},[]),[$,ee]=useState(EMPTY_CYCLE_CONFIG),te=useMemo(()=>{const e=T.methodId?r[T.methodId]?.cycle_config_fields:void 0;return Array.isArray(e)?e:[]},[r,T.methodId]),se=useCallback(async()=>{const e=T.projectId,t=T.methodId;if(t)try{const c=await s("tis.cycle_config",MessageType.Request,{project_id:e,method_id:t});if(c?.success)return void ee(cycleConfigFromPayload(c.data));ee(EMPTY_CYCLE_CONFIG)}catch(e){ee(EMPTY_CYCLE_CONFIG)}else ee(EMPTY_CYCLE_CONFIG)},[s,T.projectId,T.methodId]),ce=useCallback(async e=>{const t=T.projectId,c=T.methodId;if(c)try{const a=await s("tis.set_cycle_config",MessageType.Request,{project_id:t,method_id:c,values:e});a?.success&&ee(cycleConfigFromPayload(a.data))}catch(e){}},[s,T.projectId,T.methodId]),ae=useCallback(async()=>{const e=T.projectId,t=T.methodId;if(t)try{const c=await s("tis.clear_cycle_config",MessageType.Request,{project_id:e,method_id:t});c?.success&&ee(cycleConfigFromPayload(c.data))}catch(e){}},[s,T.projectId,T.methodId]);useEffect(()=>{se()},[se]),useEffect(()=>{const e=c("tis.schema_changed",()=>{se()});return()=>{a(e)}},[c,a,se]),useEffect(()=>{const e=c("tis.cycle_config",e=>{const t=String(e?.method_id??"");t&&T.methodId&&t!==T.methodId||ee(cycleConfigFromPayload(e))});return()=>{a(e)}},[c,a,T.methodId]);const re=useMemo(()=>({schemas:r,projectAssetRefs:o,defaultMethodId:i,schemasLoaded:l,state:f,selection:T,setSelection:E,existingProjects:P,projectKnown:q,refreshProjects:N,markProjectJustCreated:D,projectFields:V,projectFieldsLoaded:B,loadProjectFields:G,setProjectFields:O,stagedConfig:J,setStagedConfig:W,clearStagedConfig:Z,defaultsAppliedForMethod:z,markDefaultsAppliedForMethod:Q,configurationName:U,setConfigurationName:X,cycleConfig:$,cycleConfigFields:te,setCycleConfigValues:ce,clearCycleConfig:ae,refreshCycleConfig:se,fetchRuns:M,fetchRun:k,runCache:R}),[r,o,i,l,f,T,E,P,q,N,D,V,B,G,O,J,W,Z,z,Q,U,X,$,te,ce,ae,se,M,k,R]);return _jsx(TisContext.Provider,{value:re,children:e})};export const useTis=()=>useContext(TisContext);export const useTisSchemas=()=>useContext(TisContext).schemas;export const useTisState=()=>useContext(TisContext).state;export const useTisCycleConfig=()=>{const{cycleConfig:e,cycleConfigFields:t,setCycleConfigValues:s,clearCycleConfig:c}=useContext(TisContext);return{...e,fields:t,setValues:s,clear:c}};export const useTisSelection=()=>{const{selection:e,setSelection:t}=useContext(TisContext);return[e,t]};export const useTisRuns=(e,t)=>{const{fetchRuns:s}=useContext(TisContext),[c,a]=useState([]),[r,d]=useState(!1),o=useCallback(async()=>{if(e){d(!0);try{a(await s(e,t))}finally{d(!1)}}else a([])},[e,t,s]);return useEffect(()=>{o()},[o]),{runs:c,loading:r,refresh:o}};export const useTisRun=e=>{const{selection:t,fetchRun:s,runCache:c}=useContext(TisContext),[a,r]=useState(!1),d=e??t.runId;useEffect(()=>{if(!d)return;if(c[d]?.meta)return;const e=t.projectId,a=t.methodId;e&&a&&(r(!0),s(e,a,d).finally(()=>r(!1)))},[d,t.projectId,t.methodId,s,c]);const o=d?c[d]:null;return{meta:o?.meta??null,cycles:o?.cycles??[],results:o?.results??{},rawData:o?.rawData??{},loading:a}};export{TisContext};
1
+ import{jsx as _jsx}from"react/jsx-runtime";import React,{createContext,useCallback,useContext,useEffect,useMemo,useReducer,useRef,useState}from"react";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";const EMPTY_STATE={staged:!1,stagedProjectId:"",stagedMethodId:"",stagedSampleId:"",active:!1,activeProjectId:"",activeMethodId:"",activeSampleId:"",activeRunId:"",lastStartError:""},EMPTY_SELECTION={projectId:"",methodId:"",sampleId:"",runId:""},EMPTY_CYCLE_CONFIG={projectId:"",methodId:"",scope:"run",promptBeforeCycle:!1,values:{},latched:null,ready:!0,missing:[],promptDue:!1},cycleConfigFromPayload=e=>({projectId:String(e?.project_id??""),methodId:String(e?.method_id??""),scope:"cycle"===e?.scope?"cycle":"run",promptBeforeCycle:!!e?.prompt_before_cycle,values:e?.values&&"object"==typeof e.values?e.values:{},latched:e?.latched&&"object"==typeof e.latched?e.latched:null,ready:!1!==e?.ready,missing:Array.isArray(e?.missing)?e.missing:[],promptDue:!!e?.prompt_due}),TisContext=createContext({schemas:{},projectAssetRefs:[],defaultMethodId:"",schemasLoaded:!1,state:EMPTY_STATE,selection:EMPTY_SELECTION,setSelection:()=>{},existingProjects:[],projectKnown:()=>!1,refreshProjects:async()=>{},markProjectJustCreated:()=>{},projectFields:{},projectFieldsLoaded:!1,loadProjectFields:async()=>null,setProjectFields:()=>{},stagedConfig:{},setStagedConfig:()=>{},clearStagedConfig:()=>{},defaultsAppliedForMethod:"",markDefaultsAppliedForMethod:()=>{},configurationName:"",setConfigurationName:()=>{},cycleConfig:EMPTY_CYCLE_CONFIG,cycleConfigFields:[],setCycleConfigValues:async()=>{},clearCycleConfig:async()=>{},refreshCycleConfig:async()=>{},fetchRuns:async()=>[],fetchRun:async()=>null,runCache:{}});function liveReducer(e,t){switch(t.kind){case"staged":return{...e,staged:t.value};case"staged_project_id":return{...e,stagedProjectId:t.value};case"staged_method_id":return{...e,stagedMethodId:t.value};case"staged_sample_id":return{...e,stagedSampleId:t.value};case"active":return{...e,active:t.value};case"active_project_id":return{...e,activeProjectId:t.value};case"active_method_id":return{...e,activeMethodId:t.value};case"active_sample_id":return{...e,activeSampleId:t.value};case"active_run_id":return{...e,activeRunId:t.value};case"last_start_error":return{...e,lastStartError:t.value}}}export const TisProvider=({children:e,defaultMethodId:t})=>{const{invoke:s,read:c,subscribe:a,unsubscribe:d,isConnected:r}=useContext(EventEmitterContext),[o,i]=useState({}),[n,u]=useState([]),[l,_]=useState(t??""),[f,p]=useState(!1),[m,g]=useReducer(liveReducer,EMPTY_STATE),[C,h]=useState({projectId:null,methodId:null,sampleId:null,runId:null}),y=useCallback(async()=>{try{const e=await s("tis.list_schemas",MessageType.Request,{});if(e?.success&&e.data){const s=e.data.test_methods??{},c=e.data.default_method_id??"",a=Array.isArray(e.data.asset_refs)?e.data.asset_refs:[];i(s),u(a),!t&&c&&_(c),p(!0)}}catch(e){}},[s]);useEffect(()=>{y()},[y]),useEffect(()=>{const e=a("tis.schema_changed",()=>{y()});return()=>{d(e)}},[a,d,y]),useEffect(()=>{let e=!1;return(async()=>{try{const t=await s("gnv.ux.selected_project_id",MessageType.Read,{});if(e)return;const c=t?.success?t.data??"":"";"string"==typeof c&&c.length>0&&h(e=>null===e.projectId?{...e,projectId:c}:e)}catch{}})(),()=>{e=!0}},[]),useEffect(()=>{const e=[a("tis.staged",e=>g({kind:"staged",value:!!e})),a("tis.staged_project_id",e=>g({kind:"staged_project_id",value:String(e??"")})),a("tis.staged_method_id",e=>g({kind:"staged_method_id",value:String(e??"")})),a("tis.staged_sample_id",e=>g({kind:"staged_sample_id",value:String(e??"")})),a("tis.active",e=>g({kind:"active",value:!!e})),a("tis.active_project_id",e=>g({kind:"active_project_id",value:String(e??"")})),a("tis.active_method_id",e=>g({kind:"active_method_id",value:String(e??"")})),a("tis.active_sample_id",e=>g({kind:"active_sample_id",value:String(e??"")})),a("tis.active_run_id",e=>g({kind:"active_run_id",value:String(e??"")})),a("tis.last_start_error",e=>g({kind:"last_start_error",value:String(e??"")}))],t=[{fqdn:"gm.tis_staged",kind:"staged",bool:!0},{fqdn:"gm.tis_staged_project_id",kind:"staged_project_id"},{fqdn:"gm.tis_staged_method_id",kind:"staged_method_id"},{fqdn:"gm.tis_staged_sample_id",kind:"staged_sample_id"},{fqdn:"gm.tis_active",kind:"active",bool:!0},{fqdn:"gm.tis_active_project_id",kind:"active_project_id"},{fqdn:"gm.tis_active_method_id",kind:"active_method_id"},{fqdn:"gm.tis_active_sample_id",kind:"active_sample_id"},{fqdn:"gm.tis_active_run_id",kind:"active_run_id"}];let s=!1;return(async()=>{if(r)for(const{fqdn:e,kind:a,bool:d}of t)try{const t=await c(e);if(s)return;if(t&&!1===t.success)continue;const r=t?.data;if(null==r)continue;g({kind:a,value:d?!!r:String(r)})}catch{}})(),()=>{s=!0,e.forEach(d)}},[a,d,c,r]);const I=useRef({}),[v,j]=useState(0),S=useCallback(()=>j(e=>e+1),[]),T=useCallback((e,t)=>{if(!e)return;const s=I.current[e]??{meta:null,cycles:[],results:{},rawData:{}};I.current[e]={...s,cycles:[...s.cycles,t]},S()},[S]),E=useCallback((e,t)=>{if(!e)return;const s=I.current[e]??{meta:null,cycles:[],results:{},rawData:{}};I.current[e]={...s,results:t},S()},[S]);useEffect(()=>{const e=a("tis.cycle_added",e=>{e?.run_id&&e.cycle&&T(e.run_id,e.cycle)}),t=a("tis.results_updated",e=>{e?.run_id&&E(e.run_id,e.results??{})});return()=>{d(e),d(t)}},[a,d,T,E]);const k=useMemo(()=>({projectId:C.projectId??m.activeProjectId,methodId:C.methodId??(m.activeMethodId||l),sampleId:C.sampleId??m.activeSampleId,runId:C.runId??m.activeRunId}),[C,m,l]),x=useCallback(e=>{h(t=>({projectId:void 0===e.projectId?t.projectId:e.projectId,methodId:void 0===e.methodId?t.methodId:e.methodId,sampleId:void 0===e.sampleId?t.sampleId:e.sampleId,runId:void 0===e.runId?t.runId:e.runId})),void 0!==e.projectId&&s("gnv.ux.selected_project_id",MessageType.Write,e.projectId??"").catch(e=>{})},[s]),M=useRef("");useEffect(()=>{const e=m.activeRunId;e&&e!==M.current&&(M.current=e,h({projectId:null,methodId:null,sampleId:null,runId:null}))},[m.activeRunId]);const R=useCallback(async(e,t)=>{if(!e)return[];const c={project_id:e};t&&(c.method_id=t);try{const e=await s("tis.list_tests",MessageType.Request,c);if(e?.success&&e.data?.tests)return e.data.tests}catch(e){}return[]},[s]),P=useCallback(async(e,t,c)=>{if(!e||!t||!c)return null;try{const a=await s("tis.read_test",MessageType.Request,{project_id:e,method_id:t,run_id:c}),d=await s("tis.read_cycles",MessageType.Request,{project_id:e,method_id:t,run_id:c,offset:0,limit:1e3,order:"asc"});if(!a?.success)return null;const r={meta:a.data??null,cycles:d?.success?d.data?.cycles??[]:[],results:a.data?.results??{},rawData:I.current[c]?.rawData??{}};return I.current[c]=r,S(),r}catch(e){return null}},[s,S]),b=useMemo(()=>({...I.current}),[v]),[F,w]=useState([]),q=useRef(new Set),[Y,A]=useState(0),[L,N]=useState({}),D=useCallback(async()=>{try{const e=await s("tis.list_projects",MessageType.Request,{});e?.success&&e.data?.projects&&w(e.data.projects)}catch(e){}},[s]),O=useCallback(e=>{e&&(q.current.has(e)||(q.current.add(e),A(e=>e+1)))},[]),G=useCallback(e=>!!e&&(!!q.current.has(e)||F.includes(e)),[F,Y]),V=useCallback((e,t)=>{e&&N(s=>({...s,[e]:t}))},[]),B=useCallback(async e=>{if(!e)return null;try{const t=await s("tis.read_project",MessageType.Request,{project_id:e});if(t?.success){const s=t.data?.project_fields??{};return N(t=>({...t,[e]:s})),s}}catch(e){}return N(t=>({...t,[e]:{}})),{}},[s]);useEffect(()=>{D()},[D]),useEffect(()=>{const e=a("tis.project_created",()=>{D()}),t=a("tis.project_updated",e=>{const t="string"==typeof e?.project_id?e.project_id:"";t&&B(t)});return()=>{d(e),d(t)}},[a,d,D,B]),useEffect(()=>{const e=k.projectId;e&&G(e)&&void 0===L[e]&&B(e)},[k.projectId,G,L,B]);const J=L[k.projectId]??{},K=void 0!==L[k.projectId],[W,z]=useState({}),H=useCallback(e=>{z(t=>({...t,...e}))},[]),[Q,U]=useState(""),X=useCallback(e=>{U(e)},[]),[Z,$]=useState(""),ee=useCallback(()=>{z({}),U(""),$("")},[]),[te,se]=useState(EMPTY_CYCLE_CONFIG),ce=useMemo(()=>{const e=k.methodId?o[k.methodId]?.cycle_config_fields:void 0;return Array.isArray(e)?e:[]},[o,k.methodId]),ae=useCallback(async()=>{const e=k.projectId,t=k.methodId;if(t)try{const c=await s("tis.cycle_config",MessageType.Request,{project_id:e,method_id:t});if(c?.success)return void se(cycleConfigFromPayload(c.data));se(EMPTY_CYCLE_CONFIG)}catch(e){se(EMPTY_CYCLE_CONFIG)}else se(EMPTY_CYCLE_CONFIG)},[s,k.projectId,k.methodId]),de=useCallback(async e=>{const t=k.projectId,c=k.methodId;if(c)try{const a=await s("tis.set_cycle_config",MessageType.Request,{project_id:t,method_id:c,values:e});a?.success&&se(cycleConfigFromPayload(a.data))}catch(e){}},[s,k.projectId,k.methodId]),re=useCallback(async()=>{const e=k.projectId,t=k.methodId;if(t)try{const c=await s("tis.clear_cycle_config",MessageType.Request,{project_id:e,method_id:t});c?.success&&se(cycleConfigFromPayload(c.data))}catch(e){}},[s,k.projectId,k.methodId]);useEffect(()=>{ae()},[ae]),useEffect(()=>{const e=a("tis.schema_changed",()=>{ae()});return()=>{d(e)}},[a,d,ae]),useEffect(()=>{const e=a("tis.cycle_config",e=>{const t=String(e?.method_id??"");t&&k.methodId&&t!==k.methodId||se(cycleConfigFromPayload(e))});return()=>{d(e)}},[a,d,k.methodId]);const oe=useMemo(()=>({schemas:o,projectAssetRefs:n,defaultMethodId:l,schemasLoaded:f,state:m,selection:k,setSelection:x,existingProjects:F,projectKnown:G,refreshProjects:D,markProjectJustCreated:O,projectFields:J,projectFieldsLoaded:K,loadProjectFields:B,setProjectFields:V,stagedConfig:W,setStagedConfig:H,clearStagedConfig:ee,defaultsAppliedForMethod:Q,markDefaultsAppliedForMethod:X,configurationName:Z,setConfigurationName:$,cycleConfig:te,cycleConfigFields:ce,setCycleConfigValues:de,clearCycleConfig:re,refreshCycleConfig:ae,fetchRuns:R,fetchRun:P,runCache:b}),[o,n,l,f,m,k,x,F,G,D,O,J,K,B,V,W,H,ee,Q,X,Z,$,te,ce,de,re,ae,R,P,b]);return _jsx(TisContext.Provider,{value:oe,children:e})};export const useTis=()=>useContext(TisContext);export const useTisSchemas=()=>useContext(TisContext).schemas;export const useTisState=()=>useContext(TisContext).state;export const useTisCycleConfig=()=>{const{cycleConfig:e,cycleConfigFields:t,setCycleConfigValues:s,clearCycleConfig:c}=useContext(TisContext);return{...e,fields:t,setValues:s,clear:c}};export const useTisSelection=()=>{const{selection:e,setSelection:t}=useContext(TisContext);return[e,t]};export const useTisRuns=(e,t)=>{const{fetchRuns:s}=useContext(TisContext),[c,a]=useState([]),[d,r]=useState(!1),o=useCallback(async()=>{if(e){r(!0);try{a(await s(e,t))}finally{r(!1)}}else a([])},[e,t,s]);return useEffect(()=>{o()},[o]),{runs:c,loading:d,refresh:o}};export const useTisRun=e=>{const{selection:t,fetchRun:s,runCache:c}=useContext(TisContext),[a,d]=useState(!1),r=e??t.runId;useEffect(()=>{if(!r)return;if(c[r]?.meta)return;const e=t.projectId,a=t.methodId;e&&a&&(d(!0),s(e,a,r).finally(()=>d(!1)))},[r,t.projectId,t.methodId,s,c]);const o=r?c[r]:null;return{meta:o?.meta??null,cycles:o?.cycles??[],results:o?.results??{},rawData:o?.rawData??{},loading:a}};export{TisContext};
@@ -1 +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"}
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 +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)}})]})]})};
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)}})]})]})};
@@ -76,6 +76,12 @@ export interface ChartView {
76
76
  type: ChartViewType | string;
77
77
  x: ChartAxis;
78
78
  y: ChartSeries[];
79
+ /**
80
+ * Max decimal places on X-axis tick labels (display only; default 2).
81
+ * See `ChartView.x_decimals` in TestDataView for why an uncapped axis
82
+ * prints 17-digit ticks.
83
+ */
84
+ x_decimals?: number;
79
85
  }
80
86
  export type RawColumnSource = 'time' | 'derived' | string;
81
87
  export interface RawColumn {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/tis-editor/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/tis-editor/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AutoCoreTagContext.d.ts","sourceRoot":"","sources":["../../src/core/AutoCoreTagContext.tsx"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,KAAK,EAAE,EAQV,KAAK,SAAS,EACjB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EACR,gBAAgB,EAChB,SAAS,EACT,WAAW,EACd,MAAM,oBAAoB,CAAC;AAI5B;;;GAGG;AACH,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE3C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,8CAW7B,CAAC;AAsBH;;;;GAIG;AAIH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC;IACvC,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B,CA2lBA,CAAC"}
1
+ {"version":3,"file":"AutoCoreTagContext.d.ts","sourceRoot":"","sources":["../../src/core/AutoCoreTagContext.tsx"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAEH,OAAO,KAAK,EAAE,EAQV,KAAK,SAAS,EACjB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EACR,gBAAgB,EAChB,SAAS,EACT,WAAW,EAGd,MAAM,oBAAoB,CAAC;AAK5B;;;GAGG;AACH,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE3C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,8CAW7B,CAAC;AAsBH;;;;GAIG;AAIH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC;IACvC,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B,CA6uBA,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx}from"react/jsx-runtime";import React,{useRef,createContext,useCallback,useContext,useEffect,useMemo,useState}from"react";import{EventEmitterContext}from"./EventEmitterContext";import{MessageType}from"../hub/CommandMessage";export const AutoCoreTagContext=createContext({values:{},rawValues:{},isLoading:!0,write:async()=>{},tap:async()=>{},press:async()=>{},release:async()=>{},scales:{},updateScale:async()=>{},findTagByFqdn:()=>{}});const sleep=e=>new Promise(t=>setTimeout(t,e));export const AutoCoreTagProvider=({children:e,tags:t,scales:a,eagerRead:s=!0,flushIntervalMs:n=33})=>{const r=useRef(!1),c=useMemo(()=>({}),[]),o=a??c,{invoke:u,read:l,write:i,serverSubscribe:f,isConnected:m,subscribe:y,unsubscribe:b}=useContext(EventEmitterContext),[d,p]=useState(()=>{const e={};for(const a of t)void 0!==a.initialValue&&(e[a.tagName]=a.initialValue);return e}),[g,v]=useState({}),[C,N]=useState(o),h=useRef(C),w=useRef(d);useEffect(()=>{h.current=C},[C]),useEffect(()=>{w.current=d},[d]);const[T,M]=useState(!0),x=useCallback((e,t)=>{const{valueType:a,scale:s,codec:n}=e;if("number"===a&&"number"==typeof t&&s){const e=h.current[s];return t*(e?.scale??1)}if("json"===a&&n?.fromServer)try{return n.fromServer(t)}catch{}return t},[]),E=useCallback((e,t)=>{const{valueType:a,scale:s,codec:n}=e;if("json"===a&&n?.toServer)try{t=n.toServer(t)}catch{}if("number"===a&&"number"==typeof t&&s){const e=h.current[s];return t/(e?.scale??1)}return t},[]),k=useCallback(e=>{const a=t.filter(t=>t.scale===e);a.length&&v(e=>{const t={...e};for(const e of a){const a=w.current[e.tagName];if("number"!=typeof a)continue;const s=x(e,a);t[e.tagName]!==s&&(t[e.tagName]=s)}return t})},[t,x]),q=useRef(new Map),S=useRef(new Map),j=useRef(null),R=useCallback(()=>{j.current=null;const e=q.current,t=S.current;0===e.size&&0===t.size||(q.current=new Map,S.current=new Map,p(t=>{let a=t;return e.forEach((e,s)=>{a[s]!==e&&(a===t&&(a={...t}),a[s]=e)}),a}),v(e=>{let a=e;return t.forEach((t,s)=>{a[s]!==t&&(a===e&&(a={...e}),a[s]=t)}),a}))},[]),$=useCallback((e,t)=>{const a=x(e,t);if(n<=0)return p(a=>a[e.tagName]===t?a:{...a,[e.tagName]:t}),void v(t=>t[e.tagName]===a?t:{...t,[e.tagName]:a});q.current.set(e.tagName,t),S.current.set(e.tagName,a),null===j.current&&(j.current=setTimeout(R,n))},[x,n,R]);useEffect(()=>()=>{null!==j.current&&(clearTimeout(j.current),j.current=null),q.current=new Map,S.current=new Map},[]);const V=useCallback(async(e,t,a)=>{const s=a?.concurrency??4,n=a?.minDelayMs??20,r=a?.jitterMs??40;let c=0;const o=Array.from({length:s},()=>(async()=>{for(;;){const a=c++;if(a>=t.length)return;const s=t[a];try{let t=!1;try{await u(s.fqdn,MessageType.Request,{action:"refresh"}),t=!0}catch{}if(!t){const t="GNV"===e.toUpperCase()?{group:"ux"}:{};try{const e=await l(s.fqdn,t);e?.success&&$(s,e.data)}catch(e){}}}catch(e){}finally{const e=Math.floor(Math.random()*r);await sleep(n+e)}}})());await Promise.all(o)},[u,l,$]),A=useCallback(async()=>{for(const[e,t]of Object.entries(o)){if(!t.serverTag)continue;const{domain:a,symbolName:s}=t.serverTag;try{const t=await l(`${a}.${s}`,{group:"ux"});if(t.data&&(t.success??1)&&(t.valid??1)){const a=JSON.parse(t.data);if(a&&"number"==typeof a.scale){const{scale:t,label:s}=a;N(a=>({...a,[e]:{...a[e],scale:t,label:s??a[e]?.label??"---"}})),k(e)}}}catch{}}},[l,o,k]);useEffect(()=>{let e=!0;const a=[],n=async()=>{if(e&&!r.current){r.current=!0;try{await(async()=>{try{await A();for(const n of t){await f(n.tagName,n.fqdn,n.subscriptionOptions);const t=y(n.tagName,t=>{e&&$(n,t)});a.push(t),s&&l(n.fqdn).then(t=>{e&&t?.success&&$(n,t.data)}).catch(e=>{})}}finally{e&&setTimeout(()=>e&&M(!1),100)}})()}finally{e&&setTimeout(()=>e&&M(!1),100)}}};if(m())n();else{const e=y("HUB/connected",()=>{b(e),n()});a.push(e)}return()=>{e=!1,a.forEach(b),r.current=!1}},[y,b,m,u,f,s,t,A,V,$]);const O=useMemo(()=>Object.entries(o).filter(([,e])=>e.serverTag).map(([e,t])=>({scaleName:e,domain:t.serverTag.domain,symbolName:t.serverTag.symbolName})),[o]);useEffect(()=>{let e=!0;const t=[];for(const{scaleName:a,domain:s,symbolName:n}of O){const r=y(`${s}.${n}`,t=>{if(!e)return;const s=t?.value;if(s&&"object"==typeof s&&"number"==typeof s.scale){const{scale:e,label:t}=s;N(s=>({...s,[a]:{...s[a],scale:e,label:t??s[a]?.label??"---"}})),k(a)}});t.push(r)}return()=>{e=!1,t.forEach(b)}},[y,b,O,k]);const P=useCallback(async(e,a)=>{const s=t.find(t=>t.tagName===e);if(!s)return;const n=E(s,a);await i(s.fqdn,n)},[t,i,E]),B=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&(i(a.fqdn,!0).catch(e=>{}),await sleep(300),i(a.fqdn,!1).catch(e=>{}))},[t,i]),z=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&await i(a.fqdn,!0)},[t,i]),F=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&await i(a.fqdn,!1)},[t,i]),L=useCallback(async(e,t,a)=>{const s=C[e];if(s){if(s.serverTag){const n=`${s.serverTag.domain}.${s.serverTag.symbolName}`;await i(n,{name:e,scale:t,label:a})}N(s=>({...s,[e]:{...s[e],scale:t,label:a}})),k(e)}},[C,i,k]);useEffect(()=>{v(e=>{const a={...e};for(const e of t){const t=w.current[e.tagName];if(void 0===t)continue;const s=x(e,t);a[e.tagName]!==s&&(a[e.tagName]=s)}return a})},[t,x,C]);const U=useMemo(()=>{const e=new Map;for(const a of t)e.set(a.fqdn,a);return e},[t]),_=useCallback(e=>U.get(e),[U]),D=useMemo(()=>({values:g,rawValues:d,isLoading:T,write:P,tap:B,press:z,release:F,scales:C,updateScale:L,findTagByFqdn:_}),[g,d,T,P,B,z,F,C,L,_]);return _jsx(AutoCoreTagContext.Provider,{value:D,children:e})};
1
+ import{jsx as _jsx}from"react/jsx-runtime";import React,{useRef,createContext,useCallback,useContext,useEffect,useMemo,useState}from"react";import{EventEmitterContext}from"./EventEmitterContext";import{MessageType}from"../hub/CommandMessage";import{formatScaled}from"./formatScaled";export const AutoCoreTagContext=createContext({values:{},rawValues:{},isLoading:!0,write:async()=>{},tap:async()=>{},press:async()=>{},release:async()=>{},scales:{},updateScale:async()=>{},findTagByFqdn:()=>{}});const sleep=e=>new Promise(t=>setTimeout(t,e));export const AutoCoreTagProvider=({children:e,tags:t,scales:a,eagerRead:s=!0,flushIntervalMs:n=33})=>{const c=useRef(!1),r=useMemo(()=>({}),[]),o=a??r,{invoke:u,read:l,write:i,serverSubscribe:f,isConnected:m,subscribe:y,unsubscribe:b}=useContext(EventEmitterContext),[d,p]=useState(()=>{const e={};for(const a of t)void 0!==a.initialValue&&(e[a.tagName]=a.initialValue);return e}),[g,v]=useState({}),[C,N]=useState(o),h=useRef(C),w=useRef(d);useEffect(()=>{h.current=C},[C]),useEffect(()=>{w.current=d},[d]);const[T,M]=useState(!0),[k,S]=useState(null),[E,q]=useState(null),x=useRef(null),R=useRef(null);useEffect(()=>{x.current=E},[E]),useEffect(()=>{R.current=k},[k]);const j=useCallback((e,t)=>{const a={};for(const[s,n]of Object.entries(e.scales??{})){const e=n?.[t];e&&"number"==typeof e.scalar&&(a[s]={name:s,scale:e.scalar,label:e.label??"",offset:"absolute"===n?.kind?e.offset??0:0,precision:e.precision,precisionMode:e.precision_mode})}return a},[]),_=useCallback((e,a)=>{S(e),q(a);const s=j(e,a);h.current=s,N(s),v(e=>{const a={...e};for(const e of t){const t=e.quantity??e.scale;if(!t||!s[t])continue;const n=w.current[e.tagName];if("number"!=typeof n)continue;const c=s[t];a[e.tagName]=n*c.scale+(c.offset??0)}return a})},[j,t]),$=useCallback((e,t)=>{const{valueType:a,codec:s}=e,n=e.quantity??e.scale;if("number"===a&&"number"==typeof t&&n){const e=h.current[n];return t*(e?.scale??1)+(e?.offset??0)}if("json"===a&&s?.fromServer)try{return s.fromServer(t)}catch{}return t},[]),O=useCallback((e,t)=>{const{valueType:a,codec:s}=e,n=e.quantity??e.scale;if("json"===a&&s?.toServer)try{t=s.toServer(t)}catch{}if("number"===a&&"number"==typeof t&&n){const e=h.current[n],a=e?.scale??1;return(t-(e?.offset??0))/a}return t},[]),V=useCallback(e=>{const a=t.filter(t=>(t.quantity??t.scale)===e);a.length&&v(e=>{const t={...e};for(const e of a){const a=w.current[e.tagName];if("number"!=typeof a)continue;const s=$(e,a);t[e.tagName]!==s&&(t[e.tagName]=s)}return t})},[t,$]),A=useRef(new Map),P=useRef(new Map),B=useRef(null),F=useCallback(()=>{B.current=null;const e=A.current,t=P.current;0===e.size&&0===t.size||(A.current=new Map,P.current=new Map,p(t=>{let a=t;return e.forEach((e,s)=>{a[s]!==e&&(a===t&&(a={...t}),a[s]=e)}),a}),v(e=>{let a=e;return t.forEach((t,s)=>{a[s]!==t&&(a===e&&(a={...e}),a[s]=t)}),a}))},[]),U=useCallback((e,t)=>{const a=$(e,t);if(n<=0)return p(a=>a[e.tagName]===t?a:{...a,[e.tagName]:t}),void v(t=>t[e.tagName]===a?t:{...t,[e.tagName]:a});A.current.set(e.tagName,t),P.current.set(e.tagName,a),null===B.current&&(B.current=setTimeout(F,n))},[$,n,F]);useEffect(()=>()=>{null!==B.current&&(clearTimeout(B.current),B.current=null),A.current=new Map,P.current=new Map},[]);const z=useCallback(async(e,t,a)=>{const s=a?.concurrency??4,n=a?.minDelayMs??20,c=a?.jitterMs??40;let r=0;const o=Array.from({length:s},()=>(async()=>{for(;;){const a=r++;if(a>=t.length)return;const s=t[a];try{let t=!1;try{await u(s.fqdn,MessageType.Request,{action:"refresh"}),t=!0}catch{}if(!t){const t="GNV"===e.toUpperCase()?{group:"ux"}:{};try{const e=await l(s.fqdn,t);e?.success&&U(s,e.data)}catch(e){}}}catch(e){}finally{const e=Math.floor(Math.random()*c);await sleep(n+e)}}})());await Promise.all(o)},[u,l,U]),L=useCallback(async()=>{try{const e=await u("system.get_units",MessageType.Request,{}),t=e?.data??e,a=t?.units;if(!a||!a.scales)return;const s=t?.active_system??a.default_system;_(a,s)}catch(e){}},[u,_]),D=useCallback(async e=>{await u("system.set_unit_system",MessageType.Request,{system:e});k&&_(k,e)},[u,k,_]);useEffect(()=>{if(!m)return;const e=y("system.unit_system_changed",e=>{const t=e?.value?.system??e?.system;if(!t)return;const a=R.current;a&&t!==x.current&&_(a,t)});return()=>{b(e)}},[m,y,b,_]);const G=useCallback(async()=>{for(const[e,t]of Object.entries(o)){if(!t.serverTag)continue;const{domain:a,symbolName:s}=t.serverTag;try{const t=await l(`${a}.${s}`,{group:"ux"});if(t.data&&(t.success??1)&&(t.valid??1)){const a=JSON.parse(t.data);if(a&&"number"==typeof a.scale){const{scale:t,label:s}=a;N(a=>({...a,[e]:{...a[e],scale:t,label:s??a[e]?.label??"---"}})),V(e)}}}catch{}}},[l,o,V]);useEffect(()=>{let e=!0;const a=[],n=async()=>{if(e&&!c.current){c.current=!0;try{await(async()=>{try{await L(),await G();for(const n of t){await f(n.tagName,n.fqdn,n.subscriptionOptions);const t=y(n.tagName,t=>{e&&U(n,t)});a.push(t),s&&l(n.fqdn).then(t=>{e&&t?.success&&U(n,t.data)}).catch(e=>{})}}finally{e&&setTimeout(()=>e&&M(!1),100)}})()}finally{e&&setTimeout(()=>e&&M(!1),100)}}};if(m())n();else{const e=y("HUB/connected",()=>{b(e),n()});a.push(e)}return()=>{e=!1,a.forEach(b),c.current=!1}},[y,b,m,u,f,s,t,G,z,U]);const H=useMemo(()=>Object.entries(o).filter(([,e])=>e.serverTag).map(([e,t])=>({scaleName:e,domain:t.serverTag.domain,symbolName:t.serverTag.symbolName})),[o]);useEffect(()=>{let e=!0;const t=[];for(const{scaleName:a,domain:s,symbolName:n}of H){const c=y(`${s}.${n}`,t=>{if(!e)return;const s=t?.value;if(s&&"object"==typeof s&&"number"==typeof s.scale){const{scale:e,label:t}=s;N(s=>({...s,[a]:{...s[a],scale:e,label:t??s[a]?.label??"---"}})),V(a)}});t.push(c)}return()=>{e=!1,t.forEach(b)}},[y,b,H,V]);const I=useCallback(async(e,a)=>{const s=t.find(t=>t.tagName===e);if(!s)return;const n=O(s,a);await i(s.fqdn,n)},[t,i,O]),J=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&(i(a.fqdn,!0).catch(e=>{}),await sleep(300),i(a.fqdn,!1).catch(e=>{}))},[t,i]),Q=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&await i(a.fqdn,!0)},[t,i]),K=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&await i(a.fqdn,!1)},[t,i]),W=useCallback(async(e,t,a)=>{const s=C[e];if(s){if(s.serverTag){const n=`${s.serverTag.domain}.${s.serverTag.symbolName}`;await i(n,{name:e,scale:t,label:a})}N(s=>({...s,[e]:{...s[e],scale:t,label:a}})),V(e)}},[C,i,V]);useEffect(()=>{v(e=>{const a={...e};for(const e of t){const t=w.current[e.tagName];if(void 0===t)continue;const s=$(e,t);a[e.tagName]!==s&&(a[e.tagName]=s)}return a})},[t,$,C]);const X=useMemo(()=>{const e=new Map;for(const a of t)e.set(a.fqdn,a);return e},[t]),Y=useCallback(e=>X.get(e),[X]),Z=useCallback((e,t)=>{const a=C[e];return a&&Number.isFinite(t)?formatScaled(t*a.scale+(a.offset??0),a):String(t)},[C]),ee=useMemo(()=>({values:g,rawValues:d,isLoading:T,write:I,tap:J,press:Q,release:K,scales:C,updateScale:W,findTagByFqdn:Y,units:k,activeSystem:E,setUnitSystem:D,formatQuantity:Z}),[g,d,T,I,J,Q,K,C,W,Y,k,E,D,Z]);return _jsx(AutoCoreTagContext.Provider,{value:ee,children:e})};
@@ -147,17 +147,63 @@ export interface SubscriptionOptions {
147
147
  */
148
148
  args?: Record<string, unknown>;
149
149
  }
150
+ /** How a resolved scale's `precision` is interpreted. */
151
+ export type PrecisionMode = "decimals" | "significant";
150
152
  /**
151
- * Configuration for a named scale group.
152
- * Apply by setting `scale: "<name>"` on numeric tags.
153
+ * One system's display treatment of one quantity, as it appears in `units.json`.
154
+ * Mirrors `mechutil::units::SystemScale`.
155
+ */
156
+ export interface UnitSystemScale {
157
+ /** Display label ("mm", "lbf", "°C"). */
158
+ label: string;
159
+ /** `display = backend * scalar (+ offset)`. */
160
+ scalar: number;
161
+ /** Additive term — absolute quantities (temperature) only. */
162
+ offset?: number;
163
+ /** Digits, interpreted per `precision_mode`. */
164
+ precision?: number;
165
+ precision_mode?: PrecisionMode;
166
+ }
167
+ /** One quantity row of `units.json`. Mirrors `mechutil::units::Scale`. */
168
+ export interface UnitScale {
169
+ /** The unit GM/GNV actually holds on this machine. */
170
+ backend: string;
171
+ /** `"absolute"` takes the offset; `"delta"` (default) does not. */
172
+ kind?: "delta" | "absolute";
173
+ /** system name → display treatment. Flattened in the JSON. */
174
+ [system: string]: unknown;
175
+ }
176
+ /**
177
+ * The whole `units.json` document — the single definition of units for a
178
+ * machine. Fetched from `system.get_units`; see `autocore-server/UNITS_PLAN.md`.
179
+ */
180
+ export interface UnitsTable {
181
+ /** Named systems, in display order. Any names, not a fixed pair. */
182
+ systems: string[];
183
+ default_system: string;
184
+ /** quantity name → row. Quantities are DATA, not a fixed enum. */
185
+ scales: Record<string, UnitScale>;
186
+ }
187
+ /**
188
+ * A quantity resolved against the active system — what the UI actually renders
189
+ * with. Produced by the provider from `UnitsTable` + active system.
190
+ *
191
+ * `scale`/`label` keep their historical names so the provider's existing
192
+ * rescale-from-raw machinery is unchanged; `precision` is new and is what makes
193
+ * "too many decimals" configurable rather than hard-coded.
153
194
  */
154
195
  export interface ScaleConfig {
155
- /** Unique name for this scale group (e.g., "position", "load") */
196
+ /** Quantity name this resolves (e.g., "position", "force") */
156
197
  name: string;
157
198
  /** Current scale factor — incoming values ×= scale; outgoing values /= scale */
158
199
  scale: number;
159
200
  /** Units/label for display (e.g., "mm", "in", "lbs") */
160
201
  label: string;
202
+ /** Additive term for absolute quantities (temperature). Default 0. */
203
+ offset?: number;
204
+ /** Display digits. */
205
+ precision?: number;
206
+ precisionMode?: PrecisionMode;
161
207
  /** Optional description for debugging/documentation */
162
208
  description?: string;
163
209
  /**
@@ -200,10 +246,21 @@ export type TagConfig<K extends string = string, T extends PrimitiveKind = Primi
200
246
  /** Optional initial **raw** value before first server update */
201
247
  initialValue?: TagValueOf<T>;
202
248
  /**
203
- * Optional scale group for numeric tags.
204
- * If present, provider will:
205
- * - Multiply incoming numbers by the group's `scale`
206
- * - Divide outgoing numbers by the group's `scale`
249
+ * The QUANTITY this tag measures — a row name in `units.json`
250
+ * ("position", "force", "torque", …). If present, the provider will:
251
+ * - Multiply incoming numbers by the active system's `scalar` (+ offset)
252
+ * - Divide outgoing numbers back to backend units
253
+ * - Render them at the active system's `precision`
254
+ *
255
+ * Quantities are data, not an enum: a machine with a channel nobody
256
+ * anticipated just gets a new row in `units.json`.
257
+ */
258
+ quantity?: string;
259
+ /**
260
+ * @deprecated Renamed to {@link quantity} in 4.0, when hand-authored
261
+ * `acScales` was replaced by the server's `units.json`. Still read as a
262
+ * fallback so a project can be migrated without its HMI going dark, but it
263
+ * will be removed — regenerate with `acctl codegen-tags`.
207
264
  */
208
265
  scale?: string;
209
266
  /**
@@ -258,6 +315,24 @@ export type BindingOf<Spec extends readonly TagConfig[], K extends Spec[number][
258
315
  export interface BaseContextValue<VMap extends Record<string, any>> {
259
316
  /** Current app-visible tag values (already scaled/decoded). */
260
317
  values: Partial<VMap>;
318
+ /**
319
+ * The machine's units table (`units.json`), or `null` when the machine has
320
+ * none — in which case values render in backend units.
321
+ */
322
+ units?: UnitsTable | null;
323
+ /** The display system currently in effect (e.g. "Metric"). */
324
+ activeSystem?: string | null;
325
+ /**
326
+ * Switch the machine's display system. Persisted server-side and broadcast,
327
+ * so every connected client switches live with no reload.
328
+ */
329
+ setUnitSystem?: (system: string) => Promise<void>;
330
+ /**
331
+ * Format a BACKEND value for display in the active system, honouring that
332
+ * quantity's label precision. Rounding is a rendering step only — this never
333
+ * changes a stored value.
334
+ */
335
+ formatQuantity?: (quantity: string, backendValue: number) => string;
261
336
  /** Last raw (controller) values, as received (pre-scale, pre-codec). */
262
337
  rawValues: Record<string, unknown>;
263
338
  /** Whether initial reads are pending. */
@@ -1 +1 @@
1
- {"version":3,"file":"AutoCoreTagTypes.d.ts","sourceRoot":"","sources":["../../src/core/AutoCoreTagTypes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AutoCoreTagTypes.d.ts","sourceRoot":"","sources":["../../src/core/AutoCoreTagTypes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { PrecisionMode, ScaleConfig } from "./AutoCoreTagTypes";
2
+ /** Digits used when a scale declares no precision. */
3
+ export declare const DEFAULT_PRECISION = 3;
4
+ /**
5
+ * Format an already-converted (display-unit) value.
6
+ *
7
+ * Precision is a **cap, not padding**: a clean 0/1/2 axis stays "0", "1", "2"
8
+ * rather than becoming "0.000", which is what made fixed `toFixed` unusable for
9
+ * chart ticks.
10
+ */
11
+ export declare function formatValue(value: number, precision?: number, mode?: PrecisionMode): string;
12
+ /** Format a display-unit value using a resolved scale's precision settings. */
13
+ export declare function formatScaled(displayValue: number, scale?: ScaleConfig): string;
14
+ /** `"12.5 mm"` — value plus the active system's label, when there is one. */
15
+ export declare function formatScaledWithLabel(displayValue: number, scale?: ScaleConfig): string;
16
+ //# sourceMappingURL=formatScaled.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatScaled.d.ts","sourceRoot":"","sources":["../../src/core/formatScaled.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAErE,sDAAsD;AACtD,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC;;;;;;GAMG;AACH,wBAAgB,WAAW,CACvB,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,MAA0B,EACrC,IAAI,GAAE,aAA0B,GACjC,MAAM,CAwBR;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM,CAM9E;AAED,6EAA6E;AAC7E,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM,CAIvF"}
@@ -0,0 +1 @@
1
+ export const DEFAULT_PRECISION=3;export function formatValue(t,e=3,a="decimals"){if(!Number.isFinite(t))return String(t);let i;if("significant"===a){const a=Math.max(1,e);if(0===t)i="0";else{const e=Math.floor(Math.log10(Math.abs(t))),r=Math.max(0,a-1-e);i=t.toFixed(Math.min(r,100))}}else i=t.toFixed(Math.max(0,Math.min(e,100)));return i.includes(".")&&(i=i.replace(/0+$/,"").replace(/\.$/,""),""!==i&&"-"!==i||(i="0")),i}export function formatScaled(t,e){return formatValue(t,e?.precision??3,e?.precisionMode??"decimals")}export function formatScaledWithLabel(t,e){const a=formatScaled(t,e),i=e?.label?.trim();return i?`${a} ${i}`:a}
@@ -1,4 +1,4 @@
1
- import type { BaseContextValue, TagConfig, TagValueMap } from "../core/AutoCoreTagTypes";
1
+ import type { BaseContextValue, ScaleConfig, TagConfig, TagValueMap } from "../core/AutoCoreTagTypes";
2
2
  export declare function makeAutoCoreTagHooks<Spec extends readonly TagConfig[]>(Context: React.Context<BaseContextValue<TagValueMap<Spec>>>, tags: Spec): {
3
3
  readonly useAutoCoreTag: <K extends Spec[number]["tagName"]>(tagName: K) => {
4
4
  readonly value: TagValueMap<Spec>[K];
@@ -20,9 +20,17 @@ export declare function makeAutoCoreTagHooks<Spec extends readonly TagConfig[]>(
20
20
  readonly isLoading: boolean;
21
21
  };
22
22
  readonly useScales: () => {
23
- readonly scales: Record<string, import("../core/AutoCoreTagTypes").ScaleConfig>;
23
+ readonly scales: Record<string, ScaleConfig>;
24
24
  readonly updateScale: (scaleName: string, newScale: number, newLabel: string) => Promise<void>;
25
- readonly getScale: (scaleName: string) => import("../core/AutoCoreTagTypes").ScaleConfig;
25
+ readonly getScale: (scaleName: string) => ScaleConfig;
26
+ };
27
+ readonly useUnits: () => {
28
+ readonly units: import("../core/AutoCoreTagTypes").UnitsTable | null;
29
+ readonly activeSystem: string | null;
30
+ readonly systems: string[];
31
+ readonly setUnitSystem: ((system: string) => Promise<void>) | undefined;
32
+ readonly label: (quantity: string) => string;
33
+ readonly format: (quantity: string, backendValue: number) => string;
26
34
  };
27
35
  };
28
36
  //# sourceMappingURL=useAutoCoreTag.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAutoCoreTag.d.ts","sourceRoot":"","sources":["../../src/hooks/useAutoCoreTag.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEzF,wBAAgB,oBAAoB,CAAC,IAAI,SAAS,SAAS,SAAS,EAAE,EAClE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAC3D,IAAI,EAAE,IAAI;8BAYc,CAAC,2CAA4B,CAAC;;;;;;;;;+BA6B7B,CAAC,4CAA6B,SAAS,CAAC,EAAE;4BAO/C,CAAC;;kCAYyB,CAAC;;;iCAUpB,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,mBAAM,CAAC,KAAK,CAAC,SAAQ,GAAG,EAAE;;;;;;;uCAW3C,MAAM;;EAKtD"}
1
+ {"version":3,"file":"useAutoCoreTag.d.ts","sourceRoot":"","sources":["../../src/hooks/useAutoCoreTag.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEtG,wBAAgB,oBAAoB,CAAC,IAAI,SAAS,SAAS,SAAS,EAAE,EAClE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAC3D,IAAI,EAAE,IAAI;8BAYc,CAAC,2CAA4B,CAAC;;;;;;;;;+BA6B7B,CAAC,4CAA6B,SAAS,CAAC,EAAE;4BAO/C,CAAC;;kCAYyB,CAAC;;;iCAUpB,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,mBAAM,CAAC,KAAK,CAAC,SAAQ,GAAG,EAAE;;;;;;;uCAmBpE,MAAM,KAAG,WAAW;;;;;;;mCAoBrB,MAAM;oCAIN,MAAM,gBAAgB,MAAM;;EAqBlD"}
@@ -1 +1 @@
1
- import{useCallback,useContext,useMemo}from"react";export function makeAutoCoreTagHooks(e,a){return{useAutoCoreTag:s=>{const{values:t,rawValues:u,isLoading:o,write:r,tap:l,press:n,release:c}=useContext(e),i=(e=>a.find(a=>a.tagName===e))(s);if(!i)throw new Error(`useAutoCoreTag: unknown tagName '${String(s)}'`);const C=useCallback(e=>r(s,e),[r,s]),g=useCallback(()=>l?.(s),[l,s]),m=useCallback(()=>n?.(s),[n,s]),w=useCallback(()=>c?.(s),[c,s]);return{value:t[s],rawValue:u[s],write:C,tap:g,press:m,release:w,isLoading:o}},useAutoCoreTags:a=>{const{values:s,rawValues:t,isLoading:u,write:o}=useContext(e);return{values:useMemo(()=>Object.fromEntries(a.map(e=>[e,s[e]])),[s,a]),rawValues:useMemo(()=>Object.fromEntries(a.map(e=>[e,t[e]])),[t,a]),write:useCallback(async(e,a)=>{await o(e,a)},[o]),isLoading:u}},useAutoCoreSelect:(a,s=[])=>{const{values:t,isLoading:u}=useContext(e);return{selected:useMemo(()=>a(t),[t,...s]),isLoading:u}},useScales:()=>{const{scales:a,updateScale:s}=useContext(e),t=useCallback(e=>a[e],[a]);return{scales:a,updateScale:s,getScale:t}}}}
1
+ import{useCallback,useContext,useMemo}from"react";export function makeAutoCoreTagHooks(e,s){return{useAutoCoreTag:a=>{const{values:t,rawValues:u,isLoading:l,write:n,tap:o,press:r,release:i}=useContext(e),c=(e=>s.find(s=>s.tagName===e))(a);if(!c)throw new Error(`useAutoCoreTag: unknown tagName '${String(a)}'`);const m=useCallback(e=>n(a,e),[n,a]),C=useCallback(()=>o?.(a),[o,a]),g=useCallback(()=>r?.(a),[r,a]),b=useCallback(()=>i?.(a),[i,a]);return{value:t[a],rawValue:u[a],write:m,tap:C,press:g,release:b,isLoading:l}},useAutoCoreTags:s=>{const{values:a,rawValues:t,isLoading:u,write:l}=useContext(e);return{values:useMemo(()=>Object.fromEntries(s.map(e=>[e,a[e]])),[a,s]),rawValues:useMemo(()=>Object.fromEntries(s.map(e=>[e,t[e]])),[t,s]),write:useCallback(async(e,s)=>{await l(e,s)},[l]),isLoading:u}},useAutoCoreSelect:(s,a=[])=>{const{values:t,isLoading:u}=useContext(e);return{selected:useMemo(()=>s(t),[t,...a]),isLoading:u}},useScales:()=>{const{scales:s,updateScale:a}=useContext(e),t=useCallback(e=>s[e]??{name:e,scale:1,label:""},[s]);return{scales:s,updateScale:a,getScale:t}},useUnits:()=>{const{units:s,activeSystem:a,setUnitSystem:t,formatQuantity:u,scales:l}=useContext(e),n=useCallback(e=>l[e]?.label??"",[l]),o=useCallback((e,s)=>u?u(e,s):String(s),[u]);return{units:s??null,activeSystem:a??null,systems:s?.systems??[],setUnitSystem:t,label:n,format:o}}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adcops/autocore-react",
3
- "version": "3.3.123",
3
+ "version": "3.5.3",
4
4
  "description": "A React component library for industrial user interfaces.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -0,0 +1,88 @@
1
+ /*
2
+ * Copyright (C) 2026 Automated Design Corp. All Rights Reserved.
3
+ *
4
+ * UnitSystemSelector — the operator's Metric/Imperial (or any named system)
5
+ * switch.
6
+ *
7
+ * Selecting a system writes it server-side, so it is machine-wide and survives
8
+ * a restart, and so the server's CSV export follows it rather than disagreeing
9
+ * with the screen. The server broadcasts the change and every connected client
10
+ * re-derives its scales, which means the switch is **live**: readouts, tables,
11
+ * charts and the sequence view all update with no page reload and no
12
+ * control-program restart. Nothing stored is converted — only what is rendered.
13
+ *
14
+ * See autocore-server/UNITS_PLAN.md §6.3.
15
+ */
16
+
17
+ import React, { useContext } from "react";
18
+ import { SelectButton } from "primereact/selectbutton";
19
+ import { Dropdown } from "primereact/dropdown";
20
+ import { AutoCoreTagContext } from "../core/AutoCoreTagContext";
21
+
22
+ export interface UnitSystemSelectorProps {
23
+ /**
24
+ * `"buttons"` (default) renders a segmented control — right for a
25
+ * touchscreen with two or three systems. `"dropdown"` is better past that.
26
+ */
27
+ variant?: "buttons" | "dropdown";
28
+ /** Optional label rendered above the control. */
29
+ label?: string;
30
+ /** Disable interaction (e.g. while a test is running). */
31
+ disabled?: boolean;
32
+ className?: string;
33
+ style?: React.CSSProperties;
34
+ }
35
+
36
+ export const UnitSystemSelector: React.FC<UnitSystemSelectorProps> = ({
37
+ variant = "buttons",
38
+ label,
39
+ disabled = false,
40
+ className,
41
+ style,
42
+ }) => {
43
+ const ctx = useContext(AutoCoreTagContext);
44
+ const units = ctx.units;
45
+ const active = ctx.activeSystem ?? units?.default_system ?? null;
46
+
47
+ // A machine with no units.json renders nothing rather than an empty control
48
+ // the operator can't use — the HMI still works, in backend units.
49
+ if (!units || !Array.isArray(units.systems) || units.systems.length === 0) {
50
+ return null;
51
+ }
52
+
53
+ const options = units.systems.map((s) => ({ label: s, value: s }));
54
+
55
+ const onChange = (next: string | null | undefined) => {
56
+ if (!next || next === active) return;
57
+ void ctx.setUnitSystem?.(next);
58
+ };
59
+
60
+ return (
61
+ <div className={className} style={style}>
62
+ {label ? (
63
+ <div style={{ marginBottom: "0.35rem", fontWeight: 600 }}>{label}</div>
64
+ ) : null}
65
+ {variant === "dropdown" ? (
66
+ <Dropdown
67
+ value={active}
68
+ options={options}
69
+ disabled={disabled}
70
+ onChange={(e) => onChange(e.value)}
71
+ style={{ minWidth: "10rem" }}
72
+ />
73
+ ) : (
74
+ <SelectButton
75
+ value={active}
76
+ options={options}
77
+ disabled={disabled}
78
+ // PrimeReact clears the value when the active option is
79
+ // re-clicked; ignore that so there is always a system.
80
+ onChange={(e) => onChange(e.value)}
81
+ allowEmpty={false}
82
+ />
83
+ )}
84
+ </div>
85
+ );
86
+ };
87
+
88
+ export default UnitSystemSelector;