@orchestrator-ui/orchestrator-ui-components 0.1.2 → 0.2.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 (37) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +2 -2
  3. package/src/components/OrchestratorPageTemplate/OrchestratorPageHeader/OrchestratorPageHeader.stories.tsx +2 -1
  4. package/src/components/OrchestratorPageTemplate/OrchestratorPageTemplate/OrchestratorPageTemplate.stories.tsx +2 -1
  5. package/src/components/Subscription/ProcessesTimeline.tsx +1 -1
  6. package/src/components/Subscription/ProductBlock.tsx +1 -0
  7. package/src/components/Subscription/SubscriptionActions.tsx +7 -5
  8. package/src/components/Subscription/SubscriptionBlock.tsx +4 -2
  9. package/src/components/Subscription/SubscriptionDetailTree.tsx +6 -7
  10. package/src/components/Subscription/SubscriptionGeneral.tsx +6 -2
  11. package/src/components/SubscriptionsTabs/SubscriptionsTabs.tsx +25 -21
  12. package/src/components/Table/DataGridTable/DataGridTable.tsx +1 -1
  13. package/src/components/Table/utils/constants.ts +3 -0
  14. package/src/components/Tree/TreeBranch.tsx +1 -1
  15. package/src/components/Tree/TreeNode.tsx +3 -1
  16. package/src/graphqlQueries/index.ts +1 -0
  17. package/src/graphqlQueries/productBlocksQuery.ts +46 -0
  18. package/src/hooks/useDataDisplayParams.ts +1 -1
  19. package/src/index.ts +2 -0
  20. package/src/messages/en-US.json +84 -0
  21. package/src/messages/getTranslationMessages.spec.ts +51 -0
  22. package/src/messages/getTranslationMessages.ts +26 -0
  23. package/src/messages/index.ts +1 -0
  24. package/src/messages/nl-NL.json +50 -0
  25. package/src/pages/index.ts +1 -0
  26. package/src/pages/metadata/WFOMetadataPageLayout.tsx +75 -0
  27. package/src/pages/metadata/WFOProductBlocksPage.tsx +167 -0
  28. package/src/pages/metadata/index.ts +1 -0
  29. package/src/types.ts +64 -9
  30. package/tsconfig.json +4 -2
  31. package/.turbo/turbo-build.log +0 -13
  32. package/.turbo/turbo-lint.log +0 -17
  33. package/.turbo/turbo-test.log +0 -19
  34. package/.turbo/turbo-tsc.log +0 -1
  35. package/dist/index.d.ts +0 -621
  36. package/dist/index.js +0 -3291
  37. package/tsconfig.tsbuildinfo +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @orchestrator-ui/orchestrator-ui-components
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 3533525: Updated TS-Config to improve developer experience
8
+
9
+ ## 0.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 6c4cb21: Added translation setup and next-inl configuration. Translation strings are now available when using the useTranslations hook. For more on how to add translations refer to apps/wfo-ui/translations/README.md
14
+
3
15
  ## 0.1.2
4
16
 
5
17
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestrator-ui/orchestrator-ui-components",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "test": "jest",
@@ -31,7 +31,7 @@
31
31
  "@testing-library/jest-dom": "^5.16.1",
32
32
  "@testing-library/react": "^14.0.0",
33
33
  "@testing-library/react-hooks": "^8.0.1",
34
- "@testing-library/user-event": "^13.5.0",
34
+ "@testing-library/user-event": "^14.4.3",
35
35
  "@types/jest": "^27.4.0",
36
36
  "esbuild": "^0.14.10",
37
37
  "esbuild-jest": "^0.5.0",
@@ -3,6 +3,7 @@ import type { Meta } from '@storybook/react';
3
3
  import React, { ReactElement } from 'react';
4
4
  import { OrchestratorPageHeader } from './OrchestratorPageHeader';
5
5
  import Logo from '../../../../../.storybook/mockdata/logo-orchestrator.svg';
6
+ import Image from 'next/image';
6
7
 
7
8
  const Story: Meta<typeof OrchestratorPageHeader> = {
8
9
  component: OrchestratorPageHeader,
@@ -14,7 +15,7 @@ function getAppLogo(navigationLogo: number): ReactElement {
14
15
  return (
15
16
  <EuiFlexGroup alignItems="center" css={{ height: navigationLogo }}>
16
17
  <EuiFlexItem>
17
- <img
18
+ <Image
18
19
  src={Logo}
19
20
  alt="Orchestrator Logo"
20
21
  width={134}
@@ -3,6 +3,7 @@ import { OrchestratorPageTemplate } from './OrchestratorPageTemplate';
3
3
  import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
4
4
  import React, { ReactElement } from 'react';
5
5
  import Logo from '../../../../../.storybook/mockdata/logo-orchestrator.svg';
6
+ import Image from 'next/image';
6
7
 
7
8
  const Story: Meta<typeof OrchestratorPageTemplate> = {
8
9
  component: OrchestratorPageTemplate,
@@ -14,7 +15,7 @@ function getAppLogo(navigationLogo: number): ReactElement {
14
15
  return (
15
16
  <EuiFlexGroup alignItems="center" css={{ height: navigationLogo }}>
16
17
  <EuiFlexItem>
17
- <img
18
+ <Image
18
19
  src={Logo}
19
20
  alt="Orchestrator Logo"
20
21
  width={134}
@@ -10,6 +10,7 @@ import {
10
10
  import { ProcessStatusBadge } from '../Badges';
11
11
  import { SubscriptionProcess, useSubscriptionProcesses } from '../../hooks';
12
12
 
13
+ /** TODO: Adding a useTranslations hook here leads to an hooks error. https://github.com/workfloworchestrator/orchestrator-ui/issues/177 */
13
14
  const Card = (processInfo: SubscriptionProcess) => (
14
15
  <div style={{ marginTop: 5 }}>
15
16
  <table width="100%" bgcolor={'#F1F5F9'}>
@@ -87,7 +88,6 @@ export const ProcessesTimeline: FC<ProcessesTimelineProps> = ({
87
88
  }) => {
88
89
  const { data: subscriptionProcesses } =
89
90
  useSubscriptionProcesses(subscriptionId);
90
- console.log('SUB', subscriptionProcesses);
91
91
 
92
92
  return (
93
93
  <>
@@ -74,6 +74,7 @@ export const ProductBlock = (resourceTypes: ResourceTypeBase, id: number) => {
74
74
  </EuiFlexItem>
75
75
  <EuiFlexItem grow={false}>
76
76
  <EuiButtonIcon
77
+ aria-label="Close"
77
78
  size={'m'}
78
79
  iconType={'cross'}
79
80
  onClick={() => toggleSelectedId(id)}
@@ -8,6 +8,7 @@ import {
8
8
  EuiTitle,
9
9
  EuiPopover,
10
10
  } from '@elastic/eui';
11
+ import { useTranslations } from 'next-intl';
11
12
  import { useSubscriptionActions } from '../../hooks/useSubscriptionActions';
12
13
 
13
14
  type MenuItemProps = {
@@ -39,6 +40,7 @@ export type SubscriptionActionsProps = {
39
40
  export const SubscriptionActions: FC<SubscriptionActionsProps> = ({
40
41
  subscriptionId,
41
42
  }) => {
43
+ const t = useTranslations('subscriptions.detail.workflow');
42
44
  const [isPopoverOpen, setPopover] = useState(false);
43
45
  const { data: subscriptionActions } =
44
46
  useSubscriptionActions(subscriptionId);
@@ -74,7 +76,7 @@ export const SubscriptionActions: FC<SubscriptionActionsProps> = ({
74
76
  <EuiPanel color="transparent" paddingSize="s">
75
77
  {subscriptionActions && subscriptionActions.create && (
76
78
  <>
77
- <MenuBlock title={'Create workflow'}></MenuBlock>
79
+ <MenuBlock title={t('create')}></MenuBlock>
78
80
  {subscriptionActions.create.map((item, index) => (
79
81
  <MenuItem
80
82
  key={`c_${index}`}
@@ -88,7 +90,7 @@ export const SubscriptionActions: FC<SubscriptionActionsProps> = ({
88
90
 
89
91
  {subscriptionActions && subscriptionActions.modify && (
90
92
  <>
91
- <MenuBlock title={'Modify workflow'}></MenuBlock>
93
+ <MenuBlock title={t('modify')}></MenuBlock>
92
94
  {subscriptionActions.modify.map((item, index) => (
93
95
  <MenuItem
94
96
  key={`m_${index}`}
@@ -102,11 +104,11 @@ export const SubscriptionActions: FC<SubscriptionActionsProps> = ({
102
104
 
103
105
  {subscriptionActions && subscriptionActions.system && (
104
106
  <>
105
- <MenuBlock title={'System workflow'}></MenuBlock>
107
+ <MenuBlock title={t('system')}></MenuBlock>
106
108
  {subscriptionActions.system.map((item, index) => (
107
109
  <MenuItem
108
110
  key={`s_${index}`}
109
- icon={'Syste'}
111
+ icon={'System'}
110
112
  description={item.description}
111
113
  index={index}
112
114
  />
@@ -116,7 +118,7 @@ export const SubscriptionActions: FC<SubscriptionActionsProps> = ({
116
118
 
117
119
  {subscriptionActions && subscriptionActions.terminate && (
118
120
  <>
119
- <MenuBlock title={'Terminate workflow'}></MenuBlock>
121
+ <MenuBlock title={t('terminate')}></MenuBlock>
120
122
  {subscriptionActions.terminate.map(
121
123
  (item, index) => (
122
124
  <MenuItem
@@ -7,6 +7,7 @@ import {
7
7
  EuiSpacer,
8
8
  EuiText,
9
9
  } from '@elastic/eui';
10
+ import { useTranslations } from 'next-intl';
10
11
  import { CheckmarkCircleFill, MinusCircleOutline } from '../../icons';
11
12
  import { WFOStatusBadge } from '../Badges';
12
13
  import {
@@ -33,6 +34,7 @@ export const RenderField = (field: string, data: any) => {
33
34
  };
34
35
 
35
36
  export const SubscriptionBlock = (title: string, data: object) => {
37
+ const t = useTranslations('common');
36
38
  const keys = [];
37
39
  for (const key in data) {
38
40
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -56,7 +58,7 @@ export const SubscriptionBlock = (title: string, data: object) => {
56
58
  </EuiFlexItem>
57
59
  <EuiFlexItem grow={false}>
58
60
  <EuiButtonEmpty size={'s'} iconType={'starEmpty'}>
59
- Add to favorites
61
+ {t('addToFavorites')}
60
62
  </EuiButtonEmpty>
61
63
  </EuiFlexItem>
62
64
  </EuiFlexGroup>
@@ -69,7 +71,7 @@ export const SubscriptionBlock = (title: string, data: object) => {
69
71
  valign={'top'}
70
72
  css={subscriptionDefinitionCellStyle}
71
73
  >
72
- <b>Product</b>
74
+ <b>{t('product')}</b>
73
75
  </td>
74
76
  <td css={subscriptionValueCellStyle}>
75
77
  {/*
@@ -1,4 +1,5 @@
1
1
  import React, { useState } from 'react';
2
+ import { useTranslations } from 'next-intl';
2
3
  import { ProductBlockBase, ResourceTypeBase, TreeBlock } from '../../types';
3
4
  import { ProductBlock } from './ProductBlock';
4
5
  import {
@@ -40,6 +41,7 @@ function getProductBlockTitle(resourceType: ResourceTypeBase): string {
40
41
  }
41
42
 
42
43
  export const SubscriptionDetailTree = () => {
44
+ const t = useTranslations('subscriptions.detail');
43
45
  const [expandAllActive, setExpandAllActive] = useState(false);
44
46
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
45
47
  const [selectedTreeNode, setSelectedTreeNode] = useState(-1);
@@ -109,8 +111,8 @@ export const SubscriptionDetailTree = () => {
109
111
  parentNode.children?.push(shallowCopy);
110
112
  }
111
113
  });
112
- console.log('Tree', tree);
113
114
  }
115
+
114
116
  if (!tree) return null;
115
117
 
116
118
  return (
@@ -121,7 +123,7 @@ export const SubscriptionDetailTree = () => {
121
123
  <EuiFlexGroup>
122
124
  <EuiFlexItem grow={false}>
123
125
  <EuiText>
124
- <h3>Product blocks</h3>
126
+ <h3>{t('productBlocks')}</h3>
125
127
  </EuiText>
126
128
  </EuiFlexItem>
127
129
  <EuiFlexItem grow={false}>
@@ -158,13 +160,10 @@ export const SubscriptionDetailTree = () => {
158
160
  minHeight: 600,
159
161
  }}
160
162
  size="m"
161
- title="No product block selected"
163
+ title={t('noProductBlockSelected')}
162
164
  iconType="inspect"
163
165
  >
164
- <p>
165
- Select one or more product blocks to view their
166
- details
167
- </p>
166
+ <p>{t('ctaSelectProductBlock')} </p>
168
167
  </EuiCallOut>
169
168
  )}
170
169
  {selectedIds.length !== 0 &&
@@ -6,13 +6,17 @@ import {
6
6
  EuiLoadingContent,
7
7
  EuiSpacer,
8
8
  } from '@elastic/eui';
9
+ // import { useTranslations } from 'next-intl';
9
10
  import { SubscriptionContext } from '../../contexts/SubscriptionContext';
10
11
  import { SubscriptionBlock } from './SubscriptionBlock';
11
12
  import { FixedInputBlock } from './FixedInputBlock';
12
13
 
14
+ /** TODO: Adding a useTranslations hook here leads to an hooks error. https://github.com/workfloworchestrator/orchestrator-ui/issues/177 */
15
+
13
16
  export const SubscriptionGeneral = () => {
14
17
  const { subscriptionData, loadingStatus } =
15
18
  React.useContext(SubscriptionContext);
19
+
16
20
  if (!loadingStatus) {
17
21
  return (
18
22
  <>
@@ -33,12 +37,12 @@ export const SubscriptionGeneral = () => {
33
37
  </EuiFlexItem>
34
38
  <EuiFlexItem>
35
39
  {FixedInputBlock(
36
- 'Fixed inputs',
40
+ 'Fixed Inputs',
37
41
  subscriptionData.fixedInputs,
38
42
  )}
39
43
  </EuiFlexItem>
40
44
  <EuiFlexItem>
41
- {FixedInputBlock('Product info', subscriptionData.product)}
45
+ {FixedInputBlock('Product Info', subscriptionData.product)}
42
46
  </EuiFlexItem>
43
47
  </>
44
48
  </EuiFlexGrid>
@@ -1,5 +1,6 @@
1
1
  import { EuiTab, EuiTabs } from '@elastic/eui';
2
2
  import React, { FC } from 'react';
3
+ import { useTranslations } from 'next-intl';
3
4
 
4
5
  export enum SubscriptionsTabType {
5
6
  ACTIVE = 'ACTIVE',
@@ -15,14 +16,14 @@ export type FilterQuery = {
15
16
 
16
17
  export type SubscriptionsTab = {
17
18
  id: SubscriptionsTabType;
18
- name: string;
19
+ translationKey: string;
19
20
  alwaysOnFilters?: FilterQuery[];
20
21
  };
21
22
 
22
23
  export const defaultSubscriptionsTabs: SubscriptionsTab[] = [
23
24
  {
24
25
  id: SubscriptionsTabType.ACTIVE,
25
- name: 'Active',
26
+ translationKey: 'active',
26
27
  alwaysOnFilters: [
27
28
  {
28
29
  field: 'status',
@@ -32,7 +33,7 @@ export const defaultSubscriptionsTabs: SubscriptionsTab[] = [
32
33
  },
33
34
  {
34
35
  id: SubscriptionsTabType.TERMINATED,
35
- name: 'Terminated',
36
+ translationKey: 'terminated',
36
37
  alwaysOnFilters: [
37
38
  {
38
39
  field: 'status',
@@ -42,7 +43,7 @@ export const defaultSubscriptionsTabs: SubscriptionsTab[] = [
42
43
  },
43
44
  {
44
45
  id: SubscriptionsTabType.TRANSIENT,
45
- name: 'Transient',
46
+ translationKey: 'transient',
46
47
  alwaysOnFilters: [
47
48
  {
48
49
  field: 'status',
@@ -52,7 +53,7 @@ export const defaultSubscriptionsTabs: SubscriptionsTab[] = [
52
53
  },
53
54
  {
54
55
  id: SubscriptionsTabType.ALL,
55
- name: 'All',
56
+ translationKey: 'all',
56
57
  },
57
58
  ];
58
59
 
@@ -68,19 +69,22 @@ export const SubscriptionsTabs: FC<SubscriptionsTabsProps> = ({
68
69
  tabs,
69
70
  selectedSubscriptionsTab,
70
71
  onChangeSubscriptionsTab,
71
- }) => (
72
- <EuiTabs>
73
- {tabs.map(({ id, name }) => (
74
- <EuiTab
75
- key={id}
76
- isSelected={id === selectedSubscriptionsTab}
77
- onClick={() =>
78
- id !== selectedSubscriptionsTab &&
79
- onChangeSubscriptionsTab(id)
80
- }
81
- >
82
- {name}
83
- </EuiTab>
84
- ))}
85
- </EuiTabs>
86
- );
72
+ }) => {
73
+ const t = useTranslations('subscriptions.tabs');
74
+ return (
75
+ <EuiTabs>
76
+ {tabs.map(({ id, translationKey: name }) => (
77
+ <EuiTab
78
+ key={id}
79
+ isSelected={id === selectedSubscriptionsTab}
80
+ onClick={() =>
81
+ id !== selectedSubscriptionsTab &&
82
+ onChangeSubscriptionsTab(id)
83
+ }
84
+ >
85
+ {t(name)}
86
+ </EuiTab>
87
+ ))}
88
+ </EuiTabs>
89
+ );
90
+ };
@@ -100,7 +100,7 @@ export const DataGridTable = <T,>({
100
100
  ) => EuiDataGridControlColumn = ({ id, width, rowCellRender }) => ({
101
101
  id,
102
102
  width,
103
- headerCellRender: (props) => null,
103
+ headerCellRender: () => null,
104
104
  rowCellRender: ({ rowIndex }: { rowIndex: number }) => {
105
105
  const { pageSize, pageIndex } = pagination;
106
106
  const rowIndexOnPage = rowIndex - pageIndex * pageSize;
@@ -1,2 +1,5 @@
1
1
  export const DEFAULT_PAGE_SIZES = [5, 10, 15, 20, 25, 100];
2
2
  export const DEFAULT_PAGE_SIZE = 10;
3
+
4
+ export const METADATA_PRODUCTBLOCKS_TABLE_LOCAL_STORAGE_KEY =
5
+ 'metadataProductBlocksTable';
@@ -1,7 +1,7 @@
1
1
  import React, { FC } from 'react';
2
+ import { EuiListGroup } from '@elastic/eui';
2
3
 
3
4
  import { TreeNode } from './TreeNode';
4
- import { EuiListGroup } from '@elastic/eui';
5
5
  import { TreeBlock } from '../../types';
6
6
  import { TreeContext, TreeContextType } from '../../contexts/TreeContext';
7
7
 
@@ -1,4 +1,5 @@
1
1
  import React, { FC } from 'react';
2
+ import { useTranslations } from 'next-intl';
2
3
  import {
3
4
  EuiFlexGroup,
4
5
  EuiFlexItem,
@@ -21,6 +22,7 @@ type TreeNodeProps = {
21
22
  };
22
23
 
23
24
  export const TreeNode: FC<TreeNodeProps> = ({ item, hasChildren, level }) => {
25
+ const t = useTranslations('common');
24
26
  const { expandedIds, toggleExpandedId, selectedIds, toggleSelectedId } =
25
27
  React.useContext(TreeContext) as TreeContextType;
26
28
  const expanded = expandedIds.includes(item.id);
@@ -59,7 +61,7 @@ export const TreeNode: FC<TreeNodeProps> = ({ item, hasChildren, level }) => {
59
61
  onClick: () => toggleSelectedId(item.id),
60
62
  iconType: 'error',
61
63
  iconSize: 's',
62
- 'aria-label': 'Deselect',
64
+ 'aria-label': t('deselect'),
63
65
  alwaysShow: true,
64
66
  }}
65
67
  />
@@ -0,0 +1 @@
1
+ export * from './productBlocksQuery';
@@ -0,0 +1,46 @@
1
+ import { gql } from 'graphql-request';
2
+ import { parse } from 'graphql';
3
+ import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
4
+
5
+ import { SortOrder } from '../types';
6
+
7
+ import type { ProductBlockDefinition } from '../types';
8
+ import { GraphqlQueryVariables, ProductBlockDefinitionsResult } from '../types';
9
+
10
+ export const DEFAULT_SORT_FIELD: keyof ProductBlockDefinition = 'name';
11
+ export const DEFAULT_SORT_ORDER: SortOrder = SortOrder.DESC;
12
+
13
+ export const GET_PRODUCTS_BLOCKS_GRAPHQL_QUERY: TypedDocumentNode<
14
+ ProductBlockDefinitionsResult,
15
+ GraphqlQueryVariables<ProductBlockDefinition>
16
+ > = parse(gql`
17
+ query MetadataProductBlocks(
18
+ $first: IntType!
19
+ $after: IntType!
20
+ $sortBy: [GraphqlSort!]
21
+ ) {
22
+ productBlocks(first: $first, after: $after, sortBy: $sortBy) {
23
+ page {
24
+ productBlockId
25
+ name
26
+ tag
27
+ description
28
+ status
29
+ createdAt
30
+ endDate
31
+ resourceTypes {
32
+ description
33
+ resourceType
34
+ resourceTypeId
35
+ }
36
+ }
37
+ pageInfo {
38
+ endCursor
39
+ hasNextPage
40
+ hasPreviousPage
41
+ startCursor
42
+ totalItems
43
+ }
44
+ }
45
+ }
46
+ `);
@@ -12,7 +12,7 @@ import { DEFAULT_PAGE_SIZE } from '../components';
12
12
  export type DataDisplayParams<Type> = {
13
13
  pageSize: number;
14
14
  pageIndex: number;
15
- sortBy?: GraphQLSort<Type>;
15
+ sortBy: GraphQLSort<Type>;
16
16
  esQueryString?: string; // The filter param is going to send to the backend as is for parsing
17
17
  };
18
18
 
package/src/index.ts CHANGED
@@ -5,3 +5,5 @@ export * from './utils';
5
5
  export * from './contexts';
6
6
  export * from './types';
7
7
  export * from './hooks';
8
+ export * from './messages';
9
+ export * from './pages';
@@ -0,0 +1,84 @@
1
+ {
2
+ "main": {
3
+ "title": "Welcome to example-orchestrator-ui!"
4
+ },
5
+ "common": {
6
+ "addToFavorites": "Add to favorites",
7
+ "product": "Product",
8
+ "deselect": "Deselect",
9
+ "close": "Close"
10
+ },
11
+ "metadata": {
12
+ "tabs": {
13
+ "products": "Products",
14
+ "productBlocks": "Productblocks",
15
+ "resourceTypes": "Resource types",
16
+ "fixedInputs": "Fixed inputs",
17
+ "workflows": "Workflows"
18
+ },
19
+ "product": {
20
+ "name": "Name",
21
+ "description": "Description",
22
+ "tag": "Tag",
23
+ "productType": "Type",
24
+ "status": "Status",
25
+ "productBlocks": "Product blocks",
26
+ "createdAt": "Created"
27
+ },
28
+ "productBlocks": {
29
+ "id": "ID",
30
+ "name": "Name",
31
+ "description": "Description",
32
+ "tag": "Tag",
33
+ "status": "status",
34
+ "resourceTypes": "Resource types",
35
+ "createdAt": "Created",
36
+ "endDate": "End date",
37
+ "parentIds": "Parents"
38
+ }
39
+ },
40
+ "subscriptions": {
41
+ "tabs": {
42
+ "active": "Active",
43
+ "terminated": "Terminated",
44
+ "transient": "Transient",
45
+ "all": "All"
46
+ },
47
+ "index": {
48
+ "id": "ID",
49
+ "description": "Description",
50
+ "status": "Status",
51
+ "insync": "In Sync",
52
+ "product": "Product",
53
+ "tag": "Tag",
54
+ "startDate": "Start Date",
55
+ "endDate": "End Date",
56
+ "note": "Note"
57
+ },
58
+ "detail": {
59
+ "tabs": {
60
+ "general": "General",
61
+ "serviceConfiguration": "Service configuration",
62
+ "processes": "Processes",
63
+ "relatedSubscriptions": "Related subscriptions"
64
+ },
65
+ "loadingStatus": "Loading status",
66
+ "workflow": {
67
+ "create": "Create workflow",
68
+ "modify": "Modify workflow",
69
+ "system": "System workflow",
70
+ "terminate": "Terminate workflow"
71
+ },
72
+ "subscriptionDetails": "Subscription details",
73
+ "fixedInputs": "Fixed inputs",
74
+ "productInfo": "Product info",
75
+ "noProductBlockSelected": "No product block selected",
76
+ "productBlocks": "Product blocks",
77
+ "ctaSelectProductBlock": "Select one or more product blocks to view their details",
78
+ "startedBy": "Started by",
79
+ "startedAt": "Started at",
80
+ "status": "Status",
81
+ "id": "ID"
82
+ }
83
+ }
84
+ }
@@ -0,0 +1,51 @@
1
+ import { getTranslationMessages } from './getTranslationMessages';
2
+ import { Locale } from '../types';
3
+ import enUS from './en-US.json';
4
+ import nlNL from './nl-NL.json';
5
+
6
+ describe('getTransalationMessages', () => {
7
+ it('Returns nl-NL translation when nl-NL locale is requested', () => {
8
+ const translation = getTranslationMessages(Locale.nlNL);
9
+ expect(translation).toEqual(nlNL);
10
+ });
11
+
12
+ it('Returns en-US translation when en-US locale is requested', () => {
13
+ const translation = getTranslationMessages(Locale.enUS);
14
+ expect(translation).toEqual(enUS);
15
+ });
16
+
17
+ it('Returns en-US translation when no locale is requested', () => {
18
+ const translation = getTranslationMessages(undefined);
19
+ expect(translation).toEqual(enUS);
20
+ });
21
+ it('Returns en-US translation unknown locale is requested', () => {
22
+ const translation = getTranslationMessages('UNKNOWN-LOCALE');
23
+ expect(translation).toEqual(enUS);
24
+ });
25
+ it('Returns custom translation when custom translations map array is provided', () => {
26
+ const customEN = {
27
+ metadata: {
28
+ product: {
29
+ name: 'CUSTOM-EN-NAME',
30
+ },
31
+ },
32
+ };
33
+
34
+ const customMap = new Map([[Locale.enUS, customEN]]);
35
+ const translation = getTranslationMessages(Locale.enUS, customMap);
36
+ expect(translation).toEqual(customEN);
37
+ });
38
+ it('Returns en-Us translation if unknown locale is requested together with custom translations map', () => {
39
+ const customEN = {
40
+ metadata: {
41
+ product: {
42
+ name: 'CUSTOM-EN-NAME',
43
+ },
44
+ },
45
+ };
46
+
47
+ const customMap = new Map([[Locale.enUS, customEN]]);
48
+ const translation = getTranslationMessages('UNKNOWN-LOCALE', customMap);
49
+ expect(translation).toEqual(customEN);
50
+ });
51
+ });
@@ -0,0 +1,26 @@
1
+ import { AbstractIntlMessages } from 'next-intl';
2
+
3
+ import { Locale } from '../types';
4
+ import nlNL from './nl-NL.json';
5
+ import enUS from './en-US.json';
6
+
7
+ export type TranslationMessagesMap = Map<Locale, AbstractIntlMessages>;
8
+
9
+ const standardMessageMap: TranslationMessagesMap = new Map([
10
+ [Locale.enUS, enUS],
11
+ [Locale.nlNL, nlNL],
12
+ ]);
13
+
14
+ export const getTranslationMessages = (
15
+ locale: string | undefined,
16
+ messages: TranslationMessagesMap = standardMessageMap,
17
+ ) => {
18
+ switch (locale) {
19
+ case Locale.enUS:
20
+ return messages.get(Locale.enUS);
21
+ case Locale.nlNL:
22
+ return messages.get(Locale.nlNL);
23
+ default:
24
+ return messages.get(Locale.enUS);
25
+ }
26
+ };
@@ -0,0 +1 @@
1
+ export * from './getTranslationMessages';