@orchestrator-ui/orchestrator-ui-components 0.2.6 → 0.3.0

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 (121) hide show
  1. package/.turbo/turbo-build.log +6 -6
  2. package/.turbo/turbo-lint.log +0 -6
  3. package/.turbo/turbo-test.log +9 -8
  4. package/CHANGELOG.md +12 -0
  5. package/dist/index.d.ts +1005 -123
  6. package/dist/index.js +33996 -6348
  7. package/package.json +14 -12
  8. package/src/api/index.ts +55 -3
  9. package/src/components/WfoDiff/WfoDiff.tsx +119 -0
  10. package/src/components/WfoDiff/index.ts +1 -0
  11. package/src/components/WfoDiff/unidiff.d.ts +1 -0
  12. package/src/components/WfoForms/AutoFieldLoader.tsx +5 -1
  13. package/src/components/WfoForms/CreateForm.tsx +1 -1
  14. package/src/components/WfoForms/UserInputForm.tsx +75 -43
  15. package/src/components/WfoForms/UserInputFormWizard.tsx +11 -4
  16. package/src/components/WfoForms/formFields/AcceptField.tsx +8 -5
  17. package/src/components/WfoForms/formFields/BoolField.tsx +1 -1
  18. package/src/components/WfoForms/formFields/ImsNodeIdField.tsx +2 -2
  19. package/src/components/WfoForms/formFields/ImsPortIdField.tsx +238 -0
  20. package/src/components/WfoForms/formFields/ImsPortIdFieldStyling.ts +17 -0
  21. package/src/components/WfoForms/formFields/IpPrefixTableField.tsx +1 -1
  22. package/src/components/WfoForms/formFields/ListAddField.tsx +1 -1
  23. package/src/components/WfoForms/formFields/ListDelField.tsx +1 -1
  24. package/src/components/WfoForms/formFields/OptGroupField.tsx +1 -1
  25. package/src/components/WfoForms/formFields/SubscriptionField.tsx +2 -1
  26. package/src/components/WfoForms/formFields/SummaryField.tsx +103 -0
  27. package/src/components/WfoForms/formFields/SummaryFieldStyling.ts +46 -0
  28. package/src/components/WfoForms/formFields/VlanField.tsx +10 -10
  29. package/src/components/WfoForms/formFields/index.ts +2 -0
  30. package/src/components/WfoForms/formFields/surf/types.ts +26 -0
  31. package/src/components/WfoForms/formFields/utils.spec.ts +1 -0
  32. package/src/components/WfoJsonCodeBlock/index.ts +1 -0
  33. package/src/components/WfoPageTemplate/WfoPageHeader/WfoPageHeader.tsx +4 -3
  34. package/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx +14 -14
  35. package/src/components/WfoPageTemplate/WfoSidebar/WfoStartCreateWorkflowButtonComboBox.tsx +15 -9
  36. package/src/components/WfoPageTemplate/paths.ts +3 -2
  37. package/src/components/{WfoProcessesList → WfoProcessList}/WfoProcessList.tsx +18 -14
  38. package/src/components/WfoProcessList/index.ts +1 -0
  39. package/src/components/{WfoProcessesList → WfoProcessList}/processListObjectMappers.ts +4 -2
  40. package/src/components/WfoSearchBar/WfoSearchField.tsx +27 -37
  41. package/src/components/{WfoSettingsPage → WfoSettings}/WfoEngineStatusButton.tsx +7 -4
  42. package/src/components/{WfoSettingsPage → WfoSettings}/WfoFlushSettings.tsx +13 -12
  43. package/src/components/WfoSettings/WfoModifySettings.tsx +38 -0
  44. package/src/components/WfoSettings/WfoSettings.tsx +40 -0
  45. package/src/components/{WfoSettingsPage → WfoSettings}/WfoStatus.tsx +21 -14
  46. package/src/components/WfoStartPage/WfoListStartPage.tsx +3 -3
  47. package/src/components/WfoStartTaskButtonComboBox/WfoStartTaskButtonComboBox.tsx +14 -8
  48. package/src/components/WfoSubscription/WfoProcessesTimeline.tsx +11 -18
  49. package/src/components/WfoSubscription/WfoSubscription.tsx +1 -1
  50. package/src/components/WfoSubscription/WfoSubscriptionActions.tsx +41 -33
  51. package/src/components/WfoSubscription/WfoSubscriptionDetailTree.tsx +32 -22
  52. package/src/components/WfoSubscription/WfoSubscriptionProductBlock.tsx +94 -90
  53. package/src/components/WfoSubscription/WfoTargetTypeIcon.tsx +26 -0
  54. package/src/components/WfoSubscription/utils/utils.spec.ts +24 -0
  55. package/src/components/WfoSubscription/utils/utils.ts +16 -0
  56. package/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx +17 -37
  57. package/src/components/WfoTable/WfoTableWithFilter/WfoTableWithFilter.tsx +20 -19
  58. package/src/components/WfoTable/WfoTableWithFilter/updateQueryString.spec.ts +95 -0
  59. package/src/components/WfoTable/WfoTableWithFilter/updateQueryString.ts +60 -0
  60. package/src/components/WfoTable/utils/tableUtils.ts +3 -3
  61. package/src/components/WfoTextAnchor/WfoTextAnchor.stories.tsx +18 -0
  62. package/src/components/WfoTextAnchor/WfoTextAnchor.tsx +22 -0
  63. package/src/components/WfoTextAnchor/index.ts +1 -0
  64. package/src/components/WfoTextAnchor/styles.ts +17 -0
  65. package/src/components/WfoTimeline/styles.ts +10 -4
  66. package/src/components/WfoWorkflowSteps/WfoStep/WfoStep.tsx +39 -24
  67. package/src/components/WfoWorkflowSteps/WfoStep/WfoStepForm.tsx +48 -0
  68. package/src/components/WfoWorkflowSteps/WfoStepList/WfoStepList.tsx +14 -11
  69. package/src/components/WfoWorkflowSteps/WfoWorkflowStepList/WfoStepListHeader.tsx +22 -23
  70. package/src/components/WfoWorkflowSteps/WfoWorkflowStepList/WfoWorkflowStepList.tsx +97 -17
  71. package/src/components/WfoWorkflowSteps/stepListUtils.ts +1 -28
  72. package/src/components/confirmationDialog/WfoConfirmationDialog.tsx +3 -3
  73. package/src/components/index.ts +6 -1
  74. package/src/contexts/ConfirmationDialogProvider.tsx +2 -2
  75. package/src/contexts/TreeContext.tsx +5 -0
  76. package/src/graphqlQueries/index.ts +1 -0
  77. package/src/graphqlQueries/processDetailQuery.ts +8 -0
  78. package/src/graphqlQueries/processListQuery.ts +7 -6
  79. package/src/graphqlQueries/processStepsQuery.ts +22 -0
  80. package/src/graphqlQueries/productBlocksQuery.ts +9 -5
  81. package/src/graphqlQueries/productsQuery.ts +7 -3
  82. package/src/graphqlQueries/relatedSubscriptionsQuery.ts +2 -2
  83. package/src/graphqlQueries/resourceTypesQuery.ts +8 -4
  84. package/src/graphqlQueries/subscriptionDetailQuery.ts +1 -0
  85. package/src/graphqlQueries/subscriptionsListQuery.ts +5 -3
  86. package/src/graphqlQueries/workflows/workflowsQuery.ts +8 -4
  87. package/src/graphqlQueries/workflows/workflowsQueryForDropdownList.ts +2 -2
  88. package/src/hooks/DataFetchHooks.ts +9 -4
  89. package/src/hooks/index.ts +3 -0
  90. package/src/hooks/useCheckEngineStatus.ts +30 -0
  91. package/src/hooks/useDataDisplayParams.ts +3 -3
  92. package/src/hooks/useEngineStatusQuery.ts +9 -7
  93. package/src/hooks/useMutateProcess.ts +96 -0
  94. package/src/messages/{en-US.json → en-GB.json} +85 -37
  95. package/src/messages/getTranslationMessages.spec.ts +25 -40
  96. package/src/messages/index.ts +1 -1
  97. package/src/messages/nl-NL.json +95 -48
  98. package/src/messages/useGetTranslationMessages.ts +51 -0
  99. package/src/pages/metadata/WfoProductBlocksPage.tsx +12 -10
  100. package/src/pages/metadata/WfoProductsPage.tsx +24 -25
  101. package/src/pages/metadata/WfoResourceTypesPage.tsx +12 -10
  102. package/src/pages/metadata/WfoWorkflowsPage.tsx +12 -10
  103. package/src/pages/processes/WfoProcessDetail.tsx +96 -79
  104. package/src/pages/processes/WfoProcessDetailPage.tsx +5 -3
  105. package/src/pages/{workflow/WfoStartWorkflowPage.tsx → processes/WfoStartProcessPage.tsx} +102 -51
  106. package/src/pages/processes/index.ts +1 -3
  107. package/src/pages/settings/WfoSettingsPage.tsx +30 -0
  108. package/src/pages/settings/index.ts +1 -0
  109. package/src/pages/tasks/WfoTaskListPage.tsx +35 -9
  110. package/src/pages/{processes/WfoProcessListPage.tsx → workflow/WfoWorkflowListPage.tsx} +22 -23
  111. package/src/pages/workflow/getWorkflowListTabTypeFromString.ts +19 -0
  112. package/src/pages/workflow/index.ts +1 -1
  113. package/src/pages/{processes → workflow}/tabConfig.ts +6 -6
  114. package/src/types/types.ts +33 -3
  115. package/src/utils/getDefaultTableConfig.ts +1 -1
  116. package/src/components/WfoSettingsPage/WfoModifySettings.tsx +0 -33
  117. package/src/components/WfoSettingsPage/WfoSettings.tsx +0 -40
  118. package/src/hooks/ProcessesHooks/useDeleteProcess.ts +0 -37
  119. package/src/messages/getTranslationMessages.ts +0 -26
  120. package/src/pages/processes/getProcessListTabTypeFromString.ts +0 -19
  121. /package/src/components/{WfoSettingsPage → WfoSettings}/index.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestrator-ui/orchestrator-ui-components",
3
- "version": "0.2.6",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "test": "jest",
@@ -9,17 +9,19 @@
9
9
  "lint": "eslint \"src/**/*.ts*\"",
10
10
  "dev": "yarn build -- --watch",
11
11
  "storybook": "storybook dev -p 6006",
12
- "build-storybook": "storybook build",
13
- "reset": "rm -rf node_modules"
12
+ "build-storybook": "storybook build"
14
13
  },
15
14
  "dependencies": {
16
15
  "@graphql-typed-document-node/core": "3.2.0",
17
- "axios": "^0.24.0",
16
+ "axios": "^1.6.2",
18
17
  "invariant": "^2.2.4",
19
18
  "moment": "2.29.4",
20
19
  "moment-timezone": "^0.5.43",
21
- "object-hash": "^2.1.1",
20
+ "object-hash": "^3.0.0",
22
21
  "react-select": "^5.8.0",
22
+ "react-diff-view": "^3.2.0",
23
+ "unidiff": "^1.0.4",
24
+ "prism-themes": "^1.9.0",
23
25
  "scroll-into-view": "^1.16.2",
24
26
  "uniforms": "^3.8.1",
25
27
  "uniforms-bridge-json-schema": "^3.8.1",
@@ -35,8 +37,8 @@
35
37
  "next-auth": "^4.23.1",
36
38
  "next-intl": "2.19.0",
37
39
  "next-query-params": "4.2.2",
38
- "react": "^18.2.0",
39
- "react-query": "3.39.3"
40
+ "react-query": "3.39.3",
41
+ "react": "^18.2.0"
40
42
  },
41
43
  "devDependencies": {
42
44
  "@orchestrator-ui/eslint-config-custom": "*",
@@ -44,20 +46,20 @@
44
46
  "@storybook/addon-essentials": "^7.2.1",
45
47
  "@storybook/addon-interactions": "^7.2.1",
46
48
  "@storybook/addon-links": "^7.2.1",
47
- "@storybook/addon-onboarding": "^1.0.8",
49
+ "@storybook/addon-onboarding": "^1.0.10",
48
50
  "@storybook/blocks": "^7.2.1",
49
51
  "@storybook/nextjs": "^7.2.1",
50
52
  "@storybook/react": "^7.2.1",
51
53
  "@storybook/testing-library": "^0.2.0",
52
- "@testing-library/jest-dom": "^5.16.1",
54
+ "@testing-library/jest-dom": "^6.1.5",
53
55
  "@testing-library/react": "^14.0.0",
54
56
  "@testing-library/react-hooks": "^8.0.1",
55
57
  "@testing-library/user-event": "^14.4.3",
56
58
  "@types/invariant": "^2.2.33",
57
59
  "@types/jest": "^29.5.8",
58
- "@types/object-hash": "^2.1.0",
60
+ "@types/object-hash": "^3.0.6",
59
61
  "@types/scroll-into-view": "^1.16.3",
60
- "esbuild": "^0.14.10",
62
+ "esbuild": "^0.19.9",
61
63
  "esbuild-jest": "^0.5.0",
62
64
  "jest": "^29.7.0",
63
65
  "jest-watch-typeahead": "^2.2.2",
@@ -65,7 +67,7 @@
65
67
  "react": "^18.2.0",
66
68
  "react-dom": "^18.2.0",
67
69
  "storybook": "^7.2.1",
68
- "tsup": "^7.2.0",
70
+ "tsup": "^8.0.1",
69
71
  "uniforms-bridge-simple-schema-2": "^3.8.1"
70
72
  },
71
73
  "type": "module",
package/src/api/index.ts CHANGED
@@ -15,8 +15,10 @@
15
15
  import { AxiosInstance } from 'axios';
16
16
 
17
17
  import {
18
+ ImsPort,
18
19
  IpBlock,
19
20
  IpPrefix,
21
+ NodeSubscription,
20
22
  } from '../components/WfoForms/formFields/surf/types';
21
23
  import { ProductDefinition } from '../types';
22
24
  import { getAxiosInstance } from './axios';
@@ -47,9 +49,6 @@ export class BaseApiClient {
47
49
  .then((res) => res.data)
48
50
  .catch((err) => {
49
51
  if (showErrorDialog) {
50
- console.debug(
51
- `Show error dialog for GET ${path} returning ${err?.response?.status}`,
52
- );
53
52
  setTimeout(() => {
54
53
  throw err;
55
54
  }, 250);
@@ -125,6 +124,17 @@ export class ApiClient extends ApiClientInterface {
125
124
  true,
126
125
  );
127
126
  };
127
+
128
+ resumeProcess = (processId: string, userInput: object[]) => {
129
+ return this.postPutJson(
130
+ `processes/${processId}/resume`,
131
+ userInput,
132
+ 'put',
133
+ false,
134
+ false,
135
+ );
136
+ };
137
+
128
138
  products = (): Promise<ProductDefinition[]> => {
129
139
  return this.fetchJson<ProductDefinition[]>(PRODUCTS_ENDPOINT);
130
140
  };
@@ -163,6 +173,48 @@ export class ApiClient extends ApiClientInterface {
163
173
  prefixlen,
164
174
  );
165
175
  };
176
+ getFreePortsByNodeSubscriptionIdAndSpeed = (
177
+ nodeSubscriptionId: string,
178
+ interfaceSpeed: number,
179
+ mode: string,
180
+ ): Promise<ImsPort[]> => {
181
+ return this.fetchJson(
182
+ `surf/ims/free_ports/${nodeSubscriptionId}/${interfaceSpeed}/${mode}`,
183
+ );
184
+ };
185
+
186
+ // legacy : for imsPort selector
187
+ subscriptions = (
188
+ tagList: string[] = [],
189
+ statusList: string[] = [],
190
+ productList: string[] = [],
191
+ ): Promise<NodeSubscription[]> => {
192
+ const filters = [];
193
+
194
+ if (tagList.length)
195
+ filters.push(`tags,${encodeURIComponent(tagList.join('-'))}`);
196
+ if (statusList.length)
197
+ filters.push(
198
+ `statuses,${encodeURIComponent(statusList.join('-'))}`,
199
+ );
200
+ if (productList.length)
201
+ filters.push(
202
+ `products,${encodeURIComponent(productList.join('-'))}`,
203
+ );
204
+
205
+ const params = new URLSearchParams();
206
+ if (filters.length) params.set('filter', filters.join(','));
207
+
208
+ return this.fetchJson(
209
+ `subscriptions/${filters.length ? '?' : ''}${params.toString()}`,
210
+ );
211
+ };
212
+
213
+ nodeSubscriptions = (
214
+ statusList: string[] = [],
215
+ ): Promise<NodeSubscription[]> => {
216
+ return this.subscriptions(['Node'], statusList);
217
+ };
166
218
  }
167
219
 
168
220
  export function getApiClient(apiEndPoint: string) {
@@ -0,0 +1,119 @@
1
+ import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
2
+ import { Diff, Hunk, parseDiff, tokenize } from 'react-diff-view';
3
+ import 'react-diff-view/style/index.css';
4
+ import { DiffType } from 'react-diff-view/types/Diff';
5
+ import { HunkData } from 'react-diff-view/types/utils/parse';
6
+
7
+ import { useTranslations } from 'next-intl';
8
+ // CSS for syntax highlight
9
+ import 'prism-themes/themes/prism-ghcolors.min.css';
10
+ import * as refractor from 'refractor';
11
+ import { diffLines, formatLines } from 'unidiff';
12
+
13
+ import {
14
+ EuiButtonIcon,
15
+ EuiFlexGroup,
16
+ EuiFlexItem,
17
+ EuiSpacer,
18
+ EuiText,
19
+ } from '@elastic/eui';
20
+
21
+ const EMPTY_HUNKS: never[] = [];
22
+
23
+ const SMALL_CONTEXT = 3;
24
+ const FULL_CONTEXT = 1000000;
25
+
26
+ interface DiffState {
27
+ type: DiffType;
28
+ hunks: HunkData[];
29
+ }
30
+
31
+ interface WfoDiffProps {
32
+ oldText: string;
33
+ newText: string;
34
+ syntax?: 'javascript' | 'python';
35
+ }
36
+
37
+ const WfoDiff: FC<WfoDiffProps> = ({ oldText, newText, syntax }) => {
38
+ const t = useTranslations('processes.delta');
39
+ const [showSplit, setShowSplit] = useState(true);
40
+ const [showFull, setShowFull] = useState(false);
41
+
42
+ const [{ type, hunks }, setDiff] = useState<DiffState>({
43
+ type: 'modify',
44
+ hunks: [],
45
+ });
46
+ const updateDiffText = useCallback(() => {
47
+ const diffText = formatLines(diffLines(oldText, newText), {
48
+ context: showFull ? FULL_CONTEXT : SMALL_CONTEXT,
49
+ });
50
+ const [diff] = parseDiff(diffText, { nearbySequences: 'zip' });
51
+ setDiff(diff);
52
+ }, [oldText, newText, setDiff, showFull]);
53
+
54
+ const tokens = useMemo(() => {
55
+ if (!hunks) {
56
+ return undefined;
57
+ }
58
+
59
+ const options = {
60
+ refractor,
61
+ highlight: !!syntax,
62
+ language: syntax ?? '',
63
+ };
64
+
65
+ try {
66
+ return tokenize(hunks, options);
67
+ } catch (ex) {
68
+ return undefined;
69
+ }
70
+ }, [hunks, syntax]);
71
+
72
+ useEffect(() => {
73
+ updateDiffText();
74
+ }, [updateDiffText, showFull]);
75
+
76
+ return (
77
+ <div>
78
+ <EuiFlexGroup gutterSize={'xs'}>
79
+ <EuiFlexItem grow={false}>
80
+ <EuiText>
81
+ <h3>{t('title')}</h3>
82
+ </EuiText>
83
+ </EuiFlexItem>
84
+ <EuiFlexItem grow={false}>
85
+ <EuiButtonIcon
86
+ size={'s'}
87
+ iconType={
88
+ showSplit
89
+ ? 'continuityAboveBelow'
90
+ : 'continuityWithin'
91
+ }
92
+ onClick={() => setShowSplit(!showSplit)}
93
+ />
94
+ </EuiFlexItem>
95
+ <EuiFlexItem grow={false}>
96
+ <EuiButtonIcon
97
+ size={'s'}
98
+ iconType={showFull ? 'fullScreenExit' : 'fullScreen'}
99
+ onClick={() => setShowFull(!showFull)}
100
+ />
101
+ </EuiFlexItem>
102
+ </EuiFlexGroup>
103
+
104
+ <EuiSpacer />
105
+ <Diff
106
+ viewType={showSplit ? 'split' : 'unified'}
107
+ diffType={type}
108
+ hunks={hunks || EMPTY_HUNKS}
109
+ tokens={tokens}
110
+ >
111
+ {(hunks) =>
112
+ hunks.map((hunk) => <Hunk key={hunk.content} hunk={hunk} />)
113
+ }
114
+ </Diff>
115
+ </div>
116
+ );
117
+ };
118
+
119
+ export default WfoDiff;
@@ -0,0 +1 @@
1
+ export * from './WfoDiff';
@@ -0,0 +1 @@
1
+ declare module 'unidiff';
@@ -8,6 +8,7 @@ import {
8
8
  DateField,
9
9
  DividerField,
10
10
  ImsNodeIdField,
11
+ ImsPortIdField,
11
12
  IpNetworkField,
12
13
  LabelField,
13
14
  ListField,
@@ -22,6 +23,7 @@ import {
22
23
  SelectField,
23
24
  SubscriptionField,
24
25
  SubscriptionSummaryField,
26
+ SummaryField,
25
27
  TextField,
26
28
  TimestampField,
27
29
  VlanField,
@@ -43,7 +45,7 @@ export function autoFieldFunction(
43
45
  case Number:
44
46
  switch (format) {
45
47
  case 'imsPortId': // Surf specific
46
- return NumField;
48
+ return ImsPortIdField;
47
49
  case 'imsNodeId': // Surf specific
48
50
  return ImsNodeIdField;
49
51
  case 'timestamp':
@@ -68,6 +70,8 @@ export function autoFieldFunction(
68
70
  return LabelField;
69
71
  case 'divider':
70
72
  return DividerField;
73
+ case 'summary':
74
+ return SummaryField;
71
75
  case 'subscription':
72
76
  return SubscriptionSummaryField;
73
77
  case 'organisationId':
@@ -34,7 +34,6 @@ export function CreateForm(props: IProps) {
34
34
  const submit = useCallback(
35
35
  (userInputs: object[]) => {
36
36
  return apiClient.cimStartForm(formKey, userInputs).then((form) => {
37
- console.log('Submit {formkey} =', formKey);
38
37
  handleSubmit(form);
39
38
  });
40
39
  },
@@ -64,6 +63,7 @@ export function CreateForm(props: IProps) {
64
63
  validSubmit={submit}
65
64
  cancel={() => alert('cancelled')}
66
65
  hasNext={hasNext ?? false}
66
+ isTask={false}
67
67
  />
68
68
  )}
69
69
  </div>
@@ -34,11 +34,11 @@ import {
34
34
  EuiHorizontalRule,
35
35
  } from '@elastic/eui';
36
36
 
37
- import ConfirmationDialogContext from '../../contexts/ConfirmationDialogProvider';
38
- import { ConfirmDialogActions } from '../../contexts/ConfirmationDialogProvider';
39
- import { useOrchestratorTheme } from '../../hooks';
40
- import { WfoPlayFill } from '../../icons';
41
- import { ValidationError } from '../../types/forms';
37
+ import { ConfirmDialogActions, ConfirmationDialogContext } from '@/contexts';
38
+ import { useOrchestratorTheme } from '@/hooks';
39
+ import { WfoPlayFill } from '@/icons';
40
+ import { ValidationError } from '@/types/forms';
41
+
42
42
  import { autoFieldFunction } from './AutoFieldLoader';
43
43
  import AutoFields from './AutoFields';
44
44
  import { userInputFormStyling } from './UserInputFormStyling';
@@ -52,11 +52,13 @@ interface IProps {
52
52
  router: NextRouter;
53
53
  stepUserInput: JSONSchema6;
54
54
  validSubmit: (userInput: { [index: string]: unknown }) => Promise<unknown>;
55
- cancel: ConfirmDialogActions['closeConfirmDialog'];
55
+ cancel?: ConfirmDialogActions['closeConfirmDialog'];
56
56
  previous: ConfirmDialogActions['closeConfirmDialog'];
57
57
  hasNext?: boolean;
58
58
  hasPrev?: boolean;
59
59
  userInput: object;
60
+ isTask?: boolean;
61
+ isResuming?: boolean;
60
62
  }
61
63
 
62
64
  interface Buttons {
@@ -116,6 +118,18 @@ function resolveRef(reference: string, schema: Record<string, any>) {
116
118
  }
117
119
 
118
120
  class CustomTitleJSONSchemaBridge extends JSONSchemaBridge {
121
+ t: any;
122
+
123
+ constructor(schema: JSONSchema6, validator: any, t: any) {
124
+ super(schema, validator);
125
+ this.t = t;
126
+ }
127
+
128
+ translationKeyExists(key: string): boolean {
129
+ const translation = this.t(key);
130
+ return translation !== key ? true : false;
131
+ }
132
+
119
133
  // This a copy of the super class function to provide a fix for https://github.com/vazco/uniforms/issues/863
120
134
  getField(name: string) {
121
135
  return joinName(null, name).reduce(
@@ -246,12 +260,11 @@ class CustomTitleJSONSchemaBridge extends JSONSchemaBridge {
246
260
  getProps(name: string) {
247
261
  const props = super.getProps(name);
248
262
 
249
- // not translated labels for now
250
- // const translation_key = name.replace(/\.\d+(.\d+)*/, "_fields");
251
- // const translation_intl_key = `forms.fields.${translation_key}`;
252
- // const translation = intl.formatMessage({ id: translation_intl_key, defaultMessage: translation_intl_key });
253
- // let label = translation !== translation_intl_key ? translation : props.label;
254
- let label = props.label;
263
+ const translationKey = name.replace(/\.\d+(.\d+)*/, '_fields'); // This is evaluates to name or name_fields
264
+ const nextIntlKey = `pydanticForms.backendTranslations.${translationKey}`;
265
+ let label = this.translationKeyExists(nextIntlKey)
266
+ ? this.t(nextIntlKey)
267
+ : props.label;
255
268
 
256
269
  // Mark required inputs. Might be delegated to the form components itself in the future.
257
270
  if (
@@ -264,9 +277,11 @@ class CustomTitleJSONSchemaBridge extends JSONSchemaBridge {
264
277
  }
265
278
 
266
279
  props.label = label;
267
- // not translated labels for now
268
- // props.description = intl.formatMessage({ id: `forms.fields.${translation_key}_info`, defaultMessage: " " }); // Default must contain a space as not to be Falsy
269
- props.description = '';
280
+
281
+ const descriptionTranslationKey = `pydanticForms.backendTranslations.${translationKey}_info`;
282
+ props.description = this.translationKeyExists(descriptionTranslationKey)
283
+ ? this.t(descriptionTranslationKey)
284
+ : ' ';
270
285
 
271
286
  props.id = `input-${name}`;
272
287
 
@@ -369,11 +384,13 @@ function UserInputForm({
369
384
  router,
370
385
  stepUserInput,
371
386
  validSubmit,
372
- cancel,
387
+ cancel = () => {},
373
388
  previous = () => {},
374
389
  hasNext = false,
375
390
  hasPrev = false,
376
391
  userInput,
392
+ isTask = false,
393
+ isResuming = false,
377
394
  }: IProps) {
378
395
  const t = useTranslations('pydanticForms.userInputForm');
379
396
  const { theme } = useOrchestratorTheme();
@@ -382,13 +399,17 @@ function UserInputForm({
382
399
  const [nrOfValidationErrors, setNrOfValidationErrors] = useState<number>(0);
383
400
  const [rootErrors, setRootErrors] = useState<string[]>([]);
384
401
 
385
- const openDialog = () => {
386
- showConfirmDialog({
387
- question: '',
388
- confirmAction: () => {},
389
- cancelAction: cancel,
390
- leavePage: true,
391
- });
402
+ const openLeavePageDialog = (
403
+ leaveAction: ConfirmDialogActions['closeConfirmDialog'],
404
+ leaveQuestion?: string,
405
+ ) => {
406
+ return () =>
407
+ showConfirmDialog({
408
+ question: leaveQuestion || '',
409
+ confirmAction: () => {},
410
+ cancelAction: leaveAction,
411
+ leavePage: true,
412
+ });
392
413
  };
393
414
 
394
415
  const submit = async (userInput: any = {}) => {
@@ -448,11 +469,6 @@ function UserInputForm({
448
469
  question: string | undefined,
449
470
  confirm: ConfirmDialogActions['closeConfirmDialog'],
450
471
  ) => {
451
- console.log(e, question, confirm);
452
- alert('TODO: Implement on buttonClick cancel with confirm modal');
453
- // https://github.com/workfloworchestrator/orchestrator-ui/issues/325
454
-
455
- /*
456
472
  if (!question) {
457
473
  return confirm(e);
458
474
  }
@@ -463,7 +479,6 @@ function UserInputForm({
463
479
  cancelAction: () => {},
464
480
  leavePage: false,
465
481
  });
466
- */
467
482
  };
468
483
 
469
484
  const renderButtons = (buttons: Buttons) => {
@@ -473,15 +488,23 @@ function UserInputForm({
473
488
  fill
474
489
  color={buttons.previous.color ?? 'primary'}
475
490
  onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
476
- onButtonClick(e, buttons.previous.dialog, previous);
491
+ onButtonClick(
492
+ e,
493
+ buttons.previous.dialog,
494
+ openLeavePageDialog(previous, t('previousQuestion')),
495
+ );
477
496
  }}
478
497
  >
479
498
  {buttons.previous.text ?? t('previous')}
480
499
  </EuiButton>
481
- ) : (
500
+ ) : !isResuming ? (
482
501
  <div
483
502
  onClick={(e) => {
484
- onButtonClick(e, buttons.previous.dialog, openDialog);
503
+ onButtonClick(
504
+ e,
505
+ buttons.previous.dialog,
506
+ openLeavePageDialog(cancel),
507
+ );
485
508
  }}
486
509
  css={{
487
510
  cursor: 'pointer',
@@ -492,10 +515,19 @@ function UserInputForm({
492
515
  alignItems: 'center',
493
516
  }}
494
517
  >
495
- {buttons.previous.text ?? t('cancelProcess')}
518
+ {buttons.previous.text ?? t('cancel')}
496
519
  </div>
520
+ ) : (
521
+ <div></div>
497
522
  );
498
523
 
524
+ const nextButtonTranslationKey: string = (() => {
525
+ if (isResuming) {
526
+ return isTask ? 'resumeTask' : 'resumeWorkflow';
527
+ }
528
+ return isTask ? 'startTask' : 'startWorkflow';
529
+ })();
530
+
499
531
  const nextButton = hasNext ? (
500
532
  <EuiButton
501
533
  id="button-next-form-submit"
@@ -518,7 +550,7 @@ function UserInputForm({
518
550
  iconType={() => <WfoPlayFill color="#FFF" />}
519
551
  iconSide="right"
520
552
  >
521
- {buttons.next.text ?? t('runProcess')}
553
+ {buttons.next.text ?? t(nextButtonTranslationKey)}
522
554
  </EuiButton>
523
555
  );
524
556
 
@@ -534,9 +566,12 @@ function UserInputForm({
534
566
  );
535
567
  };
536
568
 
537
- //const prefilledForm = fillPreselection(stepUserInput, location.search);
538
569
  const prefilledForm = fillPreselection(stepUserInput, router);
539
- const bridge = new CustomTitleJSONSchemaBridge(prefilledForm, () => {});
570
+ const bridge = new CustomTitleJSONSchemaBridge(
571
+ prefilledForm,
572
+ () => {},
573
+ useTranslations(),
574
+ );
540
575
  const AutoFieldProvider = AutoField.componentDetectorContext.Provider;
541
576
 
542
577
  // Get the Button config from the form default values, or default to empty config
@@ -570,13 +605,10 @@ function UserInputForm({
570
605
  {nrOfValidationErrors > 0 && (
571
606
  <section className="form-errors">
572
607
  <em className="error backend-validation-metadata">
573
- {t(
574
- 'input_fields_have_validation_errors',
575
- {
576
- nrOfValidationErrors:
577
- nrOfValidationErrors,
578
- },
579
- )}
608
+ {t('inputFieldsHaveValidationErrors', {
609
+ nrOfValidationErrors:
610
+ nrOfValidationErrors,
611
+ })}
580
612
  </em>
581
613
  </section>
582
614
  )}
@@ -17,8 +17,9 @@ import React, { useEffect, useState } from 'react';
17
17
  import { useRouter } from 'next/router';
18
18
  import hash from 'object-hash';
19
19
 
20
- import { ConfirmDialogActions } from '../../contexts/ConfirmationDialogProvider';
21
- import { FormNotCompleteResponse, InputForm } from '../../types/forms';
20
+ import { ConfirmDialogActions } from '@/contexts';
21
+ import { FormNotCompleteResponse, InputForm } from '@/types/forms';
22
+
22
23
  import UserInputForm from './UserInputForm';
23
24
  import { useAxiosApiClient } from './useAxiosApiClient';
24
25
 
@@ -30,8 +31,10 @@ interface Form {
30
31
  interface UserInputFormWizardProps {
31
32
  stepUserInput: InputForm;
32
33
  validSubmit: (processInput: object[]) => Promise<unknown>;
33
- cancel: () => void;
34
+ cancel?: () => void;
35
+ isTask: boolean;
34
36
  hasNext?: boolean;
37
+ isResuming?: boolean;
35
38
  }
36
39
 
37
40
  function stop(e: React.SyntheticEvent) {
@@ -41,11 +44,13 @@ function stop(e: React.SyntheticEvent) {
41
44
  }
42
45
  }
43
46
 
44
- function UserInputFormWizard({
47
+ export function UserInputFormWizard({
45
48
  hasNext = false,
46
49
  stepUserInput,
47
50
  validSubmit,
48
51
  cancel,
52
+ isTask,
53
+ isResuming = false,
49
54
  }: UserInputFormWizardProps) {
50
55
  const router = useRouter();
51
56
  const apiClient = useAxiosApiClient();
@@ -113,6 +118,8 @@ function UserInputFormWizard({
113
118
  hasPrev={forms.length > 1}
114
119
  cancel={cancel}
115
120
  userInput={currentUserInput}
121
+ isTask={isTask}
122
+ isResuming={isResuming}
116
123
  />
117
124
  );
118
125
  }
@@ -71,11 +71,13 @@ function Accept({
71
71
  data,
72
72
  ...props
73
73
  }: AcceptFieldProps) {
74
- const t = useTranslations('pydanticForms.widgets');
74
+ const t = useTranslations();
75
75
  const { acceptFieldStyle } = useWithOrchestratorTheme(getStyles);
76
76
 
77
77
  const legacy = !data;
78
- const i18nBaseKey = data ? `forms.fields.${name}_accept` : 'forms.fields';
78
+ const i18nBaseKey = data
79
+ ? `pydanticForms.backendTranslations.${name}_accept`
80
+ : 'pydanticForms.backendTranslations';
79
81
 
80
82
  data = data ?? [
81
83
  [name, 'label', {}],
@@ -111,8 +113,8 @@ function Accept({
111
113
  state.skip
112
114
  ? 'SKIPPED'
113
115
  : state.allChecked
114
- ? 'ACCEPTED'
115
- : 'INCOMPLETE',
116
+ ? 'ACCEPTED'
117
+ : 'INCOMPLETE',
116
118
  );
117
119
 
118
120
  return { ...state };
@@ -128,6 +130,7 @@ function Accept({
128
130
  >
129
131
  {data.map((entry, index) => {
130
132
  const label = t(`${i18nBaseKey}.${entry[0]}`, entry[2]);
133
+
131
134
  switch (entry[1]) {
132
135
  case 'label':
133
136
  return (
@@ -170,7 +173,7 @@ function Accept({
170
173
  key={index}
171
174
  className="euiFormLabel euiFormRow__label warning"
172
175
  >
173
- {label}
176
+ {label}: <br />
174
177
  </label>
175
178
  );
176
179
  case 'skip':
@@ -57,7 +57,7 @@ function Bool({
57
57
  disabled={disabled}
58
58
  id={id}
59
59
  name={name}
60
- label={name}
60
+ label={label}
61
61
  onChange={() =>
62
62
  !disabled && !readOnly && onChange(!value)
63
63
  }