@adcops/autocore-react 3.3.57 → 3.3.61

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,7 +1,13 @@
1
1
  export { TisProvider, TisContext, useTis, useTisSchemas, useTisState, useTisSelection, useTisRuns, useTisRun, } from './tis/TisProvider';
2
2
  export type { TisProviderProps, TisContextValue, TisLiveState, TisSelection, TisSelectionPatch, TisRunCacheEntry, SchemaRegistry, TisMethodSchema, } from './tis/TisProvider';
3
+ export { ProjectSelector } from './tis/ProjectSelector';
4
+ export type { ProjectSelectorProps } from './tis/ProjectSelector';
3
5
  export { TestSetupForm } from './tis/TestSetupForm';
4
6
  export type { TestSetupFormProps } from './tis/TestSetupForm';
7
+ export { ProjectInfoDialog } from './tis/ProjectInfoDialog';
8
+ export type { ProjectInfoDialogProps, ProjectInfoMode } from './tis/ProjectInfoDialog';
9
+ export { TestMethodDialog } from './tis/TestMethodDialog';
10
+ export type { TestMethodDialogProps } from './tis/TestMethodDialog';
5
11
  export { ResultHistoryTable } from './tis/ResultHistoryTable';
6
12
  export type { ResultHistoryTableProps } from './tis/ResultHistoryTable';
7
13
  export { TestDataView } from './tis/TestDataView';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACH,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,EACb,WAAW,EACX,eAAe,EACf,UAAU,EACV,SAAS,GACZ,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACR,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,aAAa,EAAE,MAAY,qBAAqB,CAAC;AAC1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,kBAAkB,EAAE,MAAO,0BAA0B,CAAC;AAC/D,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,MAAa,oBAAoB,CAAC;AACzD,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7G,OAAO,EAAE,eAAe,EAAE,MAAU,uBAAuB,CAAC;AAC5D,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAQA,OAAO,EACH,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,EACb,WAAW,EACX,eAAe,EACf,UAAU,EACV,SAAS,GACZ,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACR,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,eAAe,GAClB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,MAAU,uBAAuB,CAAC;AAC5D,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,MAAY,qBAAqB,CAAC;AAC1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,iBAAiB,EAAE,MAAQ,yBAAyB,CAAC;AAC9D,YAAY,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAEvF,OAAO,EAAE,gBAAgB,EAAE,MAAS,wBAAwB,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,MAAO,0BAA0B,CAAC;AAC/D,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,MAAa,oBAAoB,CAAC;AACzD,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7G,OAAO,EAAE,eAAe,EAAE,MAAU,uBAAuB,CAAC;AAC5D,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -1 +1 @@
1
- export{TisProvider,TisContext,useTis,useTisSchemas,useTisState,useTisSelection,useTisRuns,useTisRun}from"./tis/TisProvider";export{TestSetupForm}from"./tis/TestSetupForm";export{ResultHistoryTable}from"./tis/ResultHistoryTable";export{TestDataView}from"./tis/TestDataView";export{TestRawDataView}from"./tis/TestRawDataView";
1
+ export{TisProvider,TisContext,useTis,useTisSchemas,useTisState,useTisSelection,useTisRuns,useTisRun}from"./tis/TisProvider";export{ProjectSelector}from"./tis/ProjectSelector";export{TestSetupForm}from"./tis/TestSetupForm";export{ProjectInfoDialog}from"./tis/ProjectInfoDialog";export{TestMethodDialog}from"./tis/TestMethodDialog";export{ResultHistoryTable}from"./tis/ResultHistoryTable";export{TestDataView}from"./tis/TestDataView";export{TestRawDataView}from"./tis/TestRawDataView";
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import type { TestFieldDef } from './TestSetupForm';
3
+ export type ProjectInfoMode = 'create' | 'edit';
4
+ export interface ProjectInfoDialogProps {
5
+ visible: boolean;
6
+ onHide: () => void;
7
+ mode: ProjectInfoMode;
8
+ /** Project ID being created (`create` mode) or edited (`edit`). */
9
+ projectId: string;
10
+ /** Schema field defs for `project_fields` (from the selected method). */
11
+ projectFields: TestFieldDef[];
12
+ /**
13
+ * Called after a successful create/update with the values that
14
+ * landed on the server. Used by the parent form to refresh its
15
+ * known-projects list and to fold the new fields into subsequent
16
+ * `tis.stage_test` payloads without an extra round-trip.
17
+ */
18
+ onSubmitted: (projectId: string, projectFields: Record<string, any>) => void;
19
+ }
20
+ export declare const ProjectInfoDialog: React.FC<ProjectInfoDialogProps>;
21
+ //# sourceMappingURL=ProjectInfoDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProjectInfoDialog.d.ts","sourceRoot":"","sources":["../../../src/components/tis/ProjectInfoDialog.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAShF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEhD,MAAM,WAAW,sBAAsB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,IAAI,EAAE,eAAe,CAAC;IACtB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B;;;;;OAKG;IACH,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CAChF;AAUD,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA+O9D,CAAC"}
@@ -0,0 +1 @@
1
+ import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";import React,{useContext,useEffect,useMemo,useRef,useState}from"react";import{Button}from"primereact/button";import{Dialog}from"primereact/dialog";import{Tooltip}from"primereact/tooltip";import{EventEmitterContext}from"../../core/EventEmitterContext";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";import{MessageType}from"../../hub/CommandMessage";import{ValueInput}from"../ValueInput";import{TextInput}from"../TextInput";const labelOf=e=>{const t=e.label&&e.label.length>0?e.label:e.name;return e.units?`${t} [${e.units}]`:t},hasDescription=e=>"string"==typeof e.description&&e.description.length>0;export const ProjectInfoDialog=({visible:e,onHide:t,mode:r,projectId:o,projectFields:n,onSubmitted:s})=>{const{invoke:i,write:a}=useContext(EventEmitterContext),{rawValues:c,findTagByFqdn:l}=useContext(AutoCoreTagContext),[m,p]=useState({}),[u,d]=useState(!1),[f,j]=useState(null),x=useRef("");useEffect(()=>{if(!e)return;const t=`${r}:${o}`;if(x.current===t)return;x.current=t;let s=!1;j(null);const a={};for(const e of n){if(!e.source)continue;const t=l(e.source);if(!t)continue;const r=c[t.tagName];null!=r&&(a[e.name]=r)}return"create"===r?s||p(a):(async()=>{try{const e=await i("tis.read_project",MessageType.Request,{project_id:o});if(s)return;if(e?.success){const t={...e.data?.project_fields??{}};for(const e of n)e.source&&void 0!==a[e.name]&&(t[e.name]=a[e.name]);p(t)}else j(e?.error_message??"Failed to read project")}catch(e){s||j(String(e instanceof Error?e.message:e))}})(),()=>{s=!0}},[e,o,r]),useEffect(()=>{e||(x.current="")},[e]);const g=(e,t)=>{p(r=>({...r,[e.name]:t}))},h=useMemo(()=>{for(const e of n){if(!e.required)continue;const t=m[e.name];if(null==t||""===t)return!1}return!0},[n,m]),_=_jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem"},children:[_jsx(Button,{label:"Cancel",icon:"pi pi-times",onClick:t,disabled:u,text:!0}),_jsx(Button,{label:"create"===r?"Create Project":"Save",icon:u?"pi pi-spin pi-spinner":"create"===r?"pi pi-plus":"pi pi-check",onClick:async()=>{if(h&&!u){d(!0);try{for(const e of n){if(!e.source)continue;const t=m[e.name];if(null!=t)try{await a(e.source,t)}catch(e){}}const e={};for(const t of n)void 0!==m[t.name]&&(e[t.name]=m[t.name]);const c="create"===r?"tis.create_project":"tis.update_project",l=await i(c,MessageType.Request,{project_id:o,project_fields:e});l?.success?(s(o,e),t()):alert(`Failed: ${l?.error_message??"unknown error"}`)}catch(e){alert(`Failed: ${e instanceof Error?e.message:String(e)}`)}finally{d(!1)}}},disabled:!h||u})]});return _jsxs(Dialog,{header:"create"===r?`Create project: ${o||"(no ID)"}`:`Edit project information: ${o}`,visible:e,onHide:t,footer:_,modal:!0,style:{width:"min(640px, 90vw)"},closable:!u,children:[f&&_jsx("div",{style:{color:"var(--red-500)",marginBottom:"1rem"},children:f}),0===n.length?_jsx("p",{style:{color:"var(--text-secondary-color)"},children:"create"===r?`Click "Create Project" to create the empty project "${o}". This method declares no project_fields, so there's nothing to fill in.`:"This method declares no project_fields, so there's nothing to edit."}):_jsx("div",{className:"ac-form-grid",style:{padding:"0.25rem 0",gridTemplateColumns:"auto 1fr 1.75rem 1.75rem"},children:n.map(e=>{const t=(e=>{if(!e.required)return!0;const t=m[e.name];return null!=t&&""!==t})(e),r="string"!==e.type&&"bool"!==e.type,o=`acProjInfo_${e.name}`;return _jsxs(React.Fragment,{children:[_jsx("span",{className:"ac-form-label",children:labelOf(e)}),r?_jsx(ValueInput,{label:void 0,value:null!=m[e.name]?Number(m[e.name]):null,onValueChanged:t=>g(e,t),className:t?"":"p-invalid"}):_jsx(TextInput,{label:void 0,value:null!=m[e.name]?String(m[e.name]):"",onValueChanged:t=>g(e,t),className:t?"":"p-invalid"}),hasDescription(e)?_jsxs(_Fragment,{children:[_jsx(Tooltip,{target:`#${o}`,position:"left"}),_jsx("span",{id:o,"data-pr-tooltip":e.description,style:{display:"inline-flex",alignItems:"center",justifyContent:"center",cursor:"help"},children:_jsx("i",{className:"pi pi-info-circle",style:{color:"var(--text-secondary-color)"}})})]}):_jsx("span",{"aria-hidden":"true"}),_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)})})]})};
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ export interface ProjectSelectorProps {
3
+ /**
4
+ * Optional override of the method whose `project_fields` are shown
5
+ * in the create / edit dialog. By default the dialog uses the
6
+ * provider's selected method (which is what you want — the
7
+ * project's metadata schema is per-method, and the form on the
8
+ * Test tab is going to use that same method anyway). Passing this
9
+ * is only useful if you have a "view-only" Project tab in a
10
+ * read-only HMI and want to lock the dialog to a specific method.
11
+ */
12
+ methodIdOverride?: string;
13
+ }
14
+ export declare const ProjectSelector: React.FC<ProjectSelectorProps>;
15
+ //# sourceMappingURL=ProjectSelector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProjectSelector.d.ts","sourceRoot":"","sources":["../../../src/components/tis/ProjectSelector.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAc7D,MAAM,WAAW,oBAAoB;IACjC;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA6I1D,CAAC"}
@@ -0,0 +1 @@
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useContext,useState,useMemo}from"react";import{AutoComplete}from"primereact/autocomplete";import{Button}from"primereact/button";import{EventEmitterContext}from"../../core/EventEmitterContext";import{useTis}from"./TisProvider";import{ProjectInfoDialog}from"./ProjectInfoDialog";const PROJECT_ID_RE=/^[A-Za-z0-9_-]+$/,isValidProjectIdFormat=e=>PROJECT_ID_RE.test(e);export const ProjectSelector=({methodIdOverride:e})=>{const t=useTis(),{invoke:o}=useContext(EventEmitterContext),i=t.selection.projectId,r=e??t.selection.methodId??t.defaultMethodId??Object.keys(t.schemas)[0]??"",s=r?t.schemas[r]:void 0,c=s?.project_fields??[],[n,a]=useState([]),[l,p]=useState(!1),[m,d]=useState(!1),j=""!==i.trim()&&t.projectKnown(i.trim()),u=isValidProjectIdFormat(i.trim()),x=""!==i.trim()&&u&&!t.projectKnown(i.trim()),f=(e,o)=>{t.markProjectJustCreated(e),t.setProjectFields(e,o),t.refreshProjects(),t.selection.projectId!==e&&t.setSelection({projectId:e})},_=useMemo(()=>j?{color:"var(--green-500)",icon:"pi-check-circle"}:""===i.trim()?{color:"var(--text-secondary-color)",icon:"pi-info-circle"}:{color:"var(--red-500)",icon:"pi-exclamation-circle"},[j,i]);return _jsxs("div",{className:"ac-form-grid",style:{padding:"1.25rem",gridTemplateColumns:"auto 1fr 1.75rem 1.75rem"},children:[_jsxs("h3",{className:"ac-form-section",style:{display:"flex",alignItems:"center",gap:"10px"},children:["Project",_jsx("span",{style:{color:_.color},children:_jsx("i",{className:`pi ${_.icon}`})})]}),_jsx("span",{className:"ac-form-label",children:"Project ID"}),_jsxs("div",{className:"p-inputgroup",style:{flex:1},children:[_jsx(AutoComplete,{value:i,suggestions:n,completeMethod:e=>{const o=e.query.toLowerCase();a(t.existingProjects.filter(e=>e.toLowerCase().includes(o)))},onChange:e=>(e=>{const o=(e||"").replace(/[^a-zA-Z0-9_-]/g,"");t.setSelection({projectId:o})})(e.value),dropdown:!0,placeholder:"Select an existing Project ID, or type a new one and click +",className:i.trim()&&!j?"p-invalid":"",style:{flex:1}}),_jsx(Button,{icon:"pi pi-plus",type:"button",onClick:()=>p(!0),disabled:!x,tooltip:i.trim()?u?t.projectKnown(i.trim())?"Project already exists":`Create project "${i.trim()}"`:"Letters, digits, _ and - only":"Type a project ID first",tooltipOptions:{position:"top"}}),_jsx(Button,{icon:"pi pi-pencil",type:"button",onClick:()=>d(!0),disabled:!j,tooltip:j?`Edit information for "${i.trim()}"`:"Select an existing project to edit",tooltipOptions:{position:"top"}})]}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:j?"var(--green-500)":""===i.trim()?"var(--text-secondary-color)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:j?"pi pi-check":""===i.trim()?"pi pi-minus":"pi pi-times"})}),_jsx(ProjectInfoDialog,{visible:l,onHide:()=>p(!1),mode:"create",projectId:i.trim(),projectFields:c,onSubmitted:f}),_jsx(ProjectInfoDialog,{visible:m,onHide:()=>d(!1),mode:"edit",projectId:i.trim(),projectFields:c,onSubmitted:f})]})};
@@ -39,6 +39,10 @@ export interface TestMethod {
39
39
  views?: {
40
40
  [name: string]: ChartView;
41
41
  };
42
+ /** Optional pretty label for the Test Method picker. */
43
+ label?: string;
44
+ /** Optional long-form description for the picker. */
45
+ description?: string;
42
46
  }
43
47
  export interface TestDataViewProps {
44
48
  /** Optional override; defaults to `useTisSelection().projectId`. */
@@ -1 +1 @@
1
- {"version":3,"file":"TestDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestDataView.tsx"],"names":[],"mappings":"AAUA,OAAO,KAA2D,MAAM,OAAO,CAAC;AA6BhF,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,SAAS;IAAI,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CAAE;AAChF,MAAM,WAAW,WAAW;IAAG,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAAE;AAC5G,MAAM,WAAW,SAAS;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,eAAe,GAAG,WAAW,CAAC;IACpC,CAAC,EAAE,SAAS,CAAC;IACb,CAAC,EAAE,WAAW,EAAE,CAAC;CACpB;AACD,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACrC;AACD,MAAM,WAAW,UAAU;IACvB,cAAc,EAAG,YAAY,EAAE,CAAC;IAChC,aAAa,EAAI,YAAY,EAAE,CAAC;IAChC,YAAY,EAAK,YAAY,EAAE,CAAC;IAChC,cAAc,EAAG,YAAY,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAQ,YAAY,GAAG,IAAI,CAAC;IACrC,KAAK,CAAC,EAAW;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;CAClD;AAED,MAAM,WAAW,iBAAiB;IAC9B,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,CAAC,EAAG,MAAM,CAAC;IACnB,gEAAgE;IAChE,KAAK,CAAC,EAAM,MAAM,CAAC;IACnB,kEAAkE;IAClE,MAAM,CAAC,EAAK,UAAU,CAAC;IACvB,8EAA8E;IAC9E,UAAU,CAAC,EAAG,MAAM,CAAC;IACrB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAID,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgPpD,CAAC"}
1
+ {"version":3,"file":"TestDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestDataView.tsx"],"names":[],"mappings":"AAUA,OAAO,KAA2D,MAAM,OAAO,CAAC;AA6BhF,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,SAAS;IAAI,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CAAE;AAChF,MAAM,WAAW,WAAW;IAAG,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAAE;AAC5G,MAAM,WAAW,SAAS;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,eAAe,GAAG,WAAW,CAAC;IACpC,CAAC,EAAE,SAAS,CAAC;IACb,CAAC,EAAE,WAAW,EAAE,CAAC;CACpB;AACD,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CACrC;AACD,MAAM,WAAW,UAAU;IACvB,cAAc,EAAG,YAAY,EAAE,CAAC;IAChC,aAAa,EAAI,YAAY,EAAE,CAAC;IAChC,YAAY,EAAK,YAAY,EAAE,CAAC;IAChC,cAAc,EAAG,YAAY,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAQ,YAAY,GAAG,IAAI,CAAC;IACrC,KAAK,CAAC,EAAW;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC/C,wDAAwD;IACxD,KAAK,CAAC,EAAW,MAAM,CAAC;IACxB,qDAAqD;IACrD,WAAW,CAAC,EAAK,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAC9B,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,CAAC,EAAG,MAAM,CAAC;IACnB,gEAAgE;IAChE,KAAK,CAAC,EAAM,MAAM,CAAC;IACnB,kEAAkE;IAClE,MAAM,CAAC,EAAK,UAAU,CAAC;IACvB,8EAA8E;IAC9E,UAAU,CAAC,EAAG,MAAM,CAAC;IACrB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAID,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgPpD,CAAC"}
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ export interface TestMethodDialogProps {
3
+ visible: boolean;
4
+ onHide: () => void;
5
+ /** Method ID currently selected on the form. The dropdown opens
6
+ * pointing at this value so the dialog reflects current state. */
7
+ currentMethodId: string;
8
+ /**
9
+ * Called with the chosen method_id when the operator clicks OK.
10
+ * Cancel does not fire this callback. The parent is responsible
11
+ * for actually applying the new selection (e.g., updating the
12
+ * provider's selection or local state).
13
+ */
14
+ onSelected: (methodId: string) => void;
15
+ }
16
+ export declare const TestMethodDialog: React.FC<TestMethodDialogProps>;
17
+ //# sourceMappingURL=TestMethodDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TestMethodDialog.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestMethodDialog.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAO5D,MAAM,WAAW,qBAAqB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB;uEACmE;IACnE,eAAe,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAOD,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAsG5D,CAAC"}
@@ -0,0 +1 @@
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useEffect,useMemo,useState}from"react";import{Button}from"primereact/button";import{Dialog}from"primereact/dialog";import{Dropdown}from"primereact/dropdown";import{useTisSchemas}from"./TisProvider";const methodLabelOf=(e,t)=>t?.label&&t.label.length>0?t.label:e;export const TestMethodDialog=({visible:e,onHide:t,currentMethodId:o,onSelected:r})=>{const s=useTisSchemas(),[l,i]=useState(o);useEffect(()=>{e&&i(o)},[e,o]);const d=useMemo(()=>Object.keys(s).map(e=>({label:methodLabelOf(e,s[e]),value:e})),[s]),a=s[l],n=a?.description&&a.description.length>0?a.description:null,c=_jsxs("div",{style:{display:"flex",justifyContent:"flex-end",gap:"0.5rem"},children:[_jsx(Button,{label:"Cancel",icon:"pi pi-times",onClick:t,text:!0}),_jsx(Button,{label:"OK",icon:"pi pi-check",onClick:()=>{l&&l!==o&&r(l),t()},disabled:!l})]});return _jsx(Dialog,{header:"Select Test Method",visible:e,onHide:t,footer:c,modal:!0,style:{width:"min(560px, 90vw)"},children:0===d.length?_jsxs("p",{style:{color:"var(--text-secondary-color)"},children:["No test methods are declared in this project's ",_jsx("code",{children:"test_methods"})," block."]}):_jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[_jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.75rem"},children:[_jsx("label",{htmlFor:"acTestMethodDropdown",style:{flexShrink:0},children:"Test Method:"}),_jsx(Dropdown,{inputId:"acTestMethodDropdown",value:l,options:d,onChange:e=>i(e.value),placeholder:"Select a method",style:{flex:1}})]}),_jsx("div",{style:{padding:"0.75rem 1rem",background:"var(--surface-100)",borderRadius:"6px",minHeight:"4.5rem",color:n?"var(--text-color)":"var(--text-secondary-color)",fontStyle:n?"normal":"italic",whiteSpace:"pre-wrap"},children:n??"No description provided for this test method."})]})})};
@@ -1,33 +1,42 @@
1
1
  import React from 'react';
2
2
  export interface TestFieldDef {
3
+ /** Canonical key — wire format, generated code, on-disk JSON. */
3
4
  name: string;
4
5
  type: string;
5
6
  units?: string;
6
7
  required?: boolean;
7
8
  source?: string;
9
+ /** Pretty label rendered by the form. Falls back to `name`. Units
10
+ * are appended automatically; don't pre-format `[mm]` into label. */
11
+ label?: string;
12
+ /** Long-form guidance surfaced as a hover tooltip on an info icon. */
13
+ description?: string;
8
14
  }
9
15
  export interface TestMethod {
10
16
  project_fields: TestFieldDef[];
11
17
  config_fields: TestFieldDef[];
12
18
  cycle_fields: TestFieldDef[];
13
19
  results_fields: TestFieldDef[];
20
+ /** Optional pretty label for the Test Method picker. Falls back
21
+ * to the canonical method_id key. */
22
+ label?: string;
23
+ /** Optional long-form description shown in the picker dialog
24
+ * when this method is highlighted. */
25
+ description?: string;
14
26
  }
15
27
  /**
16
- * Props are all optional overrides by default the form drives itself
17
- * from the surrounding `<TisProvider>`. Pass any of these to lock that
18
- * particular axis.
28
+ * Test-setup form. Renders Sample ID, Test Method picker, and Test
29
+ * Configuration. Project ID lives in `<ProjectSelector>` on its own
30
+ * tab — this form reads the selected project from `<TisProvider>`
31
+ * and gates staging on it being a known project (created via the
32
+ * Project tab's `+` button).
19
33
  *
20
- * - `schema`: bypass `useTisSchemas()` for the selected method.
21
- * - `defaultProjectId` / `defaultMethodId`: seed the form's local
22
- * state when the corresponding TIS-context fields are blank.
23
- * - `onProjectChange` / `onMethodChange` / `onValidationChange`:
24
- * receive callbacks in addition to the provider's selection state.
34
+ * All props are optional overrides — by default the form drives
35
+ * itself from the surrounding `<TisProvider>`.
25
36
  */
26
37
  export interface TestSetupFormProps {
27
38
  schema?: TestMethod;
28
- defaultProjectId?: string;
29
39
  defaultMethodId?: string;
30
- onProjectChange?: (projectId: string) => void;
31
40
  onMethodChange?: (methodId: string) => void;
32
41
  onValidationChange?: (isValid: boolean, config: any) => void;
33
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TestSetupForm.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestSetupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAWxE,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,UAAU;IACvB,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;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IAC/B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,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,CA2QtD,CAAC"}
1
+ {"version":3,"file":"TestSetupForm.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestSetupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAYxE,MAAM,WAAW,YAAY;IACzB,iEAAiE;IACjE,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;IAChB;0EACsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACvB,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B;0CACsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;2CACuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IAC/B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAChE;AAmBD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAmStD,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useState,useEffect,useContext,useMemo}from"react";import{AutoComplete}from"primereact/autocomplete";import{SelectButton}from"primereact/selectbutton";import{EventEmitterContext}from"../../core/EventEmitterContext";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";import{MessageType}from"../../hub/CommandMessage";import{ValueInput}from"../ValueInput";import{TextInput}from"../TextInput";import{useTis}from"./TisProvider";export const TestSetupForm=({schema:e,defaultProjectId:t,defaultMethodId:s,onProjectChange:a,onMethodChange:n,onValidationChange:o})=>{const r=useTis(),{invoke:i,write:c}=useContext(EventEmitterContext),{rawValues:l,findTagByFqdn:m}=useContext(AutoCoreTagContext),d=useMemo(()=>Object.keys(r.schemas),[r.schemas]),[p,u]=useState(r.selection.projectId||t||""),[f,h]=useState(r.selection.methodId||s||r.defaultMethodId||""),[x,g]=useState(""),[j,_]=useState({}),v=e??(f?r.schemas[f]:void 0);useEffect(()=>{r.selection.projectId!==p&&r.setSelection({projectId:p}),a&&a(p)},[p]),useEffect(()=>{r.selection.methodId!==f&&f&&r.setSelection({methodId:f}),n&&n(f)},[f]),useEffect(()=>{r.selection.sampleId!==x&&r.setSelection({sampleId:x})},[x]),useEffect(()=>{r.state.stagedSampleId&&r.state.stagedSampleId!==x&&g(r.state.stagedSampleId)},[r.state.stagedSampleId]);const[I,C]=useState([]),[y,N]=useState([]),[S,T]=useState(!1);useEffect(()=>{if(!v)return;const e=[...v.project_fields,...v.config_fields];_(t=>{let s=t;for(const a of e){if("sample_id"===a.name)continue;if(!a.source)continue;const e=m(a.source);if(!e)continue;const n=l[e.tagName];null!=n&&(s[a.name]!==n&&(s===t&&(s={...t}),s[a.name]=n))}return s})},[v,l,m]),useEffect(()=>{(async()=>{try{const e=await i("tis.list_projects",MessageType.Request,{});e.success&&e.data&&e.data.projects&&C(e.data.projects)}catch(e){}})()},[i]);useEffect(()=>{if(!v)return void T(!1);let e=!0;p.trim()||(e=!1),f.trim()||(e=!1),x.trim()||(e=!1);const t=[...v.project_fields,...v.config_fields];for(const s of t)if("sample_id"!==s.name&&s.required){const t=j[s.name];if(void 0===t||""===t||null===t){e=!1;break}}if(T(e),o&&o(e,j),e){const{sample_id:e,...t}=j??{};i("tis.stage_test",MessageType.Request,{project_id:p,method_id:f,sample_id:x,config:t}).catch(e=>{})}},[j,v,p,f,x,o,i]);const E=async(e,t)=>{if(_({...j,[e.name]:t}),e.source)try{await c(e.source,t)}catch(e){}},b=e=>{if("sample_id"===e.name)return null;const t=(e=>{if(!e.required)return!0;const t=j[e.name];return void 0!==t&&""!==t&&null!==t})(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!=j[e.name]?Number(j[e.name]):null,onValueChanged:t=>E(e,t),className:t?"":"p-invalid"}):_jsx(TextInput,{label:void 0,value:null!=j[e.name]?String(j[e.name]):"",onValueChanged:t=>E(e,t),className:t?"":"p-invalid"}),_jsx("span",{className:"ac-form-units",children:e.units??""}),_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 v?_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 & Method",_jsx("span",{style:{color:S?"var(--green-500)":"var(--red-500)"},children:_jsx("i",{className:S?"pi pi-check-circle":"pi pi-exclamation-circle"})})]}),_jsx("span",{className:"ac-form-label",children:"Project ID"}),_jsx(AutoComplete,{value:p,suggestions:y,completeMethod:e=>{const t=e.query.toLowerCase();N(I.filter(e=>e.toLowerCase().includes(t)))},onChange:e=>(e=>{const t=(e||"").replace(/[^a-zA-Z0-9_]/g,"");u(t)})(e.value),dropdown:!0,placeholder:"Enter or select Project ID",className:p.trim()?"":"p-invalid"}),_jsx("span",{}),_jsx("span",{style:{color:p.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:p.trim()?"pi pi-check":"pi pi-times"})}),_jsx("span",{className:"ac-form-label",children:"Sample ID"}),_jsx(TextInput,{label:void 0,value:x,onValueChanged:e=>{g(e)},className:x.trim()?"":"p-invalid"}),_jsx("span",{}),_jsx("span",{style:{color:x.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:x.trim()?"pi pi-check":"pi pi-times"})}),d.length>1&&_jsxs(_Fragment,{children:[_jsx("span",{className:"ac-form-label",children:"Test Method"}),_jsx(SelectButton,{value:f,options:d.map(e=>({label:e,value:e})),onChange:e=>e.value&&h(e.value)}),_jsx("span",{}),_jsx("span",{})]}),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Project Information"}),v.project_fields.map(b),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Test Configuration"}),v.config_fields.map(b)]}):_jsx("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:_jsx("h3",{className:"ac-form-section",children:r.schemasLoaded?"No Test Method Selected":"Loading test methods…"})})};
1
+ import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useEffect,useContext,useMemo}from"react";import{Button}from"primereact/button";import{InputText}from"primereact/inputtext";import{Tooltip}from"primereact/tooltip";import{EventEmitterContext}from"../../core/EventEmitterContext";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";import{MessageType}from"../../hub/CommandMessage";import{ValueInput}from"../ValueInput";import{TextInput}from"../TextInput";import{useTis}from"./TisProvider";import{TestMethodDialog}from"./TestMethodDialog";const labelOf=e=>{const t=e.label&&e.label.length>0?e.label:e.name;return e.units?`${t} [${e.units}]`:t},hasDescription=e=>"string"==typeof e.description&&e.description.length>0,methodLabelOf=(e,t)=>t?.label&&t.label.length>0?t.label:e;export const TestSetupForm=({schema:e,defaultMethodId:t,onMethodChange:s,onValidationChange:a})=>{const i=useTis(),{invoke:o,write:n}=useContext(EventEmitterContext),{rawValues:r,findTagByFqdn:l}=useContext(AutoCoreTagContext),c=useMemo(()=>Object.keys(i.schemas),[i.schemas]),d=i.selection.projectId,m=""!==d.trim()&&i.projectKnown(d.trim()),[p,u]=useState(i.selection.methodId||t||i.defaultMethodId||""),[f,h]=useState(""),[x,g]=useState({}),j=e??(p?i.schemas[p]:void 0);useEffect(()=>{i.selection.methodId!==p&&p&&i.setSelection({methodId:p}),s&&s(p)},[p]),useEffect(()=>{i.selection.sampleId!==f&&i.setSelection({sampleId:f})},[f]),useEffect(()=>{i.state.stagedSampleId&&i.state.stagedSampleId!==f&&h(i.state.stagedSampleId)},[i.state.stagedSampleId]),useEffect(()=>{i.selection.methodId&&i.selection.methodId!==p&&u(i.selection.methodId)},[i.selection.methodId]);const[_,v]=useState(!1),[y,I]=useState(!1);useEffect(()=>{j&&g(e=>{let t=e;for(const s of j.config_fields){if("sample_id"===s.name)continue;if(!s.source)continue;const a=l(s.source);if(!a)continue;const i=r[a.tagName];null!=i&&(t[s.name]!==i&&(t===e&&(t={...e}),t[s.name]=i))}return t})},[j,r,l]),useEffect(()=>{if(!j)return void v(!1);let e=!0;m||(e=!1),p.trim()||(e=!1),f.trim()||(e=!1),e&&!i.projectFieldsLoaded&&(e=!1);for(const t of j.config_fields)if("sample_id"!==t.name&&t.required){const s=x[t.name];if(void 0===s||""===s||null===s){e=!1;break}}if(v(e),a&&a(e,x),e){const{sample_id:e,...t}=x??{},s={...i.projectFields,...t};o("tis.stage_test",MessageType.Request,{project_id:d,method_id:p,sample_id:f,config:s}).catch(e=>{})}},[x,j,d,p,f,m,i.projectFields,i.projectFieldsLoaded,a,o]);const T=async(e,t)=>{if(g({...x,[e.name]:t}),e.source)try{await n(e.source,t)}catch(e){}};if(!j)return _jsx("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:_jsx("h3",{className:"ac-form-section",children:i.schemasLoaded?"No Test Method Selected":"Loading test methods…"})});if(!m)return _jsxs("div",{style:{padding:"1.25rem",maxWidth:"600px"},children:[_jsx("h3",{className:"ac-form-section",children:"No project selected"}),_jsxs("p",{style:{color:"var(--text-secondary-color)",marginTop:"0.5rem"},children:["Pick a project on the ",_jsx("strong",{children:"Project"})," tab first",""!==d.trim()&&` (or click + there to create "${d.trim()}")`,"."]})]});return _jsxs("div",{className:"ac-form-grid",style:{padding:"1.25rem",gridTemplateColumns:"auto 1fr 1.75rem 1.75rem"},children:[_jsxs("h3",{className:"ac-form-section",style:{display:"flex",alignItems:"center",gap:"10px"},children:["Test Setup",_jsx("span",{style:{color:_?"var(--green-500)":"var(--red-500)"},children:_jsx("i",{className:_?"pi pi-check-circle":"pi pi-exclamation-circle"})}),_jsxs("span",{style:{fontSize:"0.85em",color:"var(--text-secondary-color)",fontWeight:"normal",marginLeft:"0.25rem"},children:["project: ",_jsx("strong",{children:d})]})]}),_jsx("span",{className:"ac-form-label",children:"Sample ID"}),_jsx(TextInput,{label:void 0,value:f,onValueChanged:e=>{h(e)},className:f.trim()?"":"p-invalid"}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:f.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:f.trim()?"pi pi-check":"pi pi-times"})}),c.length>0&&_jsxs(_Fragment,{children:[_jsx("span",{className:"ac-form-label",children:"Test Method"}),_jsxs("div",{className:"p-inputgroup",style:{flex:1},children:[_jsx(InputText,{value:methodLabelOf(p,j),readOnly:!0,style:{flex:1},tabIndex:-1}),_jsx(Button,{icon:"pi pi-pencil",type:"button",onClick:()=>I(!0),tooltip:c.length>1?"Change test method":"View test method details",tooltipOptions:{position:"top"}})]}),_jsx("span",{"aria-hidden":"true"}),_jsx("span",{style:{color:p?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:p?"pi pi-check":"pi pi-times"})})]}),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Test Configuration"}),j.config_fields.map(e=>{if("sample_id"===e.name)return null;const t=(e=>{if(!e.required)return!0;const t=x[e.name];return void 0!==t&&""!==t&&null!==t})(e),s="string"!==e.type&&"bool"!==e.type,a=`acFormInfo_${e.name}`;return _jsxs(React.Fragment,{children:[_jsx("span",{className:"ac-form-label",children:labelOf(e)}),s?_jsx(ValueInput,{label:void 0,value:null!=x[e.name]?Number(x[e.name]):null,onValueChanged:t=>T(e,t),className:t?"":"p-invalid"}):_jsx(TextInput,{label:void 0,value:null!=x[e.name]?String(x[e.name]):"",onValueChanged:t=>T(e,t),className:t?"":"p-invalid"}),hasDescription(e)?_jsxs(_Fragment,{children:[_jsx(Tooltip,{target:`#${a}`,position:"left"}),_jsx("span",{id:a,"data-pr-tooltip":e.description,style:{display:"inline-flex",alignItems:"center",justifyContent:"center",cursor:"help"},children:_jsx("i",{className:"pi pi-info-circle",style:{color:"var(--text-secondary-color)"}})})]}):_jsx("span",{"aria-hidden":"true"}),_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)}),_jsx(TestMethodDialog,{visible:y,onHide:()=>I(!1),currentMethodId:p,onSelected:e=>u(e)})]})};
@@ -49,6 +49,34 @@ export interface TisContextValue {
49
49
  state: TisLiveState;
50
50
  selection: TisSelection;
51
51
  setSelection: (patch: TisSelectionPatch) => void;
52
+ /** Project IDs returned by the server's `tis.list_projects`. */
53
+ existingProjects: string[];
54
+ /** True when the project either exists on disk OR was created in
55
+ * this browser session via `<ProjectInfoDialog mode="create">`.
56
+ * This is the gate for staging — typing an unknown name is
57
+ * invalid until + creates the directory. */
58
+ projectKnown: (id: string) => boolean;
59
+ /** Refresh `existingProjects` from the server. Called automatically
60
+ * on `tis.project_created` / `tis.project_updated` broadcasts. */
61
+ refreshProjects: () => Promise<void>;
62
+ /** Add a project ID to the in-session "just created" set so the
63
+ * form is immediately valid for it without round-tripping to
64
+ * list_projects. Idempotent. */
65
+ markProjectJustCreated: (id: string) => void;
66
+ /** `project_fields` blob for the currently-selected project,
67
+ * fetched from project.json. `{}` when nothing is loaded yet
68
+ * (use `projectFieldsLoaded` to disambiguate "empty project" vs
69
+ * "still fetching"). */
70
+ projectFields: Record<string, any>;
71
+ projectFieldsLoaded: boolean;
72
+ /** Fetch and cache project_fields for one project. Returns the
73
+ * fields on success, or null on error. The current selection's
74
+ * fields are also re-loaded automatically when `selection.projectId`
75
+ * changes. */
76
+ loadProjectFields: (id: string) => Promise<Record<string, any> | null>;
77
+ /** Stash freshly-known project_fields without a round trip — used
78
+ * by the create / edit dialogs after a successful submit. */
79
+ setProjectFields: (id: string, fields: Record<string, any>) => void;
52
80
  /** Fetch the run list for a (project, method?) pair. Method may be
53
81
  * omitted to aggregate runs across every method in the project —
54
82
  * the History tab uses this. */
@@ -1 +1 @@
1
- {"version":3,"file":"TisProvider.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TisProvider.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,EASV,KAAK,SAAS,EACjB,MAAM,OAAO,CAAC;AAQf;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC;AAElC,MAAM,MAAM,cAAc,GAAG;IAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAAA;CAAE,CAAC;AAErE,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IAEvB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;gDACgD;AAChD,MAAM,MAAM,iBAAiB,GAAG;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC7B,IAAI,EAAE,GAAG,GAAG,IAAI,CAAC;IACjB,MAAM,EAAE,GAAG,EAAE,CAAC;IACd,OAAO,EAAE,GAAG,CAAC;IACb,OAAO,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,cAAc,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IAEvB,KAAK,EAAE,YAAY,CAAC;IAEpB,SAAS,EAAE,YAAY,CAAC;IACxB,YAAY,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAEjD;;qCAEiC;IACjC,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpE;uEACmE;IACnE,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACnG,QAAQ,EAAE;QAAE,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAAA;KAAE,CAAC;CACnD;AAeD,QAAA,MAAM,UAAU,gCAUd,CAAC;AAmCH,MAAM,WAAW,gBAAgB;IAC7B,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAmLlD,CAAC;AAMF,eAAO,MAAM,MAAM,uBAAyC,CAAC;AAC7D,eAAO,MAAM,aAAa,sBAA0C,CAAC;AACrE,eAAO,MAAM,WAAW,oBAA0C,CAAC;AACnE,eAAO,MAAM,eAAe,wCA5QF,iBAAiB,KAAK,IAAI,CA+QnD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,YAAY,MAAM,EAAE,WAAW,MAAM;;;;CAY/D,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM;;;;;;;;CAuBvC,CAAC;AAIF,OAAO,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"TisProvider.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TisProvider.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- import{jsx as _jsx}from"react/jsx-runtime";import React,{createContext,useCallback,useContext,useEffect,useMemo,useReducer,useRef,useState}from"react";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";const EMPTY_STATE={staged:!1,stagedProjectId:"",stagedMethodId:"",stagedSampleId:"",active:!1,activeProjectId:"",activeMethodId:"",activeSampleId:"",activeRunId:""},EMPTY_SELECTION={projectId:"",methodId:"",sampleId:"",runId:""},TisContext=createContext({schemas:{},defaultMethodId:"",schemasLoaded:!1,state:EMPTY_STATE,selection:EMPTY_SELECTION,setSelection:()=>{},fetchRuns:async()=>[],fetchRun:async()=>null,runCache:{}});function liveReducer(e,t){switch(t.kind){case"staged":return{...e,staged:t.value};case"staged_project_id":return{...e,stagedProjectId:t.value};case"staged_method_id":return{...e,stagedMethodId:t.value};case"staged_sample_id":return{...e,stagedSampleId:t.value};case"active":return{...e,active:t.value};case"active_project_id":return{...e,activeProjectId:t.value};case"active_method_id":return{...e,activeMethodId:t.value};case"active_sample_id":return{...e,activeSampleId:t.value};case"active_run_id":return{...e,activeRunId:t.value}}}export const TisProvider=({children:e,defaultMethodId:t})=>{const{invoke:s,subscribe:a,unsubscribe:c}=useContext(EventEmitterContext),[d,r]=useState({}),[u,n]=useState(t??""),[i,o]=useState(!1),[l,m]=useReducer(liveReducer,EMPTY_STATE),[_,v]=useState({projectId:null,methodId:null,sampleId:null,runId:null});useEffect(()=>{let e=!1;return(async()=>{try{const a=await s("tis.list_schemas",MessageType.Request,{});if(e)return;if(a?.success&&a.data){const e=a.data.test_methods??{},s=a.data.default_method_id??"";r(e),!t&&s&&n(s),o(!0)}}catch(e){}})(),()=>{e=!0}},[]),useEffect(()=>{const e=[a("tis.staged",e=>m({kind:"staged",value:!!e})),a("tis.staged_project_id",e=>m({kind:"staged_project_id",value:String(e??"")})),a("tis.staged_method_id",e=>m({kind:"staged_method_id",value:String(e??"")})),a("tis.staged_sample_id",e=>m({kind:"staged_sample_id",value:String(e??"")})),a("tis.active",e=>m({kind:"active",value:!!e})),a("tis.active_project_id",e=>m({kind:"active_project_id",value:String(e??"")})),a("tis.active_method_id",e=>m({kind:"active_method_id",value:String(e??"")})),a("tis.active_sample_id",e=>m({kind:"active_sample_id",value:String(e??"")})),a("tis.active_run_id",e=>m({kind:"active_run_id",value:String(e??"")}))];return()=>{e.forEach(c)}},[a,c]);const I=useRef({}),[p,h]=useState(0),f=useCallback(()=>h(e=>e+1),[]),C=useCallback((e,t)=>{if(!e)return;const s=I.current[e]??{meta:null,cycles:[],results:{},rawData:{}};I.current[e]={...s,cycles:[...s.cycles,t]},f()},[f]),g=useCallback((e,t)=>{if(!e)return;const s=I.current[e]??{meta:null,cycles:[],results:{},rawData:{}};I.current[e]={...s,results:t},f()},[f]);useEffect(()=>{const e=a("tis.cycle_added",e=>{e?.run_id&&e.cycle&&C(e.run_id,e.cycle)}),t=a("tis.results_updated",e=>{e?.run_id&&g(e.run_id,e.results??{})});return()=>{c(e),c(t)}},[a,c,C,g]);const x=useMemo(()=>({projectId:_.projectId??l.activeProjectId,methodId:_.methodId??(l.activeMethodId||u),sampleId:_.sampleId??l.activeSampleId,runId:_.runId??l.activeRunId}),[_,l,u]),T=useCallback(e=>{v(t=>({projectId:void 0===e.projectId?t.projectId:e.projectId,methodId:void 0===e.methodId?t.methodId:e.methodId,sampleId:void 0===e.sampleId?t.sampleId:e.sampleId,runId:void 0===e.runId?t.runId:e.runId}))},[]),S=useCallback(async(e,t)=>{if(!e)return[];const a={project_id:e};t&&(a.method_id=t);try{const e=await s("tis.list_tests",MessageType.Request,a);if(e?.success&&e.data?.tests)return e.data.tests}catch(e){}return[]},[s]),y=useCallback(async(e,t,a)=>{if(!e||!t||!a)return null;try{const c=await s("tis.read_test",MessageType.Request,{project_id:e,method_id:t,run_id:a}),d=await s("tis.read_cycles",MessageType.Request,{project_id:e,method_id:t,run_id:a,offset:0,limit:1e3,order:"asc"});if(!c?.success)return null;const r={meta:c.data??null,cycles:d?.success?d.data?.cycles??[]:[],results:c.data?.results??{},rawData:I.current[a]?.rawData??{}};return I.current[a]=r,f(),r}catch(e){return null}},[s,f]),j=useMemo(()=>({...I.current}),[p]),E=useMemo(()=>({schemas:d,defaultMethodId:u,schemasLoaded:i,state:l,selection:x,setSelection:T,fetchRuns:S,fetchRun:y,runCache:j}),[d,u,i,l,x,T,S,y,j]);return _jsx(TisContext.Provider,{value:E,children:e})};export const useTis=()=>useContext(TisContext);export const useTisSchemas=()=>useContext(TisContext).schemas;export const useTisState=()=>useContext(TisContext).state;export const useTisSelection=()=>{const{selection:e,setSelection:t}=useContext(TisContext);return[e,t]};export const useTisRuns=(e,t)=>{const{fetchRuns:s}=useContext(TisContext),[a,c]=useState([]),[d,r]=useState(!1),u=useCallback(async()=>{if(e){r(!0);try{c(await s(e,t))}finally{r(!1)}}else c([])},[e,t,s]);return useEffect(()=>{u()},[u]),{runs:a,loading:d,refresh:u}};export const useTisRun=e=>{const{selection:t,fetchRun:s,runCache:a}=useContext(TisContext),[c,d]=useState(!1),r=e??t.runId;useEffect(()=>{if(!r)return;if(a[r]?.meta)return;const e=t.projectId,c=t.methodId;e&&c&&(d(!0),s(e,c,r).finally(()=>d(!1)))},[r,t.projectId,t.methodId,s,a]);const u=r?a[r]:null;return{meta:u?.meta??null,cycles:u?.cycles??[],results:u?.results??{},rawData:u?.rawData??{},loading:c}};export{TisContext};
1
+ import{jsx as _jsx}from"react/jsx-runtime";import React,{createContext,useCallback,useContext,useEffect,useMemo,useReducer,useRef,useState}from"react";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";const EMPTY_STATE={staged:!1,stagedProjectId:"",stagedMethodId:"",stagedSampleId:"",active:!1,activeProjectId:"",activeMethodId:"",activeSampleId:"",activeRunId:""},EMPTY_SELECTION={projectId:"",methodId:"",sampleId:"",runId:""},TisContext=createContext({schemas:{},defaultMethodId:"",schemasLoaded:!1,state:EMPTY_STATE,selection:EMPTY_SELECTION,setSelection:()=>{},existingProjects:[],projectKnown:()=>!1,refreshProjects:async()=>{},markProjectJustCreated:()=>{},projectFields:{},projectFieldsLoaded:!1,loadProjectFields:async()=>null,setProjectFields:()=>{},fetchRuns:async()=>[],fetchRun:async()=>null,runCache:{}});function liveReducer(e,t){switch(t.kind){case"staged":return{...e,staged:t.value};case"staged_project_id":return{...e,stagedProjectId:t.value};case"staged_method_id":return{...e,stagedMethodId:t.value};case"staged_sample_id":return{...e,stagedSampleId:t.value};case"active":return{...e,active:t.value};case"active_project_id":return{...e,activeProjectId:t.value};case"active_method_id":return{...e,activeMethodId:t.value};case"active_sample_id":return{...e,activeSampleId:t.value};case"active_run_id":return{...e,activeRunId:t.value}}}export const TisProvider=({children:e,defaultMethodId:t})=>{const{invoke:s,subscribe:a,unsubscribe:c}=useContext(EventEmitterContext),[r,d]=useState({}),[u,n]=useState(t??""),[i,o]=useState(!1),[l,p]=useReducer(liveReducer,EMPTY_STATE),[_,m]=useState({projectId:null,methodId:null,sampleId:null,runId:null});useEffect(()=>{let e=!1;return(async()=>{try{const a=await s("tis.list_schemas",MessageType.Request,{});if(e)return;if(a?.success&&a.data){const e=a.data.test_methods??{},s=a.data.default_method_id??"";d(e),!t&&s&&n(s),o(!0)}}catch(e){}})(),()=>{e=!0}},[]),useEffect(()=>{const e=[a("tis.staged",e=>p({kind:"staged",value:!!e})),a("tis.staged_project_id",e=>p({kind:"staged_project_id",value:String(e??"")})),a("tis.staged_method_id",e=>p({kind:"staged_method_id",value:String(e??"")})),a("tis.staged_sample_id",e=>p({kind:"staged_sample_id",value:String(e??"")})),a("tis.active",e=>p({kind:"active",value:!!e})),a("tis.active_project_id",e=>p({kind:"active_project_id",value:String(e??"")})),a("tis.active_method_id",e=>p({kind:"active_method_id",value:String(e??"")})),a("tis.active_sample_id",e=>p({kind:"active_sample_id",value:String(e??"")})),a("tis.active_run_id",e=>p({kind:"active_run_id",value:String(e??"")}))];return()=>{e.forEach(c)}},[a,c]);const I=useRef({}),[v,h]=useState(0),f=useCallback(()=>h(e=>e+1),[]),j=useCallback((e,t)=>{if(!e)return;const s=I.current[e]??{meta:null,cycles:[],results:{},rawData:{}};I.current[e]={...s,cycles:[...s.cycles,t]},f()},[f]),C=useCallback((e,t)=>{if(!e)return;const s=I.current[e]??{meta:null,cycles:[],results:{},rawData:{}};I.current[e]={...s,results:t},f()},[f]);useEffect(()=>{const e=a("tis.cycle_added",e=>{e?.run_id&&e.cycle&&j(e.run_id,e.cycle)}),t=a("tis.results_updated",e=>{e?.run_id&&C(e.run_id,e.results??{})});return()=>{c(e),c(t)}},[a,c,j,C]);const g=useMemo(()=>({projectId:_.projectId??l.activeProjectId,methodId:_.methodId??(l.activeMethodId||u),sampleId:_.sampleId??l.activeSampleId,runId:_.runId??l.activeRunId}),[_,l,u]),y=useCallback(e=>{m(t=>({projectId:void 0===e.projectId?t.projectId:e.projectId,methodId:void 0===e.methodId?t.methodId:e.methodId,sampleId:void 0===e.sampleId?t.sampleId:e.sampleId,runId:void 0===e.runId?t.runId:e.runId}))},[]),x=useCallback(async(e,t)=>{if(!e)return[];const a={project_id:e};t&&(a.method_id=t);try{const e=await s("tis.list_tests",MessageType.Request,a);if(e?.success&&e.data?.tests)return e.data.tests}catch(e){}return[]},[s]),S=useCallback(async(e,t,a)=>{if(!e||!t||!a)return null;try{const c=await s("tis.read_test",MessageType.Request,{project_id:e,method_id:t,run_id:a}),r=await s("tis.read_cycles",MessageType.Request,{project_id:e,method_id:t,run_id:a,offset:0,limit:1e3,order:"asc"});if(!c?.success)return null;const d={meta:c.data??null,cycles:r?.success?r.data?.cycles??[]:[],results:c.data?.results??{},rawData:I.current[a]?.rawData??{}};return I.current[a]=d,f(),d}catch(e){return null}},[s,f]),T=useMemo(()=>({...I.current}),[v]),[E,k]=useState([]),M=useRef(new Set),[R,P]=useState(0),[b,w]=useState({}),F=useCallback(async()=>{try{const e=await s("tis.list_projects",MessageType.Request,{});e?.success&&e.data?.projects&&k(e.data.projects)}catch(e){}},[s]),q=useCallback(e=>{e&&(M.current.has(e)||(M.current.add(e),P(e=>e+1)))},[]),D=useCallback(e=>!!e&&(!!M.current.has(e)||E.includes(e)),[E,R]),L=useCallback((e,t)=>{e&&w(s=>({...s,[e]:t}))},[]),Y=useCallback(async e=>{if(!e)return null;try{const t=await s("tis.read_project",MessageType.Request,{project_id:e});if(t?.success){const s=t.data?.project_fields??{};return w(t=>({...t,[e]:s})),s}}catch(e){}return null},[s]);useEffect(()=>{F()},[F]),useEffect(()=>{const e=a("tis.project_created",()=>{F()}),t=a("tis.project_updated",e=>{const t="string"==typeof e?.project_id?e.project_id:"";t&&Y(t)});return()=>{c(e),c(t)}},[a,c,F,Y]),useEffect(()=>{const e=g.projectId;e&&D(e)&&void 0===b[e]&&Y(e)},[g.projectId,D,b,Y]);const A=b[g.projectId]??{},J=void 0!==b[g.projectId],K=useMemo(()=>({schemas:r,defaultMethodId:u,schemasLoaded:i,state:l,selection:g,setSelection:y,existingProjects:E,projectKnown:D,refreshProjects:F,markProjectJustCreated:q,projectFields:A,projectFieldsLoaded:J,loadProjectFields:Y,setProjectFields:L,fetchRuns:x,fetchRun:S,runCache:T}),[r,u,i,l,g,y,E,D,F,q,A,J,Y,L,x,S,T]);return _jsx(TisContext.Provider,{value:K,children:e})};export const useTis=()=>useContext(TisContext);export const useTisSchemas=()=>useContext(TisContext).schemas;export const useTisState=()=>useContext(TisContext).state;export const useTisSelection=()=>{const{selection:e,setSelection:t}=useContext(TisContext);return[e,t]};export const useTisRuns=(e,t)=>{const{fetchRuns:s}=useContext(TisContext),[a,c]=useState([]),[r,d]=useState(!1),u=useCallback(async()=>{if(e){d(!0);try{c(await s(e,t))}finally{d(!1)}}else c([])},[e,t,s]);return useEffect(()=>{u()},[u]),{runs:a,loading:r,refresh:u}};export const useTisRun=e=>{const{selection:t,fetchRun:s,runCache:a}=useContext(TisContext),[c,r]=useState(!1),d=e??t.runId;useEffect(()=>{if(!d)return;if(a[d]?.meta)return;const e=t.projectId,c=t.methodId;e&&c&&(r(!0),s(e,c,d).finally(()=>r(!1)))},[d,t.projectId,t.methodId,s,a]);const u=d?a[d]:null;return{meta:u?.meta??null,cycles:u?.cycles??[],results:u?.results??{},rawData:u?.rawData??{},loading:c}};export{TisContext};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adcops/autocore-react",
3
- "version": "3.3.57",
3
+ "version": "3.3.61",
4
4
  "description": "A React component library for industrial user interfaces.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -27,9 +27,18 @@ export type {
27
27
  TisMethodSchema,
28
28
  } from './tis/TisProvider';
29
29
 
30
+ export { ProjectSelector } from './tis/ProjectSelector';
31
+ export type { ProjectSelectorProps } from './tis/ProjectSelector';
32
+
30
33
  export { TestSetupForm } from './tis/TestSetupForm';
31
34
  export type { TestSetupFormProps } from './tis/TestSetupForm';
32
35
 
36
+ export { ProjectInfoDialog } from './tis/ProjectInfoDialog';
37
+ export type { ProjectInfoDialogProps, ProjectInfoMode } from './tis/ProjectInfoDialog';
38
+
39
+ export { TestMethodDialog } from './tis/TestMethodDialog';
40
+ export type { TestMethodDialogProps } from './tis/TestMethodDialog';
41
+
33
42
  export { ResultHistoryTable } from './tis/ResultHistoryTable';
34
43
  export type { ResultHistoryTableProps } from './tis/ResultHistoryTable';
35
44