@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.
Files changed (57) hide show
  1. package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
  2. package/dist/components/form/engine/CompactRow.js +24 -7
  3. package/dist/components/form/engine/CompactRow.js.map +1 -1
  4. package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
  5. package/dist/components/form/engine/FormEngine.js +11 -1
  6. package/dist/components/form/engine/FormEngine.js.map +1 -1
  7. package/dist/components/form/engine/readFirst.d.ts.map +1 -1
  8. package/dist/components/form/engine/readFirst.js +8 -2
  9. package/dist/components/form/engine/readFirst.js.map +1 -1
  10. package/dist/components/form/expressions/ExpressionField.d.ts.map +1 -1
  11. package/dist/components/form/expressions/ExpressionField.js +2 -2
  12. package/dist/components/form/expressions/ExpressionField.js.map +1 -1
  13. package/dist/components/form/fields/Field.d.ts.map +1 -1
  14. package/dist/components/form/fields/Field.js +7 -0
  15. package/dist/components/form/fields/Field.js.map +1 -1
  16. package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
  17. package/dist/components/form/fields/auto/AutoFormField.js +10 -0
  18. package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
  19. package/dist/components/form/fields/select/Select.d.ts +6 -1
  20. package/dist/components/form/fields/select/Select.d.ts.map +1 -1
  21. package/dist/components/form/fields/select/Select.js +5 -5
  22. package/dist/components/form/fields/select/Select.js.map +1 -1
  23. package/dist/components/form/fields/timeout/Timeout.d.ts +24 -0
  24. package/dist/components/form/fields/timeout/Timeout.d.ts.map +1 -0
  25. package/dist/components/form/fields/timeout/Timeout.js +73 -0
  26. package/dist/components/form/fields/timeout/Timeout.js.map +1 -0
  27. package/dist/components/form/index.d.ts +1 -0
  28. package/dist/components/form/index.d.ts.map +1 -1
  29. package/dist/components/form/index.js +1 -0
  30. package/dist/components/form/index.js.map +1 -1
  31. package/dist/helpers/common.d.ts +17 -0
  32. package/dist/helpers/common.d.ts.map +1 -1
  33. package/dist/helpers/common.js +42 -1
  34. package/dist/helpers/common.js.map +1 -1
  35. package/dist/helpers/validations.d.ts.map +1 -1
  36. package/dist/helpers/validations.js +50 -20
  37. package/dist/helpers/validations.js.map +1 -1
  38. package/dist/types/Form.d.ts +2 -2
  39. package/dist/types/Form.d.ts.map +1 -1
  40. package/package.json +1 -1
  41. package/src/components/form/engine/CompactRow.tsx +43 -20
  42. package/src/components/form/engine/FormEngine.stories.tsx +17 -11
  43. package/src/components/form/engine/FormEngine.tsx +10 -1
  44. package/src/components/form/engine/readFirst.ts +10 -3
  45. package/src/components/form/expressions/ExpressionField.stories.tsx +23 -16
  46. package/src/components/form/expressions/ExpressionField.tsx +23 -18
  47. package/src/components/form/fields/Field.tsx +17 -0
  48. package/src/components/form/fields/auto/AutoFormField.stories.tsx +30 -0
  49. package/src/components/form/fields/auto/AutoFormField.tsx +19 -0
  50. package/src/components/form/fields/select/Select.stories.tsx +26 -0
  51. package/src/components/form/fields/select/Select.tsx +9 -3
  52. package/src/components/form/fields/timeout/Timeout.stories.tsx +228 -0
  53. package/src/components/form/fields/timeout/Timeout.tsx +87 -0
  54. package/src/components/form/index.tsx +1 -0
  55. package/src/helpers/common.ts +36 -0
  56. package/src/helpers/validations.ts +49 -13
  57. package/src/types/Form.ts +4 -1
@@ -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
- const nameValue = value?.name?.value ?? value?.name;
266
- const contentValue = value?.content?.value ?? value?.content;
267
- const nameResult = validateFieldWithResult('string', nameValue);
268
- const contentResult = validateFieldWithResult('string', contentValue);
269
-
270
- if (!nameResult.isValid) {
271
- return withContext(nameResult, 'File name is invalid');
272
- }
273
-
274
- if (!contentResult.isValid) {
275
- return withContext(contentResult, 'File content is invalid');
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
- return validResult();
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>