@orchestrator-ui/orchestrator-ui-components 8.8.1 → 8.9.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 (42) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/.turbo/turbo-test.log +15 -14
  4. package/CHANGELOG.md +23 -0
  5. package/dist/index.d.ts +63 -24
  6. package/dist/index.js +2695 -2480
  7. package/dist/index.js.map +1 -1
  8. package/package.json +4 -3
  9. package/src/components/WfoBadges/WfoProductStatusBadge/WfoProductStatusBadge.tsx +2 -5
  10. package/src/components/WfoPydanticForm/fields/WfoMultiCheckboxField.tsx +2 -1
  11. package/src/components/WfoStartButton/WfoStartButtonComboBox.tsx +6 -11
  12. package/src/components/WfoStartButton/WfoStartWorkflowComboBox.tsx +1 -1
  13. package/src/components/WfoSubscription/WfoSubscriptionActions/WfoSubscriptionActions.tsx +6 -16
  14. package/src/components/WfoSubscription/utils/utils.spec.ts +57 -0
  15. package/src/components/WfoSubscription/utils/utils.ts +15 -0
  16. package/src/components/WfoTable/WfoStructuredSearchTable/WfoFieldSelector.tsx +12 -8
  17. package/src/components/WfoTable/WfoStructuredSearchTable/WfoFilterBuilder.tsx +23 -10
  18. package/src/components/WfoTable/WfoStructuredSearchTable/WfoSearchHelpModal.tsx +59 -0
  19. package/src/components/WfoTable/WfoStructuredSearchTable/WfoStructuredSearchTable.tsx +37 -20
  20. package/src/components/WfoTable/WfoStructuredSearchTable/WfoValueEditor.tsx +4 -2
  21. package/src/components/WfoTable/WfoTable/WfoTable.tsx +77 -46
  22. package/src/components/WfoTable/WfoTable/WfoTableSkeletonRows.tsx +52 -0
  23. package/src/components/WfoTable/WfoTable/index.ts +1 -0
  24. package/src/components/WfoTable/WfoTableSettingsModal/WfoTableSettingsModal.tsx +21 -18
  25. package/src/components/WfoTable/WfoTableSettingsModal/styles.ts +17 -0
  26. package/src/components/WfoTable/utils/tableConfigPersistence.ts +1 -0
  27. package/src/configuration/version.ts +1 -1
  28. package/src/hooks/useGetPydanticFormsConfig.tsx +5 -3
  29. package/src/hooks/useSearch.ts +2 -2
  30. package/src/hooks/useStoredTableConfig.ts +1 -0
  31. package/src/messages/en-GB.json +21 -0
  32. package/src/messages/nl-NL.json +22 -1
  33. package/src/pages/WfoSearchPocPage.tsx +28 -23
  34. package/src/pages/processes/WfoProductInformationWithLink.tsx +9 -4
  35. package/src/rtk/endpoints/metadata/productBlocks.ts +9 -1
  36. package/src/rtk/endpoints/metadata/products.ts +5 -2
  37. package/src/rtk/endpoints/startOptions.ts +4 -3
  38. package/src/types/search.ts +8 -0
  39. package/src/types/types.ts +3 -3
  40. package/src/utils/getProductLifecycleStatus.spec.ts +26 -0
  41. package/src/utils/getProductLifecycleStatus.ts +13 -0
  42. package/src/utils/index.ts +1 -0
@@ -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,6 +79,7 @@ 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>;
@@ -106,6 +108,7 @@ export const WfoTable = <T extends object>({
106
108
  hiddenColumns = [],
107
109
  columnOrder = [],
108
110
  isLoading = false,
111
+ loadingSkeletonRowCount,
109
112
  dataSorting = [],
110
113
  rowExpandingConfiguration,
111
114
  showExpandedRows = false,
@@ -125,6 +128,8 @@ export const WfoTable = <T extends object>({
125
128
  const dataLength = data.length;
126
129
  usePageIndexBoundsGuard({ dataLength, isLoading, pagination });
127
130
 
131
+ const showLoadingSkeleton = !!loadingSkeletonRowCount && isLoading && dataLength === 0;
132
+
128
133
  const parentRef = useRef<HTMLDivElement>(null);
129
134
 
130
135
  const columnConfigWithFiller: WfoTableColumnConfig<T> =
@@ -192,6 +197,77 @@ export const WfoTable = <T extends object>({
192
197
  const virtualTrHeight = virtualItems[0]?.start ?? 0;
193
198
  const bottomSpacerHeight = totalSize - lastVirtualItemEnd;
194
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
+
195
271
  return (
196
272
  <>
197
273
  <div
@@ -214,52 +290,7 @@ export const WfoTable = <T extends object>({
214
290
  />
215
291
  </thead>
216
292
  }
217
- {dataLength === 0 ?
218
- <tbody css={isLoading && bodyLoadingStyle}>
219
- <tr css={rowStyle}>
220
- <td colSpan={sortedVisibleColumns.length} css={[cellStyle, emptyTableMessageStyle]}>
221
- {isLoading ? t('loading') : t('noItemsFound')}
222
- </td>
223
- </tr>
224
- </tbody>
225
- : isVirtualized && height ?
226
- <tbody>
227
- <tr
228
- style={{
229
- height: virtualTrHeight,
230
- }}
231
- />
232
-
233
- {virtualItems.map((virtualRow) => (
234
- <WfoTableDataRows
235
- key={virtualRow.key}
236
- data={[data[virtualRow.index]]}
237
- columnConfig={configWithLocalWidths}
238
- hiddenColumns={hiddenColumns}
239
- columnOrder={columnOrder}
240
- rowExpandingConfiguration={rowExpandingConfiguration}
241
- showExpandedRows={showExpandedRows}
242
- onRowClick={onRowClick}
243
- />
244
- ))}
245
- <tr
246
- style={{
247
- height: bottomSpacerHeight,
248
- }}
249
- />
250
- </tbody>
251
- : <tbody css={isLoading && bodyLoadingStyle}>
252
- <WfoTableDataRows
253
- data={data}
254
- columnConfig={configWithLocalWidths}
255
- hiddenColumns={hiddenColumns}
256
- columnOrder={columnOrder}
257
- rowExpandingConfiguration={rowExpandingConfiguration}
258
- showExpandedRows={showExpandedRows}
259
- onRowClick={onRowClick}
260
- />
261
- </tbody>
262
- }
293
+ {<WfoTableBody />}
263
294
  </table>
264
295
  </div>
265
296
  {pagination && (
@@ -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';
@@ -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
  };
@@ -4,6 +4,7 @@ export type StoredTableConfig<T> = {
4
4
  hiddenColumns: TableColumnKeys<T>;
5
5
  selectedPageSize: number;
6
6
  showMatchDetails?: boolean;
7
+ advancedNestedSearch?: boolean;
7
8
  };
8
9
 
9
10
  export const isValidLocalStorageTableConfig = <T>(object: StoredTableConfig<T>): object is StoredTableConfig<T> =>
@@ -1 +1 @@
1
- export const ORCHESTRATOR_UI_LIBRARY_VERSION = '8.8.1';
1
+ export const ORCHESTRATOR_UI_LIBRARY_VERSION = '8.9.0';
@@ -163,11 +163,13 @@ const useGetComponentMatcherExtender = (): ComponentMatcherExtender => {
163
163
  isControlledElement: true,
164
164
  },
165
165
  matcher(field) {
166
+ const fieldOptions = field.arrayItem?.options;
167
+
166
168
  return (
167
169
  field.type === PydanticFormFieldType.ARRAY
168
- && _.isArray(field.options)
169
- && field.options?.length > 0
170
- && field.options?.length <= 5
170
+ && _.isArray(fieldOptions)
171
+ && fieldOptions?.length > 0
172
+ && fieldOptions?.length <= 5
171
173
  );
172
174
  },
173
175
  validator: zodValidationPresets.multiSelect,
@@ -25,7 +25,7 @@ export const useSearch = (
25
25
  ) => {
26
26
  const [results, setResults] = useState<PaginatedSearchResults>({ ...emptyResult });
27
27
 
28
- const [triggerSearch, { isLoading, isError }] = useLazySearchQuery();
28
+ const [triggerSearch, { isFetching, isError }] = useLazySearchQuery();
29
29
 
30
30
  useEffect(() => {
31
31
  const queryText = typeof query === 'string' ? query : query.text?.trim() || '';
@@ -75,7 +75,7 @@ export const useSearch = (
75
75
 
76
76
  return {
77
77
  results,
78
- loading: isLoading,
78
+ loading: isFetching,
79
79
  error: isError ? 'Search failed' : null,
80
80
  setResults,
81
81
  };
@@ -24,6 +24,7 @@ export const useStoredTableConfig = <T>(localeStorageKey: string) => {
24
24
  tableConfig.hiddenColumns = storedConfig.hiddenColumns;
25
25
  tableConfig.selectedPageSize = storedConfig.selectedPageSize;
26
26
  tableConfig.showMatchDetails = storedConfig.showMatchDetails;
27
+ tableConfig.advancedNestedSearch = storedConfig.advancedNestedSearch;
27
28
  }
28
29
  return tableConfig;
29
30
  } catch {
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "common": {
3
+ "advancedNestedSearch": "Advanced nested search",
3
4
  "applyFilter": "Apply filter",
4
5
  "createFilter": "Create a filter",
5
6
  "deselect": "Deselect",
6
7
  "editColumns": "Edit columns",
7
8
  "errorMessage": "An error occurred",
8
9
  "export": "Export",
10
+ "exportRows": "Export {numberOfRows, plural, one {# row} other {# rows}}",
9
11
  "insyncFalse": "out-of-sync",
10
12
  "insyncTrue": "in-sync",
11
13
  "loadMore": "Load more",
@@ -337,6 +339,25 @@
337
339
  "fromDate": "From date",
338
340
  "fromNumber": "From",
339
341
  "groupLabel": "Group",
342
+ "help": {
343
+ "addGroupDescription": "adds a new group with two rules inside. A group has its own AND/OR choice.",
344
+ "addRuleDescription": "adds a new rule to the current group. A rule consists of a field, an operator and a value.",
345
+ "advancedNestedSearchDescription": "when enabled, the field dropdown in the filter also offers the full nested paths. When disabled, only the paths that match the table columns are shown.",
346
+ "advancedNestedSearchLabel": "Advanced nested search",
347
+ "exportDescription": "downloads a CSV file with only the rows that match the current filter.",
348
+ "filterIntro": "Use 'Create a filter' to build a structured filter out of rules.",
349
+ "filterTitle": "Filter rules and grouping",
350
+ "matchingRowDescription": "Hover over a row to reveal an extra row with information about the matched item: the fields that matched the search text and the confidence of the match.",
351
+ "matchingRowTitle": "Matching row",
352
+ "quickFilterDescription": "You can also click a column header and enter a value there - this adds a new rule for that column to the filter.",
353
+ "quickFilterTitle": "Quick filter from a column header",
354
+ "retrievalDescription": "choose how results are retrieved: Auto, Fuzzy, Semantic or Hybrid.",
355
+ "searchFieldDescription": "Searches across all available fields - no filter applied.",
356
+ "searchFieldTitle": "Default Search box behavior",
357
+ "showMatchDetailsDescription": "always show the matching rows instead of only on hover.",
358
+ "tableSettingsTitle": "Table settings (gear button)",
359
+ "title": "How search works"
360
+ },
340
361
  "hideFilters": "Hide filters",
341
362
  "loadingSearchResults": "Loading search results...",
342
363
  "maxNestingDepth": "Maximum nesting depth reached",
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "common": {
3
+ "advancedNestedSearch": "Geavanceerd genest zoeken",
3
4
  "applyFilter": "Pas filter toe",
4
5
  "createFilter": "Filter",
5
6
  "deselect": "Deselecteer",
6
7
  "editColumns": "Wijzig kolommen",
7
8
  "errorMessage": "Er is een fout opgetreden",
8
9
  "export": "Exporteren",
10
+ "exportRows": "Exporteer {numberOfRows, plural, one {# rij} other {# rijen}}",
9
11
  "insyncFalse": "out-of-sync",
10
12
  "insyncTrue": "in-sync",
11
13
  "loadMore": "Meer laden",
@@ -62,7 +64,7 @@
62
64
  "metadataProductblocks": "Product blocks",
63
65
  "metadataProducts": "Products",
64
66
  "metadataResourceTypes": "Resource types",
65
- "metadataScheduledTasks": "Scheduled tasks",
67
+ "metadataScheduledTasks": "Geplande taken",
66
68
  "metadataTasks": "Taken",
67
69
  "metadataWorkflows": "Workflows",
68
70
  "minimumOrchestratorCoreVersion": "Minimale versie van orchestrator-core",
@@ -337,6 +339,25 @@
337
339
  "fromDate": "Vanaf datum",
338
340
  "fromNumber": "Van",
339
341
  "groupLabel": "Groep",
342
+ "help": {
343
+ "addGroupDescription": "voegt een nieuwe groep toe met daarin twee regels. Een groep heeft een eigen AND/OR-keuze.",
344
+ "addRuleDescription": "voegt een nieuwe regel toe aan de huidige groep. Een regel bestaat uit een veld, een operator en een waarde.",
345
+ "advancedNestedSearchDescription": "indien ingeschakeld biedt de veldkeuzelijst in het filter ook de volledige geneste paden. Indien uitgeschakeld worden alleen de paden getoond die overeenkomen met de tabelkolommen.",
346
+ "advancedNestedSearchLabel": "Geavanceerd genest zoeken",
347
+ "exportDescription": "downloadt een CSV-bestand met alleen de rijen die voldoen aan het huidige filter.",
348
+ "filterIntro": "Bouw met 'Filter' een gestructureerd filter op uit regels.",
349
+ "filterTitle": "Filterregels en groepen",
350
+ "matchingRowDescription": "Beweeg de muis over een rij om een extra rij te tonen met informatie over het gevonden item: de velden die overeenkomen met de zoektekst en de betrouwbaarheid van de match.",
351
+ "matchingRowTitle": "Matching rij",
352
+ "quickFilterDescription": "Je kunt ook op een tabel header klikken en daar een waarde invoeren - dit voegt een nieuwe regel voor die kolom aan het filter toe.",
353
+ "quickFilterTitle": "Snel filteren via een tabel header",
354
+ "retrievalDescription": "kies hoe resultaten worden opgehaald: Auto, Fuzzy, Semantic of Hybride.",
355
+ "searchFieldDescription": "Doorzoekt alle beschikbare velden - geen filter toegepast.",
356
+ "searchFieldTitle": "Standaardgedrag van het zoekveld",
357
+ "showMatchDetailsDescription": "toon de matching rijen altijd in plaats van alleen bij hover.",
358
+ "tableSettingsTitle": "Tabelinstellingen (tandwielknop)",
359
+ "title": "Hoe zoeken werkt"
360
+ },
340
361
  "hideFilters": "Verberg filters",
341
362
  "loadingSearchResults": "Zoekresultaten laden...",
342
363
  "maxNestingDepth": "Maximale nesting-diepte bereikt",
@@ -33,6 +33,7 @@ import {
33
33
  } from '@/components';
34
34
  import { parseCelToRuleGroup } from '@/components/WfoTable/WfoStructuredSearchTable/utils';
35
35
  import { ColumnType, WfoTableProps } from '@/components/WfoTable/WfoTable';
36
+ import { mapSortableAndFilterableValuesToTableColumnConfig } from '@/components/WfoTable/WfoTable/utils';
36
37
  import { useStoredTableConfig } from '@/hooks';
37
38
  import { SearchPayload, useLazySearchQuery, useSearchQuery } from '@/rtk';
38
39
  import {
@@ -179,8 +180,7 @@ export const WfoSearchPocPage = () => {
179
180
  );
180
181
  const [isValidFilterString, setIsValidFilterString] = useState<boolean>(true);
181
182
  const [tableDefaults, setTableDefaults] = useState<StoredTableConfig<SubscriptionListItem>>();
182
- const [pageSize, setPageSize] = useState<number>(tableDefaults?.selectedPageSize || DEFAULT_PAGE_SIZE);
183
- const [limit, setLimit] = useState<number>(pageSize);
183
+ const [pageSize, setPageSize] = useState<number>(DEFAULT_PAGE_SIZE);
184
184
  const [pageCursor, setPageCursor] = useState<{ cursor: string; searchKey: string } | undefined>(undefined);
185
185
  const [dataSorting, setDataSorting] = useState<WfoDataSorting<SubscriptionListItem>>({
186
186
  field: 'subscriptionId',
@@ -214,7 +214,7 @@ export const WfoSearchPocPage = () => {
214
214
  };
215
215
  return {
216
216
  query: committedSearchQuery,
217
- limit,
217
+ limit: pageSize,
218
218
  entity_type: EntityKind.SUBSCRIPTION,
219
219
  response_columns: Array.from(resultColumToPropertyMap.keys()),
220
220
  order_by,
@@ -222,17 +222,19 @@ export const WfoSearchPocPage = () => {
222
222
  ...(filters && { filters }),
223
223
  ...(cursor && { cursor }),
224
224
  };
225
- }, [committedSearchQuery, committedRuleGroup, selectedTab, retrieverType, limit, dataSorting, cursor]);
225
+ }, [committedSearchQuery, committedRuleGroup, selectedTab, retrieverType, pageSize, dataSorting, cursor]);
226
226
 
227
227
  const { data, isFetching } = useSearchQuery(searchPayload);
228
228
 
229
229
  const [getSubscriptionListTrigger] = useLazySearchQuery();
230
- const getSubscriptionListForExport = () => getSubscriptionListTrigger(searchPayload).unwrap();
230
+ const getSubscriptionListForExport = (exportLimit: number) =>
231
+ getSubscriptionListTrigger({ ...searchPayload, limit: exportLimit, cursor: undefined }).unwrap();
231
232
 
232
233
  useEffect(() => {
233
234
  const storedConfig = getStoredTableConfig();
234
235
  if (storedConfig) {
235
236
  setTableDefaults(storedConfig);
237
+ setPageSize(storedConfig.selectedPageSize);
236
238
  }
237
239
  }, [getStoredTableConfig]);
238
240
 
@@ -249,8 +251,6 @@ export const WfoSearchPocPage = () => {
249
251
  renderData: (value) => <WfoFirstPartUUID UUID={value} />,
250
252
  renderDetails: (value) => value,
251
253
  renderTooltip: (value) => value,
252
- isSortable: true,
253
- isFilterable: true,
254
254
  },
255
255
  description: {
256
256
  columnType: ColumnType.DATA,
@@ -258,44 +258,37 @@ export const WfoSearchPocPage = () => {
258
258
  width: '500px',
259
259
  renderData: (value, record) => <Link href={`/subscriptions/${record.subscriptionId}`}>{value}</Link>,
260
260
  renderTooltip: (value) => value,
261
- isFilterable: true,
262
261
  },
263
262
  status: {
264
263
  columnType: ColumnType.DATA,
265
264
  label: t('status'),
266
265
  width: '120px',
267
266
  renderData: (value) => <WfoSubscriptionStatusBadge status={value} />,
268
- isFilterable: true,
269
267
  },
270
268
  insync: {
271
269
  columnType: ColumnType.DATA,
272
270
  label: t('insync'),
273
271
  width: '75px',
274
272
  renderData: (value) => <WfoInsyncIcon inSync={value} />,
275
- isFilterable: true,
276
273
  },
277
274
  productName: {
278
275
  columnType: ColumnType.DATA,
279
276
  width: '260px',
280
277
  label: t('product'),
281
- isFilterable: true,
282
278
  },
283
279
  tag: {
284
280
  columnType: ColumnType.DATA,
285
281
  label: t('tag'),
286
282
  width: '100px',
287
- isFilterable: true,
288
283
  },
289
284
  customerFullname: {
290
285
  columnType: ColumnType.DATA,
291
286
  label: t('customerFullname'),
292
- isFilterable: true,
293
287
  },
294
288
  customerShortcode: {
295
289
  columnType: ColumnType.DATA,
296
290
  label: t('customerShortcode'),
297
291
  width: '150px',
298
- isFilterable: true,
299
292
  },
300
293
  startDate: {
301
294
  columnType: ColumnType.DATA,
@@ -305,7 +298,6 @@ export const WfoSearchPocPage = () => {
305
298
  renderDetails: parseDateToLocaleDateTimeString,
306
299
  clipboardText: parseDateToLocaleDateTimeString,
307
300
  renderTooltip: (cellValue) => cellValue?.toString(),
308
- isFilterable: true,
309
301
  },
310
302
  endDate: {
311
303
  columnType: ColumnType.DATA,
@@ -315,7 +307,6 @@ export const WfoSearchPocPage = () => {
315
307
  renderDetails: parseDateToLocaleDateTimeString,
316
308
  clipboardText: parseDateToLocaleDateTimeString,
317
309
  renderTooltip: (cellValue) => cellValue?.toString(),
318
- isFilterable: true,
319
310
  },
320
311
  note: {
321
312
  columnType: ColumnType.DATA,
@@ -332,7 +323,6 @@ export const WfoSearchPocPage = () => {
332
323
  />
333
324
  );
334
325
  },
335
- isFilterable: true,
336
326
  },
337
327
  metadata: {
338
328
  columnType: ColumnType.DATA,
@@ -341,10 +331,18 @@ export const WfoSearchPocPage = () => {
341
331
  renderData: (value) => <WfoInlineJson data={value} />,
342
332
  renderDetails: (value) => value && <WfoJsonCodeBlock data={value} isBasicStyle />,
343
333
  renderTooltip: (value) => value && <WfoJsonCodeBlock data={value} isBasicStyle={false} />,
344
- isFilterable: true,
345
334
  },
346
335
  };
347
336
 
337
+ const sortableAndFilterableFieldNames = Object.keys(tableColumnConfig).filter((fieldName) => fieldName !== 'actions');
338
+ const isSortingAllowed = queryText === '';
339
+ const tableColumnConfigWithSortingAndFiltering =
340
+ mapSortableAndFilterableValuesToTableColumnConfig<SubscriptionListItem>(
341
+ tableColumnConfig,
342
+ isSortingAllowed ? sortableAndFilterableFieldNames : [],
343
+ sortableAndFilterableFieldNames,
344
+ );
345
+
348
346
  const handleApplyFilter = (searchParams?: SearchParams) => {
349
347
  const ruleGroupParam = searchParams?.ruleGroup;
350
348
  // Use an explicitly passed rule group when provided (e.g. a column-header search), a cleared filter
@@ -382,7 +380,6 @@ export const WfoSearchPocPage = () => {
382
380
 
383
381
  const handleChangeTab = (updatedTab: WfoSubscriptionListTab) => {
384
382
  setActiveTab(updatedTab);
385
- setLimit(pageSize);
386
383
  setPageCursor(undefined);
387
384
  };
388
385
 
@@ -468,7 +465,7 @@ export const WfoSearchPocPage = () => {
468
465
  const nextPageCursor = data?.page_info?.next_page_cursor ?? undefined;
469
466
 
470
467
  const exportData = async () => {
471
- const exportResult = await getSubscriptionListForExport();
468
+ const exportResult = await getSubscriptionListForExport(totalItems || pageSize);
472
469
  const { items: exportItems } = getDataFromResponse<SubscriptionListItem>(
473
470
  exportResult,
474
471
  resultColumToPropertyMap,
@@ -489,7 +486,14 @@ export const WfoSearchPocPage = () => {
489
486
 
490
487
  const onUpdateDataSorting = ({ field, sortOrder }: WfoDataSorting<SubscriptionListItem>) => {
491
488
  setDataSorting({ field, sortOrder });
492
- setLimit(pageSize);
489
+ setPageCursor(undefined);
490
+ };
491
+
492
+ const onUpdatePageSize = (updatedPageSize: number) => {
493
+ if (updatedPageSize === pageSize) {
494
+ return;
495
+ }
496
+ setPageSize(updatedPageSize);
493
497
  setPageCursor(undefined);
494
498
  };
495
499
 
@@ -508,6 +512,7 @@ export const WfoSearchPocPage = () => {
508
512
  rowExpandingConfiguration={rowExpandingConfiguration}
509
513
  defaultHiddenColumns={tableDefaults?.hiddenColumns}
510
514
  defaultShowMatchDetails={tableDefaults?.showMatchDetails}
515
+ defaultAdvancedNestedSearch={tableDefaults?.advancedNestedSearch}
511
516
  filterString={filterString}
512
517
  handleSearch={handleApplyFilter}
513
518
  isLoading={isFetching}
@@ -523,11 +528,11 @@ export const WfoSearchPocPage = () => {
523
528
  queryBuilderRuleGroup={queryBuilderRuleGroup}
524
529
  queryText={queryText}
525
530
  retrieverType={retrieverType}
526
- tableColumnConfig={tableColumnConfig}
531
+ tableColumnConfig={tableColumnConfigWithSortingAndFiltering}
527
532
  getColumnSearchFieldName={(field) => getKeyByValueFromMap(resultColumToPropertyMap, field)}
528
533
  pageSize={pageSize}
529
534
  onUpdateDataSorting={onUpdateDataSorting}
530
- setPageSize={setPageSize}
535
+ setPageSize={onUpdatePageSize}
531
536
  totalItems={totalItems}
532
537
  hasNextPage={hasNextPage}
533
538
  prefilledFieldOptions={prefilledFieldOptions}