@orchestrator-ui/orchestrator-ui-components 1.6.0 → 1.7.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 (35) 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 +19 -0
  5. package/dist/index.d.ts +1282 -1143
  6. package/dist/index.js +686 -333
  7. package/package.json +1 -1
  8. package/src/components/WfoBadges/WfoProductBlockBadge/WfoProductBlockBadge.tsx +1 -0
  9. package/src/components/WfoPageTemplate/WfoSidebar/WfoSidebar.tsx +10 -0
  10. package/src/components/WfoPageTemplate/paths.ts +1 -0
  11. package/src/components/WfoProcessList/WfoProcessesList.tsx +5 -1
  12. package/src/components/WfoProcessList/processListObjectMappers.ts +7 -4
  13. package/src/components/WfoSubscription/WfoSubscriptionGeneral.tsx +10 -6
  14. package/src/components/WfoTable/utils/constants.ts +1 -0
  15. package/src/components/index.ts +1 -0
  16. package/src/messages/en-GB.json +11 -1
  17. package/src/messages/nl-NL.json +10 -1
  18. package/src/pages/metadata/WfoMetadataPageLayout.tsx +10 -5
  19. package/src/pages/metadata/WfoProductBlocksPage.tsx +25 -1
  20. package/src/pages/metadata/WfoProductsPage.tsx +27 -1
  21. package/src/pages/metadata/WfoResourceTypesPage.tsx +23 -4
  22. package/src/pages/metadata/WfoTasksPage.tsx +226 -0
  23. package/src/pages/metadata/WfoWorkflowsPage.tsx +29 -6
  24. package/src/pages/metadata/index.ts +3 -0
  25. package/src/pages/metadata/taskListObjectMapper.ts +40 -0
  26. package/src/pages/subscriptions/WfoSubscriptionDetailPage.tsx +2 -2
  27. package/src/pages/subscriptions/WfoSubscriptionsListPage.tsx +1 -1
  28. package/src/pages/workflows/index.ts +2 -0
  29. package/src/rtk/endpoints/metadata/index.ts +1 -0
  30. package/src/rtk/endpoints/metadata/tasks.ts +74 -0
  31. package/src/types/types.ts +15 -2
  32. package/src/utils/getDefaultTableConfig.ts +2 -0
  33. package/src/utils/index.ts +1 -0
  34. package/src/utils/resultFlattener.spec.ts +51 -0
  35. package/src/utils/resultFlattener.ts +25 -0
@@ -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');
@@ -89,7 +98,7 @@ export const WfoWorkflowsPage = () => {
89
98
  name: {
90
99
  field: 'name',
91
100
  name: t('name'),
92
- width: '200',
101
+ width: '20%',
93
102
  render: (name) => (
94
103
  <WfoProductBlockBadge badgeType={BadgeType.WORKFLOW}>
95
104
  {name}
@@ -99,17 +108,18 @@ export const WfoWorkflowsPage = () => {
99
108
  description: {
100
109
  field: 'description',
101
110
  name: t('description'),
102
- width: '300',
111
+ width: '40%',
103
112
  },
104
113
  target: {
105
114
  field: 'target',
106
115
  name: t('target'),
107
- width: '90',
116
+ width: '15%',
108
117
  render: (target) => <WfoWorkflowTargetBadge target={target} />,
109
118
  },
110
119
  productTags: {
111
120
  field: 'productTags',
112
121
  name: t('productTags'),
122
+ width: '20%',
113
123
  render: (productTags) => (
114
124
  <>
115
125
  {productTags
@@ -142,7 +152,7 @@ export const WfoWorkflowsPage = () => {
142
152
  createdAt: {
143
153
  field: 'createdAt',
144
154
  name: t('createdAt'),
145
- width: '110',
155
+ width: '15%',
146
156
  render: (date) => <WfoDateTime dateOrIsoString={date} />,
147
157
  renderDetails: parseIsoString(parseDateToLocaleDateTimeString),
148
158
  clipboardText: parseIsoString(parseDateToLocaleDateTimeString),
@@ -184,6 +194,19 @@ export const WfoWorkflowsPage = () => {
184
194
  totalItemCount: totalItems ? totalItems : 0,
185
195
  };
186
196
 
197
+ const mapToExportItems = (
198
+ workflowsResponse: WorkflowsResponse,
199
+ ): WorkflowListExportItem[] => {
200
+ const { workflows } = workflowsResponse;
201
+ return workflows.map((workflow) => ({
202
+ ...workflow,
203
+ productTags: getConcatenatedResult(workflow.products, [
204
+ 'tag',
205
+ 'name',
206
+ ]),
207
+ }));
208
+ };
209
+
187
210
  return (
188
211
  <WfoMetadataPageLayout>
189
212
  <WfoTableWithFilter<WorkflowListItem>
@@ -217,7 +240,7 @@ export const WfoWorkflowsPage = () => {
217
240
  localStorageKey={METADATA_WORKFLOWS_TABLE_LOCAL_STORAGE_KEY}
218
241
  onExportData={csvDownloadHandler(
219
242
  getWorkflowsForExport,
220
- (data) => data.workflows,
243
+ mapToExportItems,
221
244
  (data) => data.pageInfo,
222
245
  Object.keys(tableColumns),
223
246
  getCsvFileNameWithDate('Workflows'),
@@ -2,3 +2,6 @@ export * from './WfoProductBlocksPage';
2
2
  export * from './WfoResourceTypesPage';
3
3
  export * from './WfoProductsPage';
4
4
  export * from './WfoWorkflowsPage';
5
+ export * from './WfoTasksPage';
6
+ export * from './WfoMetadataPageLayout';
7
+ export * from './workflowListObjectMapper';
@@ -0,0 +1,40 @@
1
+ import { GraphQLSort, TaskDefinition } from '@/types';
2
+
3
+ import { TaskListItem } from './WfoTasksPage';
4
+
5
+ export const mapTaskDefinitionToTaskListItem = (
6
+ tasks: TaskDefinition[],
7
+ ): TaskListItem[] =>
8
+ tasks.map((taskDefinition) => {
9
+ const { name, target, description, createdAt, products } =
10
+ taskDefinition;
11
+
12
+ const productTags = products.map((product) => product.tag);
13
+
14
+ return {
15
+ name,
16
+ description,
17
+ target,
18
+ createdAt,
19
+ productTags,
20
+ };
21
+ });
22
+
23
+ export const taskFieldMapper = (
24
+ field: keyof TaskListItem,
25
+ ): keyof TaskDefinition => {
26
+ switch (field) {
27
+ case 'productTags':
28
+ return 'productTag' as keyof TaskDefinition;
29
+ default:
30
+ return field;
31
+ }
32
+ };
33
+
34
+ export const graphQlTaskListMapper = ({
35
+ field,
36
+ order,
37
+ }: GraphQLSort<TaskListItem>) => ({
38
+ field: taskFieldMapper(field),
39
+ order,
40
+ });
@@ -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';
@@ -1,3 +1,4 @@
1
1
  export * from './productBlocks';
2
2
  export * from './resourceTypes';
3
3
  export * from './workflows';
4
+ export * from './tasks';
@@ -0,0 +1,74 @@
1
+ import { orchestratorApi } from '@/rtk';
2
+ import {
3
+ BaseGraphQlResult,
4
+ GraphqlQueryVariables,
5
+ TaskDefinition,
6
+ TaskDefinitionsResult,
7
+ } from '@/types';
8
+
9
+ export const tasksQuery = `
10
+ query MetadataWorkflows(
11
+ $first: Int!
12
+ $after: Int!
13
+ $sortBy: [GraphqlSort!]
14
+ $query: String
15
+ ) {
16
+ workflows(
17
+ first: $first
18
+ after: $after
19
+ sortBy: $sortBy
20
+ query: $query
21
+ filterBy: { field: "target", value: "SYSTEM" }
22
+ ) {
23
+ page {
24
+ name
25
+ description
26
+ target
27
+ products {
28
+ tag
29
+ }
30
+ createdAt
31
+ }
32
+ pageInfo {
33
+ endCursor
34
+ hasNextPage
35
+ hasPreviousPage
36
+ startCursor
37
+ totalItems
38
+ sortFields
39
+ filterFields
40
+ }
41
+ }
42
+ }
43
+ `;
44
+
45
+ export type TasksResponse = {
46
+ tasks: TaskDefinition[];
47
+ } & BaseGraphQlResult;
48
+
49
+ const tasksApi = orchestratorApi.injectEndpoints({
50
+ endpoints: (builder) => ({
51
+ getTasks: builder.query<
52
+ TasksResponse,
53
+ GraphqlQueryVariables<TaskDefinition>
54
+ >({
55
+ query: (variables) => ({
56
+ document: tasksQuery,
57
+ variables,
58
+ }),
59
+ transformResponse: (
60
+ response: TaskDefinitionsResult,
61
+ ): TasksResponse => {
62
+ const tasks = response.workflows.page || [];
63
+ const pageInfo = response.workflows.pageInfo || {};
64
+
65
+ return {
66
+ tasks,
67
+ pageInfo,
68
+ };
69
+ },
70
+ }),
71
+ }),
72
+ });
73
+
74
+ export const { useGetTasksQuery, useLazyGetTasksQuery } = tasksApi;
@@ -77,6 +77,7 @@ export enum BadgeType {
77
77
  PRODUCT_BLOCK_TAG = 'product_block_tag',
78
78
  PRODUCT_TAG = 'product_tag',
79
79
  PRODUCT = 'product',
80
+ TASK = 'task',
80
81
  }
81
82
 
82
83
  export interface FixedInputDefinition {
@@ -236,6 +237,14 @@ export interface WorkflowDefinition {
236
237
  createdAt: string;
237
238
  }
238
239
 
240
+ export interface TaskDefinition {
241
+ name: string;
242
+ description?: string;
243
+ target: WorkflowTarget;
244
+ products: Pick<ProductDefinition, 'tag' | 'productId' | 'name'>[];
245
+ createdAt: string;
246
+ }
247
+
239
248
  export type Field<Type> = keyof Type;
240
249
 
241
250
  //// Utility types
@@ -333,6 +342,10 @@ export interface CustomersResult {
333
342
  customers: GraphQlSinglePage<Customer>;
334
343
  }
335
344
 
345
+ export interface TaskDefinitionsResult<T = TaskDefinition> {
346
+ workflows: GraphQlResultPage<T>;
347
+ }
348
+
336
349
  export interface WorkflowDefinitionsResult<T = WorkflowDefinition> {
337
350
  workflows: GraphQlResultPage<T>;
338
351
  }
@@ -357,12 +370,12 @@ export type StartComboBoxOption = {
357
370
  label: string;
358
371
  };
359
372
 
360
- interface GraphQlResultPage<T> {
373
+ export interface GraphQlResultPage<T> {
361
374
  page: T[];
362
375
  pageInfo: GraphQLPageInfo;
363
376
  }
364
377
 
365
- interface GraphQlSinglePage<T> {
378
+ export interface GraphQlSinglePage<T> {
366
379
  page: T[];
367
380
  }
368
381
 
@@ -7,6 +7,7 @@ import {
7
7
  METADATA_PRODUCT_BLOCKS_TABLE_LOCAL_STORAGE_KEY,
8
8
  METADATA_PRODUCT_TABLE_LOCAL_STORAGE_KEY,
9
9
  METADATA_RESOURCE_TYPES_TABLE_LOCAL_STORAGE_KEY,
10
+ METADATA_TASKS_TABLE_LOCAL_STORAGE_KEY,
10
11
  METADATA_WORKFLOWS_TABLE_LOCAL_STORAGE_KEY,
11
12
  SUBSCRIPTIONS_TABLE_LOCAL_STORAGE_KEY,
12
13
  } from '@/components';
@@ -57,6 +58,7 @@ export const getDefaultTableConfig = <T>(storageKey: string) => {
57
58
  return getTableConfig<T>(productColumns as (keyof T)[]);
58
59
 
59
60
  case METADATA_WORKFLOWS_TABLE_LOCAL_STORAGE_KEY:
61
+ case METADATA_TASKS_TABLE_LOCAL_STORAGE_KEY:
60
62
  const workflowColumns: (keyof WorkflowDefinition)[] = ['createdAt'];
61
63
  return getTableConfig<T>(workflowColumns as (keyof T)[]);
62
64
 
@@ -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
+ };