@adcops/autocore-react 3.3.50 → 3.3.57

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,3 +1,5 @@
1
+ export { TisProvider, TisContext, useTis, useTisSchemas, useTisState, useTisSelection, useTisRuns, useTisRun, } from './tis/TisProvider';
2
+ export type { TisProviderProps, TisContextValue, TisLiveState, TisSelection, TisSelectionPatch, TisRunCacheEntry, SchemaRegistry, TisMethodSchema, } from './tis/TisProvider';
1
3
  export { TestSetupForm } from './tis/TestSetupForm';
2
4
  export type { TestSetupFormProps } from './tis/TestSetupForm';
3
5
  export { ResultHistoryTable } from './tis/ResultHistoryTable';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAQA,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,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 +1 @@
1
- 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{TestSetupForm}from"./tis/TestSetupForm";export{ResultHistoryTable}from"./tis/ResultHistoryTable";export{TestDataView}from"./tis/TestDataView";export{TestRawDataView}from"./tis/TestRawDataView";
@@ -1,7 +1,19 @@
1
1
  import React from 'react';
2
2
  export interface ResultHistoryTableProps {
3
- projectId: string;
4
- definitionId: string;
3
+ /**
4
+ * Override the project scope. When omitted, the table reads from
5
+ * `useTisSelection().projectId` and follows the active project.
6
+ */
7
+ projectId?: string;
8
+ /**
9
+ * Optional method-id filter. When omitted, the table aggregates every
10
+ * run under the project regardless of which method it belongs to —
11
+ * that's the default the operator wants on the History tab so that
12
+ * switching the loaded method on the Setup tab doesn't hide
13
+ * already-recorded data. When supplied, the table is scoped to that
14
+ * single method.
15
+ */
16
+ methodId?: string;
5
17
  }
6
18
  export declare const ResultHistoryTable: React.FC<ResultHistoryTableProps>;
7
19
  //# sourceMappingURL=ResultHistoryTable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ResultHistoryTable.d.ts","sourceRoot":"","sources":["../../../src/components/tis/ResultHistoryTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAO/D,MAAM,WAAW,uBAAuB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACxB;AAqDD,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAgIhE,CAAC"}
1
+ {"version":3,"file":"ResultHistoryTable.d.ts","sourceRoot":"","sources":["../../../src/components/tis/ResultHistoryTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAQ/D,MAAM,WAAW,uBAAuB;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAwDD,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAqMhE,CAAC"}
@@ -1 +1 @@
1
- import{jsxs as _jsxs,jsx as _jsx}from"react/jsx-runtime";import React,{useState,useEffect,useContext}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Button}from"primereact/button";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";const rawBlobToCsv=e=>{if(!e||"object"!=typeof e)return"";const t=Object.entries(e).filter(([,e])=>Array.isArray(e));if(0===t.length)return"";t.sort(([e],[t])=>"t"===e?-1:"t"===t?1:0);const r=t.map(([e])=>e),o=t.reduce((e,[,t])=>Math.min(e,t.length),1/0),s=e=>{if(null==e)return"";const t=String(e);return/[",\n\r]/.test(t)?`"${t.replace(/"/g,'""')}"`:t},a=[r.join(",")];for(let e=0;e<o;e++)a.push(t.map(([,t])=>s(t[e])).join(","));return a.join("\n")},downloadCsv=(e,t)=>{const r=new Blob([t],{type:"text/csv;charset=utf-8;"}),o=URL.createObjectURL(r),s=document.createElement("a");s.href=o,s.download=e,document.body.appendChild(s),s.click(),s.remove(),URL.revokeObjectURL(o)};export const ResultHistoryTable=({projectId:e,definitionId:t})=>{const[r,o]=useState([]),[s,a]=useState(!1),[n,i]=useState(null),{invoke:l}=useContext(EventEmitterContext),d=async()=>{a(!0);try{const r=await l("results.list_tests",MessageType.Request,{project_id:e,definition_id:t});r.success&&r.data&&r.data.tests&&o(r.data.tests)}catch(e){}a(!1)};useEffect(()=>{d()},[e,t]);const c=e=>{const t=e?.config;return t&&"object"==typeof t&&"string"==typeof t.sample_id?t.sample_id:""};return _jsxs("div",{style:{width:"100%",maxWidth:"100%",overflow:"hidden",boxSizing:"border-box"},children:[_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1rem"},children:[_jsxs("h3",{style:{margin:0},children:["Test History: ",t]}),_jsx(Button,{icon:"pi pi-refresh",label:"Refresh",onClick:d,disabled:s})]}),_jsxs(DataTable,{value:r,loading:s,paginator:!0,rows:10,emptyMessage:"No tests found.",scrollable:!0,scrollHeight:"flex",tableStyle:{minWidth:0},style:{width:"100%"},children:[_jsx(Column,{field:"run_id",header:"Run ID",sortable:!0,style:{minWidth:"12rem"}}),_jsx(Column,{field:"start_time",header:"Date/Time",sortable:!0,body:e=>{return(t=e.start_time)?new Date(t).toLocaleString():"";var t},style:{minWidth:"12rem"}}),_jsx(Column,{field:"definition_id",header:"Test Name",sortable:!0,style:{minWidth:"10rem"}}),_jsx(Column,{header:"Sample ID",sortable:!0,body:c,sortFunction:e=>{const t=[...e.data];return t.sort((t,r)=>c(t).localeCompare(c(r))*(e.order??1)),t},style:{minWidth:"8rem"}}),_jsx(Column,{header:"Raw Data",style:{width:"8rem"},body:r=>_jsx(Button,{icon:n===r.run_id?"pi pi-spin pi-spinner":"pi pi-download",label:"CSV",size:"small",outlined:!0,disabled:null!==n,onClick:()=>(async r=>{const o=r?.run_id;if(o){i(o);try{const r=await l("results.read_raw",MessageType.Request,{project_id:e,definition_id:t,run_id:o,name:"trace"});if(!r?.success||!r.data)return void alert(`No raw trace available for ${o}${r?.error_message?`: ${r.error_message}`:""}`);const s=rawBlobToCsv(r.data);if(!s)return void alert(`Raw trace for ${o} is empty or has no array columns.`);downloadCsv(`${e}_${t}_${o}.csv`,s)}catch(e){alert(`Download failed: ${e instanceof Error?e.message:String(e)}`)}finally{i(null)}}})(r),tooltip:"Download raw_data/trace.json as CSV",tooltipOptions:{position:"left"}})})]})]})};
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useEffect,useContext}from"react";import{DataTable}from"primereact/datatable";import{Column}from"primereact/column";import{Button}from"primereact/button";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";const rawBlobToCsv=e=>{if(!e||"object"!=typeof e)return"";const t=Object.entries(e).filter(([,e])=>Array.isArray(e));if(0===t.length)return"";t.sort(([e],[t])=>"t"===e?-1:"t"===t?1:0);const r=t.map(([e])=>e),o=t.reduce((e,[,t])=>Math.min(e,t.length),1/0),s=e=>{if(null==e)return"";const t=String(e);return/[",\n\r]/.test(t)?`"${t.replace(/"/g,'""')}"`:t},i=[r.join(",")];for(let e=0;e<o;e++)i.push(t.map(([,t])=>s(t[e])).join(","));return i.join("\n")},downloadCsv=(e,t)=>{const r=new Blob([t],{type:"text/csv;charset=utf-8;"}),o=URL.createObjectURL(r),s=document.createElement("a");s.href=o,s.download=e,document.body.appendChild(s),s.click(),s.remove(),URL.revokeObjectURL(o)};export const ResultHistoryTable=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,o=e.methodId,[s,i]=useState([]),[n,a]=useState(!1),[l,d]=useState(null),{invoke:c}=useContext(EventEmitterContext),m=async()=>{if(r){a(!0);try{const e={project_id:r};o&&(e.method_id=o);const t=await c("tis.list_tests",MessageType.Request,e);t.success&&t.data&&t.data.tests&&i(t.data.tests)}catch(e){}a(!1)}else i([])};useEffect(()=>{m()},[r,o,t.state.activeRunId]);const u=async(e,t)=>{const s=e?.run_id,i=e?.method_id??o;if(!s||!i)return;const n="raw"===t?"tis.read_raw":"tis.read_filtered",a="raw"===t?"raw trace":"filtered trace",l="raw"===t?"raw":"filtered";d({runId:s,kind:t});try{const e=await c(n,MessageType.Request,{project_id:r,method_id:i,run_id:s,name:"trace"});if(!e?.success||!e.data)return void alert(`No ${a} available for ${s}`+(e?.error_message?`: ${e.error_message}`:""));const t=rawBlobToCsv(e.data);if(!t)return void alert(`${a} for ${s} is empty or has no array columns.`);downloadCsv(`${r}_${i}_${s}_${l}.csv`,t)}catch(e){alert(`Download failed: ${e instanceof Error?e.message:String(e)}`)}finally{d(null)}},p=e=>{const t="string"==typeof e?.sample_id?e.sample_id:"";if(t)return t;const r=e?.config;return r&&"object"==typeof r&&"string"==typeof r.sample_id?r.sample_id:""};return _jsxs("div",{style:{width:"100%",maxWidth:"100%",overflow:"hidden",boxSizing:"border-box"},children:[_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1rem"},children:[_jsx("h3",{style:{margin:0},children:r?`Test History: ${r}${o?` / ${o}`:""}`:"Test History (no project selected)"}),_jsx(Button,{icon:"pi pi-refresh",label:"Refresh",onClick:m,disabled:n})]}),_jsxs(DataTable,{value:s,loading:n,paginator:!0,rows:10,emptyMessage:"No tests found.",scrollable:!0,scrollHeight:"flex",tableStyle:{minWidth:0},style:{width:"100%"},selectionMode:"single",onSelectionChange:e=>{const r=e.value;r?.run_id&&t.setSelection({projectId:r.project_id??null,methodId:r.method_id??null,runId:r.run_id})},children:[_jsx(Column,{header:"Sample ID",sortable:!0,body:p,sortFunction:e=>{const t=[...e.data];return t.sort((t,r)=>p(t).localeCompare(p(r))*(e.order??1)),t},style:{minWidth:"8rem"}}),_jsx(Column,{field:"start_time",header:"Date/Time",sortable:!0,body:e=>{return(t=e.start_time)?new Date(t).toLocaleString():"";var t},style:{minWidth:"12rem"}}),_jsx(Column,{field:"method_id",header:"Test Method",sortable:!0,style:{minWidth:"10rem"}}),_jsx(Column,{field:"run_id",header:"Run ID",sortable:!0,style:{minWidth:"12rem"}}),_jsx(Column,{header:"Download",style:{width:"14rem"},body:e=>{const t=l?.runId===e.run_id&&"raw"===l?.kind,r=l?.runId===e.run_id&&"filtered"===l?.kind,o=null!==l;return _jsxs("div",{style:{display:"flex",gap:"0.4rem"},children:[_jsx(Button,{icon:t?"pi pi-spin pi-spinner":"pi pi-download",label:"Raw",size:"small",outlined:!0,disabled:o,onClick:()=>u(e,"raw"),tooltip:"Download raw_data/trace.json as CSV",tooltipOptions:{position:"left"}}),_jsx(Button,{icon:r?"pi pi-spin pi-spinner":"pi pi-download",label:"Filtered",size:"small",outlined:!0,disabled:o,onClick:()=>u(e,"filtered"),tooltip:"Download filtered_data/trace.json as CSV",tooltipOptions:{position:"left"}})]})}})]})]})};
@@ -30,7 +30,7 @@ export interface RawDataShape {
30
30
  [col: string]: string;
31
31
  };
32
32
  }
33
- export interface TestDefinition {
33
+ export interface TestMethod {
34
34
  project_fields: TestFieldDef[];
35
35
  config_fields: TestFieldDef[];
36
36
  cycle_fields: TestFieldDef[];
@@ -41,10 +41,14 @@ export interface TestDefinition {
41
41
  };
42
42
  }
43
43
  export interface TestDataViewProps {
44
- projectId: string;
45
- definitionId: string;
46
- runId: string;
47
- schema: TestDefinition;
44
+ /** Optional override; defaults to `useTisSelection().projectId`. */
45
+ projectId?: string;
46
+ /** Optional override; defaults to `useTisSelection().methodId`. */
47
+ methodId?: string;
48
+ /** Optional override; defaults to `useTisSelection().runId`. */
49
+ runId?: string;
50
+ /** Optional override; defaults to `useTisSchemas()[methodId]`. */
51
+ schema?: TestMethod;
48
52
  /** Minimum ms between display updates when broadcasts arrive. Default 100. */
49
53
  throttleMs?: number;
50
54
  /** Fixed cycle-table scroll height. Default "400px". */
@@ -1 +1 @@
1
- {"version":3,"file":"TestDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestDataView.tsx"],"names":[],"mappings":"AAUA,OAAO,KAA2D,MAAM,OAAO,CAAC;AA4BhF,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,cAAc;IAC3B,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,SAAS,EAAK,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAS,MAAM,CAAC;IACrB,MAAM,EAAQ,cAAc,CAAC;IAC7B,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,CAkOpD,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;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 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useContext,useEffect,useMemo,useRef,useState}from"react";import{Button}from"primereact/button";import{Column}from"primereact/column";import{DataTable}from"primereact/datatable";import{Dialog}from"primereact/dialog";import{Dropdown}from"primereact/dropdown";import{Chart as ChartJS,CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend}from"chart.js";import zoomPlugin from"chartjs-plugin-zoom";import{Line}from"react-chartjs-2";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{TestRawDataView}from"./TestRawDataView";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin);export const TestDataView=({projectId:e,definitionId:t,runId:i,schema:r,throttleMs:a=100,cycleTableHeight:s="400px"})=>{const{invoke:l,subscribe:n,unsubscribe:o}=useContext(EventEmitterContext),[c,d]=useState(null),[m,u]=useState([]),[p,f]=useState({}),[x,h]=useState(!1),g=useMemo(()=>{const e=[];for(const[t,i]of Object.entries(r.views??{}))"cycle_scatter"===i.type&&e.push({name:t,view:i});return e},[r]),[y,_]=useState(g.length>0?g[0].name:null),j=useRef([]),v=useRef(null),b=useRef(null),w=()=>{b.current||(b.current=setTimeout(()=>{if(b.current=null,j.current.length>0){const e=j.current;j.current=[],u(t=>[...e.slice().reverse(),...t])}v.current&&(f(v.current),v.current=null)},a))};useEffect(()=>{let r=!1;return(async()=>{try{const a=await l("results.read_test",MessageType.Request,{project_id:e,definition_id:t,run_id:i});!r&&a?.success&&(d(a.data),f(a.data.results??{}));const s=await l("results.read_cycles",MessageType.Request,{project_id:e,definition_id:t,run_id:i,offset:0,limit:200,order:"desc"});!r&&s?.success&&u(s.data.cycles??[])}catch(e){}})(),()=>{r=!0}},[e,t,i,l]),useEffect(()=>{const r=r=>r?.project_id===e&&r?.definition_id===t&&r?.run_id===i,a=n("results.cycle_added",e=>{r(e)&&e.cycle&&(j.current.push(e.cycle),w())}),s=n("results.results_updated",e=>{r(e)&&(v.current=e.results??{},w())});return()=>{o(a),o(s),b.current&&(clearTimeout(b.current),b.current=null)}},[e,t,i,a]);const C=useMemo(()=>{if(!y||0===g.length)return null;const e=g.find(e=>e.name===y)?.view;if(!e)return null;const t=e.x.field,i=[...m].reverse();return{labels:i.map(e=>e[t]),datasets:e.y.map((e,t)=>({label:e.label??e.field,data:i.map(t=>t[e.field]),yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(t),backgroundColor:palette(t),tension:.1,pointRadius:2}))}},[m,y,g]),R=g.find(e=>e.name===y)?.view,S=R?.y.some(e=>"right"===e.y_axis)??!1,T=useMemo(()=>({responsive:!0,maintainAspectRatio:!1,scales:{x:{title:{display:!!R?.x.label,text:R?.x.label}},y:{position:"left",title:{display:!0,text:leftAxisLabel(R)}},...S?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:rightAxisLabel(R)}}}:{}},plugins:{legend:{display:!0},zoom:{pan:{enabled:!0,mode:"xy"},zoom:{wheel:{enabled:!0},pinch:{enabled:!0},mode:"xy"}}}}),[R,S]);return _jsxs("div",{className:"vblock",style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[_jsx(Header,{meta:c,config:c?.config,runId:i,projectId:e,definitionId:t,canViewRaw:!!r.raw_data,onViewRaw:()=>h(!0)}),g.length>0&&_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("div",{className:"flex",style:{gap:"1rem",alignItems:"center",marginBottom:"0.5rem"},children:[_jsx(Dropdown,{value:y,options:g.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>_(e.value),placeholder:"Select a view"}),_jsx("h3",{style:{margin:0},children:R?.title??""})]}),_jsx("div",{style:{height:320},children:C&&_jsx(Line,{data:C,options:T})})]}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("h3",{style:{marginTop:0},children:["Cycle Data (",m.length,")"]}),_jsx(DataTable,{value:m,scrollable:!0,scrollHeight:s,virtualScrollerOptions:{itemSize:38},emptyMessage:"No cycles yet.",children:r.cycle_fields.map(e=>_jsx(Column,{field:e.name,header:e.units?`${e.name} (${e.units})`:e.name,body:t=>formatCell(t[e.name],e.type)},e.name))})]}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsx("h3",{style:{marginTop:0},children:"Results"}),_jsx(ResultsGrid,{schema:r.results_fields,values:p})]}),r.raw_data&&_jsx(Dialog,{visible:x,onHide:()=>h(!1),header:"Raw Data",style:{width:"90vw",height:"80vh"},maximizable:!0,children:_jsx(TestRawDataView,{projectId:e,definitionId:t,runId:i,schema:r})})]})};const Header=({meta:e,config:t,runId:i,projectId:r,definitionId:a,canViewRaw:s,onViewRaw:l})=>_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("div",{className:"flex",style:{justifyContent:"space-between",alignItems:"flex-start",gap:"1rem"},children:[_jsxs("div",{children:[_jsxs("h2",{style:{margin:0},children:[a," — ",i]}),_jsxs("div",{style:{color:"var(--text-secondary-color)",fontSize:"0.85em"},children:["project: ",r,e?.start_time&&_jsxs(_Fragment,{children:[" · started: ",new Date(e.start_time).toLocaleString()]})]})]}),s&&_jsx(Button,{icon:"pi pi-chart-line",label:"View Raw Data",onClick:l,outlined:!0})]}),t&&Object.keys(t).length>0&&_jsx("div",{style:{marginTop:"0.75rem",display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(220px, 1fr))",gap:"0.25rem 1rem",fontSize:"0.9em"},children:Object.entries(t).map(([e,t])=>_jsxs("div",{children:[_jsxs("strong",{children:[e,":"]})," ",formatCell(t,"string")]},e))})]}),ResultsGrid=({schema:e,values:t})=>t&&0!==Object.keys(t).length?_jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(220px, 1fr))",gap:"0.5rem 1rem"},children:e.map(e=>_jsxs("div",{children:[_jsxs("div",{style:{fontSize:"0.8em",color:"var(--text-secondary-color)"},children:[e.name,e.units?` (${e.units})`:""]}),_jsx("div",{children:formatCell(t[e.name],e.type)})]},e.name))}):_jsx("div",{style:{color:"var(--text-secondary-color)"},children:"No results yet."}),CHART_COLORS=["#4ea8de","#f59e0b","#22c55e","#a855f7","#ef4444","#14b8a6","#eab308","#ec4899"],palette=e=>CHART_COLORS[e%CHART_COLORS.length],leftAxisLabel=e=>e?.y.filter(e=>"right"!==e.y_axis).map(e=>e.label??e.field).join(" / ")??"",rightAxisLabel=e=>e?.y.filter(e=>"right"===e.y_axis).map(e=>e.label??e.field).join(" / ")??"",formatCell=(e,t)=>null==e?"":"f32"===t||"f64"===t?"number"==typeof e?e.toFixed(4):String(e):"object"==typeof e?JSON.stringify(e):String(e);
1
+ import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";import React,{useContext,useEffect,useMemo,useRef,useState}from"react";import{Button}from"primereact/button";import{Column}from"primereact/column";import{DataTable}from"primereact/datatable";import{Dialog}from"primereact/dialog";import{Dropdown}from"primereact/dropdown";import{Chart as ChartJS,CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend}from"chart.js";import zoomPlugin from"chartjs-plugin-zoom";import{Line}from"react-chartjs-2";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{TestRawDataView}from"./TestRawDataView";import{useTis}from"./TisProvider";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin);export const TestDataView=e=>{const t=useTis(),r=e.projectId??t.selection.projectId,s=e.methodId??t.selection.methodId,a=e.runId??t.selection.runId,i=e.schema??(s?t.schemas[s]:void 0),{throttleMs:l=100,cycleTableHeight:n="400px"}=e,{invoke:o,subscribe:c,unsubscribe:d}=useContext(EventEmitterContext),[m,u]=useState(null),[p,h]=useState([]),[f,y]=useState({}),[g,x]=useState(!1),_=useMemo(()=>{const e=[];for(const[t,r]of Object.entries(i?.views??{}))"cycle_scatter"===r.type&&e.push({name:t,view:r});return e},[i]),[j,v]=useState(_.length>0?_[0].name:null),b=useRef([]),w=useRef(null),C=useRef(null),R=()=>{C.current||(C.current=setTimeout(()=>{if(C.current=null,b.current.length>0){const e=b.current;b.current=[],h(t=>[...e.slice().reverse(),...t])}w.current&&(y(w.current),w.current=null)},l))};useEffect(()=>{if(!r||!s||!a)return u(null),h([]),void y({});let e=!1;return(async()=>{try{const t=await o("tis.read_test",MessageType.Request,{project_id:r,method_id:s,run_id:a});!e&&t?.success&&(u(t.data),y(t.data.results??{}));const i=await o("tis.read_cycles",MessageType.Request,{project_id:r,method_id:s,run_id:a,offset:0,limit:200,order:"desc"});!e&&i?.success&&h(i.data.cycles??[])}catch(e){}})(),()=>{e=!0}},[r,s,a,o]),useEffect(()=>{const e=e=>e?.project_id===r&&e?.method_id===s&&e?.run_id===a,t=c("tis.cycle_added",t=>{e(t)&&t.cycle&&(b.current.push(t.cycle),R())}),i=c("tis.results_updated",t=>{e(t)&&(w.current=t.results??{},R())});return()=>{d(t),d(i),C.current&&(clearTimeout(C.current),C.current=null)}},[r,s,a,l]);const T=useMemo(()=>{if(!j||0===_.length)return null;const e=_.find(e=>e.name===j)?.view;if(!e)return null;const t=e.x.field,r=[...p].reverse();return{labels:r.map(e=>e[t]),datasets:e.y.map((e,t)=>({label:e.label??e.field,data:r.map(t=>t[e.field]),yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(t),backgroundColor:palette(t),tension:.1,pointRadius:2}))}},[p,j,_]),S=_.find(e=>e.name===j)?.view,I=S?.y.some(e=>"right"===e.y_axis)??!1,D=useMemo(()=>({responsive:!0,maintainAspectRatio:!1,scales:{x:{title:{display:!!S?.x.label,text:S?.x.label}},y:{position:"left",title:{display:!0,text:leftAxisLabel(S)}},...I?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:rightAxisLabel(S)}}}:{}},plugins:{legend:{display:!0},zoom:{pan:{enabled:!0,mode:"xy"},zoom:{wheel:{enabled:!0},pinch:{enabled:!0},mode:"xy"}}}}),[S,I]);return r&&s&&a&&i?_jsxs("div",{className:"vblock",style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[_jsx(Header,{meta:m,config:m?.config,runId:a,projectId:r,methodId:s,canViewRaw:!!i.raw_data,onViewRaw:()=>x(!0)}),_.length>0&&_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("div",{className:"flex",style:{gap:"1rem",alignItems:"center",marginBottom:"0.5rem"},children:[_jsx(Dropdown,{value:j,options:_.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>v(e.value),placeholder:"Select a view"}),_jsx("h3",{style:{margin:0},children:S?.title??""})]}),_jsx("div",{style:{height:320},children:T&&_jsx(Line,{data:T,options:D})})]}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("h3",{style:{marginTop:0},children:["Cycle Data (",p.length,")"]}),_jsx(DataTable,{value:p,scrollable:!0,scrollHeight:n,virtualScrollerOptions:{itemSize:38},emptyMessage:"No cycles yet.",children:i.cycle_fields.map(e=>_jsx(Column,{field:e.name,header:e.units?`${e.name} (${e.units})`:e.name,body:t=>formatCell(t[e.name],e.type)},e.name))})]}),_jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsx("h3",{style:{marginTop:0},children:"Results"}),_jsx(ResultsGrid,{schema:i.results_fields,values:f})]}),i.raw_data&&_jsx(Dialog,{visible:g,onHide:()=>x(!1),header:"Raw Data",style:{width:"90vw",height:"80vh"},maximizable:!0,children:_jsx(TestRawDataView,{projectId:r,methodId:s,runId:a,schema:i})})]}):_jsx("div",{className:"p-card",style:{padding:"1rem",color:"var(--text-secondary-color)"},children:"No test selected. Pick a row from the History tab or start a run."})};const Header=({meta:e,config:t,runId:r,projectId:s,methodId:a,canViewRaw:i,onViewRaw:l})=>{const n="string"==typeof e?.sample_id&&e.sample_id||"string"==typeof e?.config?.sample_id&&e.config.sample_id||"",o=t&&"object"==typeof t?Object.fromEntries(Object.entries(t).filter(([e])=>"sample_id"!==e)):{};return _jsxs("div",{className:"p-card",style:{padding:"1rem"},children:[_jsxs("div",{className:"flex",style:{justifyContent:"space-between",alignItems:"flex-start",gap:"1rem"},children:[_jsxs("div",{children:[_jsx("h2",{style:{margin:0},children:n||r}),_jsxs("div",{style:{color:"var(--text-secondary-color)",fontSize:"0.85em"},children:["project: ",s," · method: ",a," · run: ",r,e?.start_time&&_jsxs(_Fragment,{children:[" · started: ",new Date(e.start_time).toLocaleString()]})]})]}),i&&_jsx(Button,{icon:"pi pi-chart-line",label:"View Raw Data",onClick:l,outlined:!0})]}),Object.keys(o).length>0&&_jsx("div",{style:{marginTop:"0.75rem",display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(220px, 1fr))",gap:"0.25rem 1rem",fontSize:"0.9em"},children:Object.entries(o).map(([e,t])=>_jsxs("div",{children:[_jsxs("strong",{children:[e,":"]})," ",formatCell(t,"string")]},e))})]})},ResultsGrid=({schema:e,values:t})=>t&&0!==Object.keys(t).length?_jsx("div",{style:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(220px, 1fr))",gap:"0.5rem 1rem"},children:e.map(e=>_jsxs("div",{children:[_jsxs("div",{style:{fontSize:"0.8em",color:"var(--text-secondary-color)"},children:[e.name,e.units?` (${e.units})`:""]}),_jsx("div",{children:formatCell(t[e.name],e.type)})]},e.name))}):_jsx("div",{style:{color:"var(--text-secondary-color)"},children:"No results yet."}),CHART_COLORS=["#4ea8de","#f59e0b","#22c55e","#a855f7","#ef4444","#14b8a6","#eab308","#ec4899"],palette=e=>CHART_COLORS[e%CHART_COLORS.length],leftAxisLabel=e=>e?.y.filter(e=>"right"!==e.y_axis).map(e=>e.label??e.field).join(" / ")??"",rightAxisLabel=e=>e?.y.filter(e=>"right"===e.y_axis).map(e=>e.label??e.field).join(" / ")??"",formatCell=(e,t)=>null==e?"":"f32"===t||"f64"===t?"number"==typeof e?e.toFixed(4):String(e):"object"==typeof e?JSON.stringify(e):String(e);
@@ -1,10 +1,14 @@
1
1
  import React from 'react';
2
- import type { TestDefinition } from './TestDataView';
2
+ import type { TestMethod } from './TestDataView';
3
3
  export interface TestRawDataViewProps {
4
- projectId: string;
5
- definitionId: string;
6
- runId: string;
7
- schema: TestDefinition;
4
+ /** Optional override; defaults to `useTisSelection().projectId`. */
5
+ projectId?: string;
6
+ /** Optional override; defaults to `useTisSelection().methodId`. */
7
+ methodId?: string;
8
+ /** Optional override; defaults to `useTisSelection().runId`. */
9
+ runId?: string;
10
+ /** Optional override; defaults to `useTisSchemas()[methodId]`. */
11
+ schema?: TestMethod;
8
12
  /** Override the blob name (default: schema.raw_data.blob_name). */
9
13
  blobName?: string;
10
14
  /** Fixed chart height. Default "60vh". */
@@ -1 +1 @@
1
- {"version":3,"file":"TestRawDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestRawDataView.tsx"],"names":[],"mappings":"AAYA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAahF,OAAO,KAAK,EAAa,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAOhE,MAAM,WAAW,oBAAoB;IACjC,SAAS,EAAK,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAS,MAAM,CAAC;IACrB,MAAM,EAAQ,cAAc,CAAC;IAC7B,mEAAmE;IACnE,QAAQ,CAAC,EAAK,MAAM,CAAC;IACrB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA2I1D,CAAC"}
1
+ {"version":3,"file":"TestRawDataView.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestRawDataView.tsx"],"names":[],"mappings":"AAYA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAahF,OAAO,KAAK,EAAa,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAQ5D,MAAM,WAAW,oBAAoB;IACjC,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,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAuJ1D,CAAC"}
@@ -1 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useContext,useEffect,useMemo,useRef,useState}from"react";import{Button}from"primereact/button";import{Dropdown}from"primereact/dropdown";import{Chart as ChartJS,CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend}from"chart.js";import zoomPlugin from"chartjs-plugin-zoom";import{Line}from"react-chartjs-2";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin);export const TestRawDataView=({projectId:e,definitionId:t,runId:a,schema:i,blobName:n,chartHeight:r="60vh"})=>{const{invoke:o}=useContext(EventEmitterContext),[s,l]=useState(null),[m,d]=useState(!0),[c,p]=useState(null),u=useRef(null),x=useMemo(()=>{const e=[];for(const[t,a]of Object.entries(i.views??{}))"raw_trace"===a.type&&e.push({name:t,view:a});return e},[i]),[h,y]=useState(x.length>0?x[0].name:null),f=n??i.raw_data?.blob_name??"trace";useEffect(()=>{let i=!1;return d(!0),p(null),(async()=>{try{const n=await o("results.read_raw",MessageType.Request,{project_id:e,definition_id:t,run_id:a,name:f});if(i)return;n?.success?l(n.data??{}):p(n?.error_message??"Failed to read raw data")}catch(e){i||p(String(e?.message??e))}finally{i||d(!1)}})(),()=>{i=!0}},[e,t,a,f,o]);const g=useMemo(()=>{if(!s||!h)return null;const e=x.find(e=>e.name===h)?.view;if(!e)return null;const t=e.x.column,a=s[t]??[];return{datasets:e.y.map((e,t)=>({label:e.label??e.column,data:(s[e.column]??[]).map((e,t)=>({x:a[t],y:e})),yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(t),backgroundColor:palette(t),pointRadius:0,borderWidth:1.5,showLine:!0}))}},[s,h,x]),_=x.find(e=>e.name===h)?.view,v=_?.y.some(e=>"right"===e.y_axis)??!1,b=useMemo(()=>({responsive:!0,maintainAspectRatio:!1,parsing:!1,scales:{x:{type:"linear",title:{display:!!_?.x.label,text:_?.x.label}},y:{position:"left",title:{display:!0,text:axisLabel(_,"left")}},...v?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:axisLabel(_,"right")}}}:{}},plugins:{legend:{display:!0},zoom:{pan:{enabled:!0,mode:"xy"},zoom:{wheel:{enabled:!0},pinch:{enabled:!0},drag:{enabled:!0,modifierKey:"shift"},mode:"xy"}}}}),[_,v]);return i.raw_data?0===x.length?_jsx(EmptyState,{message:"No raw_trace views declared. Add one to schema.views in project.json."}):_jsxs("div",{className:"vblock",style:{display:"flex",flexDirection:"column",gap:"1rem",height:"100%"},children:[_jsxs("div",{className:"flex",style:{gap:"1rem",alignItems:"center"},children:[_jsx(Dropdown,{value:h,options:x.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>y(e.value),placeholder:"Select a view"}),_jsx("h3",{style:{margin:0},children:_?.title??""}),_jsx("div",{style:{flex:1}}),_jsx(Button,{icon:"pi pi-refresh",label:"Reset Zoom",outlined:!0,onClick:()=>u.current?.resetZoom?.()})]}),_jsxs("div",{style:{flex:1,minHeight:0,height:r,position:"relative"},children:[m&&_jsx(Overlay,{children:"Loading raw data…"}),c&&_jsx(Overlay,{children:c}),g&&!m&&!c&&_jsx(Line,{ref:u,data:g,options:b})]})]}):_jsx(EmptyState,{message:"No raw_data is declared for this test definition."})};const Overlay=({children:e})=>_jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",color:"var(--text-secondary-color)",pointerEvents:"none"},children:e}),EmptyState=({message:e})=>_jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:e}),CHART_COLORS=["#4ea8de","#f59e0b","#22c55e","#a855f7","#ef4444","#14b8a6","#eab308","#ec4899"],palette=e=>CHART_COLORS[e%CHART_COLORS.length],axisLabel=(e,t)=>e?.y.filter(e=>(e.y_axis??"left")===t).map(e=>e.label??e.column).join(" / ")??"";
1
+ import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useContext,useEffect,useMemo,useRef,useState}from"react";import{Button}from"primereact/button";import{Dropdown}from"primereact/dropdown";import{Chart as ChartJS,CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend}from"chart.js";import zoomPlugin from"chartjs-plugin-zoom";import{Line}from"react-chartjs-2";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useTis}from"./TisProvider";ChartJS.register(CategoryScale,LinearScale,PointElement,LineElement,Title,Tooltip,Legend,zoomPlugin);export const TestRawDataView=e=>{const t=useTis(),a=e.projectId??t.selection.projectId,s=e.methodId??t.selection.methodId,o=e.runId??t.selection.runId,i=e.schema??(s?t.schemas[s]:void 0),{blobName:r,chartHeight:n="60vh"}=e,{invoke:l}=useContext(EventEmitterContext),[m,d]=useState(null),[c,p]=useState(!0),[u,h]=useState(null),x=useRef(null),y=useMemo(()=>{const e=[];for(const[t,a]of Object.entries(i?.views??{}))"raw_trace"===a.type&&e.push({name:t,view:a});return e},[i]),[f,g]=useState(y.length>0?y[0].name:null),_=r??i?.raw_data?.blob_name??"trace";useEffect(()=>{if(!a||!s||!o)return d(null),p(!1),void h(null);let e=!1;return p(!0),h(null),(async()=>{try{const t=await l("tis.read_raw",MessageType.Request,{project_id:a,method_id:s,run_id:o,name:_});if(e)return;t?.success?d(t.data??{}):h(t?.error_message??"Failed to read raw data")}catch(t){e||h(String(t?.message??t))}finally{e||p(!1)}})(),()=>{e=!0}},[a,s,o,_,l]);const v=useMemo(()=>{if(!m||!f)return null;const e=y.find(e=>e.name===f)?.view;if(!e)return null;const t=e.x.column,a=m[t]??[];return{datasets:e.y.map((e,t)=>({label:e.label??e.column,data:(m[e.column]??[]).map((e,t)=>({x:a[t],y:e})),yAxisID:"right"===e.y_axis?"y1":"y",borderColor:palette(t),backgroundColor:palette(t),pointRadius:0,borderWidth:1.5,showLine:!0}))}},[m,f,y]),j=y.find(e=>e.name===f)?.view,b=j?.y.some(e=>"right"===e.y_axis)??!1,w=useMemo(()=>({responsive:!0,maintainAspectRatio:!1,parsing:!1,scales:{x:{type:"linear",title:{display:!!j?.x.label,text:j?.x.label}},y:{position:"left",title:{display:!0,text:axisLabel(j,"left")}},...b?{y1:{position:"right",grid:{drawOnChartArea:!1},title:{display:!0,text:axisLabel(j,"right")}}}:{}},plugins:{legend:{display:!0},zoom:{pan:{enabled:!0,mode:"xy"},zoom:{wheel:{enabled:!0},pinch:{enabled:!0},drag:{enabled:!0,modifierKey:"shift"},mode:"xy"}}}}),[j,b]);return a&&s&&o?i?i.raw_data?0===y.length?_jsx(EmptyState,{message:"No raw_trace views declared. Add one to schema.views in project.json."}):_jsxs("div",{className:"vblock",style:{display:"flex",flexDirection:"column",gap:"1rem",height:"100%"},children:[_jsxs("div",{className:"flex",style:{gap:"1rem",alignItems:"center"},children:[_jsx(Dropdown,{value:f,options:y.map(e=>({label:e.view.title??e.name,value:e.name})),onChange:e=>g(e.value),placeholder:"Select a view"}),_jsx("h3",{style:{margin:0},children:j?.title??""}),_jsx("div",{style:{flex:1}}),_jsx(Button,{icon:"pi pi-refresh",label:"Reset Zoom",outlined:!0,onClick:()=>x.current?.resetZoom?.()})]}),_jsxs("div",{style:{flex:1,minHeight:0,height:n,position:"relative"},children:[c&&_jsx(Overlay,{children:"Loading raw data…"}),u&&_jsx(Overlay,{children:u}),v&&!c&&!u&&_jsx(Line,{ref:x,data:v,options:w})]})]}):_jsx(EmptyState,{message:"No raw_data is declared for this test method."}):_jsx(EmptyState,{message:"Schema not loaded yet."}):_jsx(EmptyState,{message:"No test selected."})};const Overlay=({children:e})=>_jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",color:"var(--text-secondary-color)",pointerEvents:"none"},children:e}),EmptyState=({message:e})=>_jsx("div",{style:{padding:"1rem",color:"var(--text-secondary-color)"},children:e}),CHART_COLORS=["#4ea8de","#f59e0b","#22c55e","#a855f7","#ef4444","#14b8a6","#eab308","#ec4899"],palette=e=>CHART_COLORS[e%CHART_COLORS.length],axisLabel=(e,t)=>e?.y.filter(e=>(e.y_axis??"left")===t).map(e=>e.label??e.column).join(" / ")??"";
@@ -6,18 +6,29 @@ export interface TestFieldDef {
6
6
  required?: boolean;
7
7
  source?: string;
8
8
  }
9
- export interface TestDefinition {
9
+ export interface TestMethod {
10
10
  project_fields: TestFieldDef[];
11
11
  config_fields: TestFieldDef[];
12
12
  cycle_fields: TestFieldDef[];
13
13
  results_fields: TestFieldDef[];
14
14
  }
15
+ /**
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.
19
+ *
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.
25
+ */
15
26
  export interface TestSetupFormProps {
16
- schema: TestDefinition;
27
+ schema?: TestMethod;
17
28
  defaultProjectId?: string;
18
- defaultDefinitionId?: string;
29
+ defaultMethodId?: string;
19
30
  onProjectChange?: (projectId: string) => void;
20
- onDefinitionChange?: (definitionId: string) => void;
31
+ onMethodChange?: (methodId: string) => void;
21
32
  onValidationChange?: (isValid: boolean, config: any) => void;
22
33
  }
23
34
  export declare const TestSetupForm: React.FC<TestSetupFormProps>;
@@ -1 +1 @@
1
- {"version":3,"file":"TestSetupForm.d.ts","sourceRoot":"","sources":["../../../src/components/tis/TestSetupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAU/D,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC3B,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,cAAc,EAAE,YAAY,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAChE;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA4NtD,CAAC"}
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 +1 @@
1
- import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useEffect,useContext}from"react";import{AutoComplete}from"primereact/autocomplete";import{EventEmitterContext}from"../../core/EventEmitterContext";import{AutoCoreTagContext}from"../../core/AutoCoreTagContext";import{MessageType}from"../../hub/CommandMessage";import{ValueInput}from"../ValueInput";import{TextInput}from"../TextInput";import{InputText}from"primereact/inputtext";export const TestSetupForm=({schema:e,defaultProjectId:t="",defaultDefinitionId:a="default",onProjectChange:s,onDefinitionChange:n,onValidationChange:r})=>{const[i,o]=useState({}),[c,l]=useState(t),[m,p]=useState(a);useEffect(()=>{s&&s(c)},[c,s]),useEffect(()=>{n&&n(m)},[m,n]);const[u,d]=useState([]),[f,x]=useState([]),[g,j]=useState(!1),{invoke:h,write:_}=useContext(EventEmitterContext),{rawValues:v,findTagByFqdn:C}=useContext(AutoCoreTagContext);useEffect(()=>{if(!e)return;const t=[...e.project_fields,...e.config_fields];o(e=>{let a=e;for(const s of t){if(!s.source)continue;const t=C(s.source);if(!t)continue;const n=v[t.tagName];null!=n&&(a[s.name]!==n&&(a===e&&(a={...e}),a[s.name]=n))}return a})},[e,v,C]),useEffect(()=>{(async()=>{try{const e=await h("results.list_projects",MessageType.Request,{});e.success&&e.data&&e.data.projects&&d(e.data.projects)}catch(e){}})()},[h]);useEffect(()=>{if(!e)return;let t=!0;c&&""!==c.trim()||(t=!1),m&&""!==m.trim()||(t=!1);const a=[...e.project_fields,...e.config_fields];for(const e of a)if(e.required&&(void 0===i[e.name]||""===i[e.name]||null===i[e.name])){t=!1;break}j(t),r&&r(t,i)},[i,e,c,m,r]);const y=async(e,t)=>{if(o({...i,[e.name]:t}),e.source)try{await _(e.source,t)}catch(e){}},N=e=>{const t=(e=>!e.required||void 0!==i[e.name]&&""!==i[e.name]&&null!==i[e.name])(e),a="string"!==e.type&&"bool"!==e.type;return _jsxs(React.Fragment,{children:[_jsx("span",{className:"ac-form-label",children:e.name}),a?_jsx(ValueInput,{label:void 0,value:null!=i[e.name]?Number(i[e.name]):null,onValueChanged:t=>y(e,t),className:t?"":"p-invalid"}):_jsx(TextInput,{label:void 0,value:null!=i[e.name]?String(i[e.name]):"",onValueChanged:t=>y(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 e?_jsxs("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:[_jsxs("h3",{className:"ac-form-section",style:{display:"flex",alignItems:"center",gap:"10px"},children:["Project & Definition",_jsx("span",{style:{color:g?"var(--green-500)":"var(--red-500)"},children:_jsx("i",{className:g?"pi pi-check-circle":"pi pi-exclamation-circle"})})]}),_jsx("span",{className:"ac-form-label",children:"Project ID"}),_jsx(AutoComplete,{value:c,suggestions:f,completeMethod:e=>{const t=e.query.toLowerCase();x(u.filter(e=>e.toLowerCase().includes(t)))},onChange:e=>(e=>{const t=(e||"").replace(/[^a-zA-Z0-9_]/g,"");l(t)})(e.value),dropdown:!0,placeholder:"Enter or select Project ID",className:c&&""!==c.trim()?"":"p-invalid"}),_jsx("span",{}),_jsx("span",{style:{color:c&&""!==c.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:c&&""!==c.trim()?"pi pi-check":"pi pi-times"})}),_jsx("span",{className:"ac-form-label",children:"Definition ID"}),_jsx(InputText,{value:m,onChange:e=>(e=>{const t=e.replace(/[^a-zA-Z0-9_]/g,"");p(t)})(e.target.value),placeholder:"Enter Definition ID",className:m&&""!==m.trim()?"":"p-invalid"}),_jsx("span",{}),_jsx("span",{style:{color:m&&""!==m.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:m&&""!==m.trim()?"pi pi-check":"pi pi-times"})}),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Project Information"}),e.project_fields.map(N),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Test Configuration"}),e.config_fields.map(N)]}):_jsx("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:_jsx("h3",{className:"ac-form-section",children:"No Test Definition Selected"})})};
1
+ import{jsx as _jsx,jsxs as _jsxs,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…"})})};
@@ -0,0 +1,93 @@
1
+ import React, { type ReactNode } from 'react';
2
+ /**
3
+ * One slot in the schema registry. Kept as an opaque object so the
4
+ * provider doesn't have to mirror every schema field — components that
5
+ * need typed access import the schema constants from the per-project
6
+ * generated `autocore/tis.ts` instead.
7
+ */
8
+ export type TisMethodSchema = any;
9
+ export type SchemaRegistry = {
10
+ [methodId: string]: TisMethodSchema;
11
+ };
12
+ export interface TisLiveState {
13
+ staged: boolean;
14
+ stagedProjectId: string;
15
+ stagedMethodId: string;
16
+ stagedSampleId: string;
17
+ active: boolean;
18
+ activeProjectId: string;
19
+ activeMethodId: string;
20
+ activeSampleId: string;
21
+ activeRunId: string;
22
+ }
23
+ export interface TisSelection {
24
+ projectId: string;
25
+ methodId: string;
26
+ sampleId: string;
27
+ runId: string;
28
+ }
29
+ /** Partial setter — pass `null` for a field to clear the pin and let
30
+ * the active scalar drive that field again. */
31
+ export type TisSelectionPatch = {
32
+ projectId?: string | null;
33
+ methodId?: string | null;
34
+ sampleId?: string | null;
35
+ runId?: string | null;
36
+ };
37
+ export interface TisRunCacheEntry {
38
+ meta: any | null;
39
+ cycles: any[];
40
+ results: any;
41
+ rawData: {
42
+ [blobName: string]: any;
43
+ };
44
+ }
45
+ export interface TisContextValue {
46
+ schemas: SchemaRegistry;
47
+ defaultMethodId: string;
48
+ schemasLoaded: boolean;
49
+ state: TisLiveState;
50
+ selection: TisSelection;
51
+ setSelection: (patch: TisSelectionPatch) => void;
52
+ /** Fetch the run list for a (project, method?) pair. Method may be
53
+ * omitted to aggregate runs across every method in the project —
54
+ * the History tab uses this. */
55
+ fetchRuns: (projectId: string, methodId?: string) => Promise<any[]>;
56
+ /** Fetch the full bundle (test.json + cycles + results) for one run.
57
+ * Subsequent broadcast deltas land in the cache automatically. */
58
+ fetchRun: (projectId: string, methodId: string, runId: string) => Promise<TisRunCacheEntry | null>;
59
+ runCache: {
60
+ [runId: string]: TisRunCacheEntry;
61
+ };
62
+ }
63
+ declare const TisContext: React.Context<TisContextValue>;
64
+ export interface TisProviderProps {
65
+ children: ReactNode;
66
+ /**
67
+ * Initial method_id when the schemas haven't loaded yet, or when the
68
+ * server's reported `default_method_id` is empty. Falls through to
69
+ * the first key of `tis.list_schemas` if not supplied.
70
+ */
71
+ defaultMethodId?: string;
72
+ }
73
+ export declare const TisProvider: React.FC<TisProviderProps>;
74
+ export declare const useTis: () => TisContextValue;
75
+ export declare const useTisSchemas: () => SchemaRegistry;
76
+ export declare const useTisState: () => TisLiveState;
77
+ export declare const useTisSelection: () => readonly [TisSelection, (patch: TisSelectionPatch) => void];
78
+ export declare const useTisRuns: (projectId?: string, methodId?: string) => {
79
+ runs: any[];
80
+ loading: boolean;
81
+ refresh: () => Promise<void>;
82
+ };
83
+ export declare const useTisRun: (runId?: string) => {
84
+ meta: any;
85
+ cycles: any[];
86
+ results: any;
87
+ rawData: {
88
+ [blobName: string]: any;
89
+ };
90
+ loading: boolean;
91
+ };
92
+ export { TisContext };
93
+ //# sourceMappingURL=TisProvider.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +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};
@@ -30,6 +30,19 @@ export declare class HubWebSocket extends HubBase {
30
30
  * Used to match asynchronous WebSocket responses to their original requests.
31
31
  */
32
32
  private pendingRequests;
33
+ /**
34
+ * Messages queued while the WebSocket is still in CONNECTING state.
35
+ * Flushed in `socket.onopen`. Without this queue, an `invoke()` fired
36
+ * from a React `useEffect` on first mount races the WS handshake —
37
+ * `socket.send()` on a non-OPEN socket throws a synchronous
38
+ * DOMException ("object not, or is no longer, usable"), which the
39
+ * caller sees as an opaque rejection and the underlying request is
40
+ * never sent.
41
+ *
42
+ * Each entry carries the request id so we can reject the matching
43
+ * pending Promise if the WS closes before we ever flush.
44
+ */
45
+ private sendQueue;
33
46
  /**
34
47
  * Initializes the WebSocket connection immediately.
35
48
  */
@@ -1 +1 @@
1
- {"version":3,"file":"HubWebSocket.d.ts","sourceRoot":"","sources":["../../src/hub/HubWebSocket.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA+DpE;;GAEG;AACH,qBAAa,YAAa,SAAQ,OAAO;IACrC,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,SAAS,CAAK;IAEtB;;;OAGG;IACH,OAAO,CAAC,eAAe,CAAoC;IAE3D;;OAEG;;IA4FH;;;;;OAKG;IACH,MAAM,GAAI,OAAO,MAAM,EAAE,aAAa,WAAW,EAAE,UAAU,MAAM,KAAG,OAAO,CAAC,cAAc,CAAC,CAqB5F;IAED;;;OAGG;IACH,wBAAwB,GAAI,KAAK,cAAc,UAO9C;IAED,UAAU,QAAO,IAAI,CAEpB;IAED,SAAS,CAAC,IAAI,GAAI,WAAW,MAAM,EAAE,UAAU,MAAM,KAAG,IAAI,CAE3D;CACJ"}
1
+ {"version":3,"file":"HubWebSocket.d.ts","sourceRoot":"","sources":["../../src/hub/HubWebSocket.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA+DpE;;GAEG;AACH,qBAAa,YAAa,SAAQ,OAAO;IACrC,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,SAAS,CAAK;IAEtB;;;OAGG;IACH,OAAO,CAAC,eAAe,CAAoC;IAE3D;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,SAAS,CAA2C;IAE5D;;OAEG;;IAqHH;;;;;OAKG;IACH,MAAM,GAAI,OAAO,MAAM,EAAE,aAAa,WAAW,EAAE,UAAU,MAAM,KAAG,OAAO,CAAC,cAAc,CAAC,CA6C5F;IAED;;;OAGG;IACH,wBAAwB,GAAI,KAAK,cAAc,UAO9C;IAED,UAAU,QAAO,IAAI,CAEpB;IAED,SAAS,CAAC,IAAI,GAAI,WAAW,MAAM,EAAE,UAAU,MAAM,KAAG,IAAI,CAE3D;CACJ"}
@@ -1 +1 @@
1
- import{HubBase}from"./HubBase";import{MessageType}from"./CommandMessage";import{getDebugPanel}from"./DebugPanel";function b64toBlob(e,t="application/octet-stream",s=512){const n=atob(e),o=[];for(let e=0;e<n.length;e+=s){const t=n.slice(e,e+s),a=new Array(t.length);for(let e=0;e<t.length;e++)a[e]=t.charCodeAt(e);const i=new Uint8Array(a);o.push(i.buffer)}return new Blob(o,{type:t})}function downloadBlob(e,t){const s=window.URL.createObjectURL(e),n=document.createElement("a");n.href=s,n.download=t,document.body.appendChild(n),n.click(),document.body.removeChild(n),window.URL.revokeObjectURL(s)}export class HubWebSocket extends HubBase{constructor(){super(),Object.defineProperty(this,"socket",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"requestId",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"pendingRequests",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"invoke",{enumerable:!0,configurable:!0,writable:!0,value:(e,t,s)=>new Promise((n,o)=>{const a=++this.requestId;this.pendingRequests.set(a,{resolve:n,reject:o});const i={transaction_id:a,topic:e,data:s||{},timecode:Date.now(),message_type:t,success:!1,error_message:""};getDebugPanel().messageSent(MessageType[t],e,a),this.socket.send(JSON.stringify(i))})}),Object.defineProperty(this,"handleUnsolicitedMessage",{enumerable:!0,configurable:!0,writable:!0,value:e=>{e.message_type==MessageType.Broadcast&&e.topic.length>1&&this.publish(e.topic,e.data)}}),Object.defineProperty(this,"disconnect",{enumerable:!0,configurable:!0,writable:!0,value:()=>{this.socket.close()}}),Object.defineProperty(this,"emit",{enumerable:!0,configurable:!0,writable:!0,value:(e,t)=>{this.socket.send(JSON.stringify({eventName:e,payload:t}))}}),getDebugPanel().hubCreated();const e=window.location.hostname,t=window.location.port,s=`${"https:"===window.location.protocol?"wss://":"ws://"}${e}${t?":"+t:""}/ws/`;this.socket=new WebSocket(s);let n=this;this.socket.onopen=function(){getDebugPanel().wsOpened(s),n.publish("HUB/connected",!0),n.setIsConnected(!0)},this.socket.onmessage=e=>{const t=JSON.parse(e.data);if(getDebugPanel().messageReceived(MessageType[t.message_type]||String(t.message_type),t.topic,t.transaction_id),t.transaction_id&&this.pendingRequests.has(t.transaction_id)){const{resolve:e,reject:s}=this.pendingRequests.get(t.transaction_id);if("FILE_DOWNLOAD"===t.topic&&void 0!==t.data.file_name&&null!==t.data.file_name&&t.data.file_name.length>0){let n=t.data.file_name.split("/");const o=n[n.length-1];if(t.success){downloadBlob(b64toBlob(t.data),o),t.data=o,e(t)}else s(new Error(t.error_message))}else t.success?e(t):s(new Error(t.error_message));this.pendingRequests.delete(t.transaction_id)}else this.handleUnsolicitedMessage(t)},this.socket.onerror=e=>{getDebugPanel().wsError(String(e))},this.socket.onclose=e=>{n.setIsConnected(!1),getDebugPanel().wsClosed(e.code,e.reason||"No reason")}}}
1
+ import{HubBase}from"./HubBase";import{MessageType}from"./CommandMessage";import{getDebugPanel}from"./DebugPanel";function b64toBlob(e,t="application/octet-stream",s=512){const n=atob(e),o=[];for(let e=0;e<n.length;e+=s){const t=n.slice(e,e+s),a=new Array(t.length);for(let e=0;e<t.length;e++)a[e]=t.charCodeAt(e);const i=new Uint8Array(a);o.push(i.buffer)}return new Blob(o,{type:t})}function downloadBlob(e,t){const s=window.URL.createObjectURL(e),n=document.createElement("a");n.href=s,n.download=t,document.body.appendChild(n),n.click(),document.body.removeChild(n),window.URL.revokeObjectURL(s)}export class HubWebSocket extends HubBase{constructor(){super(),Object.defineProperty(this,"socket",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),Object.defineProperty(this,"requestId",{enumerable:!0,configurable:!0,writable:!0,value:0}),Object.defineProperty(this,"pendingRequests",{enumerable:!0,configurable:!0,writable:!0,value:new Map}),Object.defineProperty(this,"sendQueue",{enumerable:!0,configurable:!0,writable:!0,value:[]}),Object.defineProperty(this,"invoke",{enumerable:!0,configurable:!0,writable:!0,value:(e,t,s)=>new Promise((n,o)=>{const a=++this.requestId;this.pendingRequests.set(a,{resolve:n,reject:o});const i={transaction_id:a,topic:e,data:s||{},timecode:Date.now(),message_type:t,success:!1,error_message:""};getDebugPanel().messageSent(MessageType[t],e,a);const r=JSON.stringify(i);switch(this.socket.readyState){case WebSocket.OPEN:this.socket.send(r);break;case WebSocket.CONNECTING:this.sendQueue.push({id:a,json:r});break;default:this.pendingRequests.delete(a),o(new Error(`WebSocket not open (readyState=${this.socket.readyState}); cannot send '${e}'`))}})}),Object.defineProperty(this,"handleUnsolicitedMessage",{enumerable:!0,configurable:!0,writable:!0,value:e=>{e.message_type==MessageType.Broadcast&&e.topic.length>1&&this.publish(e.topic,e.data)}}),Object.defineProperty(this,"disconnect",{enumerable:!0,configurable:!0,writable:!0,value:()=>{this.socket.close()}}),Object.defineProperty(this,"emit",{enumerable:!0,configurable:!0,writable:!0,value:(e,t)=>{this.socket.send(JSON.stringify({eventName:e,payload:t}))}}),getDebugPanel().hubCreated();const e=window.location.hostname,t=window.location.port,s=`${"https:"===window.location.protocol?"wss://":"ws://"}${e}${t?":"+t:""}/ws/`;this.socket=new WebSocket(s);let n=this;this.socket.onopen=function(){if(getDebugPanel().wsOpened(s),n.sendQueue.length>0){for(const{json:e}of n.sendQueue)n.socket.send(e);n.sendQueue=[]}n.publish("HUB/connected",!0),n.setIsConnected(!0)},this.socket.onmessage=e=>{const t=JSON.parse(e.data);if(getDebugPanel().messageReceived(MessageType[t.message_type]||String(t.message_type),t.topic,t.transaction_id),t.transaction_id&&this.pendingRequests.has(t.transaction_id)){const{resolve:e,reject:s}=this.pendingRequests.get(t.transaction_id);if("FILE_DOWNLOAD"===t.topic&&void 0!==t.data.file_name&&null!==t.data.file_name&&t.data.file_name.length>0){let n=t.data.file_name.split("/");const o=n[n.length-1];if(t.success){downloadBlob(b64toBlob(t.data),o),t.data=o,e(t)}else s(new Error(t.error_message))}else t.success?e(t):s(new Error(t.error_message));this.pendingRequests.delete(t.transaction_id)}else this.handleUnsolicitedMessage(t)},this.socket.onerror=e=>{getDebugPanel().wsError(String(e))},this.socket.onclose=e=>{if(n.setIsConnected(!1),getDebugPanel().wsClosed(e.code,e.reason||"No reason"),n.sendQueue.length>0){for(const{id:e}of n.sendQueue){const t=n.pendingRequests.get(e);t&&(t.reject(new Error("WebSocket closed before message could be sent")),n.pendingRequests.delete(e))}n.sendQueue=[]}}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adcops/autocore-react",
3
- "version": "3.3.50",
3
+ "version": "3.3.57",
4
4
  "description": "A React component library for industrial user interfaces.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -1,11 +1,32 @@
1
1
  // Re-exports for convenience. Components in `tis/` (Test Information System)
2
2
  // each declare their own types; a couple are duplicated across files
3
- // (`TestFieldDef`, `TestDefinition` exist in both `TestSetupForm` and
3
+ // (`TestFieldDef`, `TestMethod` exist in both `TestSetupForm` and
4
4
  // `TestDataView`), so we re-export components and prop types explicitly
5
5
  // instead of using `export *`.
6
6
  //
7
7
  // Callers can also deep-import: `from '@adcops/autocore-react/components/tis/<Name>'`.
8
8
 
9
+ export {
10
+ TisProvider,
11
+ TisContext,
12
+ useTis,
13
+ useTisSchemas,
14
+ useTisState,
15
+ useTisSelection,
16
+ useTisRuns,
17
+ useTisRun,
18
+ } from './tis/TisProvider';
19
+ export type {
20
+ TisProviderProps,
21
+ TisContextValue,
22
+ TisLiveState,
23
+ TisSelection,
24
+ TisSelectionPatch,
25
+ TisRunCacheEntry,
26
+ SchemaRegistry,
27
+ TisMethodSchema,
28
+ } from './tis/TisProvider';
29
+
9
30
  export { TestSetupForm } from './tis/TestSetupForm';
10
31
  export type { TestSetupFormProps } from './tis/TestSetupForm';
11
32