@orchestrator-ui/orchestrator-ui-components 8.7.3 → 8.8.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.
Files changed (52) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/.turbo/turbo-test.log +17 -15
  4. package/CHANGELOG.md +34 -0
  5. package/dist/index.d.ts +42 -20
  6. package/dist/index.js +1612 -1378
  7. package/dist/index.js.map +1 -1
  8. package/package.json +4 -3
  9. package/src/components/WfoBadges/WfoWorkflowTargetBadge/WfoWorkflowTargetBadge.tsx +2 -2
  10. package/src/components/WfoContentHeader/WfoContentHeader.tsx +1 -1
  11. package/src/components/WfoInlineNoteEdit/WfoProcessListNoteEdit.spec.tsx +35 -0
  12. package/src/components/WfoInlineNoteEdit/WfoProcessListNoteEdit.tsx +7 -9
  13. package/src/components/WfoProcessList/WfoProcessListDeltaPopover.tsx +1 -1
  14. package/src/components/WfoProcessList/WfoProcessesList.tsx +7 -5
  15. package/src/components/WfoPydanticForm/fields/WfoMultiCheckboxField.tsx +2 -1
  16. package/src/components/WfoSubscription/WfoProcessesTimeline.tsx +21 -7
  17. package/src/components/WfoSubscription/WfoSubscriptionActions/WfoSubscriptionActions.tsx +25 -9
  18. package/src/components/WfoSubscription/WfoSubscriptionGeneralSections/WfoSubscriptionDetailSection.tsx +1 -1
  19. package/src/components/WfoSubscription/styles.ts +6 -0
  20. package/src/components/WfoSubscription/utils/utils.ts +2 -4
  21. package/src/components/WfoTable/WfoStructuredSearchTable/WfoExpandingSearchRow.tsx +0 -1
  22. package/src/components/WfoTable/WfoStructuredSearchTable/WfoFieldSelector.tsx +12 -8
  23. package/src/components/WfoTable/WfoStructuredSearchTable/WfoFilterBuilder.tsx +23 -10
  24. package/src/components/WfoTable/WfoStructuredSearchTable/WfoStructuredSearchTable.tsx +73 -3
  25. package/src/components/WfoTable/WfoStructuredSearchTable/WfoValueEditor.tsx +4 -2
  26. package/src/components/WfoTable/WfoStructuredSearchTable/styles.ts +8 -9
  27. package/src/components/WfoTable/WfoTable/WfoTable.tsx +80 -45
  28. package/src/components/WfoTable/WfoTable/WfoTableDataRows.tsx +11 -2
  29. package/src/components/WfoTable/WfoTable/WfoTableExpandedRowReveal.spec.tsx +120 -0
  30. package/src/components/WfoTable/WfoTable/WfoTableSkeletonRows.tsx +52 -0
  31. package/src/components/WfoTable/WfoTable/index.ts +1 -0
  32. package/src/components/WfoTable/WfoTable/styles.ts +6 -0
  33. package/src/components/WfoTable/WfoTableSettingsModal/WfoTableSettingsModal.tsx +21 -18
  34. package/src/components/WfoTable/WfoTableSettingsModal/styles.ts +17 -0
  35. package/src/components/WfoTable/utils/tableConfigPersistence.ts +2 -0
  36. package/src/components/WfoTimeline/styles.ts +1 -1
  37. package/src/components/WfoWorkflowUserGuide/WfoPageWithUserGuide.tsx +8 -2
  38. package/src/components/WfoWorkflowUserGuide/WfoWorkflowGuideExpandablePanel.tsx +39 -30
  39. package/src/components/WfoWorkflowUserGuide/styles.ts +55 -7
  40. package/src/configuration/constants.ts +1 -1
  41. package/src/configuration/version.ts +1 -1
  42. package/src/hooks/useGetPydanticFormsConfig.tsx +5 -3
  43. package/src/hooks/useSearch.ts +2 -2
  44. package/src/hooks/useStoredTableConfig.ts +2 -0
  45. package/src/messages/en-GB.json +5 -1
  46. package/src/messages/nl-NL.json +6 -2
  47. package/src/pages/WfoSearchPocPage.tsx +29 -24
  48. package/src/pages/processes/WfoProductInformationWithLink.tsx +9 -4
  49. package/src/pages/tasks/WfoTasksListPage.tsx +1 -0
  50. package/src/types/search.ts +8 -0
  51. package/src/types/types.ts +11 -11
  52. package/src/utils/getDefaultTableConfig.ts +2 -0
@@ -10,6 +10,7 @@ import { EuiButtonGroup, EuiDatePicker, EuiFieldNumber, EuiFieldText } from '@el
10
10
  import { WfoRangeEditor } from '@/components/WfoTable/WfoStructuredSearchTable/WfoRangeEditor';
11
11
  import { getWfoStructuredSearchTableStyles } from '@/components/WfoTable/WfoStructuredSearchTable/styles';
12
12
  import { useWithOrchestratorTheme } from '@/hooks';
13
+ import type { WfoQueryBuilderContext } from '@/types';
13
14
 
14
15
  export interface EditorInputFieldProps<T = string> {
15
16
  handleOnChange: ValueEditorProps['handleOnChange'];
@@ -176,7 +177,8 @@ export const WfoValueEditor = ({
176
177
  return TextEditor;
177
178
  };
178
179
 
179
- const fieldPathInfoMap = context?.fieldPathInfoMap;
180
+ const queryBuilderContext: WfoQueryBuilderContext | undefined = context;
181
+ const fieldPathInfoMap = queryBuilderContext?.fieldPathInfoMap;
180
182
 
181
183
  const fieldInfo = fieldPathInfoMap && fieldPathInfoMap.has(fieldName) ? fieldPathInfoMap.get(fieldName) : undefined;
182
184
  const uiFieldType = fieldInfo?.ui_types?.[0] || UiFieldType.text;
@@ -198,7 +200,7 @@ export const WfoValueEditor = ({
198
200
  // the boolean buttons means "select" — its click fires only after this keydown, so
199
201
  // searching there would use the pre-toggle value.
200
202
  if (!(event.target instanceof HTMLInputElement)) return;
201
- context?.onValueEditorEnter?.();
203
+ queryBuilderContext?.onValueEditorEnter();
202
204
  };
203
205
 
204
206
  // react-querybuilder delivers the standard `rule-value` class via this prop; the wrapper
@@ -2,7 +2,7 @@ import { css } from '@emotion/react';
2
2
 
3
3
  import { WfoThemeHelpers } from '@/hooks';
4
4
 
5
- export const getWfoStructuredSearchTableStyles = ({ theme }: WfoThemeHelpers) => {
5
+ export const getWfoStructuredSearchTableStyles = ({ theme, isDarkModeActive }: WfoThemeHelpers) => {
6
6
  const queryBuilderContainerStyles = css({
7
7
  backgroundColor: theme.colors.backgroundBaseSubdued,
8
8
  padding: theme.base / 2,
@@ -63,7 +63,7 @@ export const getWfoStructuredSearchTableStyles = ({ theme }: WfoThemeHelpers) =>
63
63
  const ruleGroupContainerBlueStyles = css({
64
64
  ...ruleGroupContainerBase,
65
65
  borderRadius: theme.border.radius.small,
66
- backgroundColor: '#E9F1F9',
66
+ backgroundColor: isDarkModeActive ? theme.colors.backgroundLightPrimary : '#E9F1F9',
67
67
  });
68
68
 
69
69
  const ruleGroupContainerWhiteStyles = css({
@@ -83,7 +83,7 @@ export const getWfoStructuredSearchTableStyles = ({ theme }: WfoThemeHelpers) =>
83
83
  ...ruleGroupContainerBase,
84
84
  borderBottomLeftRadius: theme.border.radius.small,
85
85
  borderTopLeftRadius: theme.border.radius.small,
86
- backgroundColor: '#E9F1F9',
86
+ backgroundColor: isDarkModeActive ? theme.colors.backgroundLightPrimary : '#E9F1F9',
87
87
  });
88
88
 
89
89
  const removeGroupActionStyles = css({
@@ -99,11 +99,10 @@ export const getWfoStructuredSearchTableStyles = ({ theme }: WfoThemeHelpers) =>
99
99
  });
100
100
 
101
101
  const expandingSearchRowStyles = css({
102
- padding: theme.base / 2,
103
- height: theme.base * 2,
102
+ padding: `${theme.base / 4}px ${theme.base / 2}px`,
104
103
  borderRadius: theme.border.radius.medium,
105
- border: 'thin solid FEF7E0',
106
- backgroundColor: '#FEF7E0',
104
+ border: `thin solid ${theme.colors.highlight}`,
105
+ backgroundColor: theme.colors.highlight,
107
106
  });
108
107
  const expandingRowBodyStyles = css({
109
108
  display: 'flex',
@@ -166,12 +165,12 @@ export const getWfoStructuredSearchTableStyles = ({ theme }: WfoThemeHelpers) =>
166
165
  display: 'none',
167
166
  });
168
167
  const dotStyles = css({
169
- padding: theme.base / 4,
168
+ padding: `${theme.base / 8}px ${theme.base / 4}px`,
170
169
  });
171
170
 
172
171
  const expandingRowFieldStyles = css({
173
172
  display: 'flex',
174
- padding: theme.base / 4,
173
+ padding: `${theme.base / 8}px ${theme.base / 4}px`,
175
174
  alignItems: 'center',
176
175
  });
177
176
 
@@ -13,6 +13,7 @@ import { DEFAULT_PAGE_SIZES } from '../utils/constants';
13
13
  import { getPageCount } from '../utils/tableUtils';
14
14
  import { WfoTableDataRows } from './WfoTableDataRows';
15
15
  import { WfoTableHeaderRow } from './WfoTableHeaderRow';
16
+ import { WfoTableSkeletonRows } from './WfoTableSkeletonRows';
16
17
  import { getWfoTableStyles } from './styles';
17
18
  import { getColumnWidthsFromConfig, getSortedVisibleColumns, usePageIndexBoundsGuard } from './utils';
18
19
 
@@ -78,12 +79,14 @@ export type WfoTableProps<T extends object> = {
78
79
  hiddenColumns?: TableColumnKeys<T>;
79
80
  columnOrder?: TableColumnKeys<T>;
80
81
  isLoading?: boolean;
82
+ loadingSkeletonRowCount?: number;
81
83
  dataSorting?: WfoDataSorting<T>[];
82
84
  rowExpandingConfiguration?: {
83
85
  uniqueRowId: keyof WfoTableColumnConfig<T>;
84
86
  uniqueRowIdToExpandedRowMap: Record<string, ReactNode>;
85
- shouldOnlyShowOnHover?: boolean;
86
87
  };
88
+ // When true, every row's expanded detail row is revealed at once (otherwise all are hidden)
89
+ showExpandedRows?: boolean;
87
90
  pagination?: Pagination;
88
91
  overrideHeader?: (
89
92
  tableHeaderEntries: Array<[string, WfoTableControlColumnConfigItem<T> | WfoTableDataColumnConfigItem<T, keyof T>]>,
@@ -105,8 +108,10 @@ export const WfoTable = <T extends object>({
105
108
  hiddenColumns = [],
106
109
  columnOrder = [],
107
110
  isLoading = false,
111
+ loadingSkeletonRowCount,
108
112
  dataSorting = [],
109
113
  rowExpandingConfiguration,
114
+ showExpandedRows = false,
110
115
  pagination,
111
116
  overrideHeader,
112
117
  onUpdateDataSorting,
@@ -123,6 +128,8 @@ export const WfoTable = <T extends object>({
123
128
  const dataLength = data.length;
124
129
  usePageIndexBoundsGuard({ dataLength, isLoading, pagination });
125
130
 
131
+ const showLoadingSkeleton = !!loadingSkeletonRowCount && isLoading && dataLength === 0;
132
+
126
133
  const parentRef = useRef<HTMLDivElement>(null);
127
134
 
128
135
  const columnConfigWithFiller: WfoTableColumnConfig<T> =
@@ -190,6 +197,77 @@ export const WfoTable = <T extends object>({
190
197
  const virtualTrHeight = virtualItems[0]?.start ?? 0;
191
198
  const bottomSpacerHeight = totalSize - lastVirtualItemEnd;
192
199
 
200
+ const WfoTableBody = () => {
201
+ if (showLoadingSkeleton) {
202
+ return (
203
+ <tbody css={bodyLoadingStyle} aria-busy={true}>
204
+ <WfoTableSkeletonRows
205
+ rowCount={loadingSkeletonRowCount}
206
+ columnConfig={configWithLocalWidths}
207
+ hiddenColumns={hiddenColumns}
208
+ columnOrder={columnOrder}
209
+ />
210
+ </tbody>
211
+ );
212
+ }
213
+
214
+ if (dataLength === 0) {
215
+ return (
216
+ <tbody css={isLoading && bodyLoadingStyle}>
217
+ <tr css={rowStyle}>
218
+ <td colSpan={sortedVisibleColumns.length} css={[cellStyle, emptyTableMessageStyle]}>
219
+ {isLoading ? t('loading') : t('noItemsFound')}
220
+ </td>
221
+ </tr>
222
+ </tbody>
223
+ );
224
+ }
225
+
226
+ if (isVirtualized && height) {
227
+ return (
228
+ <tbody>
229
+ <tr
230
+ style={{
231
+ height: virtualTrHeight,
232
+ }}
233
+ />
234
+
235
+ {virtualItems.map((virtualRow) => (
236
+ <WfoTableDataRows
237
+ key={virtualRow.key}
238
+ data={[data[virtualRow.index]]}
239
+ columnConfig={configWithLocalWidths}
240
+ hiddenColumns={hiddenColumns}
241
+ columnOrder={columnOrder}
242
+ rowExpandingConfiguration={rowExpandingConfiguration}
243
+ showExpandedRows={showExpandedRows}
244
+ onRowClick={onRowClick}
245
+ />
246
+ ))}
247
+ <tr
248
+ style={{
249
+ height: bottomSpacerHeight,
250
+ }}
251
+ />
252
+ </tbody>
253
+ );
254
+ }
255
+
256
+ return (
257
+ <tbody css={isLoading && bodyLoadingStyle}>
258
+ <WfoTableDataRows
259
+ data={data}
260
+ columnConfig={configWithLocalWidths}
261
+ hiddenColumns={hiddenColumns}
262
+ columnOrder={columnOrder}
263
+ rowExpandingConfiguration={rowExpandingConfiguration}
264
+ showExpandedRows={showExpandedRows}
265
+ onRowClick={onRowClick}
266
+ />
267
+ </tbody>
268
+ );
269
+ };
270
+
193
271
  return (
194
272
  <>
195
273
  <div
@@ -212,50 +290,7 @@ export const WfoTable = <T extends object>({
212
290
  />
213
291
  </thead>
214
292
  }
215
- {dataLength === 0 ?
216
- <tbody css={isLoading && bodyLoadingStyle}>
217
- <tr css={rowStyle}>
218
- <td colSpan={sortedVisibleColumns.length} css={[cellStyle, emptyTableMessageStyle]}>
219
- {isLoading ? t('loading') : t('noItemsFound')}
220
- </td>
221
- </tr>
222
- </tbody>
223
- : isVirtualized && height ?
224
- <tbody>
225
- <tr
226
- style={{
227
- height: virtualTrHeight,
228
- }}
229
- />
230
-
231
- {virtualItems.map((virtualRow) => (
232
- <WfoTableDataRows
233
- key={virtualRow.key}
234
- data={[data[virtualRow.index]]}
235
- columnConfig={configWithLocalWidths}
236
- hiddenColumns={hiddenColumns}
237
- columnOrder={columnOrder}
238
- rowExpandingConfiguration={rowExpandingConfiguration}
239
- onRowClick={onRowClick}
240
- />
241
- ))}
242
- <tr
243
- style={{
244
- height: bottomSpacerHeight,
245
- }}
246
- />
247
- </tbody>
248
- : <tbody css={isLoading && bodyLoadingStyle}>
249
- <WfoTableDataRows
250
- data={data}
251
- columnConfig={configWithLocalWidths}
252
- hiddenColumns={hiddenColumns}
253
- columnOrder={columnOrder}
254
- rowExpandingConfiguration={rowExpandingConfiguration}
255
- onRowClick={onRowClick}
256
- />
257
- </tbody>
258
- }
293
+ {<WfoTableBody />}
259
294
  </table>
260
295
  </div>
261
296
  {pagination && (
@@ -11,7 +11,14 @@ import { getSortedVisibleColumns } from './utils';
11
11
 
12
12
  export type WfoTableDataRowsProps<T extends object> = Pick<
13
13
  WfoTableProps<T>,
14
- 'data' | 'columnConfig' | 'hiddenColumns' | 'columnOrder' | 'rowExpandingConfiguration' | 'onRowClick' | 'className'
14
+ | 'data'
15
+ | 'columnConfig'
16
+ | 'hiddenColumns'
17
+ | 'columnOrder'
18
+ | 'rowExpandingConfiguration'
19
+ | 'showExpandedRows'
20
+ | 'onRowClick'
21
+ | 'className'
15
22
  >;
16
23
 
17
24
  export const DATA_ROW_CLASS = 'data-row';
@@ -24,6 +31,7 @@ export const WfoTableDataRows = <T extends object>({
24
31
  hiddenColumns = [],
25
32
  columnOrder = [],
26
33
  rowExpandingConfiguration,
34
+ showExpandedRows,
27
35
  onRowClick,
28
36
  className,
29
37
  }: WfoTableDataRowsProps<T>) => {
@@ -34,6 +42,7 @@ export const WfoTableDataRows = <T extends object>({
34
42
  dataRowStyle,
35
43
  clickableStyle,
36
44
  setWidth,
45
+ showExpandedRowStyle,
37
46
  toggleExpandedRowOnHoverStyle,
38
47
  } = useWithOrchestratorTheme(getWfoTableStyles);
39
48
 
@@ -49,7 +58,7 @@ export const WfoTableDataRows = <T extends object>({
49
58
  rowStyle,
50
59
  dataRowStyle,
51
60
  onRowClick && clickableStyle,
52
- rowExpandingConfiguration?.shouldOnlyShowOnHover && toggleExpandedRowOnHoverStyle,
61
+ rowExpandingConfiguration && (showExpandedRows ? showExpandedRowStyle : toggleExpandedRowOnHoverStyle),
53
62
  ]}
54
63
  onClick={() => onRowClick?.(row)}
55
64
  >
@@ -0,0 +1,120 @@
1
+ /**
2
+ * The expanded ("match details") row under each data row hides itself with display: none and
3
+ * is revealed by sibling selectors that WfoTable puts on the data row: always when
4
+ * showExpandedRows is set, and on hover/focus otherwise. These tests pin the whole mechanism
5
+ * down at the DOM level: the detail row must be the data row's next sibling, the reveal rules
6
+ * must be emitted, and their selectors must actually match the detail row.
7
+ */
8
+ import React from 'react';
9
+
10
+ import { css } from '@emotion/react';
11
+ import '@testing-library/jest-dom';
12
+ import { render, screen } from '@testing-library/react';
13
+
14
+ import { ColumnType, WfoTable, WfoTableColumnConfig } from './WfoTable';
15
+
16
+ jest.mock('next-intl', () => ({
17
+ useTranslations: () => (key: string) => key,
18
+ }));
19
+
20
+ type Item = { id: string; name: string };
21
+
22
+ const data: Item[] = [
23
+ { id: 'row-1', name: 'First row' },
24
+ { id: 'row-2', name: 'Second row' },
25
+ ];
26
+
27
+ const columnConfig: WfoTableColumnConfig<Item> = {
28
+ name: {
29
+ columnType: ColumnType.DATA,
30
+ label: 'Name',
31
+ },
32
+ };
33
+
34
+ // Mimics WfoExpandingSearchRow: a <tr> that hides itself
35
+ const hideStyle = css({ display: 'none' });
36
+ const DetailRow = ({ text }: { text: string }) => (
37
+ <tr css={hideStyle}>
38
+ <td>{text}</td>
39
+ </tr>
40
+ );
41
+
42
+ const rowExpandingConfiguration = {
43
+ uniqueRowId: 'id' as keyof WfoTableColumnConfig<Item>,
44
+ uniqueRowIdToExpandedRowMap: {
45
+ 'row-1': <DetailRow text="detail-1" />,
46
+ 'row-2': <DetailRow text="detail-2" />,
47
+ },
48
+ };
49
+
50
+ // Emotion may insert rules through the CSSOM, leaving <style> tags without text content, so
51
+ // read the rules from document.styleSheets. Returns [selectorText, display] pairs, with the
52
+ // selector whitespace stripped since the CSSOM normalizes it.
53
+ const getDisplayRules = () =>
54
+ Array.from(document.styleSheets)
55
+ .flatMap((sheet) => Array.from(sheet.cssRules))
56
+ .filter((rule): rule is CSSStyleRule => 'selectorText' in rule)
57
+ .map((rule): [string, string] => [rule.selectorText.replace(/\s+/g, ''), rule.style.display])
58
+ .filter(([, display]) => Boolean(display));
59
+
60
+ const getRowPair = () => {
61
+ const dataRow = screen.getByText('First row').closest('tr');
62
+ const detailRow = dataRow?.nextElementSibling;
63
+ return { dataRow, detailRow };
64
+ };
65
+
66
+ // The reveal selectors resolve '&' to the emotion class composed on the data row
67
+ const getDataRowEmotionClass = (dataRow: HTMLTableRowElement) => {
68
+ const emotionClass = Array.from(dataRow.classList).find((className) => className.startsWith('css-'));
69
+ expect(emotionClass).toBeDefined();
70
+ return emotionClass;
71
+ };
72
+
73
+ describe('WfoTable expanded row reveal', () => {
74
+ it('renders the detail row as next sibling of its data row, hidden by its own style', () => {
75
+ render(
76
+ <WfoTable<Item> data={data} columnConfig={columnConfig} rowExpandingConfiguration={rowExpandingConfiguration} />,
77
+ );
78
+
79
+ const { dataRow, detailRow } = getRowPair();
80
+ expect(dataRow).toBeInTheDocument();
81
+ expect(detailRow).toHaveTextContent('detail-1');
82
+
83
+ const detailRowClass = Array.from(detailRow!.classList).find((className) => className.startsWith('css-'));
84
+ expect(getDisplayRules()).toContainEqual([`.${detailRowClass}`, 'none']);
85
+ });
86
+
87
+ it('reveals every detail row through the sibling selector when showExpandedRows is set', () => {
88
+ render(
89
+ <WfoTable<Item>
90
+ data={data}
91
+ columnConfig={columnConfig}
92
+ rowExpandingConfiguration={rowExpandingConfiguration}
93
+ showExpandedRows
94
+ />,
95
+ );
96
+
97
+ const { dataRow, detailRow } = getRowPair();
98
+ const emotionClass = getDataRowEmotionClass(dataRow!);
99
+
100
+ expect(getDisplayRules()).toContainEqual([`.${emotionClass}+tr`, 'table-row']);
101
+ expect(detailRow!.matches(`.${emotionClass} + tr`)).toBe(true);
102
+ });
103
+
104
+ it('reveals a detail row on hover/focus of the data row or of the detail row itself when showExpandedRows is not set', () => {
105
+ render(
106
+ <WfoTable<Item> data={data} columnConfig={columnConfig} rowExpandingConfiguration={rowExpandingConfiguration} />,
107
+ );
108
+
109
+ const { dataRow, detailRow } = getRowPair();
110
+ const emotionClass = getDataRowEmotionClass(dataRow!);
111
+ const displayRules = getDisplayRules();
112
+
113
+ expect(displayRules).toContainEqual([`.${emotionClass}:hover+tr,.${emotionClass}:focus-within+tr`, 'table-row']);
114
+ // The rule that keeps the row open while hovering the revealed row itself (flicker fix)
115
+ expect(displayRules).toContainEqual([`.${emotionClass}+tr:hover,.${emotionClass}+tr:focus-within`, 'table-row']);
116
+
117
+ // :hover cannot be simulated in jsdom; verify the selectors structurally instead
118
+ expect(detailRow!.matches(`.${emotionClass} + tr`)).toBe(true);
119
+ });
120
+ });
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+
3
+ import { EuiSkeletonText } from '@elastic/eui';
4
+
5
+ import { useWithOrchestratorTheme } from '@/hooks';
6
+ import { toOptionalArrayEntry } from '@/utils';
7
+
8
+ import { ColumnType, WfoTableProps } from './WfoTable';
9
+ import { getWfoTableStyles } from './styles';
10
+ import { getSortedVisibleColumns } from './utils';
11
+
12
+ export type WfoTableSkeletonRowsProps<T extends object> = Pick<
13
+ WfoTableProps<T>,
14
+ 'columnConfig' | 'hiddenColumns' | 'columnOrder'
15
+ > & {
16
+ rowCount: number;
17
+ };
18
+
19
+ export const WfoTableSkeletonRows = <T extends object>({
20
+ rowCount,
21
+ columnConfig,
22
+ hiddenColumns = [],
23
+ columnOrder = [],
24
+ }: WfoTableSkeletonRowsProps<T>) => {
25
+ const { cellStyle, cellContentStyle, rowStyle, setWidth } = useWithOrchestratorTheme(getWfoTableStyles);
26
+
27
+ const sortedVisibleColumns = getSortedVisibleColumns(columnConfig, columnOrder, hiddenColumns);
28
+
29
+ return (
30
+ <>
31
+ {[...Array(rowCount)].map((_, rowIndex) => (
32
+ <tr key={`skeleton-row-${rowIndex}`} css={rowStyle}>
33
+ {sortedVisibleColumns.map(([key, columnConfig]) => (
34
+ <td
35
+ key={key}
36
+ css={[
37
+ ...toOptionalArrayEntry(cellStyle, !columnConfig.disableDefaultCellStyle),
38
+ setWidth(columnConfig.width),
39
+ ]}
40
+ >
41
+ {columnConfig.columnType === ColumnType.DATA && (
42
+ <div css={cellContentStyle}>
43
+ <EuiSkeletonText lines={1} size="m" isLoading />
44
+ </div>
45
+ )}
46
+ </td>
47
+ ))}
48
+ </tr>
49
+ ))}
50
+ </>
51
+ );
52
+ };
@@ -11,6 +11,7 @@ export * from './WfoMultilineCell';
11
11
  export * from './WfoTable';
12
12
  export * from './WfoTableHeaderCell';
13
13
  export * from './WfoTableDataRows';
14
+ export * from './WfoTableSkeletonRows';
14
15
 
15
16
  export * from './WfoTruncateCell';
16
17
  export * from './WfoDataCell';
@@ -160,8 +160,13 @@ export const getWfoTableStyles = ({ theme, isDarkModeActive }: WfoThemeHelpers)
160
160
  '.eui-xScroll': { display: 'flex', justifyContent: 'flex-start' },
161
161
  });
162
162
 
163
+ const showExpandedRowStyle = css({
164
+ '& + tr': { display: 'table-row' },
165
+ });
166
+
163
167
  const toggleExpandedRowOnHoverStyle = css({
164
168
  '&:hover + tr, &:focus-within + tr': { display: 'table-row' },
169
+ '& + tr:hover, & + tr:focus-within': { display: 'table-row' },
165
170
  });
166
171
 
167
172
  return {
@@ -181,6 +186,7 @@ export const getWfoTableStyles = ({ theme, isDarkModeActive }: WfoThemeHelpers)
181
186
  dragAndDropStyle,
182
187
  paginationStyle,
183
188
  setWidth,
189
+ showExpandedRowStyle,
184
190
  toggleExpandedRowOnHoverStyle,
185
191
  };
186
192
  };
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
2
2
 
3
3
  import { useTranslations } from 'next-intl';
4
4
 
5
- import { EuiForm, EuiFormRow, EuiHorizontalRule, EuiSelect, EuiSpacer, EuiSwitch } from '@elastic/eui';
5
+ import { EuiForm, EuiFormRow, EuiHorizontalRule, EuiSelect, EuiSpacer, EuiSwitch, useEuiScrollBar } from '@elastic/eui';
6
6
 
7
7
  import { WfoSettingsModal } from '@/components';
8
8
  import { getWfoTableSettingsModalStyles } from '@/components/WfoTable/WfoTableSettingsModal/styles';
@@ -37,7 +37,8 @@ export const TableSettingsModal = <T,>({
37
37
  extraSettings,
38
38
  }: TableSettingsModalProps<T>) => {
39
39
  const t = useTranslations('main');
40
- const { formRowStyle, selectFieldStyle } = useWithOrchestratorTheme(getWfoTableSettingsModalStyles);
40
+ const { formRowStyle, columnsListStyle, selectFieldStyle } = useWithOrchestratorTheme(getWfoTableSettingsModalStyles);
41
+ const scrollBarStyle = useEuiScrollBar();
41
42
 
42
43
  const [columns, setColumns] = useState(tableConfig.columns);
43
44
  const [selectedPageSize, setSelectedPageSize] = useState(tableConfig.selectedPageSize);
@@ -72,22 +73,24 @@ export const TableSettingsModal = <T,>({
72
73
  }
73
74
  >
74
75
  <EuiForm>
75
- {columns.map(({ field, name, isVisible }) => (
76
- <div key={field.toString()}>
77
- <EuiFormRow display="columnCompressed" label={name} css={formRowStyle}>
78
- <EuiSwitch
79
- showLabel={false}
80
- label={name}
81
- checked={isVisible}
82
- onChange={() => {
83
- handleUpdateColumnVisibility(field);
84
- }}
85
- compressed
86
- />
87
- </EuiFormRow>
88
- <EuiHorizontalRule margin="xs" />
89
- </div>
90
- ))}
76
+ <div css={[columnsListStyle, scrollBarStyle]}>
77
+ {columns.map(({ field, name, isVisible }) => (
78
+ <div key={field.toString()}>
79
+ <EuiFormRow display="columnCompressed" label={name} css={formRowStyle}>
80
+ <EuiSwitch
81
+ showLabel={false}
82
+ label={name}
83
+ checked={isVisible}
84
+ onChange={() => {
85
+ handleUpdateColumnVisibility(field);
86
+ }}
87
+ compressed
88
+ />
89
+ </EuiFormRow>
90
+ <EuiHorizontalRule margin="xs" />
91
+ </div>
92
+ ))}
93
+ </div>
91
94
  <EuiSpacer size="xs" />
92
95
 
93
96
  <EuiFormRow css={formRowStyle} hasEmptyLabelSpace label={t('numberOfRows')} display="columnCompressed">
@@ -1,3 +1,4 @@
1
+ import { transparentize } from '@elastic/eui';
1
2
  import { css } from '@emotion/react';
2
3
 
3
4
  import { WfoThemeHelpers } from '@/hooks';
@@ -13,8 +14,24 @@ export const getWfoTableSettingsModalStyles = (wfoThemeHelpers: WfoThemeHelpers)
13
14
  },
14
15
  });
15
16
 
17
+ const { theme } = wfoThemeHelpers;
18
+
19
+ const columnsListStyle = css({
20
+ maxHeight: theme.base * 16,
21
+ overflowY: 'auto',
22
+ paddingLeft: theme.base / 4,
23
+ marginBottom: theme.base / 2,
24
+ backgroundImage: `linear-gradient(to top, ${theme.colors.textGhost} ${theme.base}px, transparent),
25
+ radial-gradient(farthest-side at 50% 100%, ${transparentize(theme.colors.shadow, 0.24)}, transparent)`,
26
+ backgroundPosition: `center bottom, center bottom -${theme.base / 2}px`,
27
+ backgroundSize: `100% ${theme.base * 2}px, 100% ${theme.base}px`,
28
+ backgroundRepeat: 'no-repeat',
29
+ backgroundAttachment: 'local, scroll',
30
+ });
31
+
16
32
  return {
17
33
  formRowStyle,
34
+ columnsListStyle,
18
35
  selectFieldStyle: formFieldBaseStyle,
19
36
  };
20
37
  };
@@ -3,6 +3,8 @@ import { TableColumnKeys } from './columns';
3
3
  export type StoredTableConfig<T> = {
4
4
  hiddenColumns: TableColumnKeys<T>;
5
5
  selectedPageSize: number;
6
+ showMatchDetails?: boolean;
7
+ advancedNestedSearch?: boolean;
6
8
  };
7
9
 
8
10
  export const isValidLocalStorageTableConfig = <T>(object: StoredTableConfig<T>): object is StoredTableConfig<T> =>
@@ -57,7 +57,7 @@ export const getTimelineStyles = ({ theme }: WfoThemeHelpers) => {
57
57
  paddingLeft: theme.font.baseline * 4,
58
58
  paddingRight: theme.font.baseline * 4,
59
59
  position: 'sticky',
60
- top: timelineOutlineWidthPx,
60
+ top: theme.base / 4,
61
61
  zIndex: 2, // Some EUI components have a zIndex
62
62
  display: 'flex',
63
63
 
@@ -29,9 +29,15 @@ export const WfoPageWithUserGuide = ({ workflowName, children }: WfoFormWithUser
29
29
  );
30
30
 
31
31
  return (
32
- <EuiFlexGroup gutterSize="s" direction={isBigScreen ? 'row' : 'column'}>
32
+ <EuiFlexGroup
33
+ gutterSize="s"
34
+ direction={isBigScreen ? 'row' : 'column'}
35
+ alignItems={isBigScreen ? 'flexStart' : 'stretch'}
36
+ >
33
37
  {!isBigScreen && workflowGuideExpandablePanel}
34
- <EuiFlexItem grow={true}>{children}</EuiFlexItem>
38
+ <EuiFlexItem grow={true} css={{ minWidth: 0 }}>
39
+ {children}
40
+ </EuiFlexItem>
35
41
  {isBigScreen && workflowGuideExpandablePanel}
36
42
  </EuiFlexGroup>
37
43
  );