@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestrator-ui/orchestrator-ui-components",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Library of UI Components used to display the workflow orchestrator frontend",
6
6
  "author": {
@@ -42,6 +42,7 @@ export function WfoProductBlockBadge({
42
42
  textColor: primaryText,
43
43
  };
44
44
  case BadgeType.WORKFLOW:
45
+ case BadgeType.PRODUCT:
45
46
  return {
46
47
  badgeColor: toSecondaryColor(danger),
47
48
  textColor: dangerText,
@@ -49,6 +49,7 @@ const testSubscriptionDetail: SubscriptionDetail = {
49
49
  startDate: '1111-01-01',
50
50
  status: SubscriptionStatus.ACTIVE,
51
51
  productBlockInstances: testProductBlockInstances,
52
+ metadata: {},
52
53
  processes: {
53
54
  page: [
54
55
  {
@@ -2,24 +2,30 @@ import React, { FC } from 'react';
2
2
 
3
3
  import { EuiCodeBlock } from '@elastic/eui';
4
4
 
5
- import { useWithOrchestratorTheme } from '../../hooks';
5
+ import { useWithOrchestratorTheme } from '@/hooks';
6
+
6
7
  import { getStyles } from './styles';
7
8
 
8
9
  export type WfoJsonCodeBlockProps = {
9
10
  data: object;
11
+ isBasicStyle?: boolean;
10
12
  };
11
13
 
12
- export const WfoJsonCodeBlock: FC<WfoJsonCodeBlockProps> = ({ data }) => {
13
- const { euiCodeBlockStyle } = useWithOrchestratorTheme(getStyles);
14
+ export const WfoJsonCodeBlock: FC<WfoJsonCodeBlockProps> = ({
15
+ data,
16
+ isBasicStyle = false,
17
+ }) => {
18
+ const { euiCodeBlockStyle, euiBasicCodeBlockStyle } =
19
+ useWithOrchestratorTheme(getStyles);
14
20
 
15
21
  const json = JSON.stringify(data, null, 4);
16
22
 
17
23
  return (
18
24
  <EuiCodeBlock
19
- css={euiCodeBlockStyle}
25
+ css={isBasicStyle ? euiBasicCodeBlockStyle : euiCodeBlockStyle}
20
26
  isCopyable={true}
21
27
  language="json"
22
- lineNumbers={true}
28
+ lineNumbers={!isBasicStyle}
23
29
  >
24
30
  {json}
25
31
  </EuiCodeBlock>
@@ -7,7 +7,20 @@ export const getStyles = (theme: EuiThemeComputed) => {
7
7
  borderRadius: theme.border.radius.medium,
8
8
  });
9
9
 
10
+ const euiBasicCodeBlockStyle = css({
11
+ backgroundColor: 'inherit',
12
+ '.euiCodeBlock__pre': {
13
+ paddingTop: 0,
14
+ paddingBottom: 0,
15
+ paddingLeft: 0,
16
+ },
17
+ '.euiCodeBlock__controls': {
18
+ backgroundColor: 'inherit',
19
+ },
20
+ });
21
+
10
22
  return {
11
23
  euiCodeBlockStyle,
24
+ euiBasicCodeBlockStyle,
12
25
  };
13
26
  };
@@ -30,9 +30,16 @@ export const WfoValueCell: FC<WfoValueCellProps> = ({
30
30
 
31
31
  const shouldRenderCopyColumn = enableCopyIcon && textToCopy;
32
32
 
33
+ const valueToRender =
34
+ typeof value === 'string' ||
35
+ typeof value === 'number' ||
36
+ React.isValidElement(value)
37
+ ? value
38
+ : JSON.stringify(value);
39
+
33
40
  return (
34
41
  <div css={[getBackgroundColorStyleForRow(rowNumber), valueColumnStyle]}>
35
- <div css={valueCellStyle}>{value}</div>
42
+ <div css={valueCellStyle}>{valueToRender}</div>
36
43
  <div css={clipboardIconStyle}>
37
44
  {shouldRenderCopyColumn && (
38
45
  <EuiCopy textToCopy={textToCopy}>
@@ -67,6 +67,10 @@ export type ProcessListItem = Pick<
67
67
  customerAbbreviation: string;
68
68
  };
69
69
 
70
+ export type ProcessListExportItem = Omit<ProcessListItem, 'subscriptions'> & {
71
+ subscriptions: string;
72
+ };
73
+
70
74
  export type WfoProcessesListProps = {
71
75
  alwaysOnFilters?: FilterQuery<ProcessListItem>[];
72
76
  defaultHiddenColumns: TableColumnKeys<ProcessListItem> | undefined;
@@ -264,7 +268,7 @@ export const WfoProcessesList = ({
264
268
  onUpdateDataSort={getDataSortHandler(setDataDisplayParam)}
265
269
  onExportData={csvDownloadHandler<
266
270
  ProcessListResponse,
267
- ProcessListItem
271
+ ProcessListExportItem
268
272
  >(
269
273
  getProcessListForExport,
270
274
  mapGraphQlProcessListExportResultToProcessListItems,
@@ -1,7 +1,8 @@
1
1
  import { ProcessListResponse } from '@/rtk';
2
- import { GraphQLSort, GraphqlFilter, Process } from '@/types';
2
+ import { GraphQLSort, GraphqlFilter, Process, Subscription } from '@/types';
3
+ import { getConcatenatedPagedResult } from '@/utils';
3
4
 
4
- import { ProcessListItem } from './WfoProcessesList';
5
+ import { ProcessListExportItem, ProcessListItem } from './WfoProcessesList';
5
6
 
6
7
  export const mapGraphQlProcessListResultToPageInfo = (
7
8
  processesResponse: ProcessListResponse,
@@ -48,7 +49,7 @@ export const mapGraphQlProcessListResultToProcessListItems = (
48
49
 
49
50
  export const mapGraphQlProcessListExportResultToProcessListItems = (
50
51
  processesResponse: ProcessListResponse,
51
- ): ProcessListItem[] =>
52
+ ): ProcessListExportItem[] =>
52
53
  processesResponse.processes.map((process) => {
53
54
  const {
54
55
  workflowName,
@@ -77,7 +78,9 @@ export const mapGraphQlProcessListExportResultToProcessListItems = (
77
78
  isTask,
78
79
  startedAt: new Date(startedAt),
79
80
  lastModifiedAt: new Date(lastModifiedAt),
80
- subscriptions,
81
+ subscriptions: getConcatenatedPagedResult<
82
+ Pick<Subscription, 'subscriptionId' | 'description'>
83
+ >(subscriptions, ['subscriptionId', 'description']),
81
84
  productName: product?.name,
82
85
  productTag: product?.tag,
83
86
  customer: customer.fullname,
@@ -103,11 +103,6 @@ export const WfoSubscription = ({ subscriptionId }: WfoSubscriptionProps) => {
103
103
  onChangeTab={onSelectedTabChanged}
104
104
  />
105
105
 
106
- {selectedTab === SubscriptionDetailTab.GENERAL_TAB && (
107
- <WfoSubscriptionGeneral
108
- subscriptionDetail={subscriptionDetail}
109
- />
110
- )}
111
106
  {selectedTab ===
112
107
  SubscriptionDetailTab.SERVICE_CONFIGURATION_TAB && (
113
108
  <WfoSubscriptionDetailTree
@@ -116,6 +111,11 @@ export const WfoSubscription = ({ subscriptionId }: WfoSubscriptionProps) => {
116
111
  }
117
112
  />
118
113
  )}
114
+ {selectedTab === SubscriptionDetailTab.GENERAL_TAB && (
115
+ <WfoSubscriptionGeneral
116
+ subscriptionDetail={subscriptionDetail}
117
+ />
118
+ )}
119
119
  {selectedTab === SubscriptionDetailTab.PROCESSES_TAB &&
120
120
  data && (
121
121
  <WfoProcessesTimeline
@@ -4,8 +4,9 @@ import { useTranslations } from 'next-intl';
4
4
 
5
5
  import { EuiFlexGrid, EuiFlexItem } from '@elastic/eui';
6
6
 
7
+ import { WfoJsonCodeBlock } from '@/components';
7
8
  import { SubscriptionDetail } from '@/types';
8
- import { formatDate } from '@/utils';
9
+ import { camelToHuman, formatDate } from '@/utils';
9
10
 
10
11
  import {
11
12
  WfoProductStatusBadge,
@@ -24,71 +25,72 @@ export const WfoSubscriptionGeneral = ({
24
25
  }: WfoSubscriptionGeneralProps) => {
25
26
  const t = useTranslations('subscriptions.detail');
26
27
 
27
- const getSubscriptionDetailBlockData = (): WfoKeyValueTableDataType[] => {
28
- return [
29
- {
30
- key: t('subscriptionId'),
31
- value: subscriptionDetail.subscriptionId,
32
- textToCopy: subscriptionDetail.subscriptionId,
33
- },
34
- {
35
- key: t('productName'),
36
- value: subscriptionDetail.product.name,
37
- },
38
- {
39
- key: t('description'),
40
- value: subscriptionDetail.description,
41
- },
42
- {
43
- key: t('startDate'),
44
- value: formatDate(subscriptionDetail.startDate),
45
- },
46
- {
47
- key: t('endDate'),
48
- value: formatDate(subscriptionDetail.endDate),
49
- },
50
- {
51
- key: t('status'),
52
- value: (
53
- <WfoSubscriptionStatusBadge
54
- status={subscriptionDetail.status}
55
- />
56
- ),
57
- },
58
- {
59
- key: t('insync'),
60
- value: (
61
- <WfoInSyncField subscriptionDetail={subscriptionDetail} />
62
- ),
63
- },
64
- {
65
- key: t('customer'),
66
- value:
67
- subscriptionDetail && subscriptionDetail.customer
68
- ? `${subscriptionDetail.customer?.fullname}`
69
- : '-',
70
- },
71
- {
72
- key: t('customerUuid'),
73
- value:
74
- subscriptionDetail && subscriptionDetail.customer
75
- ? `${subscriptionDetail.customer?.customerId}`
76
- : '-',
77
- textToCopy: subscriptionDetail.customer?.customerId,
78
- },
79
- {
80
- key: t('note'),
81
- value: (subscriptionDetail && subscriptionDetail.note) || '-',
82
- },
83
- ];
84
- };
28
+ const getSubscriptionDetailBlockData = (): WfoKeyValueTableDataType[] => [
29
+ {
30
+ key: t('subscriptionId'),
31
+ value: subscriptionDetail.subscriptionId,
32
+ textToCopy: subscriptionDetail.subscriptionId,
33
+ },
34
+ {
35
+ key: t('productName'),
36
+ value: subscriptionDetail.product.name,
37
+ },
38
+ {
39
+ key: t('description'),
40
+ value: subscriptionDetail.description,
41
+ },
42
+ {
43
+ key: t('startDate'),
44
+ value: formatDate(subscriptionDetail.startDate),
45
+ },
46
+ {
47
+ key: t('endDate'),
48
+ value: formatDate(subscriptionDetail.endDate),
49
+ },
50
+ {
51
+ key: t('status'),
52
+ value: (
53
+ <WfoSubscriptionStatusBadge
54
+ status={subscriptionDetail.status}
55
+ />
56
+ ),
57
+ },
58
+ {
59
+ key: t('insync'),
60
+ value: <WfoInSyncField subscriptionDetail={subscriptionDetail} />,
61
+ },
62
+ {
63
+ key: t('customer'),
64
+ value:
65
+ subscriptionDetail && subscriptionDetail.customer
66
+ ? `${subscriptionDetail.customer?.fullname}`
67
+ : '-',
68
+ },
69
+ {
70
+ key: t('customerUuid'),
71
+ value:
72
+ subscriptionDetail && subscriptionDetail.customer
73
+ ? `${subscriptionDetail.customer?.customerId}`
74
+ : '-',
75
+ textToCopy: subscriptionDetail.customer?.customerId,
76
+ },
77
+ {
78
+ key: t('note'),
79
+ value: (subscriptionDetail && subscriptionDetail.note) || '-',
80
+ },
81
+ ];
85
82
 
86
- const getFixedInputBlockData = (): WfoKeyValueTableDataType[] => {
87
- return subscriptionDetail.fixedInputs.map((fixedInput) => ({
83
+ const getMetadataBlockData = (): WfoKeyValueTableDataType[] =>
84
+ Object.entries(subscriptionDetail.metadata).map(([key, value]) => ({
85
+ key: camelToHuman(key),
86
+ value: <WfoJsonCodeBlock data={value} isBasicStyle />,
87
+ }));
88
+
89
+ const getFixedInputBlockData = (): WfoKeyValueTableDataType[] =>
90
+ subscriptionDetail.fixedInputs.map((fixedInput) => ({
88
91
  key: fixedInput.field,
89
92
  value: fixedInput.value,
90
93
  }));
91
- };
92
94
 
93
95
  const getProductInfoBlockData = (): WfoKeyValueTableDataType[] => {
94
96
  const product = subscriptionDetail.product;
@@ -124,6 +126,8 @@ export const WfoSubscriptionGeneral = ({
124
126
  ];
125
127
  };
126
128
 
129
+ const hasMetadata = Object.entries(subscriptionDetail.metadata).length > 0;
130
+
127
131
  return (
128
132
  <EuiFlexGrid direction={'row'}>
129
133
  <>
@@ -133,6 +137,14 @@ export const WfoSubscriptionGeneral = ({
133
137
  keyValues={getSubscriptionDetailBlockData()}
134
138
  />
135
139
  </EuiFlexItem>
140
+ {hasMetadata && (
141
+ <EuiFlexItem>
142
+ <SubscriptionKeyValueBlock
143
+ title={t('metadata')}
144
+ keyValues={getMetadataBlockData()}
145
+ />
146
+ </EuiFlexItem>
147
+ )}
136
148
  <EuiFlexItem>
137
149
  <SubscriptionKeyValueBlock
138
150
  title={t('blockTitleFixedInputs')}
@@ -20,7 +20,10 @@ import { FieldValue, InUseByRelation } from '../../types';
20
20
  import { camelToHuman } from '../../utils';
21
21
  import { PATH_SUBSCRIPTIONS } from '../WfoPageTemplate';
22
22
  import { getStyles } from './styles';
23
- import { getProductBlockTitle } from './utils';
23
+ import {
24
+ getFieldFromProductBlockInstanceValues,
25
+ getProductBlockTitle,
26
+ } from './utils';
24
27
 
25
28
  interface WfoSubscriptionProductBlockProps {
26
29
  ownerSubscriptionId: string;
@@ -84,9 +87,12 @@ export const WfoSubscriptionProductBlock = ({
84
87
  )}
85
88
  </h3>
86
89
  </EuiText>
87
- <EuiText size="s">{`${t(
88
- 'subscriptionInstanceId',
89
- )}: ${subscriptionInstanceId}`}</EuiText>
90
+ <EuiText size="s">
91
+ {getFieldFromProductBlockInstanceValues(
92
+ productBlockInstanceValues,
93
+ 'name',
94
+ )}
95
+ </EuiText>
90
96
  </EuiFlexItem>
91
97
  <EuiFlexItem grow={false}>
92
98
  <EuiButtonEmpty
@@ -109,6 +115,20 @@ export const WfoSubscriptionProductBlock = ({
109
115
  <tbody>
110
116
  {!hideDetails && (
111
117
  <>
118
+ <tr key={-3}>
119
+ <td
120
+ valign={'top'}
121
+ css={productBlockFirstLeftColStyle}
122
+ >
123
+ <b>{t('subscriptionInstanceId')}</b>
124
+ </td>
125
+ <td
126
+ valign={'top'}
127
+ css={productBlockFirstRightColStyle}
128
+ >
129
+ {subscriptionInstanceId}
130
+ </td>
131
+ </tr>
112
132
  <tr key={-2}>
113
133
  <td
114
134
  valign={'top'}
@@ -123,7 +143,6 @@ export const WfoSubscriptionProductBlock = ({
123
143
  {subscriptionId ===
124
144
  ownerSubscriptionId ? (
125
145
  <>
126
- {subscriptionId}
127
146
  <EuiBadge>
128
147
  {t('self')}
129
148
  </EuiBadge>
@@ -8,8 +8,11 @@ import { Pagination } from '@elastic/eui';
8
8
 
9
9
  import {
10
10
  FilterQuery,
11
+ PATH_SUBSCRIPTIONS,
11
12
  WfoDateTime,
13
+ WfoInlineJson,
12
14
  WfoInsyncIcon,
15
+ WfoJsonCodeBlock,
13
16
  WfoSubscriptionStatusBadge,
14
17
  } from '@/components';
15
18
  import { DataDisplayParams, useShowToastMessage } from '@/hooks';
@@ -142,6 +145,13 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
142
145
  field: 'note',
143
146
  name: t('note'),
144
147
  },
148
+ metadata: {
149
+ field: 'metadata',
150
+ name: t('metadata'),
151
+ render: (value) => <WfoInlineJson data={value} />,
152
+ renderDetails: (value) =>
153
+ value && <WfoJsonCodeBlock data={value} isBasicStyle />,
154
+ },
145
155
  };
146
156
 
147
157
  const { sortBy, queryString, pageIndex, pageSize } = dataDisplayParams;
@@ -166,7 +176,7 @@ export const WfoSubscriptionsList: FC<WfoSubscriptionsListProps> = ({
166
176
 
167
177
  const sortedColumnId = getTypedFieldFromObject(sortBy?.field, tableColumns);
168
178
  if (!sortedColumnId) {
169
- router.replace('/subscriptions');
179
+ router.replace(PATH_SUBSCRIPTIONS);
170
180
  return null;
171
181
  }
172
182
 
@@ -12,6 +12,7 @@ export type SubscriptionListItem = Pick<
12
12
  tag: string | null;
13
13
  customerFullname: string;
14
14
  customerShortcode: string;
15
+ metadata: object | null;
15
16
  };
16
17
 
17
18
  export const mapGraphQlSubscriptionsResultToPageInfo = (
@@ -32,6 +33,7 @@ export const mapGraphQlSubscriptionsResultToSubscriptionListItems = (
32
33
  subscriptionId,
33
34
  note,
34
35
  customer,
36
+ metadata,
35
37
  } = subscription;
36
38
 
37
39
  const { name: productName, tag } = product;
@@ -50,5 +52,6 @@ export const mapGraphQlSubscriptionsResultToSubscriptionListItems = (
50
52
  tag,
51
53
  customerFullname,
52
54
  customerShortcode,
55
+ metadata: Object.keys(metadata).length > 0 ? metadata : null,
53
56
  };
54
57
  });
@@ -0,0 +1,14 @@
1
+ import React, { FC } from 'react';
2
+
3
+ export type WfoInlineJsonProps = {
4
+ data: object | null;
5
+ };
6
+
7
+ export const WfoInlineJson: FC<WfoInlineJsonProps> = ({ data }) => {
8
+ if (!data) {
9
+ return null;
10
+ }
11
+
12
+ const valueAsString = JSON.stringify(data);
13
+ return <span title={valueAsString}>{valueAsString}</span>;
14
+ };
@@ -0,0 +1 @@
1
+ export * from './WfoInlineJson';
@@ -15,3 +15,4 @@ export * from './WfoTableWithFilter';
15
15
 
16
16
  export * from './WfoSortButtons';
17
17
  export * from './WfoFirstPartUUID';
18
+ export * from './WfoInlineJson';
@@ -1,5 +1,5 @@
1
- export const DEFAULT_PAGE_SIZES = [5, 10, 15, 20, 25, 100];
2
- export const DEFAULT_PAGE_SIZE = 10;
1
+ export const DEFAULT_PAGE_SIZES = [5, 10, 15, 20, 25, 50, 100];
2
+ export const DEFAULT_PAGE_SIZE = 15;
3
3
 
4
4
  export const ACTIVE_PROCESSES_LIST_TABLE_LOCAL_STORAGE_KEY =
5
5
  'activeProcessesListTable';
@@ -77,6 +77,13 @@ export const WfoStepStatusIcon = ({
77
77
  true,
78
78
  theme.colors.danger,
79
79
  ];
80
+ case StepStatus.SKIPPED:
81
+ return [
82
+ stepStateSuccessIconStyle,
83
+ theme.colors.primaryText,
84
+ true,
85
+ theme.colors.accent,
86
+ ];
80
87
  case StepStatus.FORM:
81
88
  return [stepStateSuccessIconStyle, theme.colors.link];
82
89
 
@@ -26,3 +26,4 @@ export * from './WfoErrorBoundary';
26
26
  export * from './WfoWorkflowSteps';
27
27
  export * from './WfoNoResults';
28
28
  export * from './WfoStartButton';
29
+ export * from './WfoSubscriptionsList';
@@ -0,0 +1,30 @@
1
+ import React, { FC } from 'react';
2
+
3
+ import { WfoIconProps } from './WfoIconProps';
4
+
5
+ export const WfoExternalLink: FC<WfoIconProps> = ({
6
+ width = 24,
7
+ height = 24,
8
+ color = 'currentColor',
9
+ }) => (
10
+ <svg
11
+ width={width}
12
+ height={height}
13
+ viewBox="0 0 24 24"
14
+ version="1.1"
15
+ xmlns="http://www.w3.org/2000/svg"
16
+ >
17
+ <title>icon/external-link</title>
18
+ <g
19
+ id="Symbols"
20
+ stroke="none"
21
+ strokeWidth="1"
22
+ fill="none"
23
+ fillRule="evenodd"
24
+ >
25
+ <g id="icon/external-link" fill={color}>
26
+ <path d="M10,7 C10.55228,7 11,7.44772 11,8 C11,8.55228 10.55228,9 10,9 L7,9 L7,17 L15,17 L15,14 C15,13.4477 15.4477,13 16,13 C16.5523,13 17,13.4477 17,14 L17,17 C17,18.1046 16.1046,19 15,19 L7,19 C5.89543,19 5,18.1046 5,17 L5,9 C5,7.89543 5.89543,7 7,7 Z M18,5 C18.5523,5 19,5.44772 19,6 L19,11 C19,11.55228 18.5523,12 18,12 C17.4477,12 17,11.55228 17,11 L17,8.41421 L10.70711,14.7071 C10.31658,15.0976 9.68342,15.0976 9.29289,14.7071 C8.90237,14.3166 8.90237,13.6834 9.29289,13.2929 L15.5858,7 L13,7 C12.4477,7 12,6.55228 12,6 C12,5.44772 12.4477,5 13,5 Z" />
27
+ </g>
28
+ </g>
29
+ </svg>
30
+ );
@@ -30,3 +30,4 @@ export * from './WfoViewList';
30
30
  export * from './WfoContactEnvelopeFill';
31
31
  export * from './WfoBell';
32
32
  export * from './WfoWarningTriangle';
33
+ export * from './WfoExternalLink';
@@ -121,6 +121,7 @@
121
121
  }
122
122
  },
123
123
  "metadata": {
124
+ "title": "Metadata",
124
125
  "tabs": {
125
126
  "products": "Products",
126
127
  "productBlocks": "Product blocks",
@@ -242,6 +243,7 @@
242
243
  "tag": "Product tag",
243
244
  "startDate": "Start date",
244
245
  "endDate": "End date",
246
+ "metadata": "Metadata",
245
247
  "note": "Note",
246
248
  "customerFullname": "Customer",
247
249
  "customerShortcode": "Customer abbr"
@@ -304,6 +306,7 @@
304
306
  "tag": "Tag",
305
307
  "created": "Created",
306
308
  "endDate": "End date",
309
+ "metadata": "Metadata",
307
310
  "note": "Note",
308
311
  "noRelatedSubscriptions": "No related subscriptions found",
309
312
  "hideTerminatedRelatedSubscriptions": "Hide terminated subscriptions",
@@ -242,6 +242,7 @@
242
242
  "startDate": "Startdatum",
243
243
  "endDate": "Einddatum",
244
244
  "note": "Notitie",
245
+ "metadata": "Metadata",
245
246
  "customerFullName": "Klant",
246
247
  "customerAbbreviation": "Klantafkorting"
247
248
  },
@@ -298,6 +299,7 @@
298
299
  "insync": "In sync",
299
300
  "customer": "Klant",
300
301
  "customerUuid": "Klant UUID",
302
+ "metadata": "Metadata",
301
303
  "name": "Naam",
302
304
  "productType": "Produkttype",
303
305
  "tag": "Tag",
@@ -17,7 +17,7 @@ export interface MetaDataTab {
17
17
  path: string;
18
18
  }
19
19
 
20
- const metaDataTabs: MetaDataTab[] = [
20
+ export const metaDataTabs: MetaDataTab[] = [
21
21
  {
22
22
  id: 1,
23
23
  translationKey: 'products',
@@ -45,14 +45,14 @@ export const WfoMetadataPageLayout = ({
45
45
  tabs = metaDataTabs,
46
46
  }: MetadataLayoutProps) => {
47
47
  const router = useRouter();
48
- const t = useTranslations('metadata.tabs');
48
+ const t = useTranslations('metadata');
49
49
  const currentPath = router.pathname;
50
50
 
51
51
  return (
52
52
  <>
53
53
  <EuiSpacer />
54
54
 
55
- <EuiPageHeader pageTitle="Metadata" />
55
+ <EuiPageHeader pageTitle={t('title')} />
56
56
  <EuiSpacer size="m" />
57
57
  <EuiTabs>
58
58
  {tabs.map(({ id, translationKey: name, path }) => (
@@ -61,7 +61,7 @@ export const WfoMetadataPageLayout = ({
61
61
  isSelected={path === currentPath}
62
62
  onClick={() => router.push(path)}
63
63
  >
64
- {t(name)}
64
+ {t(`tabs.${name}`)}
65
65
  </EuiTab>
66
66
  ))}
67
67
  </EuiTabs>