@qoretechnologies/reqraft 0.10.35-pr.92.ga86e098 → 0.10.35
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/form/engine/CompactRow.d.ts.map +1 -1
- package/dist/components/form/engine/CompactRow.js +24 -7
- package/dist/components/form/engine/CompactRow.js.map +1 -1
- package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
- package/dist/components/form/engine/FormEngine.js +11 -1
- package/dist/components/form/engine/FormEngine.js.map +1 -1
- package/dist/components/form/engine/readFirst.d.ts.map +1 -1
- package/dist/components/form/engine/readFirst.js +8 -2
- package/dist/components/form/engine/readFirst.js.map +1 -1
- package/dist/components/form/expressions/ExpressionField.d.ts.map +1 -1
- package/dist/components/form/expressions/ExpressionField.js +2 -2
- package/dist/components/form/expressions/ExpressionField.js.map +1 -1
- package/dist/components/form/fields/Field.d.ts.map +1 -1
- package/dist/components/form/fields/Field.js +7 -0
- package/dist/components/form/fields/Field.js.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.js +10 -0
- package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
- package/dist/components/form/fields/select/Select.d.ts +6 -1
- package/dist/components/form/fields/select/Select.d.ts.map +1 -1
- package/dist/components/form/fields/select/Select.js +5 -5
- package/dist/components/form/fields/select/Select.js.map +1 -1
- package/dist/components/form/fields/timeout/Timeout.d.ts +24 -0
- package/dist/components/form/fields/timeout/Timeout.d.ts.map +1 -0
- package/dist/components/form/fields/timeout/Timeout.js +73 -0
- package/dist/components/form/fields/timeout/Timeout.js.map +1 -0
- package/dist/components/form/index.d.ts +1 -0
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +1 -0
- package/dist/components/form/index.js.map +1 -1
- package/dist/helpers/common.d.ts +17 -0
- package/dist/helpers/common.d.ts.map +1 -1
- package/dist/helpers/common.js +42 -1
- package/dist/helpers/common.js.map +1 -1
- package/dist/helpers/validations.d.ts.map +1 -1
- package/dist/helpers/validations.js +50 -20
- package/dist/helpers/validations.js.map +1 -1
- package/dist/types/Form.d.ts +2 -2
- package/dist/types/Form.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/form/engine/CompactRow.tsx +43 -20
- package/src/components/form/engine/FormEngine.stories.tsx +17 -11
- package/src/components/form/engine/FormEngine.tsx +10 -1
- package/src/components/form/engine/readFirst.ts +10 -3
- package/src/components/form/expressions/ExpressionField.stories.tsx +23 -16
- package/src/components/form/expressions/ExpressionField.tsx +23 -18
- package/src/components/form/fields/Field.tsx +17 -0
- package/src/components/form/fields/auto/AutoFormField.stories.tsx +30 -0
- package/src/components/form/fields/auto/AutoFormField.tsx +19 -0
- package/src/components/form/fields/select/Select.stories.tsx +26 -0
- package/src/components/form/fields/select/Select.tsx +9 -3
- package/src/components/form/fields/timeout/Timeout.stories.tsx +228 -0
- package/src/components/form/fields/timeout/Timeout.tsx +87 -0
- package/src/components/form/index.tsx +1 -0
- package/src/helpers/common.ts +36 -0
- package/src/helpers/validations.ts +49 -13
- package/src/types/Form.ts +4 -1
package/src/helpers/common.ts
CHANGED
|
@@ -174,6 +174,42 @@ export const splitByteSize = (value?: string): [number | undefined, string | und
|
|
|
174
174
|
return [amount?.[0] ? Number(amount[0]) : undefined, unit?.[0]];
|
|
175
175
|
};
|
|
176
176
|
|
|
177
|
+
export type TTimeoutUnit = 'ms' | 'seconds' | 'minutes' | 'hours';
|
|
178
|
+
|
|
179
|
+
/** Timeout display units, smallest → largest, with the ms multiplier each one
|
|
180
|
+
* scales by and the symbol shown where space is tight (phone-width selector).
|
|
181
|
+
* The stored value is always the integer millisecond count. */
|
|
182
|
+
export const TIMEOUT_UNITS: { value: TTimeoutUnit; ms: number; short: string }[] = [
|
|
183
|
+
{ value: 'ms', ms: 1, short: 'ms' },
|
|
184
|
+
{ value: 'seconds', ms: 1000, short: 's' },
|
|
185
|
+
{ value: 'minutes', ms: 60000, short: 'm' },
|
|
186
|
+
{ value: 'hours', ms: 3600000, short: 'h' },
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
export const timeoutUnitToMs = (unit: TTimeoutUnit): number =>
|
|
190
|
+
TIMEOUT_UNITS.find(({ value }) => value === unit)!.ms;
|
|
191
|
+
|
|
192
|
+
export const timeoutUnitSymbol = (unit: TTimeoutUnit): string =>
|
|
193
|
+
TIMEOUT_UNITS.find(({ value }) => value === unit)!.short;
|
|
194
|
+
|
|
195
|
+
/** The largest unit that represents `value` without rounding (45000 →
|
|
196
|
+
* seconds, 90500 → ms). Zero divides evenly by everything, so it stays ms. */
|
|
197
|
+
export const getLargestExactTimeoutUnit = (value?: number): TTimeoutUnit => {
|
|
198
|
+
for (let i = TIMEOUT_UNITS.length - 1; i >= 0; i--) {
|
|
199
|
+
if (value != null && value !== 0 && value % TIMEOUT_UNITS[i].ms === 0) {
|
|
200
|
+
return TIMEOUT_UNITS[i].value;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return 'ms';
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/** Human-readable timeout (e.g. `"45 seconds"`) — scaled to the largest unit
|
|
207
|
+
* that represents the millisecond count exactly (90500 → `"90500 ms"`). */
|
|
208
|
+
export const formatTimeoutValue = (ms: number): string => {
|
|
209
|
+
const unit = getLargestExactTimeoutUnit(ms);
|
|
210
|
+
return `${ms / timeoutUnitToMs(unit)} ${unit}`;
|
|
211
|
+
};
|
|
212
|
+
|
|
177
213
|
/** Human-readable file size, e.g. `"12.3 KB"` — whole bytes below 1 KiB, one
|
|
178
214
|
* decimal above. Shared by the ticket thread / references attachment rows. */
|
|
179
215
|
export const formatBytes = (bytes: number): string => {
|
|
@@ -262,20 +262,45 @@ export const _validateField = (
|
|
|
262
262
|
case 'file': {
|
|
263
263
|
// Support both the Build-tab typed format ({ name: { type, value } })
|
|
264
264
|
// and the Upload-tab flat format ({ name: 'file.txt' })
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
265
|
+
//
|
|
266
|
+
// A Build-tab sub-value is a full option envelope: it carries its own
|
|
267
|
+
// `type` and may hold an expression (`is_expression`) or a rich-text
|
|
268
|
+
// paragraph array rather than a bare string. This used to unwrap `.value`
|
|
269
|
+
// and validate it as a hard-coded `string` with no field, discarding both
|
|
270
|
+
// the declared type and the expression flag — so a `concat(...)` filename
|
|
271
|
+
// arrived at the string validator as `{ exp, args }`, rich text arrived as
|
|
272
|
+
// an array, and both were rejected with "Value must be a non-empty text".
|
|
273
|
+
//
|
|
274
|
+
// Validate each part against its OWN type and route `is_expression`
|
|
275
|
+
// through `isFunction`, exactly as the `system-options` recursion below
|
|
276
|
+
// does, so the `field?.isFunction` branch above gets a chance to run.
|
|
277
|
+
const validateFilePart = (part: any, fallbackType: string): IValidationResult => {
|
|
278
|
+
const isEnvelope = !!part && isObject(part) && ('value' in part || 'is_expression' in part);
|
|
279
|
+
|
|
280
|
+
return isEnvelope
|
|
281
|
+
? validateFieldWithResult(part.type || fallbackType, part.value, {
|
|
282
|
+
isFunction: part.is_expression,
|
|
283
|
+
} as IFieldValidationProps)
|
|
284
|
+
: validateFieldWithResult(fallbackType, part);
|
|
285
|
+
};
|
|
277
286
|
|
|
278
|
-
|
|
287
|
+
// Fall back to the arg_schema's declared types for the flat Upload-tab
|
|
288
|
+
// shape: `name` is `richtext` (which also accepts a plain string) and
|
|
289
|
+
// `content` is `data`.
|
|
290
|
+
const nameResult = validateFilePart(value?.name, 'richtext');
|
|
291
|
+
const contentResult = validateFilePart(value?.content, 'data');
|
|
292
|
+
|
|
293
|
+
// Report both parts. Returning on the first failure meant a bad file name
|
|
294
|
+
// masked the content result entirely, so the form could only ever surface
|
|
295
|
+
// one problem at a time.
|
|
296
|
+
const reasons = [
|
|
297
|
+
...(nameResult.isValid ? [] : withContext(nameResult, 'File name is invalid').reasons),
|
|
298
|
+
...(contentResult.isValid
|
|
299
|
+
? []
|
|
300
|
+
: withContext(contentResult, 'File content is invalid').reasons),
|
|
301
|
+
];
|
|
302
|
+
|
|
303
|
+
return reasons.length ? invalidResult(reasons) : validResult();
|
|
279
304
|
}
|
|
280
305
|
case 'number': {
|
|
281
306
|
return resultFromBoolean(
|
|
@@ -508,6 +533,17 @@ export const _validateField = (
|
|
|
508
533
|
|
|
509
534
|
return validResult();
|
|
510
535
|
}
|
|
536
|
+
case 'timeout': {
|
|
537
|
+
// An integer count of milliseconds — the unit selector is display-only,
|
|
538
|
+
// so the stored value validates as an int.
|
|
539
|
+
const msResult = validateFieldWithResult('int', value);
|
|
540
|
+
|
|
541
|
+
if (!msResult.isValid) {
|
|
542
|
+
return withContext(msResult, 'Timeout must be a whole number of milliseconds');
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return validResult();
|
|
546
|
+
}
|
|
511
547
|
case 'url': {
|
|
512
548
|
const protocolResult = validateFieldWithResult('string', getProtocol(value));
|
|
513
549
|
|
package/src/types/Form.ts
CHANGED
|
@@ -8,12 +8,15 @@ export type TFormFieldType =
|
|
|
8
8
|
| TQorusType
|
|
9
9
|
| 'softint' | 'softstring' | 'softbool' | 'softfloat' | 'softnumber' | 'softdate' | 'softlist'
|
|
10
10
|
| 'byte-size'
|
|
11
|
+
// the server emits this for a connection's connect_timeout / timeout;
|
|
12
|
+
// it is not (yet) in ts-toolkit's TQorusType
|
|
13
|
+
| 'timeout'
|
|
11
14
|
| 'multi-select'
|
|
12
15
|
| 'schema-definition';
|
|
13
16
|
|
|
14
17
|
export type TFormFieldValueType<T> =
|
|
15
18
|
T extends 'string' | 'long-string' | 'binary' | 'email' | 'url' | 'enum' | 'select-string' | 'file-as-string' | 'byte-size' ? string
|
|
16
|
-
: T extends 'int' | 'integer' | 'float' | 'number' ? number
|
|
19
|
+
: T extends 'int' | 'integer' | 'float' | 'number' | 'timeout' ? number
|
|
17
20
|
: T extends 'bool' | 'boolean' ? boolean
|
|
18
21
|
: T extends 'date' ? Date | string
|
|
19
22
|
: T extends 'hash' | 'free-hash' | 'data' ? Record<string, any>
|