@adcops/autocore-react 3.3.42 → 3.3.44

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.
@@ -1 +1 @@
1
- {"version":3,"file":"TestSetupForm.d.ts","sourceRoot":"","sources":["../../src/components/TestSetupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAS/D,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC3B,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,cAAc,EAAE,YAAY,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAChE;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA4MtD,CAAC"}
1
+ {"version":3,"file":"TestSetupForm.d.ts","sourceRoot":"","sources":["../../src/components/TestSetupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAU/D,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC3B,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,cAAc,EAAE,YAAY,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAChE;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAuPtD,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useEffect,useContext}from"react";import{AutoComplete}from"primereact/autocomplete";import{EventEmitterContext}from"../core/EventEmitterContext";import{MessageType}from"../hub/CommandMessage";import{ValueInput}from"./ValueInput";import{TextInput}from"./TextInput";import{InputText}from"primereact/inputtext";export const TestSetupForm=({schema:e,defaultProjectId:t="",defaultDefinitionId:s="default",onProjectChange:a,onDefinitionChange:n,onValidationChange:i})=>{const[r,o]=useState({}),[c,l]=useState(t),[m,p]=useState(s);useEffect(()=>{a&&a(c)},[c,a]),useEffect(()=>{n&&n(m)},[m,n]);const[u,f]=useState([]),[d,x]=useState([]),[j,g]=useState(!1),{invoke:h,write:_,subscribe:v,unsubscribe:y}=useContext(EventEmitterContext);useEffect(()=>{if(!e)return;const t=[...e.project_fields,...e.config_fields],s=[];for(const e of t)if(e.source){const t=v(e.source,t=>{o(s=>s[e.name]!==t?{...s,[e.name]:t}:s)});s.push(t)}return()=>{for(const e of s)y(e)}},[e,v,y]),useEffect(()=>{(async()=>{try{const e=await h("results.list_projects",MessageType.Request,{});e.success&&e.data&&e.data.projects&&f(e.data.projects)}catch(e){}})()},[h]);useEffect(()=>{if(!e)return;let t=!0;c&&""!==c.trim()||(t=!1),m&&""!==m.trim()||(t=!1);const s=[...e.project_fields,...e.config_fields];for(const e of s)if(e.required&&(void 0===r[e.name]||""===r[e.name]||null===r[e.name])){t=!1;break}g(t),i&&i(t,r)},[r,e,c,m,i]);const I=async(e,t)=>{if(o({...r,[e.name]:t}),e.source)try{await _(e.source,t)}catch(e){}},N=e=>{const t=(e=>!e.required||void 0!==r[e.name]&&""!==r[e.name]&&null!==r[e.name])(e),s="string"!==e.type&&"bool"!==e.type;return _jsxs(React.Fragment,{children:[_jsx("span",{className:"ac-form-label",children:e.name}),s?_jsx(ValueInput,{label:void 0,value:null!=r[e.name]?Number(r[e.name]):null,suffix:e.units?` ${e.units}`:void 0,onValueChanged:t=>I(e,t),className:t?"":"p-invalid"}):_jsx(TextInput,{label:void 0,value:null!=r[e.name]?String(r[e.name]):"",suffix:e.units?` ${e.units}`:void 0,onValueChanged:t=>I(e,t),className:t?"":"p-invalid"}),_jsx("span",{style:{color:t?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:t?"pi pi-check":"pi pi-times"})})]},e.name)};return e?_jsxs("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:[_jsxs("h3",{className:"ac-form-section",style:{display:"flex",alignItems:"center",gap:"10px"},children:["Project & Definition",_jsx("span",{style:{color:j?"var(--green-500)":"var(--red-500)"},children:_jsx("i",{className:j?"pi pi-check-circle":"pi pi-exclamation-circle"})})]}),_jsx("span",{className:"ac-form-label",children:"Project ID"}),_jsx(AutoComplete,{value:c,suggestions:d,completeMethod:e=>{const t=e.query.toLowerCase();x(u.filter(e=>e.toLowerCase().includes(t)))},onChange:e=>(e=>{const t=(e||"").replace(/[^a-zA-Z0-9_]/g,"");l(t)})(e.value),dropdown:!0,placeholder:"Enter or select Project ID",className:c&&""!==c.trim()?"":"p-invalid"}),_jsx("span",{style:{color:c&&""!==c.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:c&&""!==c.trim()?"pi pi-check":"pi pi-times"})}),_jsx("span",{className:"ac-form-label",children:"Definition ID"}),_jsx(InputText,{value:m,onChange:e=>(e=>{const t=e.replace(/[^a-zA-Z0-9_]/g,"");p(t)})(e.target.value),placeholder:"Enter Definition ID",className:m&&""!==m.trim()?"":"p-invalid"}),_jsx("span",{style:{color:m&&""!==m.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:m&&""!==m.trim()?"pi pi-check":"pi pi-times"})}),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Project Information"}),e.project_fields.map(N),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Test Configuration"}),e.config_fields.map(N)]}):_jsx("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:_jsx("h3",{className:"ac-form-section",children:"No Test Definition Selected"})})};
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useEffect,useContext}from"react";import{AutoComplete}from"primereact/autocomplete";import{EventEmitterContext}from"../core/EventEmitterContext";import{AutoCoreTagContext}from"../core/AutoCoreTagContext";import{MessageType}from"../hub/CommandMessage";import{ValueInput}from"./ValueInput";import{TextInput}from"./TextInput";import{InputText}from"primereact/inputtext";export const TestSetupForm=({schema:e,defaultProjectId:t="",defaultDefinitionId:a="default",onProjectChange:s,onDefinitionChange:n,onValidationChange:r})=>{const[i,o]=useState({}),[c,l]=useState(t),[m,p]=useState(a);useEffect(()=>{s&&s(c)},[c,s]),useEffect(()=>{n&&n(m)},[m,n]);const[u,d]=useState([]),[f,x]=useState([]),[g,j]=useState(!1),{invoke:h,write:_,subscribe:v,unsubscribe:y}=useContext(EventEmitterContext),{findTagByFqdn:C}=useContext(AutoCoreTagContext);useEffect(()=>{if(!e)return;const t=[...e.project_fields,...e.config_fields],a=[];for(const e of t){if(!e.source)continue;const t=e.source,s=e.name,n=C(t);if(n){const e=v(n.tagName,e=>{o(t=>t[s]!==e?{...t,[s]:e}:t)});a.push(e)}else;(async()=>{try{const e=await h(t,MessageType.Read,{}),a=void 0!==e?.data?e.data:e;null!=a&&o(e=>void 0===e[s]||null===e[s]||""===e[s]?{...e,[s]:a}:e)}catch(e){}})()}return()=>{for(const e of a)y(e)}},[e,v,y,h,C]),useEffect(()=>{(async()=>{try{const e=await h("results.list_projects",MessageType.Request,{});e.success&&e.data&&e.data.projects&&d(e.data.projects)}catch(e){}})()},[h]);useEffect(()=>{if(!e)return;let t=!0;c&&""!==c.trim()||(t=!1),m&&""!==m.trim()||(t=!1);const a=[...e.project_fields,...e.config_fields];for(const e of a)if(e.required&&(void 0===i[e.name]||""===i[e.name]||null===i[e.name])){t=!1;break}j(t),r&&r(t,i)},[i,e,c,m,r]);const N=async(e,t)=>{if(o({...i,[e.name]:t}),e.source)try{await _(e.source,t)}catch(e){}},I=e=>{const t=(e=>!e.required||void 0!==i[e.name]&&""!==i[e.name]&&null!==i[e.name])(e),a="string"!==e.type&&"bool"!==e.type;return _jsxs(React.Fragment,{children:[_jsx("span",{className:"ac-form-label",children:e.name}),a?_jsx(ValueInput,{label:void 0,value:null!=i[e.name]?Number(i[e.name]):null,onValueChanged:t=>N(e,t),className:t?"":"p-invalid"}):_jsx(TextInput,{label:void 0,value:null!=i[e.name]?String(i[e.name]):"",onValueChanged:t=>N(e,t),className:t?"":"p-invalid"}),_jsx("span",{children:e.units?` ${e.units}`:void 0}),_jsx("span",{style:{color:t?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:t?"pi pi-check":"pi pi-times"})})]},e.name)};return e?_jsxs("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:[_jsxs("h3",{className:"ac-form-section",style:{display:"flex",alignItems:"center",gap:"10px"},children:["Project & Definition",_jsx("span",{style:{color:g?"var(--green-500)":"var(--red-500)"},children:_jsx("i",{className:g?"pi pi-check-circle":"pi pi-exclamation-circle"})})]}),_jsx("span",{className:"ac-form-label",children:"Project ID"}),_jsx(AutoComplete,{value:c,suggestions:f,completeMethod:e=>{const t=e.query.toLowerCase();x(u.filter(e=>e.toLowerCase().includes(t)))},onChange:e=>(e=>{const t=(e||"").replace(/[^a-zA-Z0-9_]/g,"");l(t)})(e.value),dropdown:!0,placeholder:"Enter or select Project ID",className:c&&""!==c.trim()?"":"p-invalid"}),_jsx("span",{style:{color:c&&""!==c.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:c&&""!==c.trim()?"pi pi-check":"pi pi-times"})}),_jsx("span",{className:"ac-form-label",children:"Definition ID"}),_jsx(InputText,{value:m,onChange:e=>(e=>{const t=e.replace(/[^a-zA-Z0-9_]/g,"");p(t)})(e.target.value),placeholder:"Enter Definition ID",className:m&&""!==m.trim()?"":"p-invalid"}),_jsx("span",{style:{color:m&&""!==m.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:m&&""!==m.trim()?"pi pi-check":"pi pi-times"})}),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Project Information"}),e.project_fields.map(I),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Test Configuration"}),e.config_fields.map(I)]}):_jsx("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:_jsx("h3",{className:"ac-form-section",children:"No Test Definition Selected"})})};
@@ -1 +1 @@
1
- {"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../../src/components/TextInput.tsx"],"names":[],"mappings":"AASA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D,UAAU,cAAe,SAAQ,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;IAClF,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAExB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAE1B,8CAA8C;IAC9C,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEzB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEzB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE9B,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6DAA6D;IAC7D,cAAc,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAqG9C,CAAC"}
1
+ {"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../../src/components/TextInput.tsx"],"names":[],"mappings":"AASA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG1D,UAAU,cAAe,SAAQ,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;IAClF,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAExB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAE1B,8CAA8C;IAC9C,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEzB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAEzB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE9B,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6DAA6D;IAC7D,cAAc,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA2G9C,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useEffect,useMemo,useState}from"react";import{InputText}from"primereact/inputtext";import{Button}from"primereact/button";function toStr(e){return e??""}export const TextInput=e=>{const{label:t,value:s,keyfilter:n,prefix:a,suffix:i,description:o,disabled:r=!1,placeholder:c,onValueChanged:u,validator:l,...p}=e,[d,m]=useState(toStr(s)),[x,f]=useState(!1),[j,v]=useState(!s||h(s,l));function h(e,t){return!t||t.test(e)}function _(){const e=d,t=h(e,l);v(t),t&&(f(!1),u?.(e))}function b(){const e=toStr(s);m(e),f(!1),v(!e||h(e,l))}useEffect(()=>{m(toStr(s)),f(!1),v(!s||h(s,l))},[s,l]);const N=useMemo(()=>toStr(d),[d]);return _jsxs("div",{children:[_jsxs("div",{className:"p-inputgroup",children:[_jsx("span",{className:"p-inputgroup-addon",children:t}),void 0!==a&&_jsx("span",{className:"p-inputgroup-addon",children:a}),_jsx(InputText,{...p,keyfilter:n,placeholder:c,value:N,onChange:e=>{m(e.target.value),f(!0)},className:j?p.className??"":`${p.className??""} p-invalid`,onKeyDown:e=>{"Enter"===e.key?_():"Escape"===e.key&&b()},disabled:r}),void 0!==i&&_jsx("span",{className:"p-inputgroup-addon",children:i}),_jsx(Button,{icon:"pi pi-check",disabled:r||!x,className:"p-button-success",onClick:_,visible:x}),_jsx(Button,{icon:"pi pi-times",disabled:r||!x,className:"p-button-danger",onClick:b,visible:x})]}),void 0!==o&&_jsx("small",{children:o})]})};
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useEffect,useMemo,useState}from"react";import{InputText}from"primereact/inputtext";import{Button}from"primereact/button";function toStr(e){return e??""}export const TextInput=e=>{const{label:t,value:s,keyfilter:n,prefix:a,suffix:i,description:o,disabled:r=!1,placeholder:c,onValueChanged:l,validator:u,...p}=e,[d,m]=useState(toStr(s)),[x,f]=useState(!1),[j,v]=useState(!s||h(s,u));function h(e,t){return!t||t.test(e)}function _(){const e=d,t=h(e,u);v(t),t&&(f(!1),l?.(e))}function b(){const e=toStr(s);m(e),f(!1),v(!e||h(e,u))}useEffect(()=>{m(toStr(s)),f(!1),v(!s||h(s,u))},[s,u]);const N=useMemo(()=>toStr(d),[d]);return _jsxs("div",{children:[_jsxs("div",{className:"p-inputgroup",children:[null!=t&&""!==t&&_jsx("span",{className:"p-inputgroup-addon",children:t}),void 0!==a&&_jsx("span",{className:"p-inputgroup-addon",children:a}),_jsx(InputText,{...p,keyfilter:n,placeholder:c,value:N,onChange:e=>{m(e.target.value),f(!0)},className:j?p.className??"":`${p.className??""} p-invalid`,onKeyDown:e=>{"Enter"===e.key?_():"Escape"===e.key&&b()},disabled:r}),void 0!==i&&_jsx("span",{className:"p-inputgroup-addon",children:i}),_jsx(Button,{icon:"pi pi-check",disabled:r||!x,className:"p-button-success",onClick:_,visible:!0}),_jsx(Button,{icon:"pi pi-times",disabled:r||!x,className:"p-button-danger",onClick:b,visible:!0})]}),void 0!==o&&_jsx("small",{children:o})]})};
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useRef,useEffect,useContext}from"react";import clsx from"clsx";import{InputNumber}from"primereact/inputnumber";import{EventEmitterContext}from"../core/EventEmitterContext";import{Button}from"primereact/button";import"./ValueInput.css";export const ValueInput=({label:e="",value:t=null,min:s,max:i,minPrecision:n=0,maxPrecision:a=3,mode:o="decimal",currency:u="USD",prefix:l,suffix:r,showButtons:c=!1,step:p=1,locale:m="en-US",description:d,disabled:x=!1,dispatchTopic:f,placeholder:v,onValueChanged:b,size:h="normal",...j})=>{const[C,E]=useState(t),[_,N]=useState(t),[S,g]=useState(t),[y,k]=useState(!1),[B,I]=useState(!1),D=useRef(null),F=useContext(EventEmitterContext);useEffect(()=>{null!==S?(N(S),g(null),I(!1)):t!==_&&(N(t),E(t),k(!1),I(!1))},[t,_]);const V=()=>{var e;y&&null!==C&&(e=C,void 0!==i&&e>i||void 0!==s&&e<s?I(!0):(N(C),k(!1),b?.(C),I(!1),f&&F.dispatch({topic:f,payload:C})))},w=()=>{y&&(E(null),N(null),k(!1),I(!1))};return _jsxs("div",{children:[_jsxs("div",{className:"p-inputgroup",children:[null!=e&&_jsx("span",{className:"p-inputgroup-addon",children:e}),_jsx(InputNumber,{...j,ref:D,className:clsx("value-input-field",`size-${h}`,j.className),invalid:B,min:s,max:i,minFractionDigits:n,maxFractionDigits:a,mode:o,prefix:l,suffix:r,showButtons:c,step:p,placeholder:v,value:_,onChange:e=>{return t=e.value,y||(g(_),k(!0)),void E(t);var t},locale:m,currency:u,onKeyDown:e=>{"Enter"===e.key?V():"Escape"===e.key&&w()},disabled:x}),_jsx(Button,{icon:"pi pi-check",disabled:x||!y,className:"p-button-success",onClick:()=>V(),visible:y,autoFocus:!1}),_jsx(Button,{icon:"pi pi-times",disabled:x||!y,className:"p-button-danger",onClickCapture:()=>w(),visible:y,autoFocus:!1})]}),d&&_jsx("small",{children:d})]})};export default ValueInput;
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useRef,useEffect,useContext}from"react";import clsx from"clsx";import{InputNumber}from"primereact/inputnumber";import{EventEmitterContext}from"../core/EventEmitterContext";import{Button}from"primereact/button";import"./ValueInput.css";export const ValueInput=({label:e,value:t=null,min:s,max:i,minPrecision:n=0,maxPrecision:a=3,mode:o="decimal",currency:u="USD",prefix:l,suffix:r,showButtons:c=!1,step:p=1,locale:m="en-US",description:d,disabled:x=!1,dispatchTopic:f,placeholder:v,onValueChanged:b,size:h="normal",...j})=>{const[C,E]=useState(t),[_,N]=useState(t),[S,g]=useState(t),[y,k]=useState(!1),[B,I]=useState(!1),D=useRef(null),F=useContext(EventEmitterContext);useEffect(()=>{null!==S?(N(S),g(null),I(!1)):t!==_&&(N(t),E(t),k(!1),I(!1))},[t,_]);const V=()=>{var e;y&&null!==C&&(e=C,void 0!==i&&e>i||void 0!==s&&e<s?I(!0):(N(C),k(!1),b?.(C),I(!1),f&&F.dispatch({topic:f,payload:C})))},w=()=>{y&&(E(null),N(null),k(!1),I(!1))};return _jsxs("div",{children:[_jsxs("div",{className:"p-inputgroup",children:[null!=e&&""!==e&&_jsx("span",{className:"p-inputgroup-addon",children:e}),_jsx(InputNumber,{...j,ref:D,className:clsx("value-input-field",`size-${h}`,j.className),invalid:B,min:s,max:i,minFractionDigits:n,maxFractionDigits:a,mode:o,prefix:l,suffix:r,showButtons:c,step:p,placeholder:v,value:_,onChange:e=>{return t=e.value,y||(g(_),k(!0)),void E(t);var t},locale:m,currency:u,onKeyDown:e=>{"Enter"===e.key?V():"Escape"===e.key&&w()},disabled:x}),_jsx(Button,{icon:"pi pi-check",disabled:x||!y,className:"p-button-success",onClick:()=>V(),visible:!0,autoFocus:!1}),_jsx(Button,{icon:"pi pi-times",disabled:x||!y,className:"p-button-danger",onClickCapture:()=>w(),visible:!0,autoFocus:!1})]}),d&&_jsx("small",{children:d})]})};export default ValueInput;
@@ -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,8CAU7B,CAAC;AAsBH;;;;GAIG;AAIH;;;;;;;;;;;;GAYG;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;CACvB,CAufA,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,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;;;;;;;;;;;;GAYG;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;CACvB,CAygBA,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()=>{}});const sleep=e=>new Promise(t=>setTimeout(t,e));export const AutoCoreTagProvider=({children:e,tags:t,scales:a,eagerRead:s=!0})=>{const n=useRef(!1),c=useMemo(()=>({}),[]),r=a??c,{invoke:o,read:l,write:u,serverSubscribe:i,isConnected:f,subscribe:m,unsubscribe:y}=useContext(EventEmitterContext),[b,d]=useState(()=>{const e={};for(const a of t)void 0!==a.initialValue&&(e[a.tagName]=a.initialValue);return e}),[g,p]=useState({}),[v,C]=useState(r),N=useRef(v),h=useRef(b);useEffect(()=>{N.current=v},[v]),useEffect(()=>{h.current=b},[b]);const[T,w]=useState(!0),x=useCallback((e,t)=>{const{valueType:a,scale:s,codec:n}=e;if("number"===a&&"number"==typeof t&&s){const e=N.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=N.current[s];return t/(e?.scale??1)}return t},[]),k=useCallback(e=>{const a=t.filter(t=>t.scale===e);a.length&&p(e=>{const t={...e};for(const e of a){const a=h.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]),S=useCallback((e,t)=>{d(a=>a[e.tagName]===t?a:{...a,[e.tagName]:t});const a=x(e,t);p(t=>t[e.tagName]===a?t:{...t,[e.tagName]:a})},[x]),M=useCallback(async(e,t,a)=>{const s=a?.concurrency??4,n=a?.minDelayMs??20,c=a?.jitterMs??40;let r=0;const u=Array.from({length:s},()=>(async()=>{for(;;){const a=r++;if(a>=t.length)return;const s=t[a];try{let t=!1;try{await o(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(s,e.data)}catch(e){}}}catch(e){}finally{const e=Math.floor(Math.random()*c);await sleep(n+e)}}})());await Promise.all(u)},[o,l,S]),j=useCallback(async()=>{for(const[e,t]of Object.entries(r)){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;C(a=>({...a,[e]:{...a[e],scale:t,label:s??a[e]?.label??"---"}})),k(e)}}}catch{}}},[l,r,k]);useEffect(()=>{let e=!0;const a=[],c=async()=>{if(e&&!n.current){n.current=!0;try{await(async()=>{try{await j();for(const n of t){await i(n.tagName,n.fqdn,n.subscriptionOptions);const t=m(n.tagName,t=>{e&&S(n,t)});a.push(t),s&&l(n.fqdn).then(t=>{e&&t?.success&&S(n,t.data)}).catch(e=>{})}}finally{e&&setTimeout(()=>e&&w(!1),100)}})()}finally{e&&setTimeout(()=>e&&w(!1),100)}}};if(f())c();else{const e=m("HUB/connected",()=>{y(e),c()});a.push(e)}return()=>{e=!1,a.forEach(y),n.current=!1}},[m,y,f,o,i,s,t,j,M,S]);const q=useMemo(()=>Object.entries(r).filter(([,e])=>e.serverTag).map(([e,t])=>({scaleName:e,domain:t.serverTag.domain,symbolName:t.serverTag.symbolName})),[r]);useEffect(()=>{let e=!0;const t=[];for(const{scaleName:a,domain:s,symbolName:n}of q){const c=m(`${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;C(s=>({...s,[a]:{...s[a],scale:e,label:t??s[a]?.label??"---"}})),k(a)}});t.push(c)}return()=>{e=!1,t.forEach(y)}},[m,y,q,k]);const R=useCallback(async(e,a)=>{const s=t.find(t=>t.tagName===e);if(!s)return;const n=E(s,a);await u(s.fqdn,n)},[t,u,E]),$=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&(u(a.fqdn,!0).catch(e=>{}),await sleep(300),u(a.fqdn,!1).catch(e=>{}))},[t,u]),V=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&await u(a.fqdn,!0)},[t,u]),A=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&await u(a.fqdn,!1)},[t,u]),O=useCallback(async(e,t,a)=>{const s=v[e];if(s){if(s.serverTag){const n=`${s.serverTag.domain}.${s.serverTag.symbolName}`;await u(n,{name:e,scale:t,label:a})}C(s=>({...s,[e]:{...s[e],scale:t,label:a}})),k(e)}},[v,u,k]);useEffect(()=>{p(e=>{const a={...e};for(const e of t){const t=h.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,v]);const P=useMemo(()=>({values:g,rawValues:b,isLoading:T,write:R,tap:$,press:V,release:A,scales:v,updateScale:O}),[g,b,T,R,$,V,A,v,O]);return _jsx(AutoCoreTagContext.Provider,{value:P,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";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})=>{const n=useRef(!1),c=useMemo(()=>({}),[]),r=a??c,{invoke:o,read:l,write:u,serverSubscribe:i,isConnected:f,subscribe:m,unsubscribe:y}=useContext(EventEmitterContext),[b,d]=useState(()=>{const e={};for(const a of t)void 0!==a.initialValue&&(e[a.tagName]=a.initialValue);return e}),[g,p]=useState({}),[v,C]=useState(r),N=useRef(v),h=useRef(b);useEffect(()=>{N.current=v},[v]),useEffect(()=>{h.current=b},[b]);const[T,w]=useState(!0),x=useCallback((e,t)=>{const{valueType:a,scale:s,codec:n}=e;if("number"===a&&"number"==typeof t&&s){const e=N.current[s];return t*(e?.scale??1)}if("json"===a&&n?.fromServer)try{return n.fromServer(t)}catch{}return t},[]),k=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=N.current[s];return t/(e?.scale??1)}return t},[]),E=useCallback(e=>{const a=t.filter(t=>t.scale===e);a.length&&p(e=>{const t={...e};for(const e of a){const a=h.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=useCallback((e,t)=>{d(a=>a[e.tagName]===t?a:{...a,[e.tagName]:t});const a=x(e,t);p(t=>t[e.tagName]===a?t:{...t,[e.tagName]:a})},[x]),M=useCallback(async(e,t,a)=>{const s=a?.concurrency??4,n=a?.minDelayMs??20,c=a?.jitterMs??40;let r=0;const u=Array.from({length:s},()=>(async()=>{for(;;){const a=r++;if(a>=t.length)return;const s=t[a];try{let t=!1;try{await o(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&&q(s,e.data)}catch(e){}}}catch(e){}finally{const e=Math.floor(Math.random()*c);await sleep(n+e)}}})());await Promise.all(u)},[o,l,q]),S=useCallback(async()=>{for(const[e,t]of Object.entries(r)){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;C(a=>({...a,[e]:{...a[e],scale:t,label:s??a[e]?.label??"---"}})),E(e)}}}catch{}}},[l,r,E]);useEffect(()=>{let e=!0;const a=[],c=async()=>{if(e&&!n.current){n.current=!0;try{await(async()=>{try{await S();for(const n of t){await i(n.tagName,n.fqdn,n.subscriptionOptions);const t=m(n.tagName,t=>{e&&q(n,t)});a.push(t),s&&l(n.fqdn).then(t=>{e&&t?.success&&q(n,t.data)}).catch(e=>{})}}finally{e&&setTimeout(()=>e&&w(!1),100)}})()}finally{e&&setTimeout(()=>e&&w(!1),100)}}};if(f())c();else{const e=m("HUB/connected",()=>{y(e),c()});a.push(e)}return()=>{e=!1,a.forEach(y),n.current=!1}},[m,y,f,o,i,s,t,S,M,q]);const j=useMemo(()=>Object.entries(r).filter(([,e])=>e.serverTag).map(([e,t])=>({scaleName:e,domain:t.serverTag.domain,symbolName:t.serverTag.symbolName})),[r]);useEffect(()=>{let e=!0;const t=[];for(const{scaleName:a,domain:s,symbolName:n}of j){const c=m(`${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;C(s=>({...s,[a]:{...s[a],scale:e,label:t??s[a]?.label??"---"}})),E(a)}});t.push(c)}return()=>{e=!1,t.forEach(y)}},[m,y,j,E]);const R=useCallback(async(e,a)=>{const s=t.find(t=>t.tagName===e);if(!s)return;const n=k(s,a);await u(s.fqdn,n)},[t,u,k]),$=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&(u(a.fqdn,!0).catch(e=>{}),await sleep(300),u(a.fqdn,!1).catch(e=>{}))},[t,u]),V=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&await u(a.fqdn,!0)},[t,u]),A=useCallback(async e=>{const a=t.find(t=>t.tagName===e);a&&"boolean"===a.valueType&&await u(a.fqdn,!1)},[t,u]),O=useCallback(async(e,t,a)=>{const s=v[e];if(s){if(s.serverTag){const n=`${s.serverTag.domain}.${s.serverTag.symbolName}`;await u(n,{name:e,scale:t,label:a})}C(s=>({...s,[e]:{...s[e],scale:t,label:a}})),E(e)}},[v,u,E]);useEffect(()=>{p(e=>{const a={...e};for(const e of t){const t=h.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,v]);const P=useMemo(()=>{const e=new Map;for(const a of t)e.set(a.fqdn,a);return e},[t]),B=useCallback(e=>P.get(e),[P]),F=useMemo(()=>({values:g,rawValues:b,isLoading:T,write:R,tap:$,press:V,release:A,scales:v,updateScale:O,findTagByFqdn:B}),[g,b,T,R,$,V,A,v,O,B]);return _jsx(AutoCoreTagContext.Provider,{value:F,children:e})};
@@ -286,6 +286,15 @@ export interface BaseContextValue<VMap extends Record<string, any>> {
286
286
  * @param newLabel - New units label (e.g., "inches")
287
287
  */
288
288
  updateScale: (scaleName: string, newScale: number, newLabel: string) => Promise<void>;
289
+ /**
290
+ * Look up a tag's full configuration by its FQDN (e.g., "gm.x_cycle_move_speed").
291
+ *
292
+ * Useful for subscribers that only know the remote topic (e.g., a
293
+ * `test_definitions` schema's `source` field) and need to resolve it to a
294
+ * local `tagName` before calling `subscribe(tagName, …)`. Returns undefined
295
+ * if no tag is registered for the given FQDN.
296
+ */
297
+ findTagByFqdn: (fqdn: string) => TagConfig | undefined;
289
298
  }
290
299
  export {};
291
300
  //# sourceMappingURL=AutoCoreTagTypes.d.ts.map
@@ -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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adcops/autocore-react",
3
- "version": "3.3.42",
3
+ "version": "3.3.44",
4
4
  "description": "A React component library for industrial user interfaces.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -2,6 +2,7 @@ import React, { useState, useEffect, useContext } from 'react';
2
2
  import { AutoComplete } from 'primereact/autocomplete';
3
3
  import type { AutoCompleteCompleteEvent } from 'primereact/autocomplete';
4
4
  import { EventEmitterContext } from '../core/EventEmitterContext';
5
+ import { AutoCoreTagContext } from '../core/AutoCoreTagContext';
5
6
  import { MessageType } from '../hub/CommandMessage';
6
7
  import { ValueInput } from './ValueInput';
7
8
  import { TextInput } from './TextInput';
@@ -57,35 +58,77 @@ export const TestSetupForm: React.FC<TestSetupFormProps> = ({
57
58
 
58
59
  const [isValid, setIsValid] = useState(false);
59
60
  const { invoke, write, subscribe, unsubscribe } = useContext(EventEmitterContext);
61
+ const { findTagByFqdn } = useContext(AutoCoreTagContext);
60
62
 
61
- // Subscribe to external tags if a field defines a source
63
+ // Subscribe to external tags if a field defines a source, and seed the
64
+ // current value once on mount so the form reflects existing GM state
65
+ // instead of staying blank until the next broadcast.
66
+ //
67
+ // The schema's `source` is the remote FQDN (e.g. "gm.x_cycle_move_speed"),
68
+ // but the frontend event bus dispatches on the local `tagName` that the
69
+ // AutoCoreTagProvider registered with the Hub. We resolve FQDN → tagName
70
+ // via `findTagByFqdn` before subscribing; otherwise the callback never
71
+ // fires. Initial reads still go by FQDN — the Hub accepts that directly.
62
72
  useEffect(() => {
63
73
  if (!schema) return;
64
-
74
+
65
75
  const allFields = [...schema.project_fields, ...schema.config_fields];
66
76
  const subs: any[] = [];
67
-
77
+
68
78
  for (const field of allFields) {
69
- if (field.source) {
70
- const subId = subscribe(field.source, (newVal: any) => {
79
+ if (!field.source) continue;
80
+
81
+ const source = field.source;
82
+ const fieldName = field.name;
83
+
84
+ const tag = findTagByFqdn(source);
85
+ if (!tag) {
86
+ console.warn(
87
+ `TestSetupForm: no tag registered for source "${source}" ` +
88
+ `(field "${fieldName}"). Add it to acTagSpec with "ux": true ` +
89
+ `in project.json, or live updates for this field won't arrive.`
90
+ );
91
+ } else {
92
+ const subId = subscribe(tag.tagName, (newVal: any) => {
71
93
  setConfig((prev: any) => {
72
- // Only update if it actually changed to prevent infinite loops
73
- if (prev[field.name] !== newVal) {
74
- return { ...prev, [field.name]: newVal };
94
+ if (prev[fieldName] !== newVal) {
95
+ return { ...prev, [fieldName]: newVal };
75
96
  }
76
97
  return prev;
77
98
  });
78
99
  });
79
100
  subs.push(subId);
80
101
  }
102
+
103
+ // Pub/sub only delivers future changes, not the current value.
104
+ // Fetch it explicitly so reloading the page doesn't blank the form.
105
+ (async () => {
106
+ try {
107
+ const resp: any = await invoke(
108
+ source as any,
109
+ MessageType.Read as any,
110
+ {} as any,
111
+ );
112
+ const current = resp?.data !== undefined ? resp.data : resp;
113
+ if (current !== undefined && current !== null) {
114
+ setConfig((prev: any) => (
115
+ prev[fieldName] === undefined || prev[fieldName] === null || prev[fieldName] === ''
116
+ ? { ...prev, [fieldName]: current }
117
+ : prev
118
+ ));
119
+ }
120
+ } catch (err) {
121
+ console.warn(`TestSetupForm: failed to seed "${fieldName}" from "${source}":`, err);
122
+ }
123
+ })();
81
124
  }
82
-
125
+
83
126
  return () => {
84
127
  for (const subId of subs) {
85
128
  unsubscribe(subId);
86
129
  }
87
130
  };
88
- }, [schema, subscribe, unsubscribe]);
131
+ }, [schema, subscribe, unsubscribe, invoke, findTagByFqdn]);
89
132
 
90
133
  useEffect(() => {
91
134
  const fetchProjects = async () => {
@@ -165,8 +208,7 @@ export const TestSetupForm: React.FC<TestSetupFormProps> = ({
165
208
  {isNum ? (
166
209
  <ValueInput
167
210
  label={undefined}
168
- value={config[field.name] != null ? Number(config[field.name]) : null}
169
- suffix={field.units ? ` ${field.units}` : undefined}
211
+ value={config[field.name] != null ? Number(config[field.name]) : null}
170
212
  onValueChanged={(val) => handleFieldChange(field, val)}
171
213
  className={!valid ? 'p-invalid' : ''}
172
214
  />
@@ -174,11 +216,13 @@ export const TestSetupForm: React.FC<TestSetupFormProps> = ({
174
216
  <TextInput
175
217
  label={undefined}
176
218
  value={config[field.name] != null ? String(config[field.name]) : ''}
177
- suffix={field.units ? ` ${field.units}` : undefined}
178
219
  onValueChanged={(val) => handleFieldChange(field, val)}
179
220
  className={!valid ? 'p-invalid' : ''}
180
221
  />
181
222
  )}
223
+
224
+ <span>{field.units ? ` ${field.units}` : undefined}</span>
225
+
182
226
  <span style={{ color: valid ? 'var(--green-500)' : 'var(--red-500)', display: 'flex', alignItems: 'center' }}>
183
227
  <i className={valid ? "pi pi-check" : "pi pi-times"}></i>
184
228
  </span>
@@ -147,10 +147,16 @@ export const TextInput: React.FC<TextInputProps> = (props) => {
147
147
  // Keep the DOM value a string at all times (no uncontrolled→controlled flip)
148
148
  const domValue = useMemo(() => toStr(entryValue), [entryValue]);
149
149
 
150
+ const isLabelDefined = () => {
151
+ return label !== undefined && label !== null && label !== '';
152
+ }
153
+
150
154
  return (
151
155
  <div>
152
156
  <div className="p-inputgroup">
153
- <span className="p-inputgroup-addon">{label}</span>
157
+ { isLabelDefined() &&
158
+ <span className="p-inputgroup-addon">{label}</span>
159
+ }
154
160
 
155
161
  {prefix !== undefined && <span className="p-inputgroup-addon">{prefix}</span>}
156
162
 
@@ -178,14 +184,14 @@ export const TextInput: React.FC<TextInputProps> = (props) => {
178
184
  disabled={disabled || !editing}
179
185
  className="p-button-success"
180
186
  onClick={accept}
181
- visible={editing}
187
+ visible={true}
182
188
  />
183
189
  <Button
184
190
  icon="pi pi-times"
185
191
  disabled={disabled || !editing}
186
192
  className="p-button-danger"
187
193
  onClick={reset}
188
- visible={editing}
194
+ visible={true}
189
195
  />
190
196
  </div>
191
197
 
@@ -205,7 +205,7 @@ interface ValueInputProps extends Omit<InputNumberProps, 'value' | 'size'> {
205
205
  * accepting and rejecting values and keyboard management.
206
206
  */
207
207
  export const ValueInput: React.FC<ValueInputProps> = ({
208
- label = '',
208
+ label,
209
209
  value = null,
210
210
  min = undefined,
211
211
  max = undefined,
@@ -322,7 +322,7 @@ export const ValueInput: React.FC<ValueInputProps> = ({
322
322
  };
323
323
 
324
324
  const isLabelDefined = () => {
325
- return label !== undefined && label !== null;
325
+ return label !== undefined && label !== null && label !== '';
326
326
  }
327
327
 
328
328
  return (
@@ -365,7 +365,7 @@ export const ValueInput: React.FC<ValueInputProps> = ({
365
365
  disabled={disabled || !editing}
366
366
  className="p-button-success"
367
367
  onClick={() => handleAcceptValue()}
368
- visible={editing}
368
+ visible={true}
369
369
  autoFocus={false}
370
370
  />
371
371
 
@@ -374,7 +374,7 @@ export const ValueInput: React.FC<ValueInputProps> = ({
374
374
  disabled={disabled || !editing}
375
375
  className="p-button-danger"
376
376
  onClickCapture={() => handleResetValue()}
377
- visible={editing}
377
+ visible={true}
378
378
  autoFocus={false}
379
379
  />
380
380
 
@@ -108,6 +108,7 @@ export const AutoCoreTagContext = createContext<BaseContextValue<VMapRuntime>>({
108
108
  release: async () => { },
109
109
  scales: {},
110
110
  updateScale: async () => { },
111
+ findTagByFqdn: () => undefined,
111
112
  });
112
113
 
113
114
  /**
@@ -636,6 +637,23 @@ export const AutoCoreTagProvider: React.FC<{
636
637
  });
637
638
  }, [tags, toDisplay, scaleValues]);
638
639
 
640
+ /**
641
+ * FQDN → TagConfig index, rebuilt whenever the `tags` prop changes.
642
+ * Used by `findTagByFqdn` below so consumers (e.g., TestSetupForm) can
643
+ * resolve a remote topic string to the local tagName the event bus
644
+ * dispatches on.
645
+ */
646
+ const tagsByFqdn = useMemo(() => {
647
+ const m = new Map<string, TagConfig>();
648
+ for (const t of tags) m.set(t.fqdn, t);
649
+ return m;
650
+ }, [tags]);
651
+
652
+ const findTagByFqdn = useCallback(
653
+ (fqdn: string): TagConfig | undefined => tagsByFqdn.get(fqdn),
654
+ [tagsByFqdn],
655
+ );
656
+
639
657
  /**
640
658
  * Construct context value. Memoized to prevent consumers from re-rendering
641
659
  * unless actual data changes.
@@ -651,7 +669,8 @@ export const AutoCoreTagProvider: React.FC<{
651
669
  release,
652
670
  scales: scaleValues,
653
671
  updateScale,
654
- }), [values, rawValues, isLoading, write, tap, press, release, scaleValues, updateScale]);
672
+ findTagByFqdn,
673
+ }), [values, rawValues, isLoading, write, tap, press, release, scaleValues, updateScale, findTagByFqdn]);
655
674
 
656
675
 
657
676
  return (
@@ -341,4 +341,14 @@ export interface BaseContextValue<VMap extends Record<string, any>> {
341
341
  * @param newLabel - New units label (e.g., "inches")
342
342
  */
343
343
  updateScale: (scaleName: string, newScale: number, newLabel: string) => Promise<void>;
344
+
345
+ /**
346
+ * Look up a tag's full configuration by its FQDN (e.g., "gm.x_cycle_move_speed").
347
+ *
348
+ * Useful for subscribers that only know the remote topic (e.g., a
349
+ * `test_definitions` schema's `source` field) and need to resolve it to a
350
+ * local `tagName` before calling `subscribe(tagName, …)`. Returns undefined
351
+ * if no tag is registered for the given FQDN.
352
+ */
353
+ findTagByFqdn: (fqdn: string) => TagConfig | undefined;
344
354
  }