@orchestrator-ui/orchestrator-ui-components 6.8.0 → 7.0.1

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 (101) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/.turbo/turbo-lint.log +5 -2
  3. package/.turbo/turbo-test.log +9 -10
  4. package/CHANGELOG.md +19 -0
  5. package/dist/index.d.ts +164 -4306
  6. package/dist/index.js +1739 -5747
  7. package/dist/index.js.map +1 -1
  8. package/package.json +4 -8
  9. package/src/components/WfoPydanticForm/Footer.tsx +33 -6
  10. package/src/components/WfoPydanticForm/RenderFormErrors.tsx +2 -1
  11. package/src/components/WfoPydanticForm/Row.tsx +3 -1
  12. package/src/components/WfoPydanticForm/fields/WfoInteger.tsx +5 -1
  13. package/src/components/WfoPydanticForm/fields/WfoSummary.tsx +3 -5
  14. package/src/components/WfoPydanticForm/fields/styles.ts +72 -0
  15. package/src/components/WfoSearchPage/WfoSearch/WfoSearch.tsx +42 -54
  16. package/src/components/WfoSearchPage/utils.ts +9 -1
  17. package/src/components/WfoWorkflowSteps/WfoStep/WfoStep.tsx +10 -27
  18. package/src/components/WfoWorkflowSteps/WfoStep/WfoStepForm.tsx +1 -1
  19. package/src/components/index.ts +0 -1
  20. package/src/configuration/version.ts +1 -1
  21. package/src/contexts/OrchestratorConfigContext.tsx +0 -1
  22. package/src/hooks/useSearch.ts +12 -2
  23. package/src/hooks/useSearchPagination.ts +4 -0
  24. package/src/messages/en-GB.json +5 -3
  25. package/src/pages/processes/WfoStartProcessPage.tsx +5 -107
  26. package/src/rtk/endpoints/index.ts +0 -2
  27. package/src/rtk/endpoints/search.ts +13 -4
  28. package/src/types/index.ts +0 -1
  29. package/src/types/search.ts +7 -0
  30. package/src/types/types.ts +0 -1
  31. package/src/components/WfoForms/AutoFieldLoader.tsx +0 -118
  32. package/src/components/WfoForms/AutoFields.tsx +0 -49
  33. package/src/components/WfoForms/CreateForm.tsx +0 -75
  34. package/src/components/WfoForms/UserInputForm.tsx +0 -697
  35. package/src/components/WfoForms/UserInputFormStyling.ts +0 -80
  36. package/src/components/WfoForms/UserInputFormWizard.tsx +0 -127
  37. package/src/components/WfoForms/formFields/AcceptField.tsx +0 -243
  38. package/src/components/WfoForms/formFields/AcceptFieldStyling.ts +0 -35
  39. package/src/components/WfoForms/formFields/BoolField.tsx +0 -77
  40. package/src/components/WfoForms/formFields/BoolFieldStyling.ts +0 -64
  41. package/src/components/WfoForms/formFields/ConnectedSelectField.tsx +0 -19
  42. package/src/components/WfoForms/formFields/CustomerField.tsx +0 -77
  43. package/src/components/WfoForms/formFields/DateField.tsx +0 -72
  44. package/src/components/WfoForms/formFields/DividerField.tsx +0 -29
  45. package/src/components/WfoForms/formFields/ErrorField.tsx +0 -40
  46. package/src/components/WfoForms/formFields/ErrorsField.tsx +0 -34
  47. package/src/components/WfoForms/formFields/LabelField.tsx +0 -43
  48. package/src/components/WfoForms/formFields/ListAddField.tsx +0 -95
  49. package/src/components/WfoForms/formFields/ListDelField.tsx +0 -95
  50. package/src/components/WfoForms/formFields/ListField.tsx +0 -117
  51. package/src/components/WfoForms/formFields/ListItemField.tsx +0 -40
  52. package/src/components/WfoForms/formFields/ListSelectField.tsx +0 -95
  53. package/src/components/WfoForms/formFields/LocationCodeField.tsx +0 -60
  54. package/src/components/WfoForms/formFields/LongTextField.tsx +0 -68
  55. package/src/components/WfoForms/formFields/NestField.tsx +0 -107
  56. package/src/components/WfoForms/formFields/NumField.tsx +0 -85
  57. package/src/components/WfoForms/formFields/OptGroupField.tsx +0 -74
  58. package/src/components/WfoForms/formFields/RadioField.tsx +0 -87
  59. package/src/components/WfoForms/formFields/SelectField/SelectField.tsx +0 -177
  60. package/src/components/WfoForms/formFields/SelectField/index.ts +0 -1
  61. package/src/components/WfoForms/formFields/SelectField/styles.ts +0 -52
  62. package/src/components/WfoForms/formFields/SubmitField.tsx +0 -50
  63. package/src/components/WfoForms/formFields/SubscriptionSummaryField.tsx +0 -74
  64. package/src/components/WfoForms/formFields/SummaryField.tsx +0 -104
  65. package/src/components/WfoForms/formFields/SummaryFieldStyling.ts +0 -44
  66. package/src/components/WfoForms/formFields/TextField.tsx +0 -81
  67. package/src/components/WfoForms/formFields/commonStyles.ts +0 -32
  68. package/src/components/WfoForms/formFields/deprecated/ContactPersonAutocomplete.tsx +0 -99
  69. package/src/components/WfoForms/formFields/deprecated/ContactPersonAutocompleteStyles.ts +0 -41
  70. package/src/components/WfoForms/formFields/deprecated/ContactPersonNameField.tsx +0 -263
  71. package/src/components/WfoForms/formFields/deprecated/FileUploadField.tsx +0 -151
  72. package/src/components/WfoForms/formFields/deprecated/ImsNodeIdField.tsx +0 -109
  73. package/src/components/WfoForms/formFields/deprecated/ImsPortIdField.tsx +0 -233
  74. package/src/components/WfoForms/formFields/deprecated/ImsPortIdFieldStyling.ts +0 -17
  75. package/src/components/WfoForms/formFields/deprecated/IpNetworkField.tsx +0 -105
  76. package/src/components/WfoForms/formFields/deprecated/IpPrefixTableField.tsx +0 -390
  77. package/src/components/WfoForms/formFields/deprecated/IpPrefixTableFieldStyling.ts +0 -117
  78. package/src/components/WfoForms/formFields/deprecated/SplitPrefix.tsx +0 -138
  79. package/src/components/WfoForms/formFields/deprecated/SplitPrefixStyling.ts +0 -11
  80. package/src/components/WfoForms/formFields/deprecated/SubscriptionField.tsx +0 -263
  81. package/src/components/WfoForms/formFields/deprecated/SubscriptionFieldStyling.ts +0 -33
  82. package/src/components/WfoForms/formFields/deprecated/TimestampField.tsx +0 -110
  83. package/src/components/WfoForms/formFields/deprecated/VlanField.tsx +0 -300
  84. package/src/components/WfoForms/formFields/deprecated/index.ts +0 -15
  85. package/src/components/WfoForms/formFields/deprecated/types.ts +0 -74
  86. package/src/components/WfoForms/formFields/deprecated/utils.ts +0 -1
  87. package/src/components/WfoForms/formFields/index.ts +0 -30
  88. package/src/components/WfoForms/formFields/listFieldStyling.ts +0 -86
  89. package/src/components/WfoForms/formFields/types.ts +0 -41
  90. package/src/components/WfoForms/formFields/utils.spec.ts +0 -296
  91. package/src/components/WfoForms/formFields/utils.ts +0 -69
  92. package/src/components/WfoForms/index.ts +0 -5
  93. package/src/components/WfoWorkflowSteps/WfoStep/WfoStepFormOld.tsx +0 -67
  94. package/src/hooks/deprecated/useGetSurfSubcriptionDropdownOptions.ts +0 -37
  95. package/src/hooks/deprecated/useIsTaggedPort.ts +0 -25
  96. package/src/rtk/endpoints/deprecated/index.ts +0 -1
  97. package/src/rtk/endpoints/deprecated/surfSubscriptionDropdownOptions.ts +0 -53
  98. package/src/rtk/endpoints/formFields.ts +0 -131
  99. package/src/rtk/endpoints/ipam.ts +0 -54
  100. package/src/types/deprecated/SurfSubscriptionDropdownOptionsFilterParams.ts +0 -10
  101. package/src/types/deprecated/index.ts +0 -1
@@ -1,697 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
-
3
- /*
4
- * Copyright 2019-2023 SURF.
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- *
16
- */
17
- import React, { useContext, useState } from 'react';
18
-
19
- import invariant from 'invariant';
20
- import { JSONSchema6 } from 'json-schema';
21
- import { isObject } from 'lodash';
22
- import cloneDeep from 'lodash/cloneDeep';
23
- import get from 'lodash/get';
24
- import { useTranslations } from 'next-intl';
25
- import { NextRouter } from 'next/router';
26
- import { filterDOMProps, joinName } from 'uniforms';
27
- import { JSONSchemaBridge } from 'uniforms-bridge-json-schema';
28
- import { AutoField, AutoForm } from 'uniforms-unstyled';
29
-
30
- import {
31
- EuiButton,
32
- EuiButtonColor,
33
- EuiFlexGroup,
34
- EuiHorizontalRule,
35
- } from '@elastic/eui';
36
-
37
- import { ConfirmDialogHandler, ConfirmationDialogContext } from '@/contexts';
38
- import { useOrchestratorTheme, useWfoErrorMonitoring } from '@/hooks';
39
- import { WfoPlayFill } from '@/icons';
40
- import { FormValidationError, ValidationError } from '@/types/forms';
41
-
42
- import { autoFieldFunction } from './AutoFieldLoader';
43
- import AutoFields from './AutoFields';
44
- import { userInputFormStyling } from './UserInputFormStyling';
45
-
46
- type UniformJSONSchemaProperty = JSONSchema6 & {
47
- uniforms: any;
48
- defaultValue: any;
49
- };
50
-
51
- interface IProps {
52
- router: NextRouter;
53
- stepUserInput: JSONSchema6;
54
- validSubmit: (userInput: { [index: string]: unknown }) => Promise<unknown>;
55
- cancel?: ConfirmDialogHandler;
56
- previous: ConfirmDialogHandler;
57
- hasNext?: boolean;
58
- hasPrev?: boolean;
59
- userInput: object;
60
- isTask?: boolean;
61
- isResuming?: boolean;
62
- disabled?: boolean;
63
- }
64
-
65
- interface Buttons {
66
- previous: {
67
- text?: string;
68
- dialog?: string;
69
- color?: EuiButtonColor;
70
- };
71
- next: {
72
- text?: string;
73
- dialog?: string;
74
- color?: EuiButtonColor;
75
- };
76
- }
77
-
78
- declare module 'uniforms' {
79
- interface FilterDOMProps {
80
- customPropToFilter: never;
81
- description: never;
82
- const: never;
83
- default: never;
84
- required: never;
85
- pattern: never;
86
- examples: never;
87
- allOf: never;
88
- anyOf: never;
89
- options: never;
90
- }
91
- }
92
- filterDOMProps.register('description');
93
- filterDOMProps.register('const');
94
- filterDOMProps.register('default');
95
- filterDOMProps.register('required');
96
- filterDOMProps.register('pattern');
97
- filterDOMProps.register('examples');
98
- filterDOMProps.register('allOf');
99
- filterDOMProps.register('anyOf');
100
- filterDOMProps.register('options');
101
-
102
- function resolveRef(reference: string, schema: Record<string, any>) {
103
- invariant(
104
- reference.startsWith('#'),
105
- 'Reference is not an internal reference, and only such are allowed: "%s"',
106
- reference,
107
- );
108
-
109
- const resolvedReference = reference
110
- .split('/')
111
- .filter((part) => part && part !== '#')
112
- .reduce((definition, next) => {
113
- // FIXME: There is a ticket to fix this in the return value from GraphQL: https://git.ia.surfsara.nl/netdev/automation/projects/orchestrator/-/issues/1891
114
- // TLDR: currently the form properties may reference things in the forms $defs property but the forms $defs property doesn't exist but is called 'definitions' instead
115
- const newDefinition = (() => {
116
- if (next === '$defs' && !definition[next]) {
117
- return definition['definitions'];
118
- }
119
- return definition[next];
120
- })();
121
- return newDefinition;
122
- }, schema);
123
-
124
- invariant(
125
- resolvedReference,
126
- 'Reference not found in schema: "%s"',
127
- reference,
128
- );
129
-
130
- return resolvedReference;
131
- }
132
-
133
- class CustomTitleJSONSchemaBridge extends JSONSchemaBridge {
134
- t: any;
135
-
136
- constructor(schema: JSONSchema6, validator: any, t: any) {
137
- super(schema, validator);
138
- this.t = t;
139
- }
140
-
141
- translationKeyExists(key: string): boolean {
142
- const translation = this.t(key);
143
- return translation && translation !== key ? true : false;
144
- }
145
-
146
- // This a copy of the super class function to provide a fix for https://github.com/vazco/uniforms/issues/863
147
- getField(name: string) {
148
- return joinName(null, name).reduce(
149
- (definition, next, nextIndex, array) => {
150
- const previous = joinName(array.slice(0, nextIndex));
151
- const isRequired = get(
152
- definition,
153
- 'required',
154
- get(this._compiledSchema, [previous, 'required'], []),
155
- ).includes(next);
156
-
157
- const _key = joinName(previous, next);
158
- const _definition = this._compiledSchema[_key] || {};
159
-
160
- if (next === '$' || next === '' + parseInt(next, 10)) {
161
- if (
162
- definition.anyOf &&
163
- definition.anyOf[0].type === 'array'
164
- ) {
165
- invariant(
166
- definition.anyOf[0].type === 'array',
167
- 'Field not found in schema: "%s"',
168
- name,
169
- );
170
- definition = Array.isArray(definition.anyOf[0].items)
171
- ? definition.anyOf[0].items[parseInt(next, 10)]
172
- : definition.anyOf[0].items;
173
- } else {
174
- invariant(
175
- definition.type === 'array',
176
- 'Field not found in schema: "%s"',
177
- name,
178
- );
179
- definition = Array.isArray(definition.items)
180
- ? definition.items[parseInt(next, 10)]
181
- : definition.items;
182
- }
183
- } else if (definition.type === 'object') {
184
- invariant(
185
- definition.properties,
186
- 'Field properties not found in schema: "%s"',
187
- name,
188
- );
189
- definition = definition.properties[next];
190
- } else {
191
- const [{ properties: combinedDefinition = {} } = {}] = [
192
- 'allOf',
193
- 'anyOf',
194
- 'oneOf',
195
- ]
196
- .filter((key) => definition[key])
197
- .map((key) => {
198
- // FIXME: Correct type for `definition`.
199
- const localDef = (definition[key] as any[]).map(
200
- (subSchema) =>
201
- subSchema.$ref
202
- ? resolveRef(
203
- subSchema.$ref,
204
- this.schema,
205
- )
206
- : subSchema,
207
- );
208
- return localDef.find(
209
- ({ properties = {} }) => properties[next],
210
- );
211
- });
212
-
213
- definition = combinedDefinition[next];
214
- }
215
-
216
- invariant(definition, 'Field not found in schema: "%s"', name);
217
-
218
- if (definition.$ref) {
219
- definition = resolveRef(definition.$ref, this.schema);
220
- }
221
-
222
- ['allOf', 'anyOf', 'oneOf'].forEach((key) => {
223
- if (definition[key]) {
224
- // FIXME: Correct type for `definition`.
225
- _definition[key] = (definition[key] as any[]).map(
226
- (def) =>
227
- def.$ref
228
- ? resolveRef(def.$ref, this.schema)
229
- : def,
230
- );
231
- }
232
- });
233
-
234
- // Naive computation of combined type, properties and required
235
- const combinedPartials: any[] = []
236
- .concat(
237
- _definition.allOf,
238
- _definition.anyOf,
239
- _definition.oneOf,
240
- )
241
- .filter(Boolean);
242
-
243
- if (combinedPartials.length) {
244
- const localProperties = definition.properties
245
- ? { ...definition.properties }
246
- : {};
247
- const localRequired = definition.required
248
- ? definition.required.slice()
249
- : [];
250
-
251
- combinedPartials.forEach((combinedPartial) => {
252
- const { properties, required } = combinedPartial;
253
- if (properties) {
254
- Object.assign(localProperties, properties);
255
- }
256
- if (required) {
257
- localRequired.push(...required);
258
- }
259
-
260
- // Copy all properties instead of only type
261
- for (const key in combinedPartial) {
262
- if (combinedPartial[key] && !_definition[key]) {
263
- _definition[key] = combinedPartial[key];
264
-
265
- // This isExtensible check is introduced to fix this bug: https://github.com/workfloworchestrator/orchestrator-ui-library/issues/878
266
- // The reason the definition object is not extensible here but is in the same place in v1 is not known but
267
- // deemed not worth to investigate further at this point.
268
- if (Object.isExtensible(definition)) {
269
- definition[key] = combinedPartial[key];
270
- }
271
- }
272
- }
273
- });
274
-
275
- if (Object.keys(localProperties).length > 0) {
276
- _definition.properties = localProperties;
277
- }
278
- if (localRequired.length > 0) {
279
- _definition.required = localRequired;
280
- }
281
- }
282
-
283
- this._compiledSchema[_key] = Object.assign(_definition, {
284
- isRequired,
285
- });
286
-
287
- return definition;
288
- },
289
- this.schema,
290
- );
291
- }
292
-
293
- getProps(name: string) {
294
- const props = super.getProps(name);
295
-
296
- const translationKey = name.replace(/\.\d+(.\d+)*/, '_fields'); // This is evaluates to name or name_fields
297
- const nextIntlKey = `pydanticForms.backendTranslations.${translationKey}`;
298
- let label = this.translationKeyExists(nextIntlKey)
299
- ? this.t(nextIntlKey)
300
- : props.label;
301
-
302
- // Mark required inputs. Might be delegated to the form components itself in the future.
303
- if (
304
- props.required &&
305
- !props.readOnly &&
306
- !props.isDisabled &&
307
- !name.includes('.')
308
- ) {
309
- label = `${label} *`;
310
- }
311
-
312
- props.label = label;
313
-
314
- const descriptionTranslationKey = `pydanticForms.backendTranslations.${translationKey}_info`;
315
- props.description = this.translationKeyExists(descriptionTranslationKey)
316
- ? this.t(descriptionTranslationKey)
317
- : ' ';
318
-
319
- props.id = `input-${name}`;
320
-
321
- if (props.const) {
322
- props.disabled = true;
323
- props.default = props.const;
324
- delete props['const'];
325
- }
326
-
327
- if (props.initialCount === undefined) {
328
- props.initialCount = props.minCount;
329
- }
330
-
331
- return props;
332
- }
333
-
334
- getInitialValue(name: string, props: Record<string, any> = {}): any {
335
- const {
336
- default: _default,
337
- const: _const,
338
- type: _type,
339
- } = this.getField(name);
340
- let {
341
- default: defaultValue = _default !== undefined
342
- ? _default
343
- : get(this.schema.default, name),
344
- } = this._compiledSchema[name];
345
- const { const: constValue = _const, type = _type } =
346
- this._compiledSchema[name];
347
-
348
- // use const if present
349
- if (defaultValue === undefined) defaultValue = constValue;
350
-
351
- // See https://github.com/vazco/uniforms/issues/749
352
- if (defaultValue === undefined) {
353
- const nameArray = joinName(null, name);
354
- const relativeName = nameArray.pop()!;
355
- const parentName = joinName(nameArray);
356
- if (parentName !== '') {
357
- const model = this.getInitialValue(parentName, {
358
- lookUpParent: true,
359
- });
360
- defaultValue = get(model, relativeName);
361
- }
362
- }
363
-
364
- if (defaultValue !== undefined) return cloneDeep(defaultValue);
365
-
366
- if (type === 'array' && !props.lookUpParent && !name.endsWith('$')) {
367
- const item = this.getInitialValue(joinName(name, '0'));
368
- const items = props.initialCount || 0;
369
- return Array(items).fill(item);
370
- }
371
-
372
- if (type === 'object') {
373
- return {};
374
- }
375
- return undefined;
376
- }
377
- }
378
-
379
- function fillPreselection(form: JSONSchema6, router: NextRouter) {
380
- const queryParams = router.query;
381
- if (form && form.properties) {
382
- Object.keys(queryParams).forEach((param) => {
383
- if (form && form.properties && form.properties[param]) {
384
- const customerInput = form.properties[
385
- param
386
- ] as UniformJSONSchemaProperty;
387
- if (!customerInput.uniforms) {
388
- customerInput.uniforms = {};
389
- }
390
- customerInput.uniforms.disabled = true;
391
- customerInput.default = queryParams[param];
392
- }
393
- });
394
-
395
- // ipvany preselect
396
- if (queryParams.prefix && queryParams.prefixlen) {
397
- if (form && form.properties.ip_prefix) {
398
- const ipPrefix = isObject(form.properties.ip_prefix)
399
- ? form.properties.ip_prefix
400
- : {};
401
- const ipPrefixInput = {
402
- ...ipPrefix,
403
- uniforms: { prefixMin: 0 },
404
- default: {},
405
- } as UniformJSONSchemaProperty;
406
- if (!ipPrefixInput.uniforms) {
407
- ipPrefixInput.uniforms = { prefixMin: 0 };
408
- }
409
- ipPrefixInput.default = `${queryParams.prefix}/${queryParams.prefixlen}`;
410
- ipPrefixInput.uniforms.prefixMin = parseInt(
411
- queryParams.prefixlen as string,
412
- 10,
413
- );
414
- return {
415
- ...form,
416
- properties: {
417
- ...form.properties,
418
- ip_prefix: ipPrefixInput,
419
- },
420
- };
421
- }
422
- }
423
- }
424
- return form;
425
- }
426
-
427
- export function WfoUserInputForm({
428
- router,
429
- stepUserInput,
430
- validSubmit,
431
- cancel = () => {},
432
- previous = () => {},
433
- hasNext = false,
434
- hasPrev = false,
435
- userInput,
436
- isTask = false,
437
- isResuming = false,
438
- disabled = false,
439
- }: IProps) {
440
- const t = useTranslations('pydanticForms.userInputForm');
441
- const tDialog = useTranslations('confirmationDialog');
442
- const { theme } = useOrchestratorTheme();
443
- const { showConfirmDialog } = useContext(ConfirmationDialogContext);
444
- const [processing, setProcessing] = useState<boolean>(false);
445
- const [nrOfValidationErrors, setNrOfValidationErrors] = useState<number>(0);
446
- const [rootErrors, setRootErrors] = useState<string[]>([]);
447
- const { reportError } = useWfoErrorMonitoring();
448
-
449
- const openLeavePageDialog = (
450
- leaveAction: ConfirmDialogHandler,
451
- leaveQuestion?: string,
452
- ) => {
453
- const question = leaveQuestion || tDialog('leavePage');
454
- const subQuestion = leaveQuestion ? tDialog('leavePageSub') : '';
455
- const cancelButtonText = tDialog('stay');
456
- const confirmButtonText = tDialog('leave');
457
-
458
- return () =>
459
- showConfirmDialog({
460
- question,
461
- subQuestion,
462
- onConfirm: leaveAction,
463
- cancelButtonText,
464
- confirmButtonText,
465
- });
466
- };
467
-
468
- const submit = async (userInput: any = {}) => {
469
- if (!processing) {
470
- setProcessing(true);
471
-
472
- try {
473
- await validSubmit(userInput);
474
- setProcessing(false);
475
- return null;
476
- } catch (error) {
477
- setProcessing(false);
478
- if (typeof error === 'object' && error !== null) {
479
- const validationError = error as FormValidationError;
480
- if (validationError?.status === 400) {
481
- const json = validationError.data;
482
- setNrOfValidationErrors(json.validation_errors.length);
483
- setRootErrors(
484
- json.validation_errors
485
- .filter(
486
- (e: ValidationError) =>
487
- e.loc[0] === '__root__',
488
- )
489
- .map((e: ValidationError) => e.msg),
490
- );
491
- throw Object.assign(new Error(), {
492
- details: json.validation_errors.map(
493
- (e: ValidationError) => ({
494
- message: e.msg,
495
- params: e.ctx || {},
496
- dataPath: '.' + e.loc.join('.'),
497
- }),
498
- ),
499
- });
500
- }
501
- }
502
- // Let the error escape, so it can be caught by our own onerror handler instead of being silenced by uniforms
503
- setTimeout(() => {
504
- reportError(
505
- new Error(`Forms error: ${JSON.stringify({ error })}`),
506
- );
507
- throw error;
508
- }, 0);
509
-
510
- // The form will clear the errors so also remove the warning
511
- setNrOfValidationErrors(0);
512
- setRootErrors([]);
513
-
514
- // The error we got contains no validation errors so don't send it to uniforms
515
- return null;
516
- }
517
- }
518
- };
519
-
520
- const onButtonClick = (
521
- e:
522
- | React.MouseEvent<HTMLButtonElement>
523
- | React.MouseEvent<HTMLDivElement, MouseEvent>,
524
- question: string | undefined,
525
- confirm: () => void,
526
- ) => {
527
- if (!question) {
528
- return confirm();
529
- }
530
-
531
- showConfirmDialog({
532
- question: question,
533
- onConfirm: confirm,
534
- });
535
- };
536
-
537
- const renderButtons = (buttons: Buttons) => {
538
- const prevButton = hasPrev ? (
539
- <EuiButton
540
- id="button-prev-form-submit"
541
- fill
542
- color={buttons.previous.color ?? 'primary'}
543
- onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
544
- onButtonClick(
545
- e,
546
- buttons.previous.dialog,
547
- openLeavePageDialog(previous, t('previousQuestion')),
548
- );
549
- }}
550
- disabled={disabled}
551
- >
552
- {buttons.previous.text ?? t('previous')}
553
- </EuiButton>
554
- ) : !isResuming ? (
555
- <div
556
- onClick={(e) => {
557
- onButtonClick(
558
- e,
559
- buttons.previous.dialog,
560
- openLeavePageDialog(cancel),
561
- );
562
- }}
563
- css={{
564
- cursor: 'pointer',
565
- color: theme.colors.link,
566
- fontWeight: theme.font.weight.bold,
567
- marginLeft: '8px',
568
- display: 'flex',
569
- alignItems: 'center',
570
- }}
571
- >
572
- {buttons.previous.text ?? t('cancel')}
573
- </div>
574
- ) : (
575
- <div></div>
576
- );
577
-
578
- const nextButtonTranslationKey: string = (() => {
579
- if (isResuming) {
580
- return isTask ? 'resumeTask' : 'resumeWorkflow';
581
- }
582
- return isTask ? 'startTask' : 'startWorkflow';
583
- })();
584
-
585
- const nextButton = hasNext ? (
586
- <EuiButton
587
- id="button-next-form-submit"
588
- tabIndex={0}
589
- fill
590
- color={buttons.next.color ?? 'primary'}
591
- isLoading={processing}
592
- type="submit"
593
- disabled={disabled}
594
- >
595
- {buttons.next.text ?? t('next')}
596
- </EuiButton>
597
- ) : (
598
- <EuiButton
599
- id="button-submit-form-submit"
600
- tabIndex={0}
601
- fill
602
- color={buttons.next.color ?? 'primary'}
603
- isLoading={processing}
604
- type="submit"
605
- iconType={
606
- buttons.next.text
607
- ? undefined
608
- : () => <WfoPlayFill color="#FFF" />
609
- }
610
- iconSide="right"
611
- disabled={disabled}
612
- >
613
- {buttons.next.text ?? t(nextButtonTranslationKey)}
614
- </EuiButton>
615
- );
616
-
617
- return (
618
- <>
619
- <EuiHorizontalRule />
620
-
621
- <EuiFlexGroup justifyContent="spaceBetween">
622
- {prevButton}
623
- {nextButton}
624
- </EuiFlexGroup>
625
- </>
626
- );
627
- };
628
-
629
- const prefilledForm = fillPreselection(stepUserInput, router);
630
- const bridge = new CustomTitleJSONSchemaBridge(
631
- prefilledForm,
632
- () => {},
633
- useTranslations(),
634
- );
635
- const AutoFieldProvider = AutoField.componentDetectorContext.Provider;
636
-
637
- // Get the Button config from the form default values, or default to empty config
638
- const buttonsFromSchema = (prefilledForm.properties?.buttons &&
639
- prefilledForm.properties?.buttons !== true &&
640
- prefilledForm.properties?.buttons.default) || {
641
- previous: {},
642
- next: {},
643
- };
644
-
645
- const buttons: Buttons = buttonsFromSchema as unknown as Buttons;
646
-
647
- return (
648
- <div css={userInputFormStyling}>
649
- <div className="user-input-form">
650
- <section className="form-fieldset">
651
- {stepUserInput.title &&
652
- stepUserInput.title !== 'unknown' && (
653
- <h3>{stepUserInput.title}</h3>
654
- )}
655
- <AutoFieldProvider value={autoFieldFunction}>
656
- <AutoForm
657
- schema={bridge}
658
- onSubmit={submit}
659
- showInlineError={true}
660
- validate="onSubmit"
661
- model={userInput}
662
- disabled={disabled}
663
- >
664
- <AutoFields omitFields={['buttons']} />
665
- {/* Show top level validation info about backend validation */}
666
- {nrOfValidationErrors > 0 && (
667
- <section className="form-errors">
668
- <em className="error backend-validation-metadata">
669
- {t('inputFieldsHaveValidationErrors', {
670
- nrOfValidationErrors:
671
- nrOfValidationErrors,
672
- })}
673
- </em>
674
- </section>
675
- )}
676
- {rootErrors.length > 0 && (
677
- <section className="form-errors">
678
- <em className="error backend-validation-metadata">
679
- {rootErrors.map((error, index) => (
680
- <div
681
- className="euiFormErrorText euiFormRow__text"
682
- key={index}
683
- >
684
- {error}
685
- </div>
686
- ))}
687
- </em>
688
- </section>
689
- )}
690
- {renderButtons(buttons)}
691
- </AutoForm>
692
- </AutoFieldProvider>
693
- </section>
694
- </div>
695
- </div>
696
- );
697
- }