@adcops/autocore-react 3.5.9 → 3.5.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/tis-editor/TisConfigEditor.css +11 -0
- package/dist/components/tis-editor/TisConfigEditor.d.ts.map +1 -1
- package/dist/components/tis-editor/TisConfigEditor.js +1 -1
- package/dist/components/tis-editor/editor/AuthoringContext.d.ts +37 -0
- package/dist/components/tis-editor/editor/AuthoringContext.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/AuthoringContext.js +1 -0
- package/dist/components/tis-editor/editor/ChartViewDialog.d.ts +11 -0
- package/dist/components/tis-editor/editor/ChartViewDialog.d.ts.map +1 -1
- package/dist/components/tis-editor/editor/ChartViewDialog.js +1 -1
- package/dist/components/tis-editor/editor/FieldArrayEditor.d.ts.map +1 -1
- package/dist/components/tis-editor/editor/FieldArrayEditor.js +1 -1
- package/dist/components/tis-editor/editor/RawDataEditor.d.ts.map +1 -1
- package/dist/components/tis-editor/editor/RawDataEditor.js +1 -1
- package/dist/components/tis-editor/editor/TestFieldDialog.d.ts +7 -0
- package/dist/components/tis-editor/editor/TestFieldDialog.d.ts.map +1 -1
- package/dist/components/tis-editor/editor/TestFieldDialog.js +1 -1
- package/dist/components/tis-editor/editor/ViewsEditor.d.ts.map +1 -1
- package/dist/components/tis-editor/editor/ViewsEditor.js +1 -1
- package/dist/components/varpick/VariableInput.d.ts +41 -0
- package/dist/components/varpick/VariableInput.d.ts.map +1 -0
- package/dist/components/varpick/VariableInput.js +1 -0
- package/dist/components/varpick/VariablePicker.d.ts +45 -0
- package/dist/components/varpick/VariablePicker.d.ts.map +1 -0
- package/dist/components/varpick/VariablePicker.js +1 -0
- package/dist/components/varpick/index.d.ts +16 -0
- package/dist/components/varpick/index.d.ts.map +1 -0
- package/dist/components/varpick/index.js +1 -0
- package/dist/components/varpick/tisCatalogs.d.ts +85 -0
- package/dist/components/varpick/tisCatalogs.d.ts.map +1 -0
- package/dist/components/varpick/tisCatalogs.js +1 -0
- package/dist/components/varpick/varpick.css +167 -0
- package/dist/core/AutoCoreTagContext.d.ts.map +1 -1
- package/dist/core/AutoCoreTagContext.js +1 -1
- package/dist/core/AutoCoreTagTypes.d.ts +13 -0
- package/dist/core/AutoCoreTagTypes.d.ts.map +1 -1
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/useGmVariables.d.ts +57 -0
- package/dist/hooks/useGmVariables.d.ts.map +1 -0
- package/dist/hooks/useGmVariables.js +1 -0
- package/dist/hooks/useSequenceProducers.d.ts +38 -0
- package/dist/hooks/useSequenceProducers.d.ts.map +1 -0
- package/dist/hooks/useSequenceProducers.js +1 -0
- package/package.json +5 -2
- package/src/components/index.ts +17 -0
- package/src/components/tis-editor/TisConfigEditor.css +11 -0
- package/src/components/tis-editor/TisConfigEditor.tsx +31 -0
- package/src/components/tis-editor/editor/AuthoringContext.tsx +43 -0
- package/src/components/tis-editor/editor/ChartViewDialog.tsx +24 -7
- package/src/components/tis-editor/editor/FieldArrayEditor.tsx +1 -0
- package/src/components/tis-editor/editor/RawDataEditor.tsx +7 -2
- package/src/components/tis-editor/editor/TestFieldDialog.tsx +66 -12
- package/src/components/tis-editor/editor/ViewsEditor.tsx +25 -0
- package/src/components/varpick/VariableInput.tsx +126 -0
- package/src/components/varpick/VariablePicker.tsx +168 -0
- package/src/components/varpick/index.ts +22 -0
- package/src/components/varpick/tisCatalogs.ts +235 -0
- package/src/components/varpick/varpick.css +167 -0
- package/src/core/AutoCoreTagContext.tsx +3 -1
- package/src/core/AutoCoreTagTypes.ts +14 -0
- package/src/hooks/index.ts +11 -0
- package/src/hooks/useGmVariables.ts +142 -0
- package/src/hooks/useSequenceProducers.ts +104 -0
- package/tools/tests/dist/TestFieldDialog-C4mKVh7q.js +32817 -0
- package/tools/tests/dist/autocore-react.css +257 -0
- package/tools/tests/dist/tis-editor.entry.js +8431 -40567
- package/tools/tests/dist/varpick.entry.js +113 -0
- package/tools/tests/live-server.probe.mjs +172 -0
- package/tools/tests/varpick.entry.tsx +81 -0
- package/tools/tests/varpick.test.mjs +208 -0
- package/tools/tests/vite.config.mjs +7 -2
- package/tools/tests/dist/tis-editor.entry.css +0 -90
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tisCatalogs.d.ts","sourceRoot":"","sources":["../../../src/components/varpick/tisCatalogs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAEH,KAAK,OAAO,EAEZ,KAAK,UAAU,EAElB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,iBAAiB;IAC9B,0DAA0D;IAC1D,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,yEAAyE;IACzE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACnD,yCAAyC;IACzC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAClD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAOnE;AAED,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAM5D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAC9B,GAAG,EAAE,iBAAiB,EACtB,IAAI,EAAE;IACF,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,GACF,OAAO,CA0CT;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACpC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CA2CV;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAqC7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{gmCatalog}from"@adcops/autocore-varpick";export function configSourceCatalog(e){return gmCatalog(e.variables,{spelling:"fqdn",writableOnly:!0,unitFor:e.unitFor,liveFor:e.liveFor})}export function boundCatalog(e){return gmCatalog(e.variables,{spelling:"token",unitFor:e.unitFor,liveFor:e.liveFor})}export function cycleSourceCatalog(e,t){const n=[],i=t.producedNames??[];if(i.length>0){const e=i.map(e=>({id:`seq:${e}`,insert:"",name:e,kind:"column",description:e===t.fieldName?"The sequence stores this name every cycle, and it matches this column. Nothing else is needed — leave Source empty.":`The sequence stores this name every cycle. It only lands in this column if the column is called "${e}" too.`,note:e===t.fieldName?void 0:`Rename this field to "${e}", or the value is recorded with no column to show it in.`,keywords:["sequence","store_value"]}));n.push({id:"sequence",title:"Recorded by the sequence",hint:"Matched by NAME, not by binding. Picking one clears Source — that is correct, and is how gen4_ac records every column.",entries:e})}return n.push(...gmCatalog(e.variables,{spelling:"fqdn",unitFor:e.unitFor,liveFor:e.liveFor})),n}export function chartFieldCatalog(e){const t=[],n=(e,t)=>e.map(e=>({id:`${t}:${e}`,insert:e,name:e,kind:"column"})),i=e.rawColumns??[],o=e.cycleFields??[],r=e.resultsFields??[],s="raw_trace"===e.viewType,l={id:"raw",title:"Raw trace columns",hint:"Per-cycle trace columns declared under Raw Data.",entries:n(i,"raw")},c={id:"cycle",title:"Cycle Data columns",hint:"One value per cycle.",entries:n(o,"cycle")};return s?t.push(l,c):t.push(c,l),t.push({id:"results",title:"Results",hint:"One value per test.",entries:n(r,"result")}),t.push({id:"test",title:"Test setup values",hint:"Entered once per test, so they plot as a constant across cycles.",entries:n(e.testFields??[],"test")}),t.filter(e=>e.entries.length>0)}export function rawSourceCatalog(e){const t=[{id:"builtin",title:"Built-in",entries:[{id:"src:time",insert:"time",name:"time",kind:"column",description:"Sample timestamp, seconds from the start of the cycle."},{id:"src:derived",insert:"derived",name:"derived",kind:"column",description:"Computed from the other columns by this column’s Formula."}]}];return e&&e.length>0&&t.push({id:"channels",title:"DAQ channels",hint:"Published by the acquisition module.",entries:e.map(e=>({id:`chan:${e}`,insert:e,name:e,kind:"column"}))}),t}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Variable picker.
|
|
3
|
+
*
|
|
4
|
+
* Colours come from the PrimeReact theme's variables so the dialog matches
|
|
5
|
+
* whatever theme the machine is running, light or dark. Every value has a
|
|
6
|
+
* literal fallback: an un-themed host (the playground, a test harness) must
|
|
7
|
+
* still render legible text rather than black on black.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.ac-varpick__input {
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: stretch;
|
|
13
|
+
gap: 0;
|
|
14
|
+
min-width: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.ac-varpick__input .p-inputtext {
|
|
18
|
+
flex: 1 1 auto;
|
|
19
|
+
min-width: 0;
|
|
20
|
+
border-top-right-radius: 0;
|
|
21
|
+
border-bottom-right-radius: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Sized to the full control height, not shrunk to fit: these screens are
|
|
25
|
+
* touchscreens, and a button an operator has to aim at is one they mis-tap. */
|
|
26
|
+
.ac-varpick__input > .p-button {
|
|
27
|
+
flex: 0 0 auto;
|
|
28
|
+
border-top-left-radius: 0;
|
|
29
|
+
border-bottom-left-radius: 0;
|
|
30
|
+
margin-left: -1px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.ac-varpick__hint {
|
|
34
|
+
font-size: 0.8125rem;
|
|
35
|
+
color: var(--text-color-secondary, #6b7280);
|
|
36
|
+
margin-bottom: 0.75rem;
|
|
37
|
+
line-height: 1.4;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.ac-varpick__search { width: 100%; }
|
|
41
|
+
|
|
42
|
+
.ac-varpick__empty {
|
|
43
|
+
padding: 1.5rem 0.25rem;
|
|
44
|
+
color: var(--text-color-secondary, #6b7280);
|
|
45
|
+
font-size: 0.875rem;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.ac-varpick__list {
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-direction: column;
|
|
51
|
+
gap: 1rem;
|
|
52
|
+
margin-top: 0.75rem;
|
|
53
|
+
/* Bounded so the search box and the footer stay put while the list moves. */
|
|
54
|
+
max-height: 55vh;
|
|
55
|
+
overflow-y: auto;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.ac-varpick__group { display: flex; flex-direction: column; gap: 2px; }
|
|
59
|
+
|
|
60
|
+
.ac-varpick__grouphead {
|
|
61
|
+
display: flex;
|
|
62
|
+
flex-wrap: wrap;
|
|
63
|
+
align-items: baseline;
|
|
64
|
+
gap: 0.5rem;
|
|
65
|
+
padding-bottom: 0.25rem;
|
|
66
|
+
margin-bottom: 0.25rem;
|
|
67
|
+
border-bottom: 1px solid var(--surface-border, rgba(127, 127, 127, 0.25));
|
|
68
|
+
position: sticky;
|
|
69
|
+
top: 0;
|
|
70
|
+
background: var(--surface-overlay, #ffffff);
|
|
71
|
+
z-index: 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.ac-varpick__grouptitle {
|
|
75
|
+
font-size: 0.75rem;
|
|
76
|
+
font-weight: 700;
|
|
77
|
+
letter-spacing: 0.04em;
|
|
78
|
+
text-transform: uppercase;
|
|
79
|
+
color: var(--text-color-secondary, #6b7280);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.ac-varpick__grouphint {
|
|
83
|
+
font-size: 0.75rem;
|
|
84
|
+
color: var(--text-color-secondary, #8b95a1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/*
|
|
88
|
+
* Two lines by design — the identifier, then what it MEANS. A one-line list of
|
|
89
|
+
* identifiers is the problem this dialog exists to solve, so the description is
|
|
90
|
+
* never truncated and never hidden behind a hover: there is no hover on a
|
|
91
|
+
* touchscreen.
|
|
92
|
+
*/
|
|
93
|
+
.ac-varpick__row {
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
align-items: flex-start;
|
|
97
|
+
gap: 2px;
|
|
98
|
+
width: 100%;
|
|
99
|
+
text-align: left;
|
|
100
|
+
min-height: 2.25rem;
|
|
101
|
+
padding: 0.375rem 0.75rem;
|
|
102
|
+
border: 1px solid transparent;
|
|
103
|
+
border-radius: 3px;
|
|
104
|
+
background: transparent;
|
|
105
|
+
color: var(--text-color, #111827);
|
|
106
|
+
font: inherit;
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.ac-varpick__row:hover { background: var(--surface-hover, rgba(127, 127, 127, 0.08)); }
|
|
111
|
+
|
|
112
|
+
.ac-varpick__row:focus-visible {
|
|
113
|
+
outline: 2px solid var(--primary-color, #2563eb);
|
|
114
|
+
outline-offset: -2px;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.ac-varpick__row--on {
|
|
118
|
+
background: var(--highlight-bg, rgba(37, 99, 235, 0.14));
|
|
119
|
+
border-color: var(--primary-color, #2563eb);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.ac-varpick__row--off { opacity: 0.55; cursor: default; }
|
|
123
|
+
|
|
124
|
+
.ac-varpick__line {
|
|
125
|
+
display: flex;
|
|
126
|
+
flex-wrap: wrap;
|
|
127
|
+
align-items: baseline;
|
|
128
|
+
gap: 0.5rem;
|
|
129
|
+
min-width: 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.ac-varpick__name {
|
|
133
|
+
font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
134
|
+
font-weight: 600;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.ac-varpick__label { font-size: 0.875rem; }
|
|
138
|
+
|
|
139
|
+
.ac-varpick__chip {
|
|
140
|
+
font-size: 0.75rem;
|
|
141
|
+
padding: 0 6px;
|
|
142
|
+
border-radius: 999px;
|
|
143
|
+
background: var(--surface-100, rgba(127, 127, 127, 0.12));
|
|
144
|
+
border: 1px solid var(--surface-border, rgba(127, 127, 127, 0.25));
|
|
145
|
+
color: var(--text-color-secondary, #6b7280);
|
|
146
|
+
/* A unit symbol's case is meaningful: "mm/s", "N", "MPa". */
|
|
147
|
+
text-transform: none;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* The current reading. Nothing turns an unfamiliar name into an obvious one
|
|
151
|
+
* faster than seeing what it says right now. */
|
|
152
|
+
.ac-varpick__live {
|
|
153
|
+
font-family: var(--font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
154
|
+
font-size: 0.75rem;
|
|
155
|
+
color: var(--green-600, #15803d);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.ac-varpick__desc {
|
|
159
|
+
font-size: 0.8125rem;
|
|
160
|
+
color: var(--text-color-secondary, #6b7280);
|
|
161
|
+
line-height: 1.35;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.ac-varpick__why { font-size: 0.8125rem; color: var(--orange-600, #b45309); }
|
|
165
|
+
.ac-varpick__note { font-size: 0.8125rem; color: var(--blue-600, #0369a1); }
|
|
166
|
+
|
|
167
|
+
.ac-varpick__foot { display: flex; justify-content: flex-end; gap: 0.5rem; }
|
|
@@ -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,EAGd,MAAM,oBAAoB,CAAC;AAK5B;;;GAGG;AACH,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE3C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,kBAAkB,
|
|
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,8CAY7B,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,CA8uBA,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";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})};
|
|
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:()=>{},tags:[]});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,tags:t,units:k,activeSystem:E,setUnitSystem:D,formatQuantity:Z}),[g,d,T,I,J,Q,K,C,W,Y,t,k,E,D,Z]);return _jsx(AutoCoreTagContext.Provider,{value:ee,children:e})};
|
|
@@ -370,6 +370,19 @@ export interface BaseContextValue<VMap extends Record<string, any>> {
|
|
|
370
370
|
* if no tag is registered for the given FQDN.
|
|
371
371
|
*/
|
|
372
372
|
findTagByFqdn: (fqdn: string) => TagConfig | undefined;
|
|
373
|
+
/**
|
|
374
|
+
* The tag spec this provider was built with.
|
|
375
|
+
*
|
|
376
|
+
* Exposed so a consumer can enumerate what the HMI knows about rather than
|
|
377
|
+
* having every host thread `acTagSpec` down by hand. The variable picker
|
|
378
|
+
* uses it as its fallback catalog when the server is an older build with no
|
|
379
|
+
* `gm.get_variables` — names and types, no descriptions.
|
|
380
|
+
*
|
|
381
|
+
* It is NOT the machine's full variable table: `acctl codegen-tags` emits
|
|
382
|
+
* only variables marked `ux: true`. Treat it as a floor, never as the
|
|
383
|
+
* authoritative list.
|
|
384
|
+
*/
|
|
385
|
+
tags: readonly TagConfig[];
|
|
373
386
|
}
|
|
374
387
|
export {};
|
|
375
388
|
//# sourceMappingURL=AutoCoreTagTypes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoCoreTagTypes.d.ts","sourceRoot":"","sources":["../../src/core/AutoCoreTagTypes.ts"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AAEH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAErE,oDAAoD;AACpD,KAAK,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AACtD,MAAM,MAAM,SAAS,GACf,aAAa,GACb;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAC5B,SAAS,EAAE,CAAC;AAElB;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,IAAI,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE1E;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,aAAa,IAC1C,CAAC,SAAS,SAAS,GAAG,OAAO,GAC7B,CAAC,SAAS,QAAQ,GAAG,MAAM,GAC3B,CAAC,SAAS,QAAQ,GAAG,MAAM,GAC3B,iBAAiB,CAAC;AAEtB;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,QAAQ,CAAC;IACjC,0CAA0C;IAC1C,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC;IACrB,6DAA6D;IAC7D,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,0EAA0E;IAC1E,KAAK,EAAE,CAAC,YAAY,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,4DAA4D;IAC5D,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,gCAAgC;IAChC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,iCAAiC;IACjC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,WAAW,mBAAmB;IAChC;;;;;;;;;;OAUG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,yDAAyD;AACzD,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,aAAa,CAAC;AAEvD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC5B,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,aAAa,CAAC;CAClC;AAED,0EAA0E;AAC1E,MAAM,WAAW,SAAS;IACtB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAC5B,8DAA8D;IAC9D,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACvB,oEAAoE;IACpE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACrC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IACxB,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE;QACR,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACtB,CAAC;CACL;AAED;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,CAAC,GAAG,GAAG,OAAO,EAAE,IAAI,SAAS,SAAS,GAAG,SAAS,IAAI;IACtE,iDAAiD;IACjD,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,GAAG,CAAC;IACnC,gDAAgD;IAChD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,SAAS,CACjB,CAAC,SAAS,MAAM,GAAG,MAAM,EACzB,CAAC,SAAS,aAAa,GAAG,aAAa,IACvC;IACA,+DAA+D;IAC/D,OAAO,EAAE,CAAC,CAAC;IAEX;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb,gEAAgE;IAChE,SAAS,EAAE,CAAC,CAAC;IAEb,gEAAgE;IAChE,YAAY,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAG7B;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,KAAK,CAAC,EAAE,QAAQ,CAAC;IAEjB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC7C,CAAC;AAEF,yEAAyE;AACzE,MAAM,MAAM,YAAY,CACpB,IAAI,SAAS,SAAS,SAAS,EAAE,EACjC,CAAC,IACD,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;IAAE,OAAO,EAAE,CAAC,CAAA;CAAE,CAAC,CAAC;AAE1C;;;GAGG;AACH,MAAM,MAAM,WAAW,CAAC,IAAI,SAAS,SAAS,SAAS,EAAE,IAAI;KACxD,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;CACjF,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,SAAS,CACjB,IAAI,SAAS,SAAS,SAAS,EAAE,EACjC,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,IACjC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAErC;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC9D,+DAA+D;IAC/D,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;;OAGG;IACH,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAE1B,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B;;;OAGG;IACH,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAC;IAEpE,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEnC,yCAAyC;IACzC,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,KAAK,EAAE,CAAC,CAAC,SAAS,MAAM,IAAI,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpF;;;OAGG;IACH,GAAG,EAAE,CAAC,CAAC,SAAS,MAAM,IAAI,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE,gCAAgC;IAChC,KAAK,EAAE,CAAC,CAAC,SAAS,MAAM,IAAI,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpE,iCAAiC;IACjC,OAAO,EAAE,CAAC,CAAC,SAAS,MAAM,IAAI,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtE,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAEpC;;;;;;OAMG;IACH,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtF;;;;;;;OAOG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"AutoCoreTagTypes.d.ts","sourceRoot":"","sources":["../../src/core/AutoCoreTagTypes.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export { useAdsRegisterSymbols, useAdsWriteValue, useAdsTapValue } from "./adsHooks";
|
|
2
2
|
export { useScaledValue, kMillimeters2Inches } from './useScaledValue';
|
|
3
3
|
export * from './useServeletData';
|
|
4
|
+
export { useGmVariables } from './useGmVariables';
|
|
5
|
+
export type { UseGmVariablesResult, UseGmVariablesOptions, GmIpcInvoker } from './useGmVariables';
|
|
6
|
+
export { useSequenceProducers, collectStoredNames } from './useSequenceProducers';
|
|
7
|
+
export type { UseSequenceProducersResult, UseSequenceProducersOptions } from './useSequenceProducers';
|
|
4
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAC,qBAAqB,EAAE,gBAAgB,EAAE,cAAc,EAAC,MAAM,YAAY,CAAC;AACnF,OAAO,EAAC,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACtE,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAC,qBAAqB,EAAE,gBAAgB,EAAE,cAAc,EAAC,MAAM,YAAY,CAAC;AACnF,OAAO,EAAC,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACtE,cAAc,mBAAmB,CAAC;AAKlC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAIlG,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAClF,YAAY,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{useAdsRegisterSymbols,useAdsWriteValue,useAdsTapValue}from"./adsHooks";export{useScaledValue,kMillimeters2Inches}from"./useScaledValue";export*from"./useServeletData";
|
|
1
|
+
export{useAdsRegisterSymbols,useAdsWriteValue,useAdsTapValue}from"./adsHooks";export{useScaledValue,kMillimeters2Inches}from"./useScaledValue";export*from"./useServeletData";export{useGmVariables}from"./useGmVariables";export{useSequenceProducers,collectStoredNames}from"./useSequenceProducers";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useGmVariables — the machine's GM variable table, for the variable picker.
|
|
3
|
+
*
|
|
4
|
+
* Reads `gm.get_variables`: `gm.get_catalog` with the metadata attached — type,
|
|
5
|
+
* description, quantity, and whether a UI may write the variable. Everything it
|
|
6
|
+
* returns already lives in project.json; the verb exists because a catalog of
|
|
7
|
+
* bare FQDN strings cannot tell an author what a name means, which is why every
|
|
8
|
+
* field that asks for one has been a text box.
|
|
9
|
+
*
|
|
10
|
+
* ## Degrading on an older server
|
|
11
|
+
*
|
|
12
|
+
* `gm.get_variables` was added alongside the picker, so a machine running an
|
|
13
|
+
* older `autocore_server` answers with an error. That is not a failure worth
|
|
14
|
+
* showing an operator: the picker still works, it just lists names without
|
|
15
|
+
* descriptions. So the hook falls back to the generated tag spec the HMI
|
|
16
|
+
* already has (`acTagSpec`), which carries FQDN, type and quantity but no prose,
|
|
17
|
+
* and reports the degradation through `partial` rather than through `error`.
|
|
18
|
+
*
|
|
19
|
+
* The fallback covers strictly less: `acctl codegen-tags` only emits variables
|
|
20
|
+
* marked `ux: true`, and a `${gm.…}` bound may legitimately name one that is
|
|
21
|
+
* not. Hence `partial` — a caller can say so on screen instead of quietly
|
|
22
|
+
* offering an incomplete list.
|
|
23
|
+
*/
|
|
24
|
+
import type { GmVariable } from '@adcops/autocore-varpick';
|
|
25
|
+
import type { TagConfig } from '../core/AutoCoreTagTypes';
|
|
26
|
+
export interface GmIpcInvoker {
|
|
27
|
+
(topic: string, payload: object): Promise<{
|
|
28
|
+
success: boolean;
|
|
29
|
+
data?: any;
|
|
30
|
+
error_message?: string;
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
export interface UseGmVariablesOptions {
|
|
34
|
+
invoker?: GmIpcInvoker;
|
|
35
|
+
/**
|
|
36
|
+
* The HMI's generated tag spec, used when the server cannot describe its
|
|
37
|
+
* own variables. Without it, an old server yields an empty picker.
|
|
38
|
+
*/
|
|
39
|
+
fallbackTags?: readonly TagConfig[];
|
|
40
|
+
/** Skip the read entirely (e.g. while a dialog is closed). */
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface UseGmVariablesResult {
|
|
44
|
+
variables: GmVariable[];
|
|
45
|
+
loading: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* True when the list came from the generated tag spec rather than the
|
|
48
|
+
* server — names and types, no descriptions, and `ux: true` variables only.
|
|
49
|
+
*/
|
|
50
|
+
partial: boolean;
|
|
51
|
+
/** Set only when there is nothing to show at all. */
|
|
52
|
+
error: string | null;
|
|
53
|
+
refresh: () => Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
export declare function useGmVariables(options?: UseGmVariablesOptions): UseGmVariablesResult;
|
|
56
|
+
export default useGmVariables;
|
|
57
|
+
//# sourceMappingURL=useGmVariables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGmVariables.d.ts","sourceRoot":"","sources":["../../src/hooks/useGmVariables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAG3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,WAAW,YAAY;IACzB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;QACtC,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,CAAC,EAAE,GAAG,CAAC;QACX,aAAa,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC,CAAC;CACN;AAED,MAAM,WAAW,qBAAqB;IAClC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACpC,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACjC,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB,qDAAqD;IACrD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAyBD,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,oBAAoB,CAsDpF;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useCallback,useContext,useEffect,useRef,useState}from"react";import{EventEmitterContext}from"../core/EventEmitterContext";import{MessageType}from"../hub/CommandMessage";function fromTagSpec(e){return e.filter(e=>"string"==typeof e.fqdn&&e.fqdn.toLowerCase().startsWith("gm.")).map(e=>({fqdn:e.fqdn,name:e.fqdn.slice(3),type:String(e.valueType??""),description:"",quantity:e.quantity??e.scale,ux:!0,nonvolatile:!1,writable:!0,is_signal:!1})).sort((e,t)=>e.name.localeCompare(t.name))}export function useGmVariables(e){const t=useContext(EventEmitterContext),a=!1!==e?.enabled,r=e?.invoker??(async(e,a)=>await t.invoke(e,MessageType.Request,a)),s=useRef(r);s.current=r;const n=useRef(e?.fallbackTags);n.current=e?.fallbackTags;const[o,i]=useState([]),[l,u]=useState(a),[c,f]=useState(!1),[m,g]=useState(null),p=useCallback(async()=>{u(!0);try{const e=await s.current("gm.get_variables",{}),t=e?.data?.variables;if(e?.success&&Array.isArray(t))return i(t),f(!1),void g(null);throw new Error(e?.error_message||"gm.get_variables returned no variables")}catch(e){const t=n.current;t&&t.length>0?(i(fromTagSpec(t)),f(!0),g(null)):(i([]),f(!1),g(String(e?.message??e)))}finally{u(!1)}},[]);return useEffect(()=>{a?p():u(!1)},[a,p]),{variables:o,loading:l,partial:c,error:m,refresh:p}}export default useGmVariables;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useSequenceProducers — the names a method's sequence actually records.
|
|
3
|
+
*
|
|
4
|
+
* A TIS cycle field has two possible producers and the method editor could only
|
|
5
|
+
* ever see one of them:
|
|
6
|
+
*
|
|
7
|
+
* 1. `source: "gm.<var>"` — the generated `add_cycle()` reads the tag.
|
|
8
|
+
* 2. `source: null` — the value arrives with the row, matched by NAME. On
|
|
9
|
+
* gen4_ac that is the sequencer: `store_value` steps fill a row buffer and
|
|
10
|
+
* `tis.add_cycle` writes `cycle_data` verbatim, without checking it against
|
|
11
|
+
* `cycle_fields`.
|
|
12
|
+
*
|
|
13
|
+
* Because nothing checks the second one, both of its failure modes are silent:
|
|
14
|
+
* a declared column nothing stores is blank on every row forever, and a stored
|
|
15
|
+
* name with no column is recorded where nothing displays it. This hook reads
|
|
16
|
+
* the `.seq.json` so the editor can say so.
|
|
17
|
+
*
|
|
18
|
+
* The method id IS the sequence filename and the TIS method id — one name, set
|
|
19
|
+
* by the sequence workbench's New / Save As / Open. A product with no sequencer
|
|
20
|
+
* simply has no such file, which is why "could not read it" resolves to
|
|
21
|
+
* `undefined` and never to `[]`: an empty list would claim every cycle field
|
|
22
|
+
* has no producer.
|
|
23
|
+
*/
|
|
24
|
+
export interface UseSequenceProducersOptions {
|
|
25
|
+
/** Override the IPC layer (tests, playground). */
|
|
26
|
+
invoker?: (topic: string, messageType: number, payload: object) => Promise<any>;
|
|
27
|
+
}
|
|
28
|
+
export interface UseSequenceProducersResult {
|
|
29
|
+
/** `store_value` names, or `undefined` when there is no sequence to read. */
|
|
30
|
+
producedNames: string[] | undefined;
|
|
31
|
+
loading: boolean;
|
|
32
|
+
refresh: () => Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
/** Every `store_value` name in a method, `cycle` bodies included. */
|
|
35
|
+
export declare function collectStoredNames(method: any): string[];
|
|
36
|
+
export declare function useSequenceProducers(methodId: string | null, options?: UseSequenceProducersOptions): UseSequenceProducersResult;
|
|
37
|
+
export default useSequenceProducers;
|
|
38
|
+
//# sourceMappingURL=useSequenceProducers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSequenceProducers.d.ts","sourceRoot":"","sources":["../../src/hooks/useSequenceProducers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAUH,MAAM,WAAW,2BAA2B;IACxC,kDAAkD;IAClD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;CACnF;AAED,MAAM,WAAW,0BAA0B;IACvC,6EAA6E;IAC7E,aAAa,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,GAAG,GAAG,MAAM,EAAE,CAiBxD;AAED,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,OAAO,CAAC,EAAE,2BAA2B,GACtC,0BAA0B,CAkC5B;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useCallback,useContext,useEffect,useRef,useState}from"react";import{EventEmitterContext}from"../core/EventEmitterContext";import{MessageType}from"../hub/CommandMessage";const METHOD_DIR="methods",METHOD_EXT=".seq.json";export function collectStoredNames(e){const t=[],o=e=>{if(Array.isArray(e))for(const s of e)s&&"object"==typeof s&&("cycle"===s.type&&o(s.body),"store_value"===s.type&&"string"==typeof s.name&&""!==s.name.trim()&&(t.includes(s.name)||t.push(s.name)))};return o(e?.steps),t}export function useSequenceProducers(e,t){const o=useContext(EventEmitterContext),s=t?.invoker??((e,t,s)=>o.invoke(e,t,s)),r=useRef(s);r.current=s;const[n,a]=useState(void 0),[c,u]=useState(!1),i=useCallback(async()=>{if(e){u(!0);try{const t=`datastore.methods/${e}${METHOD_EXT}`,o=await r.current(t,MessageType.Read,{});if(!1===o?.success)return void a(void 0);const s=o?.data??o;if(!s||!Array.isArray(s.steps))return void a(void 0);a(collectStoredNames(s))}catch{a(void 0)}finally{u(!1)}}else a(void 0)},[e]);return useEffect(()=>{i()},[i]),{producedNames:n,loading:c,refresh:i}}export default useSequenceProducers;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adcops/autocore-react",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.11",
|
|
4
4
|
"description": "A React component library for industrial user interfaces.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"release:patch": "npm version patch && npm publish",
|
|
23
23
|
"release:minor": "npm version minor && npm publish",
|
|
24
24
|
"release:major": "npm version major && npm publish",
|
|
25
|
-
"convert-assets": "npx @svgr/cli --typescript --out-dir src/assets/ src/assets/svg/ --jsx-runtime automatic --ignore-existing"
|
|
25
|
+
"convert-assets": "npx @svgr/cli --typescript --out-dir src/assets/ src/assets/svg/ --jsx-runtime automatic --ignore-existing",
|
|
26
|
+
"test:varpick": "vite build --config tools/tests/vite.config.mjs && node tools/tests/varpick.test.mjs",
|
|
27
|
+
"probe:live": "node tools/tests/live-server.probe.mjs"
|
|
26
28
|
},
|
|
27
29
|
"repository": {
|
|
28
30
|
"type": "git",
|
|
@@ -54,6 +56,7 @@
|
|
|
54
56
|
}
|
|
55
57
|
},
|
|
56
58
|
"dependencies": {
|
|
59
|
+
"@adcops/autocore-varpick": "^1.0.0",
|
|
57
60
|
"@monaco-editor/react": "^4.7.0",
|
|
58
61
|
"@tauri-apps/api": "^2.9.1",
|
|
59
62
|
"chart.js": "^4.5.1",
|
package/src/components/index.ts
CHANGED
|
@@ -127,3 +127,20 @@ export { NetworkPanel } from './network/NetworkPanel';
|
|
|
127
127
|
export type { NetworkPanelProps } from './network/NetworkPanel';
|
|
128
128
|
export { StagedChangeBanner } from './network/StagedChangeBanner';
|
|
129
129
|
export type { StagedChangeBannerProps } from './network/StagedChangeBanner';
|
|
130
|
+
|
|
131
|
+
// -----------------------------------------------------------------------
|
|
132
|
+
// Variable picker — a field with a button that opens a searchable, described
|
|
133
|
+
// list of the machine's variables, so nobody has to type `gm.<something>`
|
|
134
|
+
// from memory. Used by the TIS method editor; exported for any other
|
|
135
|
+
// authoring surface that asks for a machine value.
|
|
136
|
+
// -----------------------------------------------------------------------
|
|
137
|
+
export { VariablePicker, VariableInput } from './varpick';
|
|
138
|
+
export type { VariablePickerProps, VariableInputProps } from './varpick';
|
|
139
|
+
export {
|
|
140
|
+
boundCatalog,
|
|
141
|
+
chartFieldCatalog,
|
|
142
|
+
configSourceCatalog,
|
|
143
|
+
cycleSourceCatalog,
|
|
144
|
+
rawSourceCatalog,
|
|
145
|
+
} from './varpick';
|
|
146
|
+
export type { TisCatalogContext } from './varpick';
|
|
@@ -105,6 +105,17 @@
|
|
|
105
105
|
font-size: 0.8rem;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
/* A degradation, not a failure: the editor works, it just knows less. Amber
|
|
109
|
+
* rather than the red used for a real error. */
|
|
110
|
+
.tis-editor__notice {
|
|
111
|
+
background: #fffbeb;
|
|
112
|
+
color: #92400e;
|
|
113
|
+
border-left: 3px solid #d97706;
|
|
114
|
+
padding: 0.5rem 1rem;
|
|
115
|
+
margin: 0.5rem 1rem;
|
|
116
|
+
font-size: 0.875rem;
|
|
117
|
+
}
|
|
118
|
+
|
|
108
119
|
.tis-editor__empty {
|
|
109
120
|
flex: 1;
|
|
110
121
|
display: flex;
|
|
@@ -31,6 +31,10 @@ import { SaveDiffDialog } from './editor/SaveDiffDialog';
|
|
|
31
31
|
import type { TestMethod } from './types';
|
|
32
32
|
|
|
33
33
|
import './TisConfigEditor.css';
|
|
34
|
+
import { useGmVariables } from '../../hooks/useGmVariables';
|
|
35
|
+
import { useSequenceProducers } from '../../hooks/useSequenceProducers';
|
|
36
|
+
import { AuthoringContext } from './editor/AuthoringContext';
|
|
37
|
+
import { AutoCoreTagContext } from '../../core/AutoCoreTagContext';
|
|
34
38
|
|
|
35
39
|
export interface TisConfigEditorProps {
|
|
36
40
|
/** Project ID. Today this is informational (the server hosts one
|
|
@@ -70,6 +74,11 @@ export const TisConfigEditor: React.FC<TisConfigEditorProps> = ({ projectId, inv
|
|
|
70
74
|
);
|
|
71
75
|
|
|
72
76
|
const tis = useTisConfig(projectId, { invoker: effectiveInvoker });
|
|
77
|
+
|
|
78
|
+
// What the variable pickers offer. Read once for the editor rather than
|
|
79
|
+
// per dialog: the table is ~100 rows and every field dialog wants it.
|
|
80
|
+
const { tags } = useContext(AutoCoreTagContext);
|
|
81
|
+
const gm = useGmVariables({ invoker: effectiveInvoker, fallbackTags: tags });
|
|
73
82
|
const ams = useAmsAssetTypes({ invoker: effectiveInvoker });
|
|
74
83
|
const [selectedId, setSelectedId] = useState<string | null>(null);
|
|
75
84
|
const [draftError, setDraftError] = useState<string | null>(null);
|
|
@@ -101,6 +110,15 @@ export const TisConfigEditor: React.FC<TisConfigEditorProps> = ({ projectId, inv
|
|
|
101
110
|
// Clear errors whenever the selected method changes.
|
|
102
111
|
useEffect(() => { setDraftError(null); }, [selectedId]);
|
|
103
112
|
|
|
113
|
+
// The sequence that fills this method's cycle columns, if it has one. Keyed
|
|
114
|
+
// on the selected method because the method id IS the sequence filename.
|
|
115
|
+
const { producedNames } = useSequenceProducers(selectedId);
|
|
116
|
+
|
|
117
|
+
const authoring = useMemo(
|
|
118
|
+
() => ({ variables: gm.variables, producedNames, partial: gm.partial }),
|
|
119
|
+
[gm.variables, producedNames, gm.partial],
|
|
120
|
+
);
|
|
121
|
+
|
|
104
122
|
const onApply = async (next: TestMethod) => {
|
|
105
123
|
if (!selectedId) return;
|
|
106
124
|
setBusy(true);
|
|
@@ -197,6 +215,7 @@ export const TisConfigEditor: React.FC<TisConfigEditorProps> = ({ projectId, inv
|
|
|
197
215
|
};
|
|
198
216
|
|
|
199
217
|
return (
|
|
218
|
+
<AuthoringContext.Provider value={authoring}>
|
|
200
219
|
<div className="tis-editor">
|
|
201
220
|
<header className="tis-editor__header">
|
|
202
221
|
<h2>
|
|
@@ -228,6 +247,17 @@ export const TisConfigEditor: React.FC<TisConfigEditorProps> = ({ projectId, inv
|
|
|
228
247
|
</div>
|
|
229
248
|
)}
|
|
230
249
|
|
|
250
|
+
{/* Said out loud rather than left implicit: a picker that silently
|
|
251
|
+
lists two thirds of the machine sends an author hunting for a
|
|
252
|
+
variable that is there, just not offered. */}
|
|
253
|
+
{gm.partial && (
|
|
254
|
+
<div className="tis-editor__notice">
|
|
255
|
+
This server cannot describe its own variables, so the pickers are
|
|
256
|
+
listing only the variables published to this HMI, without descriptions.
|
|
257
|
+
Update autocore_server to get the full list.
|
|
258
|
+
</div>
|
|
259
|
+
)}
|
|
260
|
+
|
|
231
261
|
<div className="tis-editor__body">
|
|
232
262
|
<aside className="tis-editor__sidebar">
|
|
233
263
|
<div className="tis-editor__sidebar-actions">
|
|
@@ -321,6 +351,7 @@ export const TisConfigEditor: React.FC<TisConfigEditorProps> = ({ projectId, inv
|
|
|
321
351
|
onCancel={() => setSaveDialogOpen(false)}
|
|
322
352
|
/>
|
|
323
353
|
</div>
|
|
354
|
+
</AuthoringContext.Provider>
|
|
324
355
|
);
|
|
325
356
|
};
|
|
326
357
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the method editor's pickers can offer.
|
|
3
|
+
*
|
|
4
|
+
* A context rather than props because the fields that need it — a field
|
|
5
|
+
* dialog's Source, a bound, a chart axis, a raw column — sit three and four
|
|
6
|
+
* levels below the editor that fetches it, and threading the same two values
|
|
7
|
+
* through every intermediate component is how a prop list becomes noise.
|
|
8
|
+
*
|
|
9
|
+
* Everything here is optional. With none of it the pickers still open; they just
|
|
10
|
+
* have nothing to list, which is exactly the state the editor was in before they
|
|
11
|
+
* existed.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { createContext, useContext } from 'react';
|
|
15
|
+
import type { GmVariable } from '@adcops/autocore-varpick';
|
|
16
|
+
|
|
17
|
+
export interface AuthoringCatalogs {
|
|
18
|
+
/** The machine's GM variable table, from `gm.get_variables`. */
|
|
19
|
+
variables: GmVariable[];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* `store_value` names in the selected method's sequence.
|
|
23
|
+
*
|
|
24
|
+
* `undefined` means "not looked up" — the host could not read the
|
|
25
|
+
* `.seq.json`, or this product has no sequencer. That is deliberately
|
|
26
|
+
* different from `[]`, which means "read it, and it stores nothing": the
|
|
27
|
+
* first must not claim a cycle field has no producer.
|
|
28
|
+
*/
|
|
29
|
+
producedNames?: string[];
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* True when `variables` came from the generated tag spec rather than the
|
|
33
|
+
* server — names and types, no descriptions, `ux: true` only.
|
|
34
|
+
*
|
|
35
|
+
* Worth surfacing: a picker that silently lists two thirds of the machine
|
|
36
|
+
* is worse than one that says it is listing two thirds of the machine.
|
|
37
|
+
*/
|
|
38
|
+
partial?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const AuthoringContext = createContext<AuthoringCatalogs>({ variables: [] });
|
|
42
|
+
|
|
43
|
+
export const useAuthoringCatalogs = (): AuthoringCatalogs => useContext(AuthoringContext);
|