@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
@@ -74,3 +74,19 @@ export const getWorkflowTargetColor = (
74
74
 
75
75
  return theme.colors.body;
76
76
  };
77
+
78
+ export const getWorkflowTargetIconContent = (
79
+ workflowTarget: WorkflowTarget,
80
+ ) => {
81
+ // Data returned from graphql can't always be depended on to be lowercase
82
+ switch (workflowTarget.toLocaleLowerCase()) {
83
+ case WorkflowTarget.CREATE:
84
+ return 'C';
85
+ case WorkflowTarget.SYSTEM:
86
+ return 'T';
87
+ case WorkflowTarget.TERMINATE:
88
+ return 'X';
89
+ default:
90
+ return 'M';
91
+ }
92
+ };
@@ -4,32 +4,29 @@ import { useTranslations } from 'next-intl';
4
4
  import Link from 'next/link';
5
5
  import { useRouter } from 'next/router';
6
6
 
7
- import { EuiFlexItem, Pagination } from '@elastic/eui';
7
+ import { Pagination } from '@elastic/eui';
8
+
9
+ import { WfoSubscriptionStatusBadge } from '@/components';
10
+ import { FilterQuery, WfoDateTime, WfoLoading } from '@/components';
11
+ import { WfoInsyncIcon } from '@/components/WfoInsyncIcon';
12
+ import { getSubscriptionsListGraphQlQuery } from '@/graphqlQueries';
13
+ import { DataDisplayParams, useQueryWithGraphql } from '@/hooks';
14
+ import { SortOrder } from '@/types';
15
+ import {
16
+ getTypedFieldFromObject,
17
+ parseDateToLocaleDateTimeString,
18
+ } from '@/utils';
8
19
 
9
- import { getSubscriptionsListGraphQlQuery } from '../../graphqlQueries/subscriptionsListQuery';
10
- import { DataDisplayParams } from '../../hooks/useDataDisplayParams';
11
- import { useOrchestratorTheme } from '../../hooks/useOrchestratorTheme';
12
- import { useQueryWithGraphql } from '../../hooks/useQueryWithGraphql';
13
- import { WfoPlusCircleFill } from '../../icons';
14
- import { SortOrder } from '../../types';
15
- import { parseDateToLocaleDateTimeString } from '../../utils';
16
- import { getTypedFieldFromObject } from '../../utils/getTypedFieldFromObject';
17
- import { WfoSubscriptionStatusBadge } from '../WfoBadges/WfoSubscriptionStatusBadge';
18
- import { WfoDateTime } from '../WfoDateTime/WfoDateTime';
19
- import { FilterQuery } from '../WfoFilterTabs';
20
- import { WfoInsyncIcon } from '../WfoInsyncIcon/WfoInsyncIcon';
21
- import { WfoLoading } from '../WfoLoading';
22
20
  import {
23
21
  DEFAULT_PAGE_SIZES,
24
22
  SUBSCRIPTIONS_TABLE_LOCAL_STORAGE_KEY,
25
23
  TableColumnKeys,
26
24
  WfoDataSorting,
27
25
  WfoTableColumns,
28
- WfoTableControlColumnConfig,
29
26
  WfoTableWithFilter,
30
27
  getDataSortHandler,
31
- getEsQueryStringHandler,
32
28
  getPageChangeHandler,
29
+ getQueryStringHandler,
33
30
  } from '../WfoTable';
34
31
  import { WfoFirstPartUUID } from '../WfoTable/WfoFirstPartUUID';
35
32
  import { mapSortableAndFilterableValuesToTableColumnConfig } from '../WfoTable/utils/mapSortableAndFilterableValuesToTableColumnConfig';
@@ -38,8 +35,6 @@ import {
38
35
  mapGrapghQlSubscriptionsResultToSubscriptionListItems,
39
36
  } from './mapGrapghQlSubscriptionsResultToSubscriptionListItems';
40
37
 
41
- const FIELD_NAME_INLINE_SUBSCRIPTION_DETAILS = 'inlineSubscriptionDetails';
42
-
43
38
  export type WfoSubscriptionsListProps = {
44
39
  alwaysOnFilters?: FilterQuery<SubscriptionListItem>[];
45
40
  dataDisplayParams: DataDisplayParams<SubscriptionListItem>;
@@ -64,8 +59,6 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
64
59
  const router = useRouter();
65
60
  const t = useTranslations('subscriptions.index');
66
61
 
67
- const { theme } = useOrchestratorTheme();
68
-
69
62
  const tableColumns: WfoTableColumns<SubscriptionListItem> = {
70
63
  subscriptionId: {
71
64
  field: 'subscriptionId',
@@ -127,20 +120,7 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
127
120
  },
128
121
  };
129
122
 
130
- const leadingControlColumns: WfoTableControlColumnConfig<SubscriptionListItem> =
131
- {
132
- inlineSubscriptionDetails: {
133
- field: FIELD_NAME_INLINE_SUBSCRIPTION_DETAILS,
134
- width: '40',
135
- render: () => (
136
- <EuiFlexItem>
137
- <WfoPlusCircleFill color={theme.colors.mediumShade} />
138
- </EuiFlexItem>
139
- ),
140
- },
141
- };
142
-
143
- const { sortBy } = dataDisplayParams;
123
+ const { sortBy, queryString } = dataDisplayParams;
144
124
  const { data, isFetching } = useQueryWithGraphql(
145
125
  getSubscriptionsListGraphQlQuery<SubscriptionListItem>(),
146
126
  {
@@ -148,6 +128,7 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
148
128
  after: dataDisplayParams.pageIndex * dataDisplayParams.pageSize,
149
129
  sortBy,
150
130
  filterBy: alwaysOnFilters,
131
+ query: queryString || undefined,
151
132
  },
152
133
  'subscriptions',
153
134
  );
@@ -177,8 +158,8 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
177
158
 
178
159
  return (
179
160
  <WfoTableWithFilter<SubscriptionListItem>
180
- esQueryString={dataDisplayParams.esQueryString}
181
- onUpdateEsQueryString={getEsQueryStringHandler<SubscriptionListItem>(
161
+ queryString={dataDisplayParams.queryString}
162
+ onUpdateQueryString={getQueryStringHandler<SubscriptionListItem>(
182
163
  setDataDisplayParam,
183
164
  )}
184
165
  data={mapGrapghQlSubscriptionsResultToSubscriptionListItems(data)}
@@ -187,7 +168,6 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
187
168
  sortFields,
188
169
  filterFields,
189
170
  )}
190
- leadingControlColumns={leadingControlColumns}
191
171
  defaultHiddenColumns={hiddenColumns}
192
172
  dataSorting={dataSorting}
193
173
  pagination={pagination}
@@ -1,5 +1,7 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
 
3
+ import { useTranslations } from 'next-intl';
4
+
3
5
  import {
4
6
  Criteria,
5
7
  EuiButton,
@@ -39,6 +41,7 @@ import {
39
41
  clearTableConfigFromLocalStorage,
40
42
  setTableConfigToLocalStorage,
41
43
  } from '../utils/tableConfigPersistence';
44
+ import { updateQueryString } from './updateQueryString';
42
45
 
43
46
  export type WfoTableWithFilterProps<T> = {
44
47
  data: T[];
@@ -48,12 +51,12 @@ export type WfoTableWithFilterProps<T> = {
48
51
  defaultHiddenColumns?: TableColumnKeys<T>;
49
52
  dataSorting: WfoDataSorting<T>;
50
53
  pagination: Pagination;
51
- esQueryString?: string;
54
+ queryString?: string;
52
55
  isLoading: boolean;
53
56
  localStorageKey: string;
54
57
  detailModal?: boolean;
55
58
  detailModalTitle?: string;
56
- onUpdateEsQueryString: (esQueryString: string) => void;
59
+ onUpdateQueryString: (queryString: string) => void;
57
60
  onUpdatePage: (criterion: Criteria<T>['page']) => void;
58
61
  onUpdateDataSort: (dataSorting: WfoDataSorting<T>) => void;
59
62
  };
@@ -66,12 +69,12 @@ export const WfoTableWithFilter = <T,>({
66
69
  defaultHiddenColumns = [],
67
70
  dataSorting,
68
71
  pagination,
69
- esQueryString,
72
+ queryString,
70
73
  isLoading,
71
74
  localStorageKey,
72
75
  detailModal = true,
73
76
  detailModalTitle = 'Details',
74
- onUpdateEsQueryString,
77
+ onUpdateQueryString,
75
78
  onUpdatePage,
76
79
  onUpdateDataSort,
77
80
  }: WfoTableWithFilterProps<T>) => {
@@ -83,6 +86,7 @@ export const WfoTableWithFilter = <T,>({
83
86
  const [showSettingsModal, setShowSettingsModal] = useState(false);
84
87
  const [selectedDataForDetailModal, setSelectedDataForDetailModal] =
85
88
  useState<T | undefined>(undefined);
89
+ const t = useTranslations('common');
86
90
 
87
91
  useEffect(() => {
88
92
  if (defaultHiddenColumns) {
@@ -189,12 +193,12 @@ export const WfoTableWithFilter = <T,>({
189
193
  <EuiFlexGroup>
190
194
  <EuiFlexItem>
191
195
  <WfoSearchField
192
- esQueryString={esQueryString}
193
- onUpdateEsQueryString={onUpdateEsQueryString}
196
+ queryString={queryString}
197
+ onUpdateQueryString={onUpdateQueryString}
194
198
  />
195
199
  </EuiFlexItem>
196
200
  <EuiButton onClick={() => setShowSettingsModal(true)}>
197
- Edit columns
201
+ {t('editColumns')}
198
202
  </EuiButton>
199
203
  </EuiFlexGroup>
200
204
  <EuiSpacer size="m" />
@@ -207,18 +211,15 @@ export const WfoTableWithFilter = <T,>({
207
211
  pagination={pagination}
208
212
  isLoading={isLoading}
209
213
  onCriteriaChange={onCriteriaChange}
210
- onDataSearch={({ field, searchText }) => {
211
- // Todo: This is not the final implementation. Need to decide to use esquery in the frontend.
212
- // In that case, string concatenation is not the best solution
213
- // https://github.com/workfloworchestrator/orchestrator-ui/issues/81
214
- onUpdateEsQueryString(
215
- esQueryString
216
- ? esQueryString +
217
- ' AND ' +
218
- `${field.toString()}:"${searchText}"`
219
- : `${field.toString()}:"${searchText}"`,
220
- );
221
- }}
214
+ onDataSearch={({ field, searchText }) =>
215
+ onUpdateQueryString(
216
+ updateQueryString(
217
+ queryString ?? '',
218
+ field.toString(),
219
+ searchText,
220
+ ),
221
+ )
222
+ }
222
223
  />
223
224
 
224
225
  {showSettingsModal && (
@@ -0,0 +1,95 @@
1
+ import { updateQueryString } from './updateQueryString';
2
+
3
+ describe('updateQueryString', () => {
4
+ it('adds a new field when the query string is empty', () => {
5
+ const queryString = '';
6
+ const fieldName = 'field1';
7
+ const value = 'value1';
8
+
9
+ const result = updateQueryString(queryString, fieldName, value);
10
+
11
+ expect(result).toBe('field1:value1');
12
+ });
13
+
14
+ it('adds a new field when the query string does not contain the field yet', () => {
15
+ const queryString = 'field1:value1';
16
+ const fieldName = 'field2';
17
+ const value = 'value2';
18
+
19
+ const result = updateQueryString(queryString, fieldName, value);
20
+
21
+ expect(result).toBe('field1:value1 field2:value2');
22
+ });
23
+
24
+ it('updates an existing field with a single value in the query string', () => {
25
+ const queryString = 'field1:value1 field2:value2';
26
+ const fieldName = 'field1';
27
+ const value = 'value3';
28
+
29
+ const result = updateQueryString(queryString, fieldName, value);
30
+
31
+ expect(result).toBe('field1:(value1|value3) field2:value2');
32
+ });
33
+
34
+ it('updates an existing field with with already 2 values in the query string', () => {
35
+ const queryString = 'field1:(value1|value3) field2:value2';
36
+ const fieldName = 'field1';
37
+ const value = 'value4';
38
+
39
+ const result = updateQueryString(queryString, fieldName, value);
40
+
41
+ expect(result).toBe('field1:(value1|value3|value4) field2:value2');
42
+ });
43
+
44
+ it('uses quotes when the added value contains spaces', () => {
45
+ const queryString = 'field1:(value1|value3) field2:value2';
46
+ const fieldName = 'field1';
47
+ const value = 'value 4';
48
+
49
+ const result = updateQueryString(queryString, fieldName, value);
50
+
51
+ expect(result).toBe('field1:(value1|value3|"value 4") field2:value2');
52
+ });
53
+
54
+ it('adds a new value to an exising field where one existing value contains spaces', () => {
55
+ const queryString = 'field1:("value 1"|value3) field2:value2';
56
+ const fieldName = 'field1';
57
+ const value = 'value 4';
58
+
59
+ const result = updateQueryString(queryString, fieldName, value);
60
+
61
+ expect(result).toBe(
62
+ 'field1:("value 1"|value3|"value 4") field2:value2',
63
+ );
64
+ });
65
+
66
+ it('returns the same query string when the given field name is an empty string', () => {
67
+ const queryString = 'field1:value1 field2:value2';
68
+ const fieldName = 'field1';
69
+ const value = '';
70
+
71
+ const result = updateQueryString(queryString, fieldName, value);
72
+
73
+ expect(result).toBe('field1:value1 field2:value2');
74
+ });
75
+
76
+ it('returns the same query string when the given value is an empty string', () => {
77
+ const queryString = 'field1:value1 field2:value2';
78
+ const fieldName = '';
79
+ const value = 'value 3';
80
+
81
+ const result = updateQueryString(queryString, fieldName, value);
82
+
83
+ expect(result).toBe('field1:value1 field2:value2');
84
+ });
85
+
86
+ it('updates an existing field ignoring case in the field name', () => {
87
+ const queryString = 'field1:value1 field2:value2';
88
+ const fieldName = 'Field1';
89
+ const value = 'value3';
90
+
91
+ const result = updateQueryString(queryString, fieldName, value);
92
+
93
+ expect(result).toBe('field1:(value1|value3) field2:value2');
94
+ });
95
+ });
@@ -0,0 +1,60 @@
1
+ // Four cases to consider when this function is called
2
+ // 1 - fieldName or value is empty
3
+ // 2 - queryString is empty
4
+ // 3 - fieldName does not exist in query string
5
+ // 4 - fieldName already exists in query string
6
+ export const updateQueryString = (
7
+ queryString: string,
8
+ fieldName: string,
9
+ value: string,
10
+ ) => {
11
+ // 1 - Returning the exising query string when either fieldName or value is empty
12
+ if (fieldName === '' || value === '') {
13
+ return queryString;
14
+ }
15
+
16
+ // 2 - Empty query string returning directly fieldName:value
17
+ if (queryString === '') {
18
+ return `${fieldName}:${toQueryValue(value)}`;
19
+ }
20
+
21
+ // Finding fieldName with values in queryString in this order:
22
+ // - Value surrounded with double quotes
23
+ // field:"value"
24
+ // - Value is surrounded with brackets
25
+ // field:(value1|value2)
26
+ // field:("value1 with spaces"|value2|value3)
27
+ // - Value is a single word (no quotes and no brackets)
28
+ // field:value
29
+ const fieldRegex = new RegExp(
30
+ String.raw`(${fieldName}):(".*?"|\(.*?\)|[^()|!:<>*"\s]+\*?)`,
31
+ 'i',
32
+ );
33
+ const match = queryString.match(fieldRegex);
34
+
35
+ // 3 - Field name does not exist in query string yet, appending fieldName:value
36
+ if (!match) {
37
+ return `${queryString} ${fieldName}:${toQueryValue(value)}`;
38
+ }
39
+
40
+ // 4 - Field name already exists in query string as:
41
+ const existingFieldName = match[1];
42
+ const existingValue = getValueWithoutBrackets(match[2]);
43
+ const updatedValue = `${existingValue}|${toQueryValue(value)}`;
44
+ return queryString.replace(
45
+ fieldRegex,
46
+ `${existingFieldName}:(${updatedValue})`,
47
+ );
48
+ };
49
+
50
+ const getValueWithoutBrackets = (value: string) => {
51
+ if (value.startsWith('(') && value.endsWith(')')) {
52
+ return value.slice(1, -1);
53
+ }
54
+ return value;
55
+ };
56
+
57
+ const hasSpaces = (value: string) => value.indexOf(' ') !== -1;
58
+
59
+ const toQueryValue = (value: string) =>
60
+ hasSpaces(value) ? `"${value}"` : value;
@@ -44,10 +44,10 @@ export const getPageChangeHandler =
44
44
  }
45
45
  };
46
46
 
47
- export const getEsQueryStringHandler =
47
+ export const getQueryStringHandler =
48
48
  <Type>(
49
49
  setDataDisplayParam: DataDisplayReturnValues<Type>['setDataDisplayParam'],
50
50
  ) =>
51
- (esQueryString: string) => {
52
- setDataDisplayParam('esQueryString', esQueryString);
51
+ (queryString: string) => {
52
+ setDataDisplayParam('queryString', queryString);
53
53
  };
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+
3
+ import type { Meta } from '@storybook/react';
4
+
5
+ import { WfoTextAnchor } from './WfoTextAnchor';
6
+
7
+ const Story: Meta<typeof WfoTextAnchor> = {
8
+ component: ({ text, url }) => <WfoTextAnchor text={text} url={url} />,
9
+ title: 'Text/WfoTextAnchor',
10
+ };
11
+ export default Story;
12
+
13
+ export const Primary = {
14
+ args: {
15
+ text: 'Text',
16
+ url: 'Url',
17
+ },
18
+ };
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+
3
+ import { EuiText } from '@elastic/eui';
4
+
5
+ import { useWithOrchestratorTheme } from '@/hooks';
6
+
7
+ import { getStyles } from './styles';
8
+
9
+ interface WfoTextAnchorProps {
10
+ text: string;
11
+ onClick: () => void;
12
+ }
13
+
14
+ export const WfoTextAnchor = ({ text, onClick }: WfoTextAnchorProps) => {
15
+ const { textAnchorStyle } = useWithOrchestratorTheme(getStyles);
16
+
17
+ return (
18
+ <EuiText onClick={onClick} css={textAnchorStyle}>
19
+ {text}
20
+ </EuiText>
21
+ );
22
+ };
@@ -0,0 +1 @@
1
+ export { WfoTextAnchor } from './WfoTextAnchor';
@@ -0,0 +1,17 @@
1
+ import { EuiThemeComputed } from '@elastic/eui/src/services/theme/types';
2
+ import { css } from '@emotion/react';
3
+
4
+ export const getStyles = (theme: EuiThemeComputed) => {
5
+ const textAnchorStyle = css({
6
+ marginTop: theme.size.xxs,
7
+ marginLeft: 0,
8
+ fontSize: theme.size.m,
9
+ fontWeight: theme.font.weight.bold,
10
+ color: theme.colors.link,
11
+ cursor: 'pointer',
12
+ });
13
+
14
+ return {
15
+ textAnchorStyle,
16
+ };
17
+ };
@@ -1,4 +1,3 @@
1
- import { makeHighContrastColor } from '@elastic/eui';
2
1
  import { EuiThemeComputed } from '@elastic/eui/src/services/theme/types';
3
2
  import { css } from '@emotion/react';
4
3
 
@@ -29,6 +28,15 @@ export const getStyles = (theme: EuiThemeComputed) => {
29
28
  }
30
29
  };
31
30
 
31
+ const getTextColorForStepStatusIcon = (processStepStatus: StepStatus) => {
32
+ switch (processStepStatus) {
33
+ case StepStatus.SUSPEND:
34
+ return theme.colors.ink;
35
+ default:
36
+ return theme.colors.ghost;
37
+ }
38
+ };
39
+
32
40
  const timelinePanelStyle = css({
33
41
  backgroundColor: theme.colors.body,
34
42
  borderRadius: theme.border.radius.medium,
@@ -133,9 +141,7 @@ export const getStyles = (theme: EuiThemeComputed) => {
133
141
  display: 'flex',
134
142
  alignItems: 'center',
135
143
  justifyContent: 'center',
136
- color: makeHighContrastColor(theme.colors.text)(
137
- getColorForStepStatus(stepStatus),
138
- ),
144
+ color: getTextColorForStepStatusIcon(stepStatus),
139
145
  });
140
146
  };
141
147
 
@@ -4,40 +4,44 @@ import { useTranslations } from 'next-intl';
4
4
 
5
5
  import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui';
6
6
 
7
- import { useOrchestratorTheme } from '../../../hooks';
8
- import { WfoChevronDown, WfoChevronUp } from '../../../icons';
9
- import type { EmailState, Step, StepState } from '../../../types';
10
- import { formatDate } from '../../../utils';
11
- import { calculateTimeDifference } from '../../../utils';
12
- import { WfoJsonCodeBlock } from '../../WfoJsonCodeBlock/WfoJsonCodeBlock';
7
+ import { WfoJsonCodeBlock } from '@/components';
8
+ import { useOrchestratorTheme } from '@/hooks';
9
+ import { WfoChevronDown, WfoChevronUp } from '@/icons';
10
+ import type { EmailState } from '@/types';
11
+ import { StepStatus } from '@/types';
12
+ import { calculateTimeDifference, formatDate } from '@/utils';
13
+
13
14
  import { WfoStepStatusIcon } from '../WfoStepStatusIcon';
15
+ import type { StepListItem } from '../WfoWorkflowStepList';
14
16
  import { getStepContent } from '../stepListUtils';
15
17
  import { getStyles } from '../styles';
18
+ import { WfoStepForm } from './WfoStepForm';
16
19
 
17
20
  export interface WfoStepProps {
18
- step: Step;
19
- stepDelta: StepState;
20
- stepDetailIsOpen: boolean;
21
+ stepListItem: StepListItem;
21
22
  startedAt: string;
22
23
  showHiddenKeys: boolean;
23
24
  onToggleStepDetail: () => void;
25
+ isTask: boolean;
24
26
  isStartStep?: boolean;
27
+ processId?: string;
25
28
  }
26
29
 
27
30
  export const WfoStep = React.forwardRef(
28
31
  (
29
32
  {
30
- step,
31
- stepDelta,
32
- stepDetailIsOpen,
33
+ stepListItem,
33
34
  onToggleStepDetail,
34
35
  startedAt,
35
36
  showHiddenKeys,
36
37
  isStartStep = false,
38
+ isTask,
39
+ processId,
37
40
  }: WfoStepProps,
38
41
  ref: LegacyRef<HTMLDivElement>,
39
42
  ) => {
40
- const { name, executed, status } = step;
43
+ const { isExpanded, step, userInputForm } = stepListItem;
44
+
41
45
  const { theme } = useOrchestratorTheme();
42
46
  const {
43
47
  stepEmailContainerStyle,
@@ -49,9 +53,12 @@ export const WfoStep = React.forwardRef(
49
53
  getStepToggleExpandStyle,
50
54
  } = getStyles(theme);
51
55
  const t = useTranslations('processes.steps');
52
- const hasHtmlMail = stepDelta?.hasOwnProperty('confirmation_mail');
56
+ const hasHtmlMail =
57
+ step.stateDelta?.hasOwnProperty('confirmation_mail');
53
58
 
54
- const stepContent = getStepContent(stepDelta, showHiddenKeys);
59
+ const stepContent = step.stateDelta
60
+ ? getStepContent(step.stateDelta, showHiddenKeys)
61
+ : {};
55
62
  const hasStepContent = Object.keys(stepContent).length > 0;
56
63
 
57
64
  const displayMailConfirmation = (value: EmailState) => {
@@ -103,17 +110,18 @@ export const WfoStep = React.forwardRef(
103
110
  onClick={() => hasStepContent && onToggleStepDetail()}
104
111
  >
105
112
  <WfoStepStatusIcon
106
- stepStatus={status}
113
+ stepStatus={step.status}
107
114
  isStartStep={isStartStep}
108
115
  />
109
116
 
110
117
  <EuiFlexItem grow={0}>
111
118
  <EuiText css={stepListContentBoldTextStyle}>
112
- {name}
119
+ {step.name}
113
120
  </EuiText>
114
121
  <EuiText>
115
- {status}{' '}
116
- {executed && `- ${formatDate(executed)}`}
122
+ {step.status}{' '}
123
+ {step.executed &&
124
+ `- ${formatDate(step.executed)}`}
117
125
  </EuiText>
118
126
  </EuiFlexItem>
119
127
 
@@ -140,24 +148,31 @@ export const WfoStep = React.forwardRef(
140
148
  hasStepContent,
141
149
  )}
142
150
  >
143
- {(stepDetailIsOpen && (
144
- <WfoChevronUp />
145
- )) || <WfoChevronDown />}
151
+ {(isExpanded && <WfoChevronUp />) || (
152
+ <WfoChevronDown />
153
+ )}
146
154
  </EuiFlexItem>
147
155
  </>
148
156
  )}
149
157
  </EuiFlexGroup>
150
158
  </EuiFlexGroup>
151
- {hasStepContent && stepDetailIsOpen && (
159
+ {hasStepContent && isExpanded && (
152
160
  <WfoJsonCodeBlock data={stepContent} />
153
161
  )}
154
- {stepDetailIsOpen && hasHtmlMail && (
162
+ {isExpanded && hasHtmlMail && (
155
163
  <div css={stepEmailContainerStyle}>
156
164
  {displayMailConfirmation(
157
165
  step.state.confirmation_mail as EmailState,
158
166
  )}
159
167
  </div>
160
168
  )}
169
+ {step.status === StepStatus.SUSPEND && userInputForm && (
170
+ <WfoStepForm
171
+ userInputForm={userInputForm}
172
+ isTask={isTask}
173
+ processId={processId}
174
+ />
175
+ )}
161
176
  </EuiPanel>
162
177
  </div>
163
178
  );
@@ -0,0 +1,48 @@
1
+ import React, { useState } from 'react';
2
+
3
+ import { EuiFlexItem } from '@elastic/eui';
4
+
5
+ import { UserInputFormWizard, WfoLoading } from '@/components';
6
+ import { useAxiosApiClient } from '@/components/WfoForms/useAxiosApiClient';
7
+ import { useOrchestratorTheme } from '@/hooks';
8
+ import { InputForm } from '@/types/forms';
9
+
10
+ interface WfoStepFormProps {
11
+ userInputForm: InputForm;
12
+ isTask: boolean;
13
+ processId?: string;
14
+ }
15
+
16
+ export const WfoStepForm = ({
17
+ userInputForm,
18
+ isTask,
19
+ processId,
20
+ }: WfoStepFormProps) => {
21
+ const [isProcessing, setIsProcessing] = useState<boolean>(false);
22
+ const { theme } = useOrchestratorTheme();
23
+ const apiClient = useAxiosApiClient();
24
+
25
+ const submitForm = (processInput: object[]) => {
26
+ if (!processId) {
27
+ return Promise.reject();
28
+ }
29
+
30
+ return apiClient.resumeProcess(processId, processInput).then(() => {
31
+ setIsProcessing(true);
32
+ });
33
+ };
34
+
35
+ return (
36
+ <EuiFlexItem css={{ margin: theme.size.m }}>
37
+ {(isProcessing && <WfoLoading />) || (
38
+ <UserInputFormWizard
39
+ stepUserInput={userInputForm}
40
+ validSubmit={submitForm}
41
+ hasNext={false}
42
+ isTask={isTask}
43
+ isResuming={true}
44
+ />
45
+ )}
46
+ </EuiFlexItem>
47
+ );
48
+ };