@orchestrator-ui/orchestrator-ui-components 3.4.0 → 3.4.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchestrator-ui/orchestrator-ui-components",
3
- "version": "3.4.0",
3
+ "version": "3.4.2",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Library of UI Components used to display the workflow orchestrator frontend",
6
6
  "author": {
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+
3
+ import type { Meta } from '@storybook/react';
4
+
5
+ import { WfoVersionIncompatibleBadge } from './WfoVersionIncompatibleBadge';
6
+
7
+ const Story: Meta<typeof WfoVersionIncompatibleBadge> = {
8
+ component: (args) => (
9
+ <div style={{ display: 'flex' }}>
10
+ <WfoVersionIncompatibleBadge {...args} />
11
+ </div>
12
+ ),
13
+ title: 'Badges/WfoVersionIncompatibleBadge',
14
+ };
15
+ export default Story;
16
+
17
+ export const Primary = {
18
+ args: {},
19
+ };
@@ -0,0 +1,65 @@
1
+ import React, { FC } from 'react';
2
+
3
+ import { useTranslations } from 'next-intl';
4
+
5
+ import { EuiSpacer, EuiToolTip } from '@elastic/eui';
6
+
7
+ import { WfoHeaderBadge } from '@/components';
8
+ import { useOrchestratorTheme } from '@/hooks';
9
+ import { MappedVersion } from '@/types';
10
+ import { getOrchestratorCoreVersionIfNotCompatible } from '@/utils/compareVersions';
11
+
12
+ import versionCompatibility from '../../../../../../version-compatibility.json';
13
+
14
+ interface WfoVersionIncompatibleBadgeProps {
15
+ orchestratorUiVersion: string;
16
+ orchestratorCoreVersion: string;
17
+ }
18
+
19
+ export const WfoVersionIncompatibleBadge: FC<
20
+ WfoVersionIncompatibleBadgeProps
21
+ > = ({ orchestratorUiVersion, orchestratorCoreVersion }) => {
22
+ const t = useTranslations('main');
23
+ const { theme } = useOrchestratorTheme();
24
+ const mappedVersions: MappedVersion[] = versionCompatibility;
25
+ const minimumOrchestratorCoreVersion =
26
+ getOrchestratorCoreVersionIfNotCompatible(
27
+ orchestratorUiVersion,
28
+ orchestratorCoreVersion,
29
+ mappedVersions,
30
+ );
31
+
32
+ return (
33
+ <EuiToolTip
34
+ content={
35
+ <>
36
+ <p>{t('incompatibleVersionText')}</p>
37
+ <EuiSpacer size="s" />
38
+ <p>
39
+ WFO UI: <b>{orchestratorUiVersion}</b>
40
+ </p>
41
+ <p>
42
+ orchestrator-core: <b>{orchestratorCoreVersion}</b>
43
+ </p>
44
+ <p>
45
+ {t('minimumOrchestratorCoreVersion')}:{' '}
46
+ <b>{minimumOrchestratorCoreVersion}</b>
47
+ </p>
48
+ </>
49
+ }
50
+ >
51
+ <WfoHeaderBadge
52
+ color="danger"
53
+ textColor={theme.colors.ghost}
54
+ css={{
55
+ marginLeft: theme.size.s,
56
+ visibility: minimumOrchestratorCoreVersion
57
+ ? 'visible'
58
+ : 'hidden',
59
+ }}
60
+ >
61
+ {t('incompatibleVersion')}
62
+ </WfoHeaderBadge>
63
+ </EuiToolTip>
64
+ );
65
+ };
@@ -0,0 +1 @@
1
+ export * from './WfoVersionIncompatibleBadge';
@@ -2,6 +2,7 @@ import React, { FC, ReactElement } from 'react';
2
2
 
3
3
  import { useTranslations } from 'next-intl';
4
4
 
5
+ import type { EuiThemeColorMode } from '@elastic/eui';
5
6
  import {
6
7
  EuiBadgeGroup,
7
8
  EuiButtonIcon,
@@ -11,7 +12,6 @@ import {
11
12
  EuiHeaderSectionItem,
12
13
  EuiToolTip,
13
14
  } from '@elastic/eui';
14
- import type { EuiThemeColorMode } from '@elastic/eui';
15
15
 
16
16
  import {
17
17
  WfoEngineStatusBadge,
@@ -19,6 +19,7 @@ import {
19
19
  WfoFailedTasksBadge,
20
20
  WfoWebsocketStatusBadge,
21
21
  } from '@/components';
22
+ import { WfoVersionIncompatibleBadge } from '@/components/WfoBadges/WfoVersionIncompatibleBadge/WfoVersionIncompatibleBadge';
22
23
  import { WfoAppLogo } from '@/components/WfoPageTemplate/WfoPageHeader/WfoAppLogo';
23
24
  import { getWfoPageHeaderStyles } from '@/components/WfoPageTemplate/WfoPageHeader/styles';
24
25
  import { ORCHESTRATOR_UI_LIBRARY_VERSION } from '@/configuration';
@@ -27,6 +28,7 @@ import {
27
28
  useOrchestratorTheme,
28
29
  useWithOrchestratorTheme,
29
30
  } from '@/hooks';
31
+ import { useGetVersionsQuery } from '@/rtk/endpoints/versions';
30
32
  import { ColorModes } from '@/types';
31
33
 
32
34
  import { WfoHamburgerMenu } from './WfoHamburgerMenu';
@@ -49,6 +51,9 @@ export const WfoPageHeader: FC<WfoPageHeaderProps> = ({
49
51
  const { getHeaderStyle, appNameStyle } = useWithOrchestratorTheme(
50
52
  getWfoPageHeaderStyles,
51
53
  );
54
+ const { data } = useGetVersionsQuery();
55
+ const coreVersion =
56
+ data?.version.applicationVersions[0].split(' ')[1] ?? '';
52
57
 
53
58
  return (
54
59
  <EuiHeader css={getHeaderStyle(navigationHeight)}>
@@ -66,6 +71,12 @@ export const WfoPageHeader: FC<WfoPageHeaderProps> = ({
66
71
  <EuiHeaderSectionItem>
67
72
  <WfoEnvironmentBadge />
68
73
  </EuiHeaderSectionItem>
74
+ <EuiHeaderSectionItem>
75
+ <WfoVersionIncompatibleBadge
76
+ orchestratorUiVersion={ORCHESTRATOR_UI_LIBRARY_VERSION}
77
+ orchestratorCoreVersion={coreVersion}
78
+ />
79
+ </EuiHeaderSectionItem>
69
80
  </EuiHeaderSection>
70
81
 
71
82
  <EuiHeaderSection>
@@ -44,7 +44,6 @@ export const WfoPageTemplate: FC<WfoPageTemplateProps> = ({
44
44
  panelled={false}
45
45
  grow={false}
46
46
  contentBorder={false}
47
- minHeight={`calc(100vh - ${NAVIGATION_HEIGHT}px)`}
48
47
  restrictWidth={false}
49
48
  >
50
49
  {isSideMenuVisible && (
@@ -59,7 +58,11 @@ export const WfoPageTemplate: FC<WfoPageTemplateProps> = ({
59
58
  contentRef={headerRowRef}
60
59
  navigationHeight={NAVIGATION_HEIGHT}
61
60
  >
62
- <EuiPageTemplate.Section>
61
+ <EuiPageTemplate.Section
62
+ css={{
63
+ minHeight: `calc(100vh - ${NAVIGATION_HEIGHT}px)`,
64
+ }}
65
+ >
63
66
  <WfoBreadcrumbs
64
67
  handleSideMenuClick={() =>
65
68
  setIsSideMenuVisible((prevState) => !prevState)
@@ -33,20 +33,27 @@ export const WfoDragHandler: FC<WfoDragHandlerProps> = ({
33
33
 
34
34
  const { dragAndDropStyle } = useWithOrchestratorTheme(getWfoTableStyles);
35
35
 
36
+ const thElement =
37
+ headerRowRef.current &&
38
+ (headerRowRef.current.querySelector(
39
+ `th[data-field-name="${fieldName}"]`,
40
+ ) as HTMLTableCellElement);
41
+ const startWidth =
42
+ thElement?.getBoundingClientRect().width ?? MINIMUM_COLUMN_WIDTH;
43
+
36
44
  return (
37
45
  <div>
38
46
  <Draggable
39
47
  axis="x"
40
48
  position={position}
41
49
  onDrag={onDrag}
42
- bounds="thead"
50
+ bounds={{
51
+ left: MINIMUM_COLUMN_WIDTH - startWidth,
52
+ top: 0,
53
+ bottom: 0,
54
+ }}
43
55
  onStop={(_, data) => {
44
56
  if (headerRowRef.current) {
45
- const thElement = headerRowRef.current.querySelector(
46
- `th[data-field-name="${fieldName}"]`,
47
- ) as HTMLTableCellElement;
48
- const startWidth =
49
- thElement.getBoundingClientRect().width;
50
57
  const newWidth = startWidth + data.x;
51
58
 
52
59
  onUpdateColumWidth(
@@ -72,6 +72,7 @@ export const useGroupedTableConfig = <T extends object>({
72
72
  groupName: {
73
73
  columnType: ColumnType.CONTROL,
74
74
  label: groupNameLabel,
75
+ width: 'calc(100vw - 300px)', //TODO: #1807
75
76
  numberOfColumnsToSpan: numberOfColumnsInnerTable,
76
77
  renderControl: ({ groupName }) => {
77
78
  const isExpanded = expandedRowIds.includes(groupName);
@@ -146,6 +146,7 @@ export const WfoTable = <T extends object>({
146
146
  cellStyle,
147
147
  rowStyle,
148
148
  emptyTableMessageStyle,
149
+ paginationStyle,
149
150
  } = useWithOrchestratorTheme(getWfoTableStyles);
150
151
  const t = useTranslations('common');
151
152
 
@@ -228,7 +229,7 @@ export const WfoTable = <T extends object>({
228
229
  </table>
229
230
  </div>
230
231
  {pagination && (
231
- <>
232
+ <div css={paginationStyle}>
232
233
  <EuiSpacer size="xs" />
233
234
  <EuiTablePagination
234
235
  pageCount={Math.ceil(
@@ -242,7 +243,7 @@ export const WfoTable = <T extends object>({
242
243
  onChangePage={pagination.onChangePage}
243
244
  onChangeItemsPerPage={pagination.onChangeItemsPerPage}
244
245
  />
245
- </>
246
+ </div>
246
247
  )}
247
248
  </>
248
249
  );
@@ -37,7 +37,7 @@ export const getWfoTableStyles = ({ theme, isDarkThemeActive }: WfoTheme) => {
37
37
  });
38
38
 
39
39
  const tableStyle = css({
40
- width: '100%',
40
+ width: 'auto',
41
41
  });
42
42
 
43
43
  const headerStyle = css({
@@ -136,14 +136,31 @@ export const getWfoTableStyles = ({ theme, isDarkThemeActive }: WfoTheme) => {
136
136
  height: '100%',
137
137
  zIndex: theme.levels.modal,
138
138
  '&:hover, &:active': {
139
+ transition: 'background-color 0.15s',
139
140
  backgroundColor: isDarkThemeActive
140
141
  ? theme.colors.mediumShade
141
142
  : theme.colors.header,
142
143
  },
143
144
  '&::after': {
144
- content: '""',
145
+ display: 'flex',
146
+ paddingTop: theme.base - (theme.base / 16) * 2,
147
+ content: `"|"`, // Inserts a vertical line
148
+ fontSize: theme.size.m,
149
+ color: theme.colors.mediumShade,
150
+ cursor: 'col-resize',
151
+ opacity: 0.6,
152
+ zIndex: theme.levels.navigation,
153
+ },
154
+ '&:hover::after, &:active::after': {
155
+ transition: 'opacity 0.15s',
156
+ opacity: 0,
145
157
  },
146
158
  });
159
+
160
+ const paginationStyle = css({
161
+ '.eui-xScroll': { display: 'flex', justifyContent: 'flex-start' },
162
+ });
163
+
147
164
  return {
148
165
  tableContainerStyle,
149
166
  tableStyle,
@@ -159,6 +176,7 @@ export const getWfoTableStyles = ({ theme, isDarkThemeActive }: WfoTheme) => {
159
176
  emptyTableMessageStyle,
160
177
  clickableStyle,
161
178
  dragAndDropStyle,
179
+ paginationStyle,
162
180
  setWidth,
163
181
  };
164
182
  };
@@ -1 +1 @@
1
- export const ORCHESTRATOR_UI_LIBRARY_VERSION = '3.4.0';
1
+ export const ORCHESTRATOR_UI_LIBRARY_VERSION = '3.4.2';
@@ -24,7 +24,11 @@
24
24
  "resetToDefault": "Reset to default",
25
25
  "savePreferences": "Save preferences",
26
26
  "numberOfRows": "Number of rows",
27
- "tableSettings": "Table settings"
27
+ "tableSettings": "Table settings",
28
+ "openMenu": "Open menu",
29
+ "incompatibleVersion": "Incompatible version",
30
+ "incompatibleVersionText": "The version of the WFO UI is incompatible with this version of orchestrator-core.",
31
+ "minimumOrchestratorCoreVersion": "Minimum orchestrator-core version"
28
32
  },
29
33
  "common": {
30
34
  "product": "Product",
@@ -25,7 +25,9 @@
25
25
  "savePreferences": "Voorkeuren opslaan",
26
26
  "numberOfRows": "Aantal rijen",
27
27
  "tableSettings": "Tabel instellingen",
28
- "openMenu": "Open menu"
28
+ "openMenu": "Open menu",
29
+ "incompatibleVersion": "Incompatibele versie",
30
+ "minimumOrchestratorCoreVersion": "Minimale versie van orchestrator-core"
29
31
  },
30
32
  "common": {
31
33
  "product": "Produkt",
@@ -604,6 +604,13 @@ export enum CacheTagType {
604
604
  processStatusCounts = 'processStatusCounts',
605
605
  subscriptions = 'subscriptions',
606
606
  }
607
+
608
+ export interface MappedVersion {
609
+ orchestratorUiVersion: string;
610
+ minimumOrchestratorCoreVersion: string;
611
+ changes: string;
612
+ }
613
+
607
614
  export type CacheTag = { type: CacheTagType; id?: string };
608
615
 
609
616
  export const CACHETAG_TYPE_LIST = 'LIST';
@@ -0,0 +1,129 @@
1
+ import { MappedVersion } from '@/types';
2
+
3
+ import { getOrchestratorCoreVersionIfNotCompatible } from './compareVersions';
4
+
5
+ const TEST_VERSIONS: MappedVersion[] = [
6
+ {
7
+ orchestratorUiVersion: '3.4.0',
8
+ minimumOrchestratorCoreVersion: '2.10.0',
9
+ changes: 'Endpoints in BE to modify description on metadata pages',
10
+ },
11
+ {
12
+ orchestratorUiVersion: '3.8.1',
13
+ minimumOrchestratorCoreVersion: '3.0.0',
14
+ changes: 'Endpoints in BE to modify description on metadata pages',
15
+ },
16
+ {
17
+ orchestratorUiVersion: '3.10.0',
18
+ minimumOrchestratorCoreVersion: '3.1.1',
19
+ changes: 'Endpoints in BE to modify description on metadata pages',
20
+ },
21
+ ];
22
+
23
+ describe('isOrchestratorUiVersionCompatible', () => {
24
+ test('returns true if orchestratorCoreVersion matches exactly the minimum required orchestratorCoreVersion', () => {
25
+ expect(
26
+ getOrchestratorCoreVersionIfNotCompatible(
27
+ '3.4.0',
28
+ '2.10.0',
29
+ TEST_VERSIONS,
30
+ ),
31
+ ).toBe(null);
32
+ expect(
33
+ getOrchestratorCoreVersionIfNotCompatible(
34
+ '3.8.1',
35
+ '3.0.0',
36
+ TEST_VERSIONS,
37
+ ),
38
+ ).toBe(null);
39
+ expect(
40
+ getOrchestratorCoreVersionIfNotCompatible(
41
+ '3.10.0',
42
+ '3.1.1',
43
+ TEST_VERSIONS,
44
+ ),
45
+ ).toBe(null);
46
+ });
47
+
48
+ test('returns true if orchestratorCoreVersion is newer than the minimum required orchestratorCoreVersion', () => {
49
+ expect(
50
+ getOrchestratorCoreVersionIfNotCompatible(
51
+ '3.4.0',
52
+ '2.11.0',
53
+ TEST_VERSIONS,
54
+ ),
55
+ ).toBe(null);
56
+ expect(
57
+ getOrchestratorCoreVersionIfNotCompatible(
58
+ '3.8.1',
59
+ '3.0.1',
60
+ TEST_VERSIONS,
61
+ ),
62
+ ).toBe(null);
63
+ expect(
64
+ getOrchestratorCoreVersionIfNotCompatible(
65
+ '3.10.0',
66
+ '4.2.0',
67
+ TEST_VERSIONS,
68
+ ),
69
+ ).toBe(null);
70
+ });
71
+
72
+ test('returns false if orchestratorCoreVersion is older than minimum required orchestratorCoreVersion', () => {
73
+ expect(
74
+ getOrchestratorCoreVersionIfNotCompatible(
75
+ '3.4.0',
76
+ '2.9.9',
77
+ TEST_VERSIONS,
78
+ ),
79
+ ).toBe('2.10.0');
80
+ expect(
81
+ getOrchestratorCoreVersionIfNotCompatible(
82
+ '3.8.1',
83
+ '2.10.9',
84
+ TEST_VERSIONS,
85
+ ),
86
+ ).toBe('3.0.0');
87
+ expect(
88
+ getOrchestratorCoreVersionIfNotCompatible(
89
+ '3.10.0',
90
+ '3.0.5',
91
+ TEST_VERSIONS,
92
+ ),
93
+ ).toBe('3.1.1');
94
+ });
95
+
96
+ test('handles orchestratorUiVersions not exactly in MAPPED_VERSIONS by selecting previous compatible minimum version', () => {
97
+ expect(
98
+ getOrchestratorCoreVersionIfNotCompatible(
99
+ '3.9.0',
100
+ '3.0.0',
101
+ TEST_VERSIONS,
102
+ ),
103
+ ).toBe(null); // nearest lower mapped version is 3.8.1
104
+ expect(
105
+ getOrchestratorCoreVersionIfNotCompatible(
106
+ '3.11.0',
107
+ '3.1.1',
108
+ TEST_VERSIONS,
109
+ ),
110
+ ).toBe(null); // nearest lower mapped is 3.10.0
111
+ });
112
+
113
+ test('handles orchestratorUiVersions lower than lowest mapped version', () => {
114
+ expect(
115
+ getOrchestratorCoreVersionIfNotCompatible(
116
+ '1.0.0',
117
+ '2.10.0',
118
+ TEST_VERSIONS,
119
+ ),
120
+ ).toBe(null); // falls back to first MAPPED_VERSION
121
+ expect(
122
+ getOrchestratorCoreVersionIfNotCompatible(
123
+ '1.0.0',
124
+ '2.9.9',
125
+ TEST_VERSIONS,
126
+ ),
127
+ ).toBe('2.10.0');
128
+ });
129
+ });
@@ -0,0 +1,64 @@
1
+ import { MappedVersion } from '@/types';
2
+
3
+ const compareVersions = (
4
+ versionString1: string,
5
+ versionString2: string,
6
+ ): number => {
7
+ const splittedVersion1 = versionString1.split('.');
8
+ const splittedVersion2 = versionString2.split('.');
9
+
10
+ for (let i = 0; i < splittedVersion1.length; i++) {
11
+ if (parseInt(splittedVersion1[i]) > parseInt(splittedVersion2[i])) {
12
+ return 1;
13
+ } else if (
14
+ parseInt(splittedVersion1[i]) < parseInt(splittedVersion2[i])
15
+ ) {
16
+ return -1;
17
+ }
18
+ }
19
+ return 0;
20
+ };
21
+
22
+ const findMinimumOrchestratorCoreVersion = (
23
+ orchestratorUiVersion: string,
24
+ versionMappings: MappedVersion[],
25
+ ): string => {
26
+ const orchestratorUiVersions = versionMappings.map(
27
+ (version) => version.orchestratorUiVersion,
28
+ );
29
+ let mappedVersion = versionMappings[0];
30
+
31
+ for (let i = 0; i < orchestratorUiVersions.length; i++) {
32
+ if (
33
+ [0, 1].includes(
34
+ compareVersions(
35
+ orchestratorUiVersion,
36
+ orchestratorUiVersions[i],
37
+ ),
38
+ )
39
+ ) {
40
+ mappedVersion = versionMappings[i];
41
+ }
42
+ }
43
+
44
+ return mappedVersion.minimumOrchestratorCoreVersion;
45
+ };
46
+
47
+ export const getOrchestratorCoreVersionIfNotCompatible = (
48
+ orchestratorUiVersion: string,
49
+ orchestratorCoreVersion: string,
50
+ versionMappings: MappedVersion[],
51
+ ): string | null => {
52
+ const minimumOrchestratorCoreVersion = findMinimumOrchestratorCoreVersion(
53
+ orchestratorUiVersion,
54
+ versionMappings,
55
+ );
56
+ const comparison = compareVersions(
57
+ orchestratorCoreVersion,
58
+ minimumOrchestratorCoreVersion,
59
+ );
60
+ if (comparison === -1) {
61
+ return minimumOrchestratorCoreVersion;
62
+ }
63
+ return null;
64
+ };