@orchestrator-ui/orchestrator-ui-components 1.5.0 → 1.6.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 (45) hide show
  1. package/.turbo/turbo-build.log +5 -5
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/.turbo/turbo-test.log +9 -8
  4. package/CHANGELOG.md +21 -0
  5. package/dist/index.d.ts +1218 -1137
  6. package/dist/index.js +1166 -976
  7. package/package.json +1 -1
  8. package/src/components/WfoBadges/WfoProductBlockBadge/WfoProductBlockBadge.tsx +1 -0
  9. package/src/components/WfoForms/formFields/utils.spec.ts +1 -0
  10. package/src/components/WfoJsonCodeBlock/WfoJsonCodeBlock.tsx +11 -5
  11. package/src/components/WfoJsonCodeBlock/styles.ts +13 -0
  12. package/src/components/WfoKeyValueTable/WfoValueCell.tsx +8 -1
  13. package/src/components/WfoProcessList/WfoProcessesList.tsx +5 -1
  14. package/src/components/WfoProcessList/processListObjectMappers.ts +7 -4
  15. package/src/components/WfoSubscription/WfoSubscription.tsx +5 -5
  16. package/src/components/WfoSubscription/WfoSubscriptionGeneral.tsx +74 -62
  17. package/src/components/WfoSubscription/WfoSubscriptionProductBlock.tsx +24 -5
  18. package/src/components/WfoSubscriptionsList/WfoSubscriptionsList.tsx +11 -1
  19. package/src/components/WfoSubscriptionsList/subscriptionResultMappers.ts +3 -0
  20. package/src/components/WfoTable/WfoInlineJson/WfoInlineJson.tsx +14 -0
  21. package/src/components/WfoTable/WfoInlineJson/index.ts +1 -0
  22. package/src/components/WfoTable/index.ts +1 -0
  23. package/src/components/WfoTable/utils/constants.ts +2 -2
  24. package/src/components/WfoWorkflowSteps/WfoStepStatusIcon/WfoStepStatusIcon.tsx +7 -0
  25. package/src/components/index.ts +1 -0
  26. package/src/icons/WfoExternalLink.tsx +30 -0
  27. package/src/icons/index.ts +1 -0
  28. package/src/messages/en-GB.json +3 -0
  29. package/src/messages/nl-NL.json +2 -0
  30. package/src/pages/metadata/WfoMetadataPageLayout.tsx +4 -4
  31. package/src/pages/metadata/WfoProductBlocksPage.tsx +25 -1
  32. package/src/pages/metadata/WfoProductsPage.tsx +32 -1
  33. package/src/pages/metadata/WfoResourceTypesPage.tsx +23 -4
  34. package/src/pages/metadata/WfoWorkflowsPage.tsx +24 -2
  35. package/src/pages/metadata/index.ts +2 -0
  36. package/src/pages/subscriptions/WfoSubscriptionDetailPage.tsx +2 -2
  37. package/src/pages/subscriptions/WfoSubscriptionsListPage.tsx +1 -1
  38. package/src/pages/workflows/index.ts +2 -0
  39. package/src/rtk/endpoints/subscriptionDetail.ts +1 -0
  40. package/src/rtk/endpoints/subscriptionList.ts +1 -0
  41. package/src/types/types.ts +5 -2
  42. package/src/utils/getDefaultTableConfig.ts +1 -0
  43. package/src/utils/index.ts +1 -0
  44. package/src/utils/resultFlattener.spec.ts +51 -0
  45. package/src/utils/resultFlattener.ts +25 -0
@@ -28,6 +28,7 @@ import {
28
28
  useStoredTableConfig,
29
29
  } from '@/hooks';
30
30
  import { useGetProductBlocksQuery, useLazyGetProductBlocksQuery } from '@/rtk';
31
+ import type { ProductBlocksResponse } from '@/rtk';
31
32
  import {
32
33
  BadgeType,
33
34
  GraphqlQueryVariables,
@@ -36,6 +37,7 @@ import {
36
37
  } from '@/types';
37
38
  import {
38
39
  csvDownloadHandler,
40
+ getConcatenatedResult,
39
41
  getCsvFileNameWithDate,
40
42
  getQueryVariablesForExport,
41
43
  parseDateToLocaleDateTimeString,
@@ -59,6 +61,14 @@ const PRODUCT_BLOCK_FIELD_RESOURCE_TYPES: keyof ProductBlockDefinition =
59
61
  const PRODUCT_BLOCK_FIELD_PRODUCT_BLOCKS: keyof ProductBlockDefinition =
60
62
  'dependsOn';
61
63
 
64
+ type ProductBlockDefinitionExportItem = Omit<
65
+ ProductBlockDefinition,
66
+ 'resourceTypes' | 'dependsOn'
67
+ > & {
68
+ resourceTypes: string;
69
+ dependsOn: string;
70
+ };
71
+
62
72
  export const WfoProductBlocksPage = () => {
63
73
  const t = useTranslations('metadata.productBlocks');
64
74
  const tError = useTranslations('errors');
@@ -218,6 +228,20 @@ export const WfoProductBlocksPage = () => {
218
228
  totalItemCount: totalItems ? totalItems : 0,
219
229
  };
220
230
 
231
+ const mapToExportItems = (
232
+ productBlocksResponse: ProductBlocksResponse,
233
+ ): ProductBlockDefinitionExportItem[] => {
234
+ const { productBlocks } = productBlocksResponse;
235
+ return productBlocks.map((productBlock) => ({
236
+ ...productBlock,
237
+ resourceTypes: getConcatenatedResult(productBlock.resourceTypes, [
238
+ 'resourceType',
239
+ 'description',
240
+ ]),
241
+ dependsOn: getConcatenatedResult(productBlock.dependsOn, ['name']),
242
+ }));
243
+ };
244
+
221
245
  return (
222
246
  <WfoMetadataPageLayout>
223
247
  <WfoTableWithFilter<ProductBlockDefinition>
@@ -247,7 +271,7 @@ export const WfoProductBlocksPage = () => {
247
271
  }
248
272
  onExportData={csvDownloadHandler(
249
273
  getProductBlocksForExport,
250
- (data) => data.productBlocks,
274
+ mapToExportItems,
251
275
  (data) => data.pageInfo,
252
276
  Object.keys(tableColumns),
253
277
  getCsvFileNameWithDate('ProductBlocks'),
@@ -26,9 +26,11 @@ import {
26
26
  useStoredTableConfig,
27
27
  } from '@/hooks';
28
28
  import { useGetProductsQuery, useLazyGetProductsQuery } from '@/rtk';
29
+ import { ProductsResponse } from '@/rtk';
29
30
  import type { GraphqlQueryVariables, ProductDefinition } from '@/types';
30
31
  import { BadgeType, SortOrder } from '@/types';
31
32
  import {
33
+ getConcatenatedResult,
32
34
  getQueryVariablesForExport,
33
35
  parseDateToLocaleDateTimeString,
34
36
  parseIsoString,
@@ -50,6 +52,14 @@ const PRODUCT_FIELD_PRODUCT_BLOCKS: keyof ProductDefinition = 'productBlocks';
50
52
  const PRODUCT_FIELD_FIXED_INPUTS: keyof ProductDefinition = 'fixedInputs';
51
53
  const PRODUCT_FIELD_CREATED_AT: keyof ProductDefinition = 'createdAt';
52
54
 
55
+ type ProductDefinitionExportItem = Omit<
56
+ ProductDefinition,
57
+ 'fixedInputs' | 'productBlocks'
58
+ > & {
59
+ fixedInputs: string;
60
+ productBlocks: string;
61
+ };
62
+
53
63
  export const WfoProductsPage = () => {
54
64
  const t = useTranslations('metadata.products');
55
65
  const tError = useTranslations('errors');
@@ -94,6 +104,11 @@ export const WfoProductsPage = () => {
94
104
  field: PRODUCT_FIELD_NAME,
95
105
  name: t('name'),
96
106
  width: '200',
107
+ render: (name) => (
108
+ <WfoProductBlockBadge badgeType={BadgeType.PRODUCT}>
109
+ {name}
110
+ </WfoProductBlockBadge>
111
+ ),
97
112
  },
98
113
  tag: {
99
114
  field: PRODUCT_FIELD_TAG,
@@ -192,6 +207,22 @@ export const WfoProductsPage = () => {
192
207
  sortOrder: sortBy?.order ?? SortOrder.ASC,
193
208
  };
194
209
 
210
+ const mapToExportItems = (
211
+ productsResponse: ProductsResponse,
212
+ ): ProductDefinitionExportItem[] => {
213
+ const { products } = productsResponse;
214
+ return products.map((product) => ({
215
+ ...product,
216
+ fixedInputs: getConcatenatedResult(product.fixedInputs, [
217
+ 'name',
218
+ 'value',
219
+ ]),
220
+ productBlocks: getConcatenatedResult(product.productBlocks, [
221
+ 'name',
222
+ ]),
223
+ }));
224
+ };
225
+
195
226
  return (
196
227
  <WfoMetadataPageLayout>
197
228
  <WfoTableWithFilter<ProductDefinition>
@@ -219,7 +250,7 @@ export const WfoProductsPage = () => {
219
250
  localStorageKey={METADATA_PRODUCT_TABLE_LOCAL_STORAGE_KEY}
220
251
  onExportData={csvDownloadHandler(
221
252
  getProductsForExport,
222
- (data) => data?.products ?? [],
253
+ mapToExportItems,
223
254
  (data) => data?.pageInfo || {},
224
255
  Object.keys(tableColumns),
225
256
  getCsvFileNameWithDate('Products'),
@@ -25,14 +25,18 @@ import {
25
25
  useShowToastMessage,
26
26
  useStoredTableConfig,
27
27
  } from '@/hooks';
28
- import { useGetResourceTypesQuery, useLazyGetResourceTypesQuery } from '@/rtk';
28
+ import {
29
+ ResourceTypesResponse,
30
+ useGetResourceTypesQuery,
31
+ useLazyGetResourceTypesQuery,
32
+ } from '@/rtk';
29
33
  import {
30
34
  BadgeType,
31
35
  GraphqlQueryVariables,
32
36
  ResourceTypeDefinition,
33
37
  SortOrder,
34
38
  } from '@/types';
35
- import { getQueryVariablesForExport } from '@/utils';
39
+ import { getConcatenatedResult, getQueryVariablesForExport } from '@/utils';
36
40
  import {
37
41
  csvDownloadHandler,
38
42
  getCsvFileNameWithDate,
@@ -51,6 +55,10 @@ export const RESOURCE_TYPE_FIELD_DESCRIPTION: keyof ResourceTypeDefinition =
51
55
  export const RESOURCE_TYPE_FIELD_PRODUCT_BLOCKS: keyof ResourceTypeDefinition =
52
56
  'productBlocks';
53
57
 
58
+ type ResourceTypeExportItem = Omit<ResourceTypeDefinition, 'productBlocks'> & {
59
+ productBlocks: string;
60
+ };
61
+
54
62
  export const WfoResourceTypesPage = () => {
55
63
  const t = useTranslations('metadata.resourceTypes');
56
64
  const tError = useTranslations('errors');
@@ -168,7 +176,18 @@ export const WfoResourceTypesPage = () => {
168
176
  pageSizeOptions: DEFAULT_PAGE_SIZES,
169
177
  totalItemCount: totalItems ? totalItems : 0,
170
178
  };
171
-
179
+ const mapToExportItems = (
180
+ resourceTypesResponse: ResourceTypesResponse,
181
+ ): ResourceTypeExportItem[] => {
182
+ const { resourceTypes } = resourceTypesResponse;
183
+ return resourceTypes.map((resourceType) => ({
184
+ ...resourceType,
185
+ productBlocks: getConcatenatedResult(resourceType.productBlocks, [
186
+ 'productBlockId',
187
+ 'name',
188
+ ]),
189
+ }));
190
+ };
172
191
  return (
173
192
  <WfoMetadataPageLayout>
174
193
  <WfoTableWithFilter<ResourceTypeDefinition>
@@ -198,7 +217,7 @@ export const WfoResourceTypesPage = () => {
198
217
  }
199
218
  onExportData={csvDownloadHandler(
200
219
  getResourceTypesForExport,
201
- (data) => data.resourceTypes,
220
+ mapToExportItems,
202
221
  (data) => data.pageInfo,
203
222
  Object.keys(tableColumns),
204
223
  getCsvFileNameWithDate('ResourceTypes'),
@@ -24,10 +24,15 @@ import {
24
24
  useShowToastMessage,
25
25
  useStoredTableConfig,
26
26
  } from '@/hooks';
27
- import { useGetWorkflowsQuery, useLazyGetWorkflowsQuery } from '@/rtk';
27
+ import {
28
+ WorkflowsResponse,
29
+ useGetWorkflowsQuery,
30
+ useLazyGetWorkflowsQuery,
31
+ } from '@/rtk';
28
32
  import type { GraphqlQueryVariables, WorkflowDefinition } from '@/types';
29
33
  import { BadgeType, SortOrder } from '@/types';
30
34
  import {
35
+ getConcatenatedResult,
31
36
  getQueryVariablesForExport,
32
37
  onlyUnique,
33
38
  parseDateToLocaleDateTimeString,
@@ -52,6 +57,10 @@ export type WorkflowListItem = Pick<
52
57
  productTags: string[];
53
58
  };
54
59
 
60
+ type WorkflowListExportItem = Omit<WorkflowListItem, 'productTags'> & {
61
+ productTags: string;
62
+ };
63
+
55
64
  export const WfoWorkflowsPage = () => {
56
65
  const t = useTranslations('metadata.workflows');
57
66
  const tError = useTranslations('errors');
@@ -184,6 +193,19 @@ export const WfoWorkflowsPage = () => {
184
193
  totalItemCount: totalItems ? totalItems : 0,
185
194
  };
186
195
 
196
+ const mapToExportItems = (
197
+ workflowsResponse: WorkflowsResponse,
198
+ ): WorkflowListExportItem[] => {
199
+ const { workflows } = workflowsResponse;
200
+ return workflows.map((workflow) => ({
201
+ ...workflow,
202
+ productTags: getConcatenatedResult(workflow.products, [
203
+ 'tag',
204
+ 'name',
205
+ ]),
206
+ }));
207
+ };
208
+
187
209
  return (
188
210
  <WfoMetadataPageLayout>
189
211
  <WfoTableWithFilter<WorkflowListItem>
@@ -217,7 +239,7 @@ export const WfoWorkflowsPage = () => {
217
239
  localStorageKey={METADATA_WORKFLOWS_TABLE_LOCAL_STORAGE_KEY}
218
240
  onExportData={csvDownloadHandler(
219
241
  getWorkflowsForExport,
220
- (data) => data.workflows,
242
+ mapToExportItems,
221
243
  (data) => data.pageInfo,
222
244
  Object.keys(tableColumns),
223
245
  getCsvFileNameWithDate('Workflows'),
@@ -2,3 +2,5 @@ export * from './WfoProductBlocksPage';
2
2
  export * from './WfoResourceTypesPage';
3
3
  export * from './WfoProductsPage';
4
4
  export * from './WfoWorkflowsPage';
5
+ export * from './WfoMetadataPageLayout';
6
+ export * from './workflowListObjectMapper';
@@ -2,8 +2,8 @@ import React from 'react';
2
2
 
3
3
  import { useRouter } from 'next/router';
4
4
 
5
- import { WfoSubscription } from '../../components';
6
- import { TreeProvider } from '../../contexts';
5
+ import { WfoSubscription } from '@/components';
6
+ import { TreeProvider } from '@/contexts';
7
7
 
8
8
  export const WfoSubscriptionDetailPage = () => {
9
9
  const router = useRouter();
@@ -11,12 +11,12 @@ import {
11
11
  } from '@/components';
12
12
  import { WfoFilterTabs } from '@/components';
13
13
  import { StoredTableConfig } from '@/components';
14
+ import type { SubscriptionListItem } from '@/components';
14
15
  import {
15
16
  WfoSubscriptionListTab,
16
17
  WfoSubscriptionsList,
17
18
  subscriptionListTabs,
18
19
  } from '@/components/WfoSubscriptionsList';
19
- import { SubscriptionListItem } from '@/components/WfoSubscriptionsList';
20
20
  import { useDataDisplayParams, useStoredTableConfig } from '@/hooks';
21
21
  import { SortOrder } from '@/types';
22
22
 
@@ -1 +1,3 @@
1
1
  export * from './WfoWorkflowsListPage';
2
+ export * from './tabConfig';
3
+ export * from './getWorkflowsListTabTypeFromString';
@@ -30,6 +30,7 @@ export const subscriptionDetailQuery = `
30
30
  startDate
31
31
  status
32
32
  customerId
33
+ metadata
33
34
  customer {
34
35
  fullname
35
36
  customerId
@@ -38,6 +38,7 @@ export const subscriptionListQuery = `query SubscriptionsList(
38
38
  fullname
39
39
  shortcode
40
40
  }
41
+ metadata
41
42
  }
42
43
  pageInfo {
43
44
  totalItems
@@ -76,6 +76,7 @@ export enum BadgeType {
76
76
  PRODUCT_BLOCK = 'product_block',
77
77
  PRODUCT_BLOCK_TAG = 'product_block_tag',
78
78
  PRODUCT_TAG = 'product_tag',
79
+ PRODUCT = 'product',
79
80
  }
80
81
 
81
82
  export interface FixedInputDefinition {
@@ -356,12 +357,12 @@ export type StartComboBoxOption = {
356
357
  label: string;
357
358
  };
358
359
 
359
- interface GraphQlResultPage<T> {
360
+ export interface GraphQlResultPage<T> {
360
361
  page: T[];
361
362
  pageInfo: GraphQLPageInfo;
362
363
  }
363
364
 
364
- interface GraphQlSinglePage<T> {
365
+ export interface GraphQlSinglePage<T> {
365
366
  page: T[];
366
367
  }
367
368
 
@@ -395,6 +396,7 @@ export type Subscription = {
395
396
  product: Pick<ProductDefinition, 'name' | 'tag' | 'productType'>;
396
397
  productBlockInstances: ProductBlockInstance[];
397
398
  customer: Pick<Customer, 'fullname' | 'shortcode'>;
399
+ metadata: object;
398
400
  };
399
401
 
400
402
  export type SubscriptionSummary = Pick<
@@ -434,6 +436,7 @@ export type SubscriptionDetail = {
434
436
  endDate: string;
435
437
  startDate: string;
436
438
  status: SubscriptionStatus;
439
+ metadata: object;
437
440
  productBlockInstances: ProductBlockInstance[];
438
441
 
439
442
  customerId?: string | null;
@@ -101,6 +101,7 @@ export const getDefaultTableConfig = <T>(storageKey: string) => {
101
101
  case SUBSCRIPTIONS_TABLE_LOCAL_STORAGE_KEY:
102
102
  const subscriptionColumns: (keyof SubscriptionListItem)[] = [
103
103
  'productName',
104
+ 'metadata',
104
105
  ];
105
106
  return getTableConfig<T>(subscriptionColumns as (keyof T)[]);
106
107
  default:
@@ -8,3 +8,4 @@ export * from './strings';
8
8
  export * from './getProductNamesFromProcess';
9
9
  export * from './getQueryVariablesForExport';
10
10
  export * from './onlyUnique';
11
+ export * from './resultFlattener';
@@ -0,0 +1,51 @@
1
+ import {
2
+ getConcatenatedPagedResult,
3
+ getConcatenatedResult,
4
+ } from './resultFlattener';
5
+
6
+ describe('pagedResultFlattener', () => {
7
+ it('returns an empty string when the paged result is empty', () => {
8
+ const pagedResult = { page: [] };
9
+ const fields = ['name', 'age'];
10
+
11
+ const result = getConcatenatedPagedResult(pagedResult, fields);
12
+
13
+ expect(result).toBe('');
14
+ });
15
+ });
16
+
17
+ describe('resultFlattener', () => {
18
+ it('returns a flattened string of the specified fields', () => {
19
+ type TestItem = {
20
+ name: string;
21
+ age: number;
22
+ };
23
+ const results = [
24
+ { name: 'John', age: 25 },
25
+ { name: 'Jane', age: 30 },
26
+ { name: 'Bob', age: 40 },
27
+ ];
28
+ const fields: Array<keyof TestItem> = ['name', 'age'];
29
+ const result = getConcatenatedResult<TestItem>(results, fields);
30
+ expect(result).toBe('John: 25 - Jane: 30 - Bob: 40');
31
+ });
32
+
33
+ it('returns a flattened string with selected fields only', () => {
34
+ type TestItem = {
35
+ name: string;
36
+ age: number;
37
+ city: string;
38
+ };
39
+ const results: TestItem[] = [
40
+ { name: 'John', age: 25, city: 'New York' },
41
+ { name: 'Jane', age: 30, city: 'London' },
42
+ { name: 'Bob', age: 40, city: 'Paris' },
43
+ ];
44
+
45
+ const fields: Array<keyof TestItem> = ['name', 'city'];
46
+
47
+ const result = getConcatenatedResult(results, fields);
48
+
49
+ expect(result).toBe('John: New York - Jane: London - Bob: Paris');
50
+ });
51
+ });
@@ -0,0 +1,25 @@
1
+ import { GraphQlSinglePage } from '@/types';
2
+
3
+ export const getConcatenatedPagedResult = <T>(
4
+ pagedResult: GraphQlSinglePage<T>,
5
+ fields: Array<keyof T>,
6
+ ): string => {
7
+ const results = pagedResult.page || [];
8
+ return getConcatenatedResult(results, fields);
9
+ };
10
+
11
+ export const getConcatenatedResult = <T>(
12
+ results: T[],
13
+ fields: Array<keyof T>,
14
+ ): string => {
15
+ return results.reduce((accumulator, result, index) => {
16
+ const resultFields = fields.reduce((accumulator, field, index) => {
17
+ return (
18
+ accumulator +
19
+ `${result[field]}${index !== fields.length - 1 ? ': ' : ''}`
20
+ );
21
+ }, '');
22
+
23
+ return `${accumulator}${resultFields}${index !== results.length - 1 ? ' - ' : ''}`;
24
+ }, '');
25
+ };