@adcops/autocore-react 3.3.84 → 3.3.87
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/ValueInput.css +9 -12
- package/dist/components/ValueInput.d.ts +45 -154
- package/dist/components/ValueInput.d.ts.map +1 -1
- package/dist/components/ValueInput.js +1 -1
- package/dist/components/ams/AssetEditDialog.d.ts.map +1 -1
- package/dist/components/ams/AssetEditDialog.js +1 -1
- package/dist/components/forms/FormRow.d.ts +20 -0
- package/dist/components/forms/FormRow.d.ts.map +1 -0
- package/dist/components/forms/FormRow.js +1 -0
- package/dist/components/forms/FormSection.d.ts +19 -0
- package/dist/components/forms/FormSection.d.ts.map +1 -0
- package/dist/components/forms/FormSection.js +1 -0
- package/dist/components/forms/forms.css +89 -0
- package/dist/components/forms/index.d.ts +3 -0
- package/dist/components/forms/index.d.ts.map +1 -0
- package/dist/components/forms/index.js +1 -0
- package/dist/components/tis-editor/TisConfigEditor.css +121 -0
- package/dist/components/tis-editor/TisConfigEditor.d.ts +28 -0
- package/dist/components/tis-editor/TisConfigEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/TisConfigEditor.js +1 -0
- package/dist/components/tis-editor/editor/AnalysisEditor.d.ts +7 -0
- package/dist/components/tis-editor/editor/AnalysisEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/AnalysisEditor.js +1 -0
- package/dist/components/tis-editor/editor/AssetRefsEditor.d.ts +10 -0
- package/dist/components/tis-editor/editor/AssetRefsEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/AssetRefsEditor.js +1 -0
- package/dist/components/tis-editor/editor/ChartViewDialog.d.ts +16 -0
- package/dist/components/tis-editor/editor/ChartViewDialog.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/ChartViewDialog.js +1 -0
- package/dist/components/tis-editor/editor/FieldArrayEditor.d.ts +8 -0
- package/dist/components/tis-editor/editor/FieldArrayEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/FieldArrayEditor.js +1 -0
- package/dist/components/tis-editor/editor/IdentitySection.d.ts +7 -0
- package/dist/components/tis-editor/editor/IdentitySection.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/IdentitySection.js +1 -0
- package/dist/components/tis-editor/editor/MethodFormEditor.d.ts +20 -0
- package/dist/components/tis-editor/editor/MethodFormEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/MethodFormEditor.js +1 -0
- package/dist/components/tis-editor/editor/RawDataEditor.d.ts +7 -0
- package/dist/components/tis-editor/editor/RawDataEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/RawDataEditor.js +1 -0
- package/dist/components/tis-editor/editor/SaveDiffDialog.d.ts +22 -0
- package/dist/components/tis-editor/editor/SaveDiffDialog.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/SaveDiffDialog.js +1 -0
- package/dist/components/tis-editor/editor/TestFieldDialog.d.ts +11 -0
- package/dist/components/tis-editor/editor/TestFieldDialog.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/TestFieldDialog.js +1 -0
- package/dist/components/tis-editor/editor/ViewsEditor.d.ts +7 -0
- package/dist/components/tis-editor/editor/ViewsEditor.d.ts.map +1 -0
- package/dist/components/tis-editor/editor/ViewsEditor.js +1 -0
- package/dist/components/tis-editor/types.d.ts +78 -0
- package/dist/components/tis-editor/types.d.ts.map +1 -0
- package/dist/components/tis-editor/types.js +1 -0
- package/dist/components/tis-editor/validation.d.ts +20 -0
- package/dist/components/tis-editor/validation.d.ts.map +1 -0
- package/dist/components/tis-editor/validation.js +1 -0
- package/dist/hooks/useAmsAssetTypes.d.ts +23 -0
- package/dist/hooks/useAmsAssetTypes.d.ts.map +1 -0
- package/dist/hooks/useAmsAssetTypes.js +1 -0
- package/dist/hooks/useTisConfig.d.ts +51 -0
- package/dist/hooks/useTisConfig.d.ts.map +1 -0
- package/dist/hooks/useTisConfig.js +1 -0
- package/package.json +9 -3
- package/src/components/ValueInput.css +9 -12
- package/src/components/ValueInput.tsx +132 -317
- package/src/components/ams/AssetEditDialog.tsx +357 -20
- package/src/components/forms/FormRow.tsx +37 -0
- package/src/components/forms/FormSection.tsx +39 -0
- package/src/components/forms/forms.css +89 -0
- package/src/components/forms/index.ts +2 -0
- package/src/components/tis-editor/TisConfigEditor.css +121 -0
- package/src/components/tis-editor/TisConfigEditor.tsx +321 -0
- package/src/components/tis-editor/editor/AnalysisEditor.tsx +54 -0
- package/src/components/tis-editor/editor/AssetRefsEditor.tsx +187 -0
- package/src/components/tis-editor/editor/ChartViewDialog.tsx +170 -0
- package/src/components/tis-editor/editor/FieldArrayEditor.tsx +131 -0
- package/src/components/tis-editor/editor/IdentitySection.tsx +36 -0
- package/src/components/tis-editor/editor/MethodFormEditor.tsx +176 -0
- package/src/components/tis-editor/editor/RawDataEditor.tsx +117 -0
- package/src/components/tis-editor/editor/SaveDiffDialog.tsx +160 -0
- package/src/components/tis-editor/editor/TestFieldDialog.tsx +134 -0
- package/src/components/tis-editor/editor/ViewsEditor.tsx +101 -0
- package/src/components/tis-editor/types.ts +95 -0
- package/src/components/tis-editor/validation.ts +104 -0
- package/src/hooks/useAmsAssetTypes.ts +70 -0
- package/src/hooks/useTisConfig.ts +164 -0
|
@@ -1,29 +1,26 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* ValueInput sizing.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* accept/cancel buttons keep their
|
|
4
|
+
* NumericFormat with customInput=InputText renders a plain <input class="p-inputtext">
|
|
5
|
+
* (no .p-inputwrapper span like PrimeReact's InputNumber). In a .p-inputgroup the
|
|
6
|
+
* input defaults to flex: 1 1 auto; we override that so the field stays at a
|
|
7
|
+
* fixed width while the label addon and accept/cancel buttons keep their
|
|
8
|
+
* natural sizes.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
|
-
.value-input-field.p-
|
|
11
|
+
.value-input-field.p-inputtext {
|
|
11
12
|
flex: 0 0 auto;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.value-input-field.p-inputwrapper .p-inputtext {
|
|
15
|
-
width: 100%;
|
|
16
13
|
box-sizing: border-box;
|
|
17
14
|
}
|
|
18
15
|
|
|
19
|
-
.value-input-field.size-small.p-
|
|
16
|
+
.value-input-field.size-small.p-inputtext {
|
|
20
17
|
width: 30mm;
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
.value-input-field.size-normal.p-
|
|
20
|
+
.value-input-field.size-normal.p-inputtext {
|
|
24
21
|
width: 55mm;
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
.value-input-field.size-large.p-
|
|
24
|
+
.value-input-field.size-large.p-inputtext {
|
|
28
25
|
width: 70mm;
|
|
29
26
|
}
|
|
@@ -1,167 +1,58 @@
|
|
|
1
1
|
/** @file
|
|
2
|
-
* `ValueInput` is a React component for
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* with configurable precision and optional prefix/suffix text.
|
|
2
|
+
* `ValueInput` is a React component for numeric entry built on top of
|
|
3
|
+
* `react-number-format`. It wraps a PrimeReact `InputText` so the field
|
|
4
|
+
* inherits the standard inputgroup styling and integrates with the
|
|
5
|
+
* accept/cancel button row below.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* - `mode`: Determines whether the input is treated as a plain decimal or currency. Defaults to "decimal".
|
|
16
|
-
* - `currency`: ISO 4217 currency code for formatting the value as currency.
|
|
17
|
-
* - `prefix`: String to display before the value.
|
|
18
|
-
* - `suffix`: String to display after the value.
|
|
19
|
-
* - `showButtons`: Whether to display increment and decrement buttons.
|
|
20
|
-
* - `step`: The amount by which the value should be incremented or decremented.
|
|
21
|
-
* - `locale`: Locale code for formatting the value.
|
|
22
|
-
* - `description`: Additional descriptive text to display below the input.
|
|
23
|
-
* - `disabled`: Whether the input is disabled.
|
|
24
|
-
* - `dispatchTopic`: Event topic to dispatch on value change.
|
|
25
|
-
* - `placeholder`: Placeholder text when the input is empty.
|
|
26
|
-
* - `onValueChanged`: Callback function that is called when the user accepts a new value.
|
|
27
|
-
*
|
|
28
|
-
* Example Usage:
|
|
29
|
-
* ```tsx
|
|
30
|
-
* <ValueInput
|
|
31
|
-
* label="Quantity"
|
|
32
|
-
* value={10}
|
|
33
|
-
* min={1}
|
|
34
|
-
* max={100}
|
|
35
|
-
* minPrecision={0}
|
|
36
|
-
* maxPrecision={2}
|
|
37
|
-
* mode="decimal"
|
|
38
|
-
* showButtons={true}
|
|
39
|
-
* step={1}
|
|
40
|
-
* locale="en-US"
|
|
41
|
-
* onValueChanged={(newValue) => console.log("New Value:", newValue)}
|
|
42
|
-
* />
|
|
43
|
-
* ```
|
|
7
|
+
* Why react-number-format and not PrimeReact's `InputNumber`:
|
|
8
|
+
* - `InputNumber` handles the `-` key via `onKeyDown` (sign-toggle action).
|
|
9
|
+
* On Wayland on-screen keyboards (Ubuntu 24 virtual keyboard) keydown is
|
|
10
|
+
* not always delivered, so negative entry was broken on touch HMIs.
|
|
11
|
+
* - `NumericFormat` treats the input as text and validates it against a
|
|
12
|
+
* numeric format. The user can simply type `-`, `2`, `0`, `0` to get
|
|
13
|
+
* `-200` on every input device.
|
|
44
14
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
15
|
+
* Properties:
|
|
16
|
+
* - `label`: Optional label addon shown before the field.
|
|
17
|
+
* - `value`: Externally controlled value.
|
|
18
|
+
* - `min` / `max`: Range validation, applied on accept.
|
|
19
|
+
* - `minPrecision` / `maxPrecision`: Decimal precision. (Aliases
|
|
20
|
+
* `minFractionDigits` / `maxFractionDigits` are also accepted for
|
|
21
|
+
* compatibility with older call sites.)
|
|
22
|
+
* - `prefix` / `suffix`: Inline string before/after the number.
|
|
23
|
+
* - `description`: Small advisory text below the field.
|
|
24
|
+
* - `disabled`: Disable all interaction.
|
|
25
|
+
* - `dispatchTopic`: Topic dispatched on accept via the EventEmitter context.
|
|
26
|
+
* - `placeholder`: Placeholder when empty.
|
|
27
|
+
* - `onValueChanged`: Called with the new numeric value when the user accepts.
|
|
28
|
+
* - `size`: Field width — small (30mm), normal (55mm), large (70mm).
|
|
48
29
|
*/
|
|
49
30
|
import React from 'react';
|
|
50
|
-
import
|
|
51
|
-
import "./ValueInput.css";
|
|
31
|
+
import './ValueInput.css';
|
|
52
32
|
export type ValueInputSize = 'small' | 'normal' | 'large';
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
*/
|
|
56
|
-
interface ValueInputProps extends Omit<InputNumberProps, 'value' | 'size'> {
|
|
57
|
-
/**
|
|
58
|
-
* The label for the ValueInput field.
|
|
59
|
-
*/
|
|
60
|
-
label: React.ReactNode | undefined | null;
|
|
61
|
-
/**
|
|
62
|
-
* The value for the field.
|
|
63
|
-
*/
|
|
33
|
+
export interface ValueInputProps {
|
|
34
|
+
label?: React.ReactNode | null;
|
|
64
35
|
value: number | null;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
minPrecision?: number | undefined;
|
|
82
|
-
/**
|
|
83
|
-
* Maximum number of decimal points.
|
|
84
|
-
* Set to 0 for integer-only. Must be greater or equal to than minPrecision, or
|
|
85
|
-
* the component will throw an error.
|
|
86
|
-
* @default 3
|
|
87
|
-
*/
|
|
88
|
-
maxPrecision?: number | undefined;
|
|
89
|
-
/**
|
|
90
|
-
* Defines the behavior of the component.
|
|
91
|
-
* If set to "currency", then you need to specify the
|
|
92
|
-
* currency type using the currency property.
|
|
93
|
-
* @default "decimal"
|
|
94
|
-
*/
|
|
95
|
-
mode?: "currency" | "decimal" | undefined;
|
|
96
|
-
/**
|
|
97
|
-
* The currency to use in currency formatting. Possible values are the
|
|
98
|
-
* [ISO 4217 currency codes](https://www.six-group.com/en/products-services/financial-information/data-standards.html#scrollTo=maintenance-agency),
|
|
99
|
-
* such as "USD" for the US dollar, "EUR" for the euro, or "CNY" for the Chinese RMB.
|
|
100
|
-
* If the mode is "currency", the currency property must be provided.
|
|
101
|
-
*
|
|
102
|
-
* @default "USD"
|
|
103
|
-
*/
|
|
104
|
-
currency?: string;
|
|
105
|
-
/**
|
|
106
|
-
* An optional prefix before the value of the field.
|
|
107
|
-
* Unlike the TextInput control, this prefix is internal to the field.
|
|
108
|
-
*/
|
|
109
|
-
prefix?: string | undefined;
|
|
110
|
-
/**
|
|
111
|
-
* An optional suffix after the value of the field.
|
|
112
|
-
* Unlike the TextInput control, this prefix is internal to the field.
|
|
113
|
-
*/
|
|
114
|
-
suffix?: string | undefined;
|
|
115
|
-
/**
|
|
116
|
-
* Set true to display buttons to increment/decrement the value.
|
|
117
|
-
* Use the step property to adjust the amount that the value will change.
|
|
118
|
-
*
|
|
119
|
-
* @default false
|
|
120
|
-
*/
|
|
121
|
-
showButtons?: boolean;
|
|
122
|
-
/**
|
|
123
|
-
* The amount clicking an increment/decrement buttion will change the value.
|
|
124
|
-
*/
|
|
125
|
-
step?: number | undefined;
|
|
126
|
-
/**
|
|
127
|
-
* Locale to be used in formatting. Changes how the numbers/separators are displayed
|
|
128
|
-
* for international users. The typical locale codes are used.
|
|
129
|
-
*
|
|
130
|
-
* @default "en-US"
|
|
131
|
-
*/
|
|
132
|
-
locale?: string | undefined;
|
|
133
|
-
/**
|
|
134
|
-
* A small, advisory text below the field.
|
|
135
|
-
*/
|
|
136
|
-
description?: React.ReactNode | undefined;
|
|
137
|
-
/**
|
|
138
|
-
* If true, all functions of the field will be disabled.
|
|
139
|
-
*/
|
|
140
|
-
disabled?: boolean | undefined;
|
|
141
|
-
/** Topic on which the value will be dispatched through the user interfave on successful data entry. */
|
|
142
|
-
dispatchTopic?: string | undefined;
|
|
143
|
-
/**
|
|
144
|
-
* Placeholder string to display if the value is empty.
|
|
145
|
-
*/
|
|
146
|
-
placeholder?: string | undefined;
|
|
147
|
-
/**
|
|
148
|
-
* The user has accepted a new value.
|
|
149
|
-
* @param newValue New value accepted by the user.
|
|
150
|
-
*/
|
|
36
|
+
min?: number;
|
|
37
|
+
max?: number;
|
|
38
|
+
/** Minimum decimal places displayed. @default 0 */
|
|
39
|
+
minPrecision?: number;
|
|
40
|
+
/** Maximum decimal places allowed. @default 3 */
|
|
41
|
+
maxPrecision?: number;
|
|
42
|
+
/** Alias for `minPrecision` (compat with older call sites). */
|
|
43
|
+
minFractionDigits?: number;
|
|
44
|
+
/** Alias for `maxPrecision` (compat with older call sites). */
|
|
45
|
+
maxFractionDigits?: number;
|
|
46
|
+
prefix?: string;
|
|
47
|
+
suffix?: string;
|
|
48
|
+
description?: React.ReactNode;
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
dispatchTopic?: string;
|
|
51
|
+
placeholder?: string;
|
|
151
52
|
onValueChanged?(newValue: number): void;
|
|
152
|
-
/**
|
|
153
|
-
* Width of the InputNumber field. The label addon and accept/cancel buttons
|
|
154
|
-
* keep their natural size; only the numeric input is constrained.
|
|
155
|
-
* Widths: small=30mm, normal=55mm, large=70mm.
|
|
156
|
-
* @default 'normal'
|
|
157
|
-
*/
|
|
158
53
|
size?: ValueInputSize;
|
|
54
|
+
className?: string;
|
|
159
55
|
}
|
|
160
|
-
/**
|
|
161
|
-
* A convenient field with all the usual features of inputing numbers.
|
|
162
|
-
* Wraps the common features of use of a InputNumber, p-inputgroup, some icon buttons,
|
|
163
|
-
* accepting and rejecting values and keyboard management.
|
|
164
|
-
*/
|
|
165
56
|
export declare const ValueInput: React.FC<ValueInputProps>;
|
|
166
57
|
export default ValueInput;
|
|
167
58
|
//# sourceMappingURL=ValueInput.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValueInput.d.ts","sourceRoot":"","sources":["../../src/components/ValueInput.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ValueInput.d.ts","sourceRoot":"","sources":["../../src/components/ValueInput.tsx"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAA0C,MAAM,OAAO,CAAC;AAO/D,OAAO,kBAAkB,CAAC;AAE1B,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,+DAA+D;IAC/D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA8HhD,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import React,{useState,useEffect,useContext}from"react";import clsx from"clsx";import{NumericFormat}from"react-number-format";import{InputText}from"primereact/inputtext";import{Button}from"primereact/button";import{EventEmitterContext}from"../core/EventEmitterContext";import"./ValueInput.css";export const ValueInput=({label:e,value:t=null,min:i,max:a,minPrecision:s,maxPrecision:o,minFractionDigits:n,maxFractionDigits:r,prefix:c,suffix:u,description:l,disabled:m=!1,dispatchTopic:p,placeholder:d,onValueChanged:x,size:f="normal",className:v})=>{const h=s??n??0,j=o??r??3,[N,b]=useState(t),[E,C]=useState(!1),[_,g]=useState(!1),S=useContext(EventEmitterContext);useEffect(()=>{E||(b(t),g(!1))},[t,E]);const F=()=>{if(!E)return;if(null===(e=N)||Number.isNaN(e)||void 0!==i&&e<i||void 0!==a&&e>a)return void g(!0);var e;const t=N;x?.(t),p&&S.dispatch({topic:p,payload:t}),C(!1),g(!1)},I=()=>{b(t),C(!1),g(!1)},V=void 0===i||i<0;return _jsxs("div",{children:[_jsxs("div",{className:"p-inputgroup",children:[null!=e&&""!==e&&_jsx("span",{className:"p-inputgroup-addon",children:e}),_jsx(NumericFormat,{value:N??"",onValueChange:(e,t)=>{"event"===t.source&&(b(e.floatValue??null),C(!0),g(!1))},decimalScale:j,fixedDecimalScale:h>0&&!E,allowNegative:V,decimalSeparator:".",thousandSeparator:!1,prefix:c,suffix:u,placeholder:d,disabled:m,customInput:InputText,className:clsx("value-input-field",`size-${f}`,v),invalid:_||void 0,onKeyDown:e=>{"Enter"===e.key?F():"Escape"===e.key&&I()}}),_jsx(Button,{icon:"pi pi-check",disabled:m||!E,className:"p-button-success",onClick:F,autoFocus:!1}),_jsx(Button,{icon:"pi pi-times",disabled:m||!E,className:"p-button-danger",onClick:I,autoFocus:!1})]}),l&&_jsx("small",{children:l})]})};export default ValueInput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetEditDialog.d.ts","sourceRoot":"","sources":["../../../src/components/ams/AssetEditDialog.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AssetEditDialog.d.ts","sourceRoot":"","sources":["../../../src/components/ams/AssetEditDialog.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAkCxE,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB;;yDAEqD;IACrD,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AA8DD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAypB1D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";import React,{useContext,useEffect,useMemo,useState}from"react";import{Button}from"primereact/button";import{Dialog}from"primereact/dialog";import{Dropdown}from"primereact/dropdown";import{InputText}from"primereact/inputtext";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useAms}from"./AmsProvider";const ROLE_OTHER="__other__";function fieldsFor(e,t){const s=e?.[t]?.fields;return Array.isArray(s)?s:[]}function subLocationsFor(e,t){const s=e?.[t]?.sub_locations;return s&&Array.isArray(s.keys)&&Array.isArray(s.fields)?s:null}function coerceField(e,t){if(void 0!==t&&""!==t)switch(e.type){case"f32":case"f64":case"i8":case"i16":case"i32":case"i64":case"u8":case"u16":case"u32":case"u64":{const e=Number(t);return Number.isFinite(e)?e:void 0}case"bool":return"true"===t||"1"===t;default:return t}}function seedFromCustom(e,t){if(!e)return"";const s=e[t];return null==s?"":String(s)}export const AssetEditDialog=({visible:e,asset:t,onHide:s,onSaved:r})=>{const{schemas:o,roles:n}=useAms(),{invoke:a}=useContext(EventEmitterContext),i=t?.asset_type??"",l=useMemo(()=>fieldsFor(o,i),[o,i]),c=useMemo(()=>subLocationsFor(o,i),[o,i]),d=useMemo(()=>i?n[i]??[]:[],[i,n]),m=d.length>0,u=useMemo(()=>{const e=d.map(e=>({label:e.label??e.location,value:e.location}));return e.push({label:"Other (advanced — type a custom role)",value:ROLE_OTHER}),e},[d]),[p,_]=useState(""),[f,h]=useState(""),[x,g]=useState({}),[y,j]=useState({}),[b,v]=useState(!1),[E,C]=useState(null);useEffect(()=>{if(!e||!t)return;C(null),v(!1);const s="string"==typeof t.location?t.location:"",r=d.find(e=>e.location===s);""===s?(_(""),h("")):r?(_(s),h(s)):(_(ROLE_OTHER),h(s));const o={};for(const e of l)o[e.name]=seedFromCustom(t.custom,e.name);g(o);const n={};if(c){const e=t.sub_locations&&"object"==typeof t.sub_locations?t.sub_locations:{};for(const t of c.keys){const s=e[t]&&"object"==typeof e[t]?e[t]:{},r={};for(const e of c.fields){const t=s[e.name];r[e.name]=null==t?"":String(t)}n[t]=r}}j(n)},[e,t,l,c,d]);const S=!t?.asset_id||b||m&&(""===p||p===ROLE_OTHER&&!f.trim())||l.some(e=>e.required&&!x[e.name]?.toString().trim())||(c?.keys.some(e=>c.fields.some(t=>t.required&&!y[e]?.[t.name]?.toString().trim()))??!1);if(!t)return null;const R=o[i]?.label??i;return _jsxs(Dialog,{header:`Edit Asset — ${t.asset_id}`,visible:e,style:{width:"32rem"},onHide:()=>{b||s()},footer:_jsxs(_Fragment,{children:[_jsx(Button,{label:"Cancel",severity:"secondary",onClick:s,disabled:b}),_jsx(Button,{label:"Save",icon:"pi pi-check",onClick:async()=>{if(!t?.asset_id)return;v(!0),C(null);const e={};for(const t of l){const s=coerceField(t,x[t.name]??"");void 0!==s&&(e[t.name]=s)}let o;if(c){o={};for(const e of c.keys){const t={};for(const s of c.fields){const r=coerceField(s,y[e]?.[s.name]??"");void 0!==r&&(t[s.name]=r)}o[e]=t}}const n={asset_id:t.asset_id,location:f,custom:e};o&&(n.sub_locations=o);try{const e=await a("ams.update_asset",MessageType.Request,n);e?.success?(r?.(),s()):C(e?.error_message??"update_asset failed")}catch(e){C(String(e?.message??e))}finally{v(!1)}},loading:b,disabled:S})]}),children:[_jsxs("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.25rem 1rem",fontSize:"0.875rem",color:"var(--text-secondary-color)",marginBottom:"0.75rem"},children:[_jsx("span",{children:"Type"})," ",_jsx("span",{children:R}),_jsx("span",{children:"Serial"})," ",_jsx("span",{children:t.serial||_jsx("em",{children:"(none)"})}),t.install_date&&_jsxs(_Fragment,{children:[_jsx("span",{children:"Installed"}),_jsx("span",{children:new Date(t.install_date).toLocaleString()})]})]}),_jsxs("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.5rem 1rem",alignItems:"center"},children:[m&&_jsxs(_Fragment,{children:[_jsx("label",{children:"Role *"}),_jsx(Dropdown,{value:p,options:u,onChange:e=>{var t;(t=e.value)===ROLE_OTHER?_(ROLE_OTHER):(_(t),h(t))},placeholder:"Choose where this asset is mounted"}),p===ROLE_OTHER&&_jsxs(_Fragment,{children:[_jsx("label",{children:"Custom role"}),_jsx(InputText,{value:f,placeholder:"e.g. tsdr_secondary",onChange:e=>h(e.target.value)})]})]}),l.map(e=>{const t=e.label??e.name,s=e.units?`${t} [${e.units}]${e.required?" *":""}`:`${t}${e.required?" *":""}`,r="string"!==e.type&&"bool"!==e.type;return _jsxs(React.Fragment,{children:[_jsx("label",{title:e.description??void 0,children:s}),"bool"===e.type?_jsx(Dropdown,{value:x[e.name]??"",options:[{label:"true",value:"true"},{label:"false",value:"false"}],onChange:t=>g(s=>({...s,[e.name]:t.value})),placeholder:"—"}):_jsx(InputText,{value:x[e.name]??"",keyfilter:r?"num":void 0,placeholder:e.description??void 0,onChange:t=>g(s=>({...s,[e.name]:t.target.value}))})]},e.name)})]}),c&&_jsxs("div",{style:{marginTop:"1.5rem"},children:[_jsx("h4",{style:{margin:"0 0 0.5rem 0"},children:c.label??"Sub-locations"}),_jsx("div",{style:{overflowX:"auto"},children:_jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.875rem"},children:[_jsx("thead",{children:_jsxs("tr",{children:[_jsx("th",{style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:c.key_label??"Key"}),c.fields.map(e=>_jsxs("th",{title:e.description??void 0,style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:[e.label??e.name,e.units?` [${e.units}]`:"",e.required?" *":""]},e.name))]})}),_jsx("tbody",{children:c.keys.map(e=>_jsxs("tr",{children:[_jsx("td",{style:{padding:"0.25rem 0.5rem",fontWeight:600},children:e}),c.fields.map(t=>{const s=y[e]?.[t.name]??"",r="string"!==t.type&&"bool"!==t.type;return _jsx("td",{style:{padding:"0.25rem 0.5rem"},children:_jsx(InputText,{value:s,keyfilter:r?"num":void 0,onChange:s=>{const r=s.target.value;j(s=>({...s,[e]:{...s[e]??{},[t.name]:r}}))},style:{width:"100%"}})},t.name)})]},e))})]})})]}),E&&_jsx("div",{style:{marginTop:"1rem",color:"#ef4444"},children:E})]})};
|
|
1
|
+
import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";import React,{useContext,useEffect,useMemo,useState}from"react";import{Button}from"primereact/button";import{Calendar}from"primereact/calendar";import{Dialog}from"primereact/dialog";import{Dropdown}from"primereact/dropdown";import{InputText}from"primereact/inputtext";import{InputTextarea}from"primereact/inputtextarea";import{TabPanel,TabView}from"primereact/tabview";import{EventEmitterContext}from"../../core/EventEmitterContext";import{MessageType}from"../../hub/CommandMessage";import{useAms}from"./AmsProvider";const ROLE_OTHER="__other__";function fieldsFor(e,t){const r=e?.[t]?.fields;return Array.isArray(r)?r:[]}function subLocationsFor(e,t){const r=e?.[t]?.sub_locations;return r&&Array.isArray(r.keys)&&Array.isArray(r.fields)?r:null}function calibrationFieldsFor(e,t){const r=e?.[t]?.calibration_fields;return Array.isArray(r)?r:[]}function perAxisCalibrationFieldsFor(e){return e?.calibration_fields??[]}function coerceField(e,t){if(void 0!==t&&""!==t)switch(e.type){case"f32":case"f64":case"i8":case"i16":case"i32":case"i64":case"u8":case"u16":case"u32":case"u64":{const e=Number(t);return Number.isFinite(e)?e:void 0}case"bool":return"true"===t||"1"===t;default:return t}}function seedFromCustom(e,t){if(!e)return"";const r=e[t];return null==r?"":String(r)}export const AssetEditDialog=({visible:e,asset:t,onHide:r,onSaved:s})=>{const{schemas:n,roles:a,readCalibration:o}=useAms(),{invoke:i}=useContext(EventEmitterContext),l=t?.asset_type??"",d=useMemo(()=>fieldsFor(n,l),[n,l]),c=useMemo(()=>subLocationsFor(n,l),[n,l]),u=useMemo(()=>calibrationFieldsFor(n,l),[n,l]),m=useMemo(()=>perAxisCalibrationFieldsFor(c),[c]),p=m.length>0,_=p||u.length>0,f=useMemo(()=>l?a[l]??[]:[],[l,a]),x=f.length>0,h=useMemo(()=>{const e=f.map(e=>({label:e.label??e.location,value:e.location}));return e.push({label:"Other (advanced — type a custom role)",value:ROLE_OTHER}),e},[f]),[g,y]=useState(""),[b,v]=useState(""),[j,C]=useState({}),[T,S]=useState({}),[F,E]=useState(!1),[w,A]=useState(null),[R,k]=useState(0),[I,O]=useState(null),[$,L]=useState(""),[M,q]=useState(null),[D,H]=useState(""),[B,P]=useState(""),[z,N]=useState({}),[K,V]=useState({});useEffect(()=>{if(!e||!t)return;A(null),E(!1),k(0);const r="string"==typeof t.location?t.location:"",s=f.find(e=>e.location===r);""===r?(y(""),v("")):s?(y(r),v(r)):(y(ROLE_OTHER),v(r));const n={};for(const e of d)n[e.name]=seedFromCustom(t.custom,e.name);C(n);const a={};if(c){const e=t.sub_locations&&"object"==typeof t.sub_locations?t.sub_locations:{};for(const t of c.keys){const r=e[t]&&"object"==typeof e[t]?e[t]:{},s={};for(const e of c.fields){const t=r[e.name];s[e.name]=null==t?"":String(t)}a[t]=s}}S(a),O(null),L(""),q(null),H(""),P(""),N({}),V({});const i="string"==typeof t.current_calibration_id?t.current_calibration_id:"";if(!i)return;let l=!1;return(async()=>{const e=await o(t.asset_id,i);if(l||!e)return;O(e),L("string"==typeof e.performed_by?e.performed_by:""),H("string"==typeof e.cert_ref?e.cert_ref:""),P("string"==typeof e.notes?e.notes:""),q(e.expires_at?new Date(e.expires_at):null);const r=e.values&&"object"==typeof e.values?e.values:{};if(p&&c){const e={};for(const t of c.keys){const s=r[t]&&"object"==typeof r[t]?r[t]:{},n={};for(const e of m){const t=s[e.name];n[e.name]=null==t?"":String(t)}e[t]=n}V(e)}else{const e={};for(const t of u){const s=r[t.name];e[t.name]=null==s?"":String(s)}N(e)}})(),()=>{l=!0}},[e,t,d,c,f,u,m,p,o]);const W=()=>{if(p&&c){const e={};for(const t of c.keys){const r={};for(const e of m){const s=coerceField(e,K[t]?.[e.name]??"");void 0!==s&&(r[e.name]=s)}e[t]=r}return e}const e={};for(const t of u){const r=coerceField(t,z[t.name]??"");void 0!==r&&(e[t.name]=r)}return e},X=!t?.asset_id||F||x&&(""===g||g===ROLE_OTHER&&!b.trim())||d.some(e=>e.required&&!j[e.name]?.toString().trim())||(c?.keys.some(e=>c.fields.some(t=>t.required&&!T[e]?.[t.name]?.toString().trim()))??!1);if(!t)return null;const G=n[l]?.label??l;return _jsxs(Dialog,{header:`Edit Asset — ${t.asset_id}`,visible:e,style:{width:"32rem"},onHide:()=>{F||r()},footer:_jsxs(_Fragment,{children:[_jsx(Button,{label:"Cancel",severity:"secondary",onClick:r,disabled:F}),_jsx(Button,{label:"Save",icon:"pi pi-check",onClick:async()=>{if(!t?.asset_id)return;E(!0),A(null);const e={};for(const t of d){const r=coerceField(t,j[t.name]??"");void 0!==r&&(e[t.name]=r)}let n;if(c){n={};for(const e of c.keys){const t={};for(const r of c.fields){const s=coerceField(r,T[e]?.[r.name]??"");void 0!==s&&(t[r.name]=s)}n[e]=t}}const a={asset_id:t.asset_id,location:b,custom:e};n&&(a.sub_locations=n);try{const e=await i("ams.update_asset",MessageType.Request,a);if(!e?.success)return void A(e?.error_message??"update_asset failed");if(I){const e={asset_id:t.asset_id,cal_id:I.cal_id,performed_by:$,expires_at:M?M.toISOString():null,cert_ref:D,notes:B,values:W()},r=await i("ams.update_calibration",MessageType.Request,e);if(!r?.success)return A(r?.error_message??"update_calibration failed"),void k(1)}s?.(),r()}catch(e){A(String(e?.message??e))}finally{E(!1)}},loading:F,disabled:X})]}),children:[_jsxs("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.25rem 1rem",fontSize:"0.875rem",color:"var(--text-secondary-color)",marginBottom:"0.75rem"},children:[_jsx("span",{children:"Type"})," ",_jsx("span",{children:G}),_jsx("span",{children:"Serial"})," ",_jsx("span",{children:t.serial||_jsx("em",{children:"(none)"})}),t.install_date&&_jsxs(_Fragment,{children:[_jsx("span",{children:"Installed"}),_jsx("span",{children:new Date(t.install_date).toLocaleString()})]})]}),_jsxs(TabView,{activeIndex:R,onTabChange:e=>k(e.index),children:[_jsxs(TabPanel,{header:"Asset",children:[_jsxs("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.5rem 1rem",alignItems:"center"},children:[x&&_jsxs(_Fragment,{children:[_jsx("label",{children:"Role *"}),_jsx(Dropdown,{value:g,options:h,onChange:e=>{var t;(t=e.value)===ROLE_OTHER?y(ROLE_OTHER):(y(t),v(t))},placeholder:"Choose where this asset is mounted"}),g===ROLE_OTHER&&_jsxs(_Fragment,{children:[_jsx("label",{children:"Custom role"}),_jsx(InputText,{value:b,placeholder:"e.g. tsdr_secondary",onChange:e=>v(e.target.value)})]})]}),d.map(e=>{const t=e.label??e.name,r=e.units?`${t} [${e.units}]${e.required?" *":""}`:`${t}${e.required?" *":""}`,s="string"!==e.type&&"bool"!==e.type;return _jsxs(React.Fragment,{children:[_jsx("label",{title:e.description??void 0,children:r}),"bool"===e.type?_jsx(Dropdown,{value:j[e.name]??"",options:[{label:"true",value:"true"},{label:"false",value:"false"}],onChange:t=>C(r=>({...r,[e.name]:t.value})),placeholder:"—"}):_jsx(InputText,{value:j[e.name]??"",keyfilter:s?"num":void 0,placeholder:e.description??void 0,onChange:t=>C(r=>({...r,[e.name]:t.target.value}))})]},e.name)})]}),c&&_jsxs("div",{style:{marginTop:"1.5rem"},children:[_jsx("h4",{style:{margin:"0 0 0.5rem 0"},children:c.label??"Sub-locations"}),_jsx("div",{style:{overflowX:"auto"},children:_jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.875rem"},children:[_jsx("thead",{children:_jsxs("tr",{children:[_jsx("th",{style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:c.key_label??"Key"}),c.fields.map(e=>_jsxs("th",{title:e.description??void 0,style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:[e.label??e.name,e.units?` [${e.units}]`:"",e.required?" *":""]},e.name))]})}),_jsx("tbody",{children:c.keys.map(e=>_jsxs("tr",{children:[_jsx("td",{style:{padding:"0.25rem 0.5rem",fontWeight:600},children:e}),c.fields.map(t=>{const r=T[e]?.[t.name]??"",s="string"!==t.type&&"bool"!==t.type;return _jsx("td",{style:{padding:"0.25rem 0.5rem"},children:_jsx(InputText,{value:r,keyfilter:s?"num":void 0,onChange:r=>{const s=r.target.value;S(r=>({...r,[e]:{...r[e]??{},[t.name]:s}}))},style:{width:"100%"}})},t.name)})]},e))})]})})]})]}),I&&_jsxs(TabPanel,{header:`Calibration (${I.cal_id})`,children:[_jsxs("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.5rem 1rem",alignItems:"center"},children:[_jsx("label",{children:"Performed by"}),_jsx(InputText,{value:$,onChange:e=>L(e.target.value)}),_jsx("label",{children:"Expires at"}),_jsx(Calendar,{value:M,onChange:e=>q(e.value??null),showIcon:!0,dateFormat:"yy-mm-dd"}),_jsx("label",{children:"Certificate ref"}),_jsx(InputText,{value:D,onChange:e=>H(e.target.value),placeholder:"e.g. ADC-CAL-2026-1043"}),_jsx("label",{children:"Notes"}),_jsx(InputTextarea,{value:B,rows:3,onChange:e=>P(e.target.value),autoResize:!0})]}),_&&_jsxs("div",{style:{marginTop:"1rem"},children:[_jsx("h4",{style:{margin:"0 0 0.5rem 0"},children:p?c?.label??"Per-axis calibration":"Calibration values"}),_jsx("div",p&&c?{style:{overflowX:"auto"},children:_jsxs("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:"0.875rem"},children:[_jsx("thead",{children:_jsxs("tr",{children:[_jsx("th",{style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:c.key_label??"Key"}),m.map(e=>_jsxs("th",{title:e.description??void 0,style:{textAlign:"left",padding:"0.25rem 0.5rem",borderBottom:"1px solid var(--surface-border)"},children:[e.label??e.name,e.units?` [${e.units}]`:"",e.required?" *":""]},e.name))]})}),_jsx("tbody",{children:c.keys.map(e=>_jsxs("tr",{children:[_jsx("td",{style:{padding:"0.25rem 0.5rem",fontWeight:600},children:e}),m.map(t=>{const r=K[e]?.[t.name]??"",s="string"!==t.type&&"bool"!==t.type;return _jsx("td",{style:{padding:"0.25rem 0.5rem"},children:_jsx(InputText,{value:r,keyfilter:s?"num":void 0,onChange:r=>{const s=r.target.value;V(r=>({...r,[e]:{...r[e]??{},[t.name]:s}}))},style:{width:"100%"}})},t.name)})]},e))})]})}:{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"0.5rem 1rem",alignItems:"center"},children:u.map(e=>{const t=e.label??e.name,r=e.units?`${t} [${e.units}]${e.required?" *":""}`:`${t}${e.required?" *":""}`,s="string"!==e.type&&"bool"!==e.type;return _jsxs(React.Fragment,{children:[_jsx("label",{title:e.description??void 0,children:r}),_jsx(InputText,{value:z[e.name]??"",keyfilter:s?"num":void 0,onChange:t=>N(r=>({...r,[e.name]:t.target.value}))})]},e.name)})})]})]})]}),w&&_jsx("div",{style:{marginTop:"1rem",color:"#ef4444"},children:w})]})};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FormRow — grid-aligned label/input pair with optional required marker
|
|
3
|
+
* and inline error text. Drop inside a FormSection.
|
|
4
|
+
*/
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import './forms.css';
|
|
7
|
+
export interface FormRowProps {
|
|
8
|
+
label: React.ReactNode;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
/** Optional descriptive hint shown beneath the label. */
|
|
11
|
+
hint?: React.ReactNode;
|
|
12
|
+
/** Inline error text shown beneath the input. */
|
|
13
|
+
error?: React.ReactNode;
|
|
14
|
+
/** Optional `htmlFor` association on the label tag. */
|
|
15
|
+
htmlFor?: string;
|
|
16
|
+
children?: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
export declare const FormRow: React.FC<FormRowProps>;
|
|
19
|
+
export default FormRow;
|
|
20
|
+
//# sourceMappingURL=FormRow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormRow.d.ts","sourceRoot":"","sources":["../../../src/components/forms/FormRow.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,aAAa,CAAC;AAErB,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yDAAyD;IACzD,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,iDAAiD;IACjD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B;AAED,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAc1C,CAAC;AAEF,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import*as React from"react";import"./forms.css";export const FormRow=({label:r,required:s,hint:a,error:e,htmlFor:o,children:l})=>_jsxs("div",{className:"ac-form-row"+(e?" ac-form-row--error":""),children:[_jsxs("label",{className:"ac-form-row__label",htmlFor:o,children:[r,s&&_jsx("span",{className:"ac-form-row__required","aria-hidden":!0,children:" *"}),a&&_jsx("small",{className:"ac-form-row__hint",children:a})]}),_jsxs("div",{className:"ac-form-row__field",children:[l,e&&_jsx("small",{className:"ac-form-row__error",children:e})]})]});export default FormRow;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FormSection — labeled bordered region containing a group of FormRow rows.
|
|
3
|
+
*
|
|
4
|
+
* Used by the TIS editor subforms and intended for app-level settings
|
|
5
|
+
* pages. Replaces the ad-hoc `.ac-form-grid` divs scattered across project
|
|
6
|
+
* settings views.
|
|
7
|
+
*/
|
|
8
|
+
import * as React from 'react';
|
|
9
|
+
import './forms.css';
|
|
10
|
+
export interface FormSectionProps {
|
|
11
|
+
title?: React.ReactNode;
|
|
12
|
+
description?: React.ReactNode;
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
/** Right-aligned controls (buttons, dirty pill, etc.). */
|
|
15
|
+
actions?: React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
export declare const FormSection: React.FC<FormSectionProps>;
|
|
18
|
+
export default FormSection;
|
|
19
|
+
//# sourceMappingURL=FormSection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormSection.d.ts","sourceRoot":"","sources":["../../../src/components/forms/FormSection.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,aAAa,CAAC;AAErB,MAAM,WAAW,gBAAgB;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,0DAA0D;IAC1D,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAiBlD,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";import*as React from"react";import"./forms.css";export const FormSection=({title:s,description:c,actions:e,children:a})=>_jsxs("section",{className:"ac-form-section",children:[(s||e)&&_jsxs("header",{className:"ac-form-section__header",children:[_jsxs("div",{children:[s&&_jsx("h3",{className:"ac-form-section__title",children:s}),c&&_jsx("small",{className:"ac-form-section__desc",children:c})]}),e&&_jsx("div",{className:"ac-form-section__actions",children:e})]}),_jsx("div",{className:"ac-form-section__body",children:a})]});export default FormSection;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
.ac-form-section {
|
|
2
|
+
border: 1px solid var(--surface-d, #e2e8f0);
|
|
3
|
+
border-radius: 6px;
|
|
4
|
+
background: var(--surface-card, #fff);
|
|
5
|
+
margin-bottom: 1rem;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.ac-form-section__header {
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: flex-start;
|
|
11
|
+
justify-content: space-between;
|
|
12
|
+
padding: 0.5rem 1rem;
|
|
13
|
+
border-bottom: 1px solid var(--surface-d, #e2e8f0);
|
|
14
|
+
background: var(--surface-b, #f8fafc);
|
|
15
|
+
border-top-left-radius: 6px;
|
|
16
|
+
border-top-right-radius: 6px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.ac-form-section__title {
|
|
20
|
+
margin: 0;
|
|
21
|
+
font-size: 0.95rem;
|
|
22
|
+
font-weight: 600;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.ac-form-section__desc {
|
|
26
|
+
color: var(--text-color-secondary, #64748b);
|
|
27
|
+
display: block;
|
|
28
|
+
margin-top: 0.15rem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.ac-form-section__actions {
|
|
32
|
+
display: flex;
|
|
33
|
+
gap: 0.5rem;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.ac-form-section__body {
|
|
37
|
+
padding: 0.75rem 1rem;
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
gap: 0.5rem;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.ac-form-row {
|
|
44
|
+
display: grid;
|
|
45
|
+
grid-template-columns: minmax(8rem, 14rem) 1fr;
|
|
46
|
+
gap: 0.5rem 1rem;
|
|
47
|
+
align-items: start;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.ac-form-row--error .ac-form-row__field input,
|
|
51
|
+
.ac-form-row--error .ac-form-row__field .p-inputtext {
|
|
52
|
+
border-color: #dc2626;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.ac-form-row__label {
|
|
56
|
+
font-weight: 500;
|
|
57
|
+
padding-top: 0.4rem;
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.ac-form-row__required {
|
|
63
|
+
color: #dc2626;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.ac-form-row__hint {
|
|
67
|
+
color: var(--text-color-secondary, #64748b);
|
|
68
|
+
font-weight: 400;
|
|
69
|
+
font-size: 0.75rem;
|
|
70
|
+
margin-top: 0.15rem;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.ac-form-row__field {
|
|
74
|
+
display: flex;
|
|
75
|
+
flex-direction: column;
|
|
76
|
+
gap: 0.25rem;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.ac-form-row__field > input,
|
|
80
|
+
.ac-form-row__field > .p-inputtext,
|
|
81
|
+
.ac-form-row__field > .p-dropdown,
|
|
82
|
+
.ac-form-row__field > .p-inputtextarea {
|
|
83
|
+
width: 100%;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.ac-form-row__error {
|
|
87
|
+
color: #dc2626;
|
|
88
|
+
font-size: 0.75rem;
|
|
89
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/forms/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{FormSection}from"./FormSection";export{FormRow}from"./FormRow";
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
.tis-editor {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
height: 100%;
|
|
5
|
+
min-height: 0;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.tis-editor__header {
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
justify-content: space-between;
|
|
12
|
+
padding: 0.75rem 1rem;
|
|
13
|
+
border-bottom: 1px solid var(--surface-d, #e2e8f0);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.tis-editor__header h2 {
|
|
17
|
+
margin: 0;
|
|
18
|
+
font-size: 1.125rem;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.tis-editor__header-actions {
|
|
22
|
+
display: flex;
|
|
23
|
+
gap: 0.5rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.tis-editor__dirty-pill {
|
|
27
|
+
display: inline-block;
|
|
28
|
+
background: #ea580c;
|
|
29
|
+
color: white;
|
|
30
|
+
font-size: 0.7rem;
|
|
31
|
+
font-weight: 600;
|
|
32
|
+
text-transform: uppercase;
|
|
33
|
+
letter-spacing: 0.05em;
|
|
34
|
+
padding: 0.15rem 0.5rem;
|
|
35
|
+
border-radius: 999px;
|
|
36
|
+
margin-left: 0.5rem;
|
|
37
|
+
vertical-align: middle;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.tis-editor__body {
|
|
41
|
+
flex: 1;
|
|
42
|
+
display: flex;
|
|
43
|
+
min-height: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.tis-editor__sidebar {
|
|
47
|
+
flex: 0 0 320px;
|
|
48
|
+
border-right: 1px solid var(--surface-d, #e2e8f0);
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-direction: column;
|
|
51
|
+
min-height: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.tis-editor__sidebar-actions {
|
|
55
|
+
display: flex;
|
|
56
|
+
gap: 0.25rem;
|
|
57
|
+
padding: 0.5rem;
|
|
58
|
+
border-bottom: 1px solid var(--surface-d, #e2e8f0);
|
|
59
|
+
flex-wrap: wrap;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.tis-editor__sidebar-actions .p-button {
|
|
63
|
+
flex: 1 1 auto;
|
|
64
|
+
min-width: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.tis-editor__detail {
|
|
68
|
+
flex: 1;
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
min-height: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.tis-editor__detail-header {
|
|
75
|
+
display: flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: space-between;
|
|
78
|
+
padding: 0.5rem 1rem;
|
|
79
|
+
border-bottom: 1px solid var(--surface-d, #e2e8f0);
|
|
80
|
+
background: var(--surface-b, #f8fafc);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.tis-editor__editor-wrap {
|
|
84
|
+
flex: 1;
|
|
85
|
+
min-height: 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.tis-editor__editor-wrap > * {
|
|
89
|
+
height: 100%;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.tis-editor__error {
|
|
93
|
+
background: #fef2f2;
|
|
94
|
+
color: #991b1b;
|
|
95
|
+
border-left: 3px solid #dc2626;
|
|
96
|
+
padding: 0.5rem 1rem;
|
|
97
|
+
margin: 0.5rem 1rem;
|
|
98
|
+
font-size: 0.875rem;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.tis-editor__error pre {
|
|
102
|
+
white-space: pre-wrap;
|
|
103
|
+
margin: 0.25rem 0 0 0;
|
|
104
|
+
font-family: ui-monospace, monospace;
|
|
105
|
+
font-size: 0.8rem;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.tis-editor__empty {
|
|
109
|
+
flex: 1;
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: center;
|
|
113
|
+
color: var(--text-color-secondary, #64748b);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.tis-editor__new-method-label {
|
|
117
|
+
display: flex;
|
|
118
|
+
flex-direction: column;
|
|
119
|
+
gap: 0.25rem;
|
|
120
|
+
margin-bottom: 0.25rem;
|
|
121
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TisConfigEditor — master-detail UI for editing TIS test_methods.
|
|
3
|
+
*
|
|
4
|
+
* Left: PrimeReact DataTable listing methods (method_id + label).
|
|
5
|
+
* Right: tabbed editor for the selected method. Phase 1 ships a single
|
|
6
|
+
* JSON-via-Monaco tab; Phase 2 layers form editors on top of it.
|
|
7
|
+
* Action bar: New / Duplicate / Delete / Apply / Save / Revert.
|
|
8
|
+
*
|
|
9
|
+
* "Apply" pushes the local Monaco buffer to the server-side stage
|
|
10
|
+
* (`tis.put_method`). "Save" persists the entire stage to project.json
|
|
11
|
+
* (`tis.save_config`). "Revert" drops the stage (`tis.discard_config_changes`).
|
|
12
|
+
*
|
|
13
|
+
* Save is disabled (with a tooltip) when active tests are open against
|
|
14
|
+
* any method — the server enforces the same gate, but disabling on the
|
|
15
|
+
* client gives clearer UX.
|
|
16
|
+
*/
|
|
17
|
+
import { type TisIpcInvoker } from '../../hooks/useTisConfig';
|
|
18
|
+
import './TisConfigEditor.css';
|
|
19
|
+
export interface TisConfigEditorProps {
|
|
20
|
+
/** Project ID. Today this is informational (the server hosts one
|
|
21
|
+
* project) but the wire contract carries it for forward compatibility. */
|
|
22
|
+
projectId: string;
|
|
23
|
+
/** Optional invoker override — primarily for the playground / tests. */
|
|
24
|
+
invoker?: TisIpcInvoker;
|
|
25
|
+
}
|
|
26
|
+
export declare const TisConfigEditor: React.FC<TisConfigEditorProps>;
|
|
27
|
+
export default TisConfigEditor;
|
|
28
|
+
//# sourceMappingURL=TisConfigEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TisConfigEditor.d.ts","sourceRoot":"","sources":["../../../src/components/tis-editor/TisConfigEditor.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAM5E,OAAO,uBAAuB,CAAC;AAE/B,MAAM,WAAW,oBAAoB;IACjC;+EAC2E;IAC3E,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,OAAO,CAAC,EAAE,aAAa,CAAC;CAC3B;AAkBD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAoQ1D,CAAC;AAEF,eAAe,eAAe,CAAC"}
|