@adcops/autocore-react 3.3.39 → 3.3.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ResultHistoryTable.d.ts.map +1 -1
- package/dist/components/ResultHistoryTable.js +1 -1
- package/dist/components/TestSetupForm.d.ts.map +1 -1
- package/dist/components/TestSetupForm.js +1 -1
- package/package.json +1 -1
- package/src/components/ResultHistoryTable.tsx +2 -1
- package/src/components/TestSetupForm.tsx +106 -60
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResultHistoryTable.d.ts","sourceRoot":"","sources":["../../src/components/ResultHistoryTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0C,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ResultHistoryTable.d.ts","sourceRoot":"","sources":["../../src/components/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;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAiDhE,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";export const ResultHistoryTable=({projectId:
|
|
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";export const ResultHistoryTable=({projectId:e,definitionId:t})=>{const[s,r]=useState([]),[i,o]=useState(!1),{invoke:n}=useContext(EventEmitterContext),a=async()=>{o(!0);try{const s=await n("results.list_tests",MessageType.Request,{project_id:e,definition_id:t});s.success&&s.data&&s.data.tests&&r(s.data.tests)}catch(e){}o(!1)};useEffect(()=>{a()},[e,t]);return _jsxs("div",{children:[_jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1rem"},children:[_jsxs("h3",{children:["Test History: ",t]}),_jsx(Button,{icon:"pi pi-refresh",label:"Refresh",onClick:a,disabled:i})]}),_jsxs(DataTable,{value:s,loading:i,paginator:!0,rows:10,emptyMessage:"No tests found.",children:[_jsx(Column,{field:"run_id",header:"Run ID",sortable:!0}),_jsx(Column,{field:"start_time",header:"Date/Time",body:e=>{return(t=e.start_time)?new Date(t).toLocaleString():"";var t},sortable:!0}),_jsx(Column,{header:"Config / Results",body:e=>_jsxs("div",{style:{fontSize:"0.85em",color:"var(--text-secondary-color)"},children:[_jsxs("div",{children:[_jsx("strong",{children:"Config:"})," ",JSON.stringify(e.config)]}),_jsxs("div",{children:[_jsx("strong",{children:"Results:"})," ",JSON.stringify(e.results)]})]})})]})]})};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestSetupForm.d.ts","sourceRoot":"","sources":["../../src/components/TestSetupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0C,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"TestSetupForm.d.ts","sourceRoot":"","sources":["../../src/components/TestSetupForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAS/D,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC3B,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,cAAc,EAAE,YAAY,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,IAAI,CAAC;CAChE;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA4MtD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useEffect,useContext}from"react";import{
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useEffect,useContext}from"react";import{AutoComplete}from"primereact/autocomplete";import{EventEmitterContext}from"../core/EventEmitterContext";import{MessageType}from"../hub/CommandMessage";import{ValueInput}from"./ValueInput";import{TextInput}from"./TextInput";import{InputText}from"primereact/inputtext";export const TestSetupForm=({schema:e,defaultProjectId:t="",defaultDefinitionId:s="default",onProjectChange:a,onDefinitionChange:n,onValidationChange:i})=>{const[r,o]=useState({}),[c,l]=useState(t),[m,p]=useState(s);useEffect(()=>{a&&a(c)},[c,a]),useEffect(()=>{n&&n(m)},[m,n]);const[u,f]=useState([]),[d,x]=useState([]),[j,g]=useState(!1),{invoke:h,write:_,subscribe:v,unsubscribe:y}=useContext(EventEmitterContext);useEffect(()=>{if(!e)return;const t=[...e.project_fields,...e.config_fields],s=[];for(const e of t)if(e.source){const t=v(e.source,t=>{o(s=>s[e.name]!==t?{...s,[e.name]:t}:s)});s.push(t)}return()=>{for(const e of s)y(e)}},[e,v,y]),useEffect(()=>{(async()=>{try{const e=await h("results.list_projects",MessageType.Request,{});e.success&&e.data&&e.data.projects&&f(e.data.projects)}catch(e){}})()},[h]);useEffect(()=>{if(!e)return;let t=!0;c&&""!==c.trim()||(t=!1),m&&""!==m.trim()||(t=!1);const s=[...e.project_fields,...e.config_fields];for(const e of s)if(e.required&&(void 0===r[e.name]||""===r[e.name]||null===r[e.name])){t=!1;break}g(t),i&&i(t,r)},[r,e,c,m,i]);const I=async(e,t)=>{if(o({...r,[e.name]:t}),e.source)try{await _(e.source,t)}catch(e){}},N=e=>{const t=(e=>!e.required||void 0!==r[e.name]&&""!==r[e.name]&&null!==r[e.name])(e),s="string"!==e.type&&"bool"!==e.type;return _jsxs(React.Fragment,{children:[_jsx("span",{className:"ac-form-label",children:e.name}),s?_jsx(ValueInput,{label:void 0,value:null!=r[e.name]?Number(r[e.name]):null,suffix:e.units?` ${e.units}`:void 0,onValueChanged:t=>I(e,t),className:t?"":"p-invalid"}):_jsx(TextInput,{label:void 0,value:null!=r[e.name]?String(r[e.name]):"",suffix:e.units?` ${e.units}`:void 0,onValueChanged:t=>I(e,t),className:t?"":"p-invalid"}),_jsx("span",{style:{color:t?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:t?"pi pi-check":"pi pi-times"})})]},e.name)};return e?_jsxs("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:[_jsxs("h3",{className:"ac-form-section",style:{display:"flex",alignItems:"center",gap:"10px"},children:["Project & Definition",_jsx("span",{style:{color:j?"var(--green-500)":"var(--red-500)"},children:_jsx("i",{className:j?"pi pi-check-circle":"pi pi-exclamation-circle"})})]}),_jsx("span",{className:"ac-form-label",children:"Project ID"}),_jsx(AutoComplete,{value:c,suggestions:d,completeMethod:e=>{const t=e.query.toLowerCase();x(u.filter(e=>e.toLowerCase().includes(t)))},onChange:e=>(e=>{const t=(e||"").replace(/[^a-zA-Z0-9_]/g,"");l(t)})(e.value),dropdown:!0,placeholder:"Enter or select Project ID",className:c&&""!==c.trim()?"":"p-invalid"}),_jsx("span",{style:{color:c&&""!==c.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:c&&""!==c.trim()?"pi pi-check":"pi pi-times"})}),_jsx("span",{className:"ac-form-label",children:"Definition ID"}),_jsx(InputText,{value:m,onChange:e=>(e=>{const t=e.replace(/[^a-zA-Z0-9_]/g,"");p(t)})(e.target.value),placeholder:"Enter Definition ID",className:m&&""!==m.trim()?"":"p-invalid"}),_jsx("span",{style:{color:m&&""!==m.trim()?"var(--green-500)":"var(--red-500)",display:"flex",alignItems:"center"},children:_jsx("i",{className:m&&""!==m.trim()?"pi pi-check":"pi pi-times"})}),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Project Information"}),e.project_fields.map(N),_jsx("h3",{className:"ac-form-section",style:{marginTop:"1rem"},children:"Test Configuration"}),e.config_fields.map(N)]}):_jsx("div",{className:"ac-form-grid",style:{padding:"1.25rem"},children:_jsx("h3",{className:"ac-form-section",children:"No Test Definition Selected"})})};
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@ import { DataTable } from 'primereact/datatable';
|
|
|
3
3
|
import { Column } from 'primereact/column';
|
|
4
4
|
import { Button } from 'primereact/button';
|
|
5
5
|
import { EventEmitterContext } from '../core/EventEmitterContext';
|
|
6
|
+
import { MessageType } from '../hub/CommandMessage';
|
|
6
7
|
|
|
7
8
|
export interface ResultHistoryTableProps {
|
|
8
9
|
projectId: string;
|
|
@@ -17,7 +18,7 @@ export const ResultHistoryTable: React.FC<ResultHistoryTableProps> = ({ projectI
|
|
|
17
18
|
const loadTests = async () => {
|
|
18
19
|
setLoading(true);
|
|
19
20
|
try {
|
|
20
|
-
const resp: any = await invoke('results.list_tests' as any, {
|
|
21
|
+
const resp: any = await invoke('results.list_tests' as any, MessageType.Request, {
|
|
21
22
|
project_id: projectId,
|
|
22
23
|
definition_id: definitionId
|
|
23
24
|
} as any);
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React, { useState, useEffect, useContext } from 'react';
|
|
2
|
-
import { InputText } from 'primereact/inputtext';
|
|
3
2
|
import { AutoComplete } from 'primereact/autocomplete';
|
|
4
3
|
import type { AutoCompleteCompleteEvent } from 'primereact/autocomplete';
|
|
5
4
|
import { EventEmitterContext } from '../core/EventEmitterContext';
|
|
6
5
|
import { MessageType } from '../hub/CommandMessage';
|
|
6
|
+
import { ValueInput } from './ValueInput';
|
|
7
|
+
import { TextInput } from './TextInput';
|
|
8
|
+
import { InputText } from 'primereact/inputtext';
|
|
7
9
|
|
|
8
10
|
export interface TestFieldDef {
|
|
9
11
|
name: string;
|
|
@@ -54,7 +56,36 @@ export const TestSetupForm: React.FC<TestSetupFormProps> = ({
|
|
|
54
56
|
const [filteredProjects, setFilteredProjects] = useState<string[]>([]);
|
|
55
57
|
|
|
56
58
|
const [isValid, setIsValid] = useState(false);
|
|
57
|
-
const { invoke } = useContext(EventEmitterContext);
|
|
59
|
+
const { invoke, write, subscribe, unsubscribe } = useContext(EventEmitterContext);
|
|
60
|
+
|
|
61
|
+
// Subscribe to external tags if a field defines a source
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (!schema) return;
|
|
64
|
+
|
|
65
|
+
const allFields = [...schema.project_fields, ...schema.config_fields];
|
|
66
|
+
const subs: any[] = [];
|
|
67
|
+
|
|
68
|
+
for (const field of allFields) {
|
|
69
|
+
if (field.source) {
|
|
70
|
+
const subId = subscribe(field.source, (newVal: any) => {
|
|
71
|
+
setConfig((prev: any) => {
|
|
72
|
+
// Only update if it actually changed to prevent infinite loops
|
|
73
|
+
if (prev[field.name] !== newVal) {
|
|
74
|
+
return { ...prev, [field.name]: newVal };
|
|
75
|
+
}
|
|
76
|
+
return prev;
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
subs.push(subId);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return () => {
|
|
84
|
+
for (const subId of subs) {
|
|
85
|
+
unsubscribe(subId);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}, [schema, subscribe, unsubscribe]);
|
|
58
89
|
|
|
59
90
|
useEffect(() => {
|
|
60
91
|
const fetchProjects = async () => {
|
|
@@ -75,17 +106,13 @@ export const TestSetupForm: React.FC<TestSetupFormProps> = ({
|
|
|
75
106
|
setFilteredProjects(existingProjects.filter(p => p.toLowerCase().includes(query)));
|
|
76
107
|
};
|
|
77
108
|
|
|
78
|
-
const handleProjectIdChange = (value: string) => {
|
|
79
|
-
const sanitized = value.replace(/[^a-zA-Z0-9_]/g, '');
|
|
80
|
-
setProjectId(sanitized);
|
|
81
|
-
};
|
|
82
|
-
|
|
83
109
|
const handleDefinitionIdChange = (value: string) => {
|
|
84
110
|
const sanitized = value.replace(/[^a-zA-Z0-9_]/g, '');
|
|
85
111
|
setDefinitionId(sanitized);
|
|
86
112
|
};
|
|
87
113
|
|
|
88
114
|
useEffect(() => {
|
|
115
|
+
if (!schema) return;
|
|
89
116
|
let valid = true;
|
|
90
117
|
if (!projectId || projectId.trim() === '') valid = false;
|
|
91
118
|
if (!definitionId || definitionId.trim() === '') valid = false;
|
|
@@ -93,8 +120,8 @@ export const TestSetupForm: React.FC<TestSetupFormProps> = ({
|
|
|
93
120
|
const allFields = [...schema.project_fields, ...schema.config_fields];
|
|
94
121
|
|
|
95
122
|
for (const field of allFields) {
|
|
96
|
-
if (field.required
|
|
97
|
-
if (config[field.name] === undefined || config[field.name] === '') {
|
|
123
|
+
if (field.required) {
|
|
124
|
+
if (config[field.name] === undefined || config[field.name] === '' || config[field.name] === null) {
|
|
98
125
|
valid = false;
|
|
99
126
|
break;
|
|
100
127
|
}
|
|
@@ -107,43 +134,66 @@ export const TestSetupForm: React.FC<TestSetupFormProps> = ({
|
|
|
107
134
|
}, [config, schema, projectId, definitionId, onValidationChange]);
|
|
108
135
|
|
|
109
136
|
const isFieldValid = (field: TestFieldDef) => {
|
|
110
|
-
if (!field.required
|
|
111
|
-
return config[field.name] !== undefined && config[field.name] !== '';
|
|
137
|
+
if (!field.required) return true;
|
|
138
|
+
return config[field.name] !== undefined && config[field.name] !== '' && config[field.name] !== null;
|
|
112
139
|
};
|
|
113
140
|
|
|
114
|
-
const
|
|
141
|
+
const handleProjectIdChange = (value: string | null | undefined) => {
|
|
142
|
+
const val = value || '';
|
|
143
|
+
const sanitized = val.replace(/[^a-zA-Z0-9_]/g, '');
|
|
144
|
+
setProjectId(sanitized);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const handleFieldChange = async (field: TestFieldDef, val: any) => {
|
|
148
|
+
setConfig({...config, [field.name]: val});
|
|
115
149
|
if (field.source) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
<span className="p-inputgroup-addon" style={{ color: 'var(--green-500)' }}>
|
|
122
|
-
<i className="pi pi-check"></i>
|
|
123
|
-
</span>
|
|
124
|
-
</div>
|
|
125
|
-
);
|
|
150
|
+
try {
|
|
151
|
+
await write(field.source, val);
|
|
152
|
+
} catch(e) {
|
|
153
|
+
console.error("Failed to write to source:", e);
|
|
154
|
+
}
|
|
126
155
|
}
|
|
156
|
+
};
|
|
127
157
|
|
|
158
|
+
const renderField = (field: TestFieldDef) => {
|
|
128
159
|
const valid = isFieldValid(field);
|
|
160
|
+
const isNum = field.type !== 'string' && field.type !== 'bool';
|
|
129
161
|
|
|
130
162
|
return (
|
|
131
|
-
<
|
|
132
|
-
<span className="
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
163
|
+
<React.Fragment key={field.name}>
|
|
164
|
+
<span className="ac-form-label">{field.name}</span>
|
|
165
|
+
{isNum ? (
|
|
166
|
+
<ValueInput
|
|
167
|
+
label={undefined}
|
|
168
|
+
value={config[field.name] != null ? Number(config[field.name]) : null}
|
|
169
|
+
suffix={field.units ? ` ${field.units}` : undefined}
|
|
170
|
+
onValueChanged={(val) => handleFieldChange(field, val)}
|
|
171
|
+
className={!valid ? 'p-invalid' : ''}
|
|
172
|
+
/>
|
|
173
|
+
) : (
|
|
174
|
+
<TextInput
|
|
175
|
+
label={undefined}
|
|
176
|
+
value={config[field.name] != null ? String(config[field.name]) : ''}
|
|
177
|
+
suffix={field.units ? ` ${field.units}` : undefined}
|
|
178
|
+
onValueChanged={(val) => handleFieldChange(field, val)}
|
|
179
|
+
className={!valid ? 'p-invalid' : ''}
|
|
180
|
+
/>
|
|
181
|
+
)}
|
|
182
|
+
<span style={{ color: valid ? 'var(--green-500)' : 'var(--red-500)', display: 'flex', alignItems: 'center' }}>
|
|
141
183
|
<i className={valid ? "pi pi-check" : "pi pi-times"}></i>
|
|
142
184
|
</span>
|
|
143
|
-
</
|
|
185
|
+
</React.Fragment>
|
|
144
186
|
);
|
|
145
187
|
};
|
|
146
188
|
|
|
189
|
+
if (!schema) {
|
|
190
|
+
return (
|
|
191
|
+
<div className="ac-form-grid" style={{ padding: '1.25rem' }}>
|
|
192
|
+
<h3 className="ac-form-section">No Test Definition Selected</h3>
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
147
197
|
return (
|
|
148
198
|
<div className="ac-form-grid" style={{ padding: '1.25rem' }}>
|
|
149
199
|
<h3 className="ac-form-section" style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
|
|
@@ -153,34 +203,30 @@ export const TestSetupForm: React.FC<TestSetupFormProps> = ({
|
|
|
153
203
|
</span>
|
|
154
204
|
</h3>
|
|
155
205
|
|
|
156
|
-
<
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
<
|
|
168
|
-
|
|
169
|
-
</span>
|
|
170
|
-
</div>
|
|
206
|
+
<span className="ac-form-label">Project ID</span>
|
|
207
|
+
<AutoComplete
|
|
208
|
+
value={projectId}
|
|
209
|
+
suggestions={filteredProjects}
|
|
210
|
+
completeMethod={searchProjects}
|
|
211
|
+
onChange={(e) => handleProjectIdChange(e.value)}
|
|
212
|
+
dropdown
|
|
213
|
+
placeholder="Enter or select Project ID"
|
|
214
|
+
className={!projectId || projectId.trim() === '' ? 'p-invalid' : ''}
|
|
215
|
+
/>
|
|
216
|
+
<span style={{ color: projectId && projectId.trim() !== '' ? 'var(--green-500)' : 'var(--red-500)', display: 'flex', alignItems: 'center' }}>
|
|
217
|
+
<i className={projectId && projectId.trim() !== '' ? "pi pi-check" : "pi pi-times"}></i>
|
|
218
|
+
</span>
|
|
171
219
|
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
<
|
|
181
|
-
|
|
182
|
-
</span>
|
|
183
|
-
</div>
|
|
220
|
+
<span className="ac-form-label">Definition ID</span>
|
|
221
|
+
<InputText
|
|
222
|
+
value={definitionId}
|
|
223
|
+
onChange={(e) => handleDefinitionIdChange(e.target.value)}
|
|
224
|
+
placeholder="Enter Definition ID"
|
|
225
|
+
className={!definitionId || definitionId.trim() === '' ? 'p-invalid' : ''}
|
|
226
|
+
/>
|
|
227
|
+
<span style={{ color: definitionId && definitionId.trim() !== '' ? 'var(--green-500)' : 'var(--red-500)', display: 'flex', alignItems: 'center' }}>
|
|
228
|
+
<i className={definitionId && definitionId.trim() !== '' ? "pi pi-check" : "pi pi-times"}></i>
|
|
229
|
+
</span>
|
|
184
230
|
|
|
185
231
|
<h3 className="ac-form-section" style={{ marginTop: '1rem' }}>Project Information</h3>
|
|
186
232
|
{schema.project_fields.map(renderField)}
|