@adaptabletools/adaptable 21.0.0-canary.0 → 21.0.0-canary.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 (50) hide show
  1. package/package.json +1 -1
  2. package/src/AdaptableInterfaces/IAdaptable.d.ts +3 -2
  3. package/src/AdaptableOptions/DefaultAdaptableOptions.js +0 -1
  4. package/src/AdaptableOptions/EditOptions.d.ts +6 -1
  5. package/src/AdaptableOptions/FilterOptions.d.ts +20 -8
  6. package/src/AdaptableOptions/LayoutOptions.d.ts +35 -1
  7. package/src/AdaptableState/Common/AdaptableColumn.d.ts +2 -2
  8. package/src/Api/ColumnFilterApi.d.ts +5 -5
  9. package/src/Api/Implementation/ColumnApiImpl.js +1 -1
  10. package/src/Api/Implementation/ColumnFilterApiImpl.d.ts +3 -3
  11. package/src/Api/Implementation/ColumnFilterApiImpl.js +6 -6
  12. package/src/Api/Implementation/LayoutApiImpl.js +6 -6
  13. package/src/Api/Internal/ColumnFilterInternalApi.d.ts +2 -3
  14. package/src/Api/Internal/ColumnFilterInternalApi.js +17 -25
  15. package/src/Api/Internal/ColumnInternalApi.js +1 -1
  16. package/src/Api/Internal/GridInternalApi.d.ts +3 -2
  17. package/src/Api/Internal/GridInternalApi.js +3 -2
  18. package/src/Api/Internal/LayoutInternalApi.d.ts +5 -0
  19. package/src/Api/Internal/LayoutInternalApi.js +44 -1
  20. package/src/Api/Internal/PredicateInternalApi.js +0 -1
  21. package/src/Redux/Store/AdaptableStore.js +0 -2
  22. package/src/Strategy/ColumnFilterModule.js +8 -1
  23. package/src/Utilities/Helpers/AdaptableHelper.d.ts +1 -0
  24. package/src/Utilities/Helpers/AdaptableHelper.js +1 -0
  25. package/src/Utilities/ObjectFactory.d.ts +7 -3
  26. package/src/Utilities/ObjectFactory.js +25 -17
  27. package/src/Utilities/adaptableQlUtils.js +1 -1
  28. package/src/View/Components/ColumnFilter/components/FloatingFilterValues.d.ts +2 -0
  29. package/src/View/Components/ColumnFilter/components/FloatingFilterValues.js +20 -5
  30. package/src/View/Components/ColumnFilter/utils.js +0 -1
  31. package/src/View/Components/PredicateEditor/PredicateEditor.js +14 -0
  32. package/src/View/Components/Selectors/PermittedValuesSelector.d.ts +2 -4
  33. package/src/View/Components/Selectors/PermittedValuesSelector.js +6 -5
  34. package/src/View/Layout/Wizard/LayoutWizard.js +5 -7
  35. package/src/agGrid/AdaptableAgGrid.d.ts +3 -2
  36. package/src/agGrid/AdaptableAgGrid.js +20 -10
  37. package/src/agGrid/AdaptableFilterHandler.d.ts +9 -4
  38. package/src/agGrid/AdaptableFilterHandler.js +28 -11
  39. package/src/agGrid/AgGridColumnAdapter.js +5 -2
  40. package/src/agGrid/AgGridExportAdapter.js +2 -4
  41. package/src/agGrid/AgGridModulesAdapter.js +5 -1
  42. package/src/agGrid/agGridDataTypeDefinitions.js +1 -8
  43. package/src/components/Select/Select.d.ts +1 -0
  44. package/src/components/Select/Select.js +5 -4
  45. package/src/env.js +2 -2
  46. package/src/metamodel/adaptable.metamodel.d.ts +49 -22
  47. package/src/metamodel/adaptable.metamodel.js +1 -1
  48. package/src/migration/VersionUpgrade20.js +1 -2
  49. package/src/types.d.ts +3 -3
  50. package/tsconfig.esm.tsbuildinfo +1 -1
@@ -246,36 +246,43 @@ export function CreateEmptyFreeTextColumn(defaultSpecialColumnSettings) {
246
246
  },
247
247
  };
248
248
  }
249
- export function CreateEmptyPivotLayout(layout) {
249
+ export function CreateEmptyPivotLayout(pivotLayout) {
250
250
  const result = {
251
- Name: layout.Name,
252
- ColumnSorts: layout.ColumnSorts || [],
253
- ColumnFilters: layout.ColumnFilters || [],
251
+ ...pivotLayout,
254
252
  Uuid: createUuid(),
255
- PivotColumns: layout.PivotColumns || [],
256
- PivotAggregationColumns: layout.PivotAggregationColumns || [],
257
- PivotGroupedColumns: layout.PivotGroupedColumns || [],
258
- ColumnSizing: layout.ColumnSizing || {},
253
+ ColumnSizing: pivotLayout.ColumnSizing || {},
254
+ ColumnHeaders: pivotLayout.ColumnHeaders || {},
255
+ ColumnPinning: pivotLayout.ColumnPinning || {},
256
+ ColumnSorts: pivotLayout.ColumnSorts || [],
257
+ ColumnFilters: pivotLayout.ColumnFilters || [],
258
+ PivotColumns: pivotLayout.PivotColumns || [],
259
+ PivotAggregationColumns: pivotLayout.PivotAggregationColumns || [],
260
+ PivotGroupedColumns: pivotLayout.PivotGroupedColumns || [],
259
261
  };
260
262
  return result;
261
263
  }
262
- export function CreateEmptyLayout(layout, adaptableColumns) {
263
- if (isPivotLayout(layout)) {
264
- return CreateEmptyPivotLayout(layout);
265
- }
266
- const tableLayout = layout;
264
+ export function CreateEmptyTableLayout(tableLayout) {
267
265
  const result = {
268
266
  ...tableLayout,
269
267
  Uuid: createUuid(),
270
- TableColumns: tableLayout.TableColumns || [],
268
+ ColumnSizing: tableLayout.ColumnSizing || {},
269
+ ColumnHeaders: tableLayout.ColumnHeaders || {},
270
+ ColumnPinning: tableLayout.ColumnPinning || {},
271
271
  ColumnSorts: tableLayout.ColumnSorts || [],
272
272
  ColumnFilters: tableLayout.ColumnFilters || [],
273
- ColumnSizing: tableLayout.ColumnSizing || {},
274
- RowGroupedColumns: tableLayout.RowGroupedColumns ||
275
- (adaptableColumns ? adaptableColumns.filter((c) => c.isGrouped).map((c) => c.columnId) : []),
273
+ TableColumns: tableLayout.TableColumns || [],
274
+ RowGroupedColumns: tableLayout.RowGroupedColumns || [],
276
275
  };
277
276
  return result;
278
277
  }
278
+ export function CreateEmptyLayout(layout) {
279
+ if (isPivotLayout(layout)) {
280
+ return CreateEmptyPivotLayout(layout);
281
+ }
282
+ else {
283
+ return CreateEmptyTableLayout(layout);
284
+ }
285
+ }
279
286
  export function CreateEmptyStyle() {
280
287
  return {
281
288
  BackColor: undefined,
@@ -444,6 +451,7 @@ export const ObjectFactory = {
444
451
  CreateEmptyFreeTextColumn,
445
452
  CreateEmptyLayout,
446
453
  CreateEmptyPivotLayout,
454
+ CreateEmptyTableLayout,
447
455
  CreateColumnFilter,
448
456
  CreateEmptyStyle,
449
457
  CreateEmptyCellSummmary,
@@ -8,7 +8,7 @@ export const mapColumnDataTypeToExpressionFunctionType = (dataType) => {
8
8
  if (dataType === 'text') {
9
9
  return 'text';
10
10
  }
11
- if (dataType === 'date' || dataType === 'dateString') {
11
+ if (dataType === 'date') {
12
12
  return 'date';
13
13
  }
14
14
  if (dataType === 'numberArray') {
@@ -25,6 +25,7 @@ export declare function useDistinctFilterColumnValues(options: {
25
25
  label: string;
26
26
  }[];
27
27
  dataLoadIsComplete: boolean;
28
+ skipDefaultSearch: boolean;
28
29
  searchValueUsedInFilterValue: boolean;
29
30
  };
30
31
  setQuickFilterValues: React.Dispatch<React.SetStateAction<{
@@ -33,6 +34,7 @@ export declare function useDistinctFilterColumnValues(options: {
33
34
  label: string;
34
35
  }[];
35
36
  dataLoadIsComplete: boolean;
37
+ skipDefaultSearch: boolean;
36
38
  searchValueUsedInFilterValue: boolean;
37
39
  }>>;
38
40
  triggerValuesLoad: () => void;
@@ -23,7 +23,12 @@ export function useDistinctFilterColumnValues(options) {
23
23
  const triggerValuesLoad = React.useCallback(() => {
24
24
  setValuesLoadTrigger((prev) => prev + 1);
25
25
  }, []);
26
- const [quickFilterValues, setQuickFilterValues] = React.useState({ values: [], dataLoadIsComplete: false, searchValueUsedInFilterValue: false });
26
+ const [quickFilterValues, setQuickFilterValues] = React.useState({
27
+ values: [],
28
+ dataLoadIsComplete: false,
29
+ skipDefaultSearch: false,
30
+ searchValueUsedInFilterValue: false,
31
+ });
27
32
  const [isDistinctColumnValuesLoading, setIsDistinctColumnValuesLoading] = React.useState(false);
28
33
  useEffect(() => {
29
34
  if (valuesLoadTrigger === 0) {
@@ -45,9 +50,11 @@ export function useDistinctFilterColumnValues(options) {
45
50
  if (ignore) {
46
51
  return;
47
52
  }
53
+ const values = distinctFilterDisplayValues.values;
48
54
  setQuickFilterValues({
49
- values: distinctFilterDisplayValues,
55
+ values,
50
56
  dataLoadIsComplete: true,
57
+ skipDefaultSearch: !!distinctFilterDisplayValues.skipDefaultSearch,
51
58
  searchValueUsedInFilterValue,
52
59
  });
53
60
  setIsDistinctColumnValuesLoading(false);
@@ -116,16 +123,19 @@ export const FloatingFilterValues = (props) => {
116
123
  const onMenuOpen = triggerValuesLoad;
117
124
  const onInputChange = React.useCallback((value) => {
118
125
  searchValueRef.current = value;
119
- if (quickFilterValues.searchValueUsedInFilterValue) {
126
+ const quickFilterValues = quickFilterValuesRef.current;
127
+ if (quickFilterValues.searchValueUsedInFilterValue || quickFilterValues.skipDefaultSearch) {
120
128
  triggerValuesLoad();
121
129
  }
122
- }, [quickFilterValues.searchValueUsedInFilterValue]);
130
+ }, []);
131
+ const { skipDefaultSearch } = quickFilterValues;
123
132
  return (React.createElement(ColumnValuesSelect, { selectProps: props.inline
124
133
  ? {
125
134
  ...props.selectProps,
126
135
  'data-name': 'Select Values',
127
136
  renderMultipleValues,
128
137
  isClearable: false,
138
+ skipDefaultFiltering: skipDefaultSearch,
129
139
  styles: {
130
140
  dropdownIndicator: {
131
141
  display: 'none',
@@ -154,5 +164,10 @@ export const FloatingFilterValues = (props) => {
154
164
  onMenuOpen,
155
165
  onInputChange,
156
166
  }
157
- : { ...props.selectProps, onMenuOpen, onInputChange }, disabled: props.disabled, isLoading: isDistinctColumnValuesLoading, column: currentColumn, dataType: currentColumn.dataType, options: quickFilterValues.values, value: props.value, onChange: props.onChange }));
167
+ : {
168
+ ...props.selectProps,
169
+ skipDefaultFiltering: skipDefaultSearch,
170
+ onMenuOpen,
171
+ onInputChange,
172
+ }, disabled: props.disabled, isLoading: isDistinctColumnValuesLoading, column: currentColumn, dataType: currentColumn.dataType, options: quickFilterValues.values, value: props.value, onChange: props.onChange }));
158
173
  };
@@ -133,7 +133,6 @@ export const mapColumnFilterToQlPredicate = (columnFilter, abColumn, qlPredicate
133
133
  : { operator: 'Contains', args: [] };
134
134
  break;
135
135
  case 'date':
136
- case 'dateString':
137
136
  let defaultQlDatePredicate;
138
137
  const defaultDateColumnFilter = columnFilterOptions.defaultDateColumnFilter;
139
138
  if (defaultDateColumnFilter) {
@@ -45,13 +45,25 @@ export const PredicateEditor = (props) => {
45
45
  const adaptable = useAdaptable();
46
46
  const columnId = props.columnId;
47
47
  const column = adaptable.api.columnApi.getColumnWithColumnId(columnId);
48
+ const searchValueRef = React.useRef('');
48
49
  const { quickFilterValues, isDistinctColumnValuesLoading, triggerValuesLoad } = useDistinctFilterColumnValues({
49
50
  columnId,
51
+ searchValueRef,
50
52
  });
53
+ const quickFilterValuesRef = React.useRef(quickFilterValues);
54
+ quickFilterValuesRef.current = quickFilterValues;
51
55
  useEffect(triggerValuesLoad, []);
52
56
  const onMenuOpen = () => {
53
57
  triggerValuesLoad();
54
58
  };
59
+ const onInputChange = React.useCallback((value) => {
60
+ searchValueRef.current = value;
61
+ const quickFilterValues = quickFilterValuesRef.current;
62
+ if (quickFilterValues.searchValueUsedInFilterValue || quickFilterValues.skipDefaultSearch) {
63
+ triggerValuesLoad();
64
+ }
65
+ }, []);
66
+ const { skipDefaultSearch } = quickFilterValues;
55
67
  return (React.createElement(Box, { className: baseClassName },
56
68
  React.createElement(Flex, { justifyContent: "stretch", alignItems: "center" },
57
69
  icon && React.createElement(Tag, { mr: 2 }, icon),
@@ -70,5 +82,7 @@ export const PredicateEditor = (props) => {
70
82
  adaptable.api.predicateApi.internalApi.IsInorNotInPredicateDef(currentPredicateDef) && (React.createElement(Box, { mt: 2 },
71
83
  React.createElement(ColumnValuesSelect, { isLoading: isDistinctColumnValuesLoading, column: column, options: quickFilterValues.values, selectProps: {
72
84
  onMenuOpen,
85
+ onInputChange,
86
+ skipDefaultFiltering: skipDefaultSearch,
73
87
  }, dataType: column.dataType, value: props.predicate.Inputs, onChange: handlePredicateValuesChange })))));
74
88
  };
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { SelectProps } from '../../../components/Select';
3
+ import { InFilterValue } from '../../../AdaptableOptions/FilterOptions';
3
4
  export type ValueType = number | string | Date;
4
5
  interface PermittedValuesSelectorProps<Value extends ValueType, IsMulti extends boolean> {
5
6
  searchable?: false | 'inline' | 'menulist';
@@ -17,10 +18,7 @@ interface PermittedValuesSelectorProps<Value extends ValueType, IsMulti extends
17
18
  menuPortalTarget?: HTMLElement;
18
19
  loadValues?: (options: {
19
20
  currentSearchValue: string;
20
- }) => Promise<{
21
- value: any;
22
- label: string;
23
- }[]>;
21
+ }) => Promise<InFilterValue[]>;
24
22
  }
25
23
  export declare const PermittedValuesSelector: <Value extends ValueType, IsMulti extends boolean = false>(props: PermittedValuesSelectorProps<Value, IsMulti>) => React.JSX.Element;
26
24
  export {};
@@ -22,9 +22,7 @@ export const PermittedValuesSelector = function (props) {
22
22
  (async () => {
23
23
  let searchValueUsedInFilterValue = false;
24
24
  const currentSearchValue = searchFilterRef.current;
25
- const distinctColumnValues = await runIfNotResolvedIn(
26
- // we are here ALWAYS getting Filter values but sometimes we want to get other things!!!
27
- props.loadValues
25
+ const p = props.loadValues
28
26
  ? props.loadValues({
29
27
  get currentSearchValue() {
30
28
  searchValueUsedInFilterValue = true;
@@ -37,12 +35,15 @@ export const PermittedValuesSelector = function (props) {
37
35
  searchValueUsedInFilterValue = true;
38
36
  return currentSearchValue;
39
37
  },
40
- }), () => {
38
+ });
39
+ const distinctColumnValues = await runIfNotResolvedIn(
40
+ // we are here ALWAYS getting Filter values but sometimes we want to get other things!!!
41
+ p, () => {
41
42
  setIsLoading(true);
42
43
  });
43
44
  setSearchValueWasUsedWhenFiltering(searchValueUsedInFilterValue);
44
45
  setIsLoading(false);
45
- setOptions(distinctColumnValues);
46
+ setOptions(Array.isArray(distinctColumnValues) ? distinctColumnValues : distinctColumnValues.values);
46
47
  })();
47
48
  }, [props.columnId, props.loadValues, refetchKey]);
48
49
  const isCreatable = (props.allowNewValues && !dataType) || ['text', 'number'].includes(dataType);
@@ -1,7 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import * as LayoutRedux from '../../../Redux/ActionsReducers/LayoutRedux';
3
3
  import { OnePageAdaptableWizard, OnePageWizardSummary } from '../../Wizard/OnePageAdaptableWizard';
4
- import ObjectFactory from '../../../Utilities/ObjectFactory';
5
4
  import { cloneObject } from '../../../Utilities/Helpers/Helper';
6
5
  import { SettingsSection, SettingsSectionSummary } from './sections/SettingsSection';
7
6
  import { Box } from 'rebass';
@@ -29,17 +28,17 @@ export const LayoutWizard = (props) => {
29
28
  if (initialLayout) {
30
29
  preparedLayout = cloneObject(initialLayout);
31
30
  if (props?.popupParams?.action === 'Clone') {
32
- preparedLayout.Name = '';
33
- delete preparedLayout.Uuid;
31
+ preparedLayout = {
32
+ ...adaptable.api.layoutApi.internalApi.cloneLayout(preparedLayout),
33
+ Name: '',
34
+ };
34
35
  }
35
36
  }
36
37
  else {
37
38
  const shouldCreatePivot = props.popupParams?.config?.layoutType === 'pivot' ||
38
39
  props.abObjectType?.name?.toLowerCase().includes('pivot') ||
39
40
  false;
40
- preparedLayout = shouldCreatePivot
41
- ? ObjectFactory.CreateEmptyPivotLayout({ Name: '' })
42
- : ObjectFactory.CreateEmptyLayout({ Name: '' });
41
+ preparedLayout = adaptable.api.layoutApi.internalApi.buildInitialLayout({ Name: '' }, shouldCreatePivot ? 'pivot' : 'table');
43
42
  }
44
43
  if (preparedLayout.SuppressAggFuncInHeader === undefined) {
45
44
  preparedLayout.SuppressAggFuncInHeader =
@@ -62,7 +61,6 @@ export const LayoutWizard = (props) => {
62
61
  break;
63
62
  case 'Clone':
64
63
  const clonedLayout = { ...layout };
65
- delete clonedLayout.Uuid;
66
64
  dispatch(LayoutRedux.LayoutAdd(clonedLayout));
67
65
  dispatch(LayoutRedux.LayoutSelect(clonedLayout.Name));
68
66
  break;
@@ -21,7 +21,7 @@ import { Fdc3Service } from '../Utilities/Services/Fdc3Service';
21
21
  import { AnnotationsService } from '../Utilities/Services/AnnotationsService';
22
22
  import { IModuleCollection } from '../Strategy/Interface/IModule';
23
23
  import { AgGridMenuAdapter } from './AgGridMenuAdapter';
24
- import { AdaptableColumn, AdaptableTheme, ChartDefinition, ColumnSort, DataUpdateConfig, GridCell, InFilterValue, Layout, SelectedCellInfo, SelectedRowInfo } from '../types';
24
+ import { AdaptableColumn, AdaptableTheme, ChartDefinition, ColumnSort, InFilterValueResult, DataUpdateConfig, GridCell, Layout, SelectedCellInfo, SelectedRowInfo } from '../types';
25
25
  import { RenderReactRootFn } from '../renderReactRoot';
26
26
  import { AgGridOptionsService } from './AgGridOptionsService';
27
27
  import { AgGridColumnAdapter } from './AgGridColumnAdapter';
@@ -257,7 +257,8 @@ export declare class AdaptableAgGrid implements IAdaptable {
257
257
  getDistinctFilterValuesForColumn(options: {
258
258
  column: AdaptableColumn;
259
259
  currentSearchValue: string;
260
- }): Promise<InFilterValue[]>;
260
+ previousResult: InFilterValueResult | undefined;
261
+ }): Promise<InFilterValueResult>;
261
262
  getDistinctEditValuesForColumn(options: {
262
263
  column: AdaptableColumn;
263
264
  currentSearchValue: string;
@@ -428,7 +428,6 @@ export class AdaptableAgGrid {
428
428
  this.lifecycleState = 'available';
429
429
  this.api.themeApi.applyCurrentTheme();
430
430
  this.validatePrimaryKey();
431
- // TODO AFL MIG: we could just patch the defautl Layout on init? instead
432
431
  this.checkShouldClearExistingFiltersOrSearches();
433
432
  // FIXME AFL FILTER: talk with Radu: should ColumnFilters still be ignored?!
434
433
  // see layoutModel.Ignore_ColumnFilters
@@ -1853,7 +1852,7 @@ You need to define at least one Layout!`);
1853
1852
  if (dataType === 'boolean') {
1854
1853
  return typeof rawValue !== 'boolean' ? Boolean(rawValue) : rawValue;
1855
1854
  }
1856
- if (dataType === 'date' || dataType === 'dateString') {
1855
+ if (dataType === 'date') {
1857
1856
  return rawValue instanceof Date ? rawValue : parseDateValue(rawValue);
1858
1857
  }
1859
1858
  return rawValue;
@@ -2254,10 +2253,19 @@ You need to define at least one Layout!`);
2254
2253
  return this.getDistinctGridCellsForColumn(column);
2255
2254
  }
2256
2255
  async getDistinctFilterValuesForColumn(options) {
2257
- const { column } = options;
2256
+ const { column, previousResult } = options;
2258
2257
  const self = this;
2259
2258
  // First get the Grid Cells in the Column
2260
- const currentGridCells = this.getDistinctGridCellsForColumn(column);
2259
+ let currentGridCells;
2260
+ const getCurrentGridCells = () => {
2261
+ // we do this in a function so it's lazy
2262
+ // but we also store in the outside closure, so we can reuse the value if
2263
+ // already called
2264
+ if (currentGridCells) {
2265
+ return currentGridCells;
2266
+ }
2267
+ return (currentGridCells = this.getDistinctGridCellsForColumn(column));
2268
+ };
2261
2269
  // If there are custom distinct value, return them; otherwise return the Grids Cells just retrieved
2262
2270
  const customInFilterValues = this.adaptableOptions.filterOptions.customInFilterValues;
2263
2271
  if (customInFilterValues) {
@@ -2265,12 +2273,13 @@ You need to define at least one Layout!`);
2265
2273
  const customInFilterValuesContext = {
2266
2274
  ...this.api.internalApi.buildBaseContext(),
2267
2275
  column,
2276
+ previousFilterResult: previousResult,
2268
2277
  get currentSearchValue() {
2269
2278
  return options.currentSearchValue;
2270
2279
  },
2271
2280
  get sortedValues() {
2272
2281
  const result = gridApiInternal
2273
- .sortDistinctValues(currentGridCells, column)
2282
+ .sortDistinctValues(getCurrentGridCells(), column)
2274
2283
  .map((gridCell) => {
2275
2284
  return {
2276
2285
  label: gridCell.displayValue,
@@ -2289,7 +2298,7 @@ You need to define at least one Layout!`);
2289
2298
  return result;
2290
2299
  },
2291
2300
  get defaultValues() {
2292
- const result = currentGridCells.map((gridCell) => {
2301
+ const result = getCurrentGridCells().map((gridCell) => {
2293
2302
  return {
2294
2303
  label: gridCell.displayValue,
2295
2304
  value: gridCell.rawValue,
@@ -2327,23 +2336,24 @@ You need to define at least one Layout!`);
2327
2336
  return result;
2328
2337
  },
2329
2338
  };
2330
- let customDistinctValues;
2339
+ let customInFilterValuesResult;
2331
2340
  try {
2332
- customDistinctValues = await customInFilterValues(customInFilterValuesContext);
2341
+ customInFilterValuesResult = await customInFilterValues(customInFilterValuesContext);
2333
2342
  }
2334
2343
  catch (error) {
2335
2344
  this.logger.consoleError(`Failed to fetch custom filter values`, column, error);
2336
2345
  }
2337
- return customDistinctValues ?? [];
2346
+ return customInFilterValuesResult;
2338
2347
  }
2339
2348
  // No distinct values so lets return unique grid cells
2340
- return currentGridCells.map((gridCell) => {
2349
+ const values = getCurrentGridCells().map((gridCell) => {
2341
2350
  const inFilterValue = {
2342
2351
  value: gridCell.rawValue,
2343
2352
  label: gridCell.displayValue,
2344
2353
  };
2345
2354
  return inFilterValue;
2346
2355
  });
2356
+ return { values };
2347
2357
  }
2348
2358
  async getDistinctEditValuesForColumn(options) {
2349
2359
  const { column, gridCell } = options;
@@ -1,18 +1,23 @@
1
1
  import { DoesFilterPassParams, FilterHandler, FilterHandlerParams } from 'ag-grid-enterprise';
2
2
  import { AdaptableApi } from '../Api/AdaptableApi';
3
3
  import { ColumnSetupInfo } from '../AdaptableState/Common/ColumnSetupInfo';
4
- import { InFilterValue } from '../AdaptableOptions/FilterOptions';
4
+ import { InFilterValueResult } from '../AdaptableOptions/FilterOptions';
5
5
  export declare class AdaptableFilterHandler implements FilterHandler {
6
6
  private adaptableApi;
7
7
  readonly colId: string;
8
- private filterDisplayValues;
8
+ private filterDisplayValuesResult;
9
9
  constructor(adaptableApi: AdaptableApi, columnSetup: ColumnSetupInfo);
10
10
  doesFilterPass(params: DoesFilterPassParams): boolean;
11
- getFilterDisplayValues(currentSearchValue: string): Promise<InFilterValue[]>;
11
+ getFilterDisplayValuesFromCache(options: {
12
+ currentSearchValue: string;
13
+ }): Promise<InFilterValueResult>;
14
+ fetchFilterDisplayValues(options: {
15
+ currentSearchValue: string;
16
+ }): Promise<InFilterValueResult>;
12
17
  onNewRowsLoaded(): void;
13
18
  onAnyFilterChanged(): void;
14
19
  resetFilterDisplayValues(): void;
15
- refreshFilterDisplayValues(): Promise<InFilterValue<any>[]>;
20
+ refreshFilterDisplayValues(): Promise<InFilterValueResult>;
16
21
  refresh(params: FilterHandlerParams<any, any, any, any>): void;
17
22
  destroy(): void;
18
23
  }
@@ -27,35 +27,52 @@ export class AdaptableFilterHandler {
27
27
  return false;
28
28
  }
29
29
  }
30
- getFilterDisplayValues(currentSearchValue) {
31
- if (!this.filterDisplayValues) {
32
- this.filterDisplayValues =
33
- this.adaptableApi.gridApi.internalApi.getDistinctFilterDisplayValuesForColumn({
34
- columnId: this.colId,
35
- currentSearchValue,
36
- });
30
+ getFilterDisplayValuesFromCache(options) {
31
+ if (this.filterDisplayValuesResult) {
32
+ return Promise.resolve(this.filterDisplayValuesResult);
37
33
  }
38
- return this.filterDisplayValues;
34
+ return this.fetchFilterDisplayValues(options);
35
+ }
36
+ fetchFilterDisplayValues(options) {
37
+ return this.adaptableApi.gridApi.internalApi
38
+ .getDistinctFilterDisplayValuesForColumn({
39
+ columnId: this.colId,
40
+ get currentSearchValue() {
41
+ return options.currentSearchValue;
42
+ },
43
+ previousResult: this.filterDisplayValuesResult,
44
+ })
45
+ .then((result) => {
46
+ this.filterDisplayValuesResult = result;
47
+ return result;
48
+ });
39
49
  }
40
50
  onNewRowsLoaded() {
41
51
  this.resetFilterDisplayValues();
42
52
  }
43
53
  onAnyFilterChanged() {
54
+ const filterOptions = this.adaptableApi.optionsApi.getFilterOptions();
55
+ if (!filterOptions.customInFilterValues) {
56
+ // no-one is using value.count or value.visible
57
+ // or context.sortedValues
58
+ // so no need to reset the filter display values
59
+ return;
60
+ }
44
61
  this.resetFilterDisplayValues();
45
62
  }
46
63
  resetFilterDisplayValues() {
47
64
  // Reset the filter display values manually
48
- this.filterDisplayValues = null;
65
+ this.filterDisplayValuesResult = undefined;
49
66
  }
50
67
  async refreshFilterDisplayValues() {
51
68
  this.resetFilterDisplayValues();
52
- return this.getFilterDisplayValues('');
69
+ return this.getFilterDisplayValuesFromCache({ currentSearchValue: '' });
53
70
  }
54
71
  refresh(params) {
55
72
  // No specific refresh logic needed for this handler
56
73
  // The filter display values will be reset on new rows loaded or any filter changed
57
74
  }
58
75
  destroy() {
59
- this.filterDisplayValues = null;
76
+ this.filterDisplayValuesResult = undefined;
60
77
  }
61
78
  }
@@ -20,7 +20,7 @@ export function getEditorForColumnDataType(columnDataType, variant) {
20
20
  if (columnDataType === 'number') {
21
21
  return variant === 'react' ? AdaptableReactNumberEditor : AdaptableNumberEditor;
22
22
  }
23
- if (columnDataType === 'date' || columnDataType === 'dateString') {
23
+ if (columnDataType === 'date') {
24
24
  return variant === 'react' ? AdaptableReactDateEditor : AdaptableDateEditor;
25
25
  }
26
26
  }
@@ -506,7 +506,10 @@ export class AgGridColumnAdapter {
506
506
  : Array.isArray(original_columnType)
507
507
  ? original_columnType
508
508
  : [original_columnType];
509
- const columnTypes = new Set(originalTypes);
509
+ // Adaptable uses type 'date' for all date columns, while AG Grid uses 'date' and 'dateString'
510
+ // #data_type_dateString
511
+ let normalisedTypes = originalTypes.map((t) => (t === 'dateString' ? 'date' : t));
512
+ const columnTypes = new Set(normalisedTypes);
510
513
  if (this.adaptableApi.columnApi.isCalculatedColumn(colId)) {
511
514
  columnTypes.add(CALCULATED_COLUMN_TYPE);
512
515
  }
@@ -431,7 +431,7 @@ export class AgGridExportAdapter {
431
431
  return;
432
432
  }
433
433
  const columnDataType = this.adaptableApi.columnApi.getColumnDataTypeForColumnId(columnId);
434
- if ((columnDataType === 'date' || columnDataType === 'dateString') &&
434
+ if (columnDataType === 'date' &&
435
435
  typeof rawValue === 'string' &&
436
436
  // rawValue is composed only of digits
437
437
  /^\d+$/.test(rawValue)) {
@@ -689,7 +689,6 @@ export class AgGridExportAdapter {
689
689
  case 'boolean':
690
690
  return 'Boolean';
691
691
  case 'date':
692
- case 'dateString':
693
692
  return 'DateTime';
694
693
  case 'text':
695
694
  default:
@@ -819,7 +818,7 @@ export class AgGridExportAdapter {
819
818
  if (exportContext.isVisualExcelReport) {
820
819
  return this.getCellExportValueFromRawValueByType(rowNode, cellRawValue, columnId, 'formattedValue');
821
820
  }
822
- const isDateColumn = columnDataType === 'date' || columnDataType === 'dateString';
821
+ const isDateColumn = columnDataType === 'date';
823
822
  // 2. if this is a date column and there is a custom export date format provided, that will next take precedence
824
823
  if (isDateColumn) {
825
824
  const customExportDateFormat = this.getCustomExportDateFormat(column, exportContext);
@@ -877,7 +876,6 @@ export class AgGridExportAdapter {
877
876
  case 'number':
878
877
  return dataFormatDataType.number;
879
878
  case 'date':
880
- case 'dateString':
881
879
  return dataFormatDataType.date;
882
880
  default:
883
881
  // default to rawValue for all other column types
@@ -1,3 +1,4 @@
1
+ import { AdaptableLogger } from '.';
1
2
  import { AllEnterpriseModule } from 'ag-grid-enterprise';
2
3
  export const AG_GRID_VERSION = AllEnterpriseModule.version;
3
4
  export class AgGridModulesAdapter {
@@ -42,7 +43,10 @@ export class AgGridModulesAdapter {
42
43
  mandatoryModules.push('ServerSideRowModelApiModule');
43
44
  break;
44
45
  case 'infinite':
45
- mandatoryModules.push('InfiniteRowModelModule');
46
+ AdaptableLogger.consoleErrorBase("AdapTable does not support AG Grid's Infinite Row Model");
47
+ break;
48
+ case 'viewport':
49
+ mandatoryModules.push('ViewportRowModelModule');
46
50
  break;
47
51
  default:
48
52
  mandatoryModules.push('ClientSideRowModelModule');
@@ -7,7 +7,6 @@ export const ALL_ADAPTABLE_DATA_TYPES = [
7
7
  'number',
8
8
  'boolean',
9
9
  'date',
10
- 'dateString',
11
10
  'object',
12
11
  TEXT_ARRAY_DATA_TYPE,
13
12
  NUMBER_ARRAY_DATA_TYPE,
@@ -31,13 +30,7 @@ export const agGridDataTypeDefinitions = {
31
30
  valueFormatter: null,
32
31
  suppressDefaultProperties: true,
33
32
  },
34
- dateString: {
35
- baseDataType: 'dateString',
36
- extendsDataType: 'dateString',
37
- valueParser: null,
38
- valueFormatter: null,
39
- suppressDefaultProperties: true,
40
- },
33
+ // dateString is force-cast to date in AdapTable, see #data_type_dateString
41
34
  // text: is kept as is
42
35
  // boolean: is kept as is
43
36
  // object: is kept as is
@@ -16,6 +16,7 @@ export type SelectProps<SelectValue extends unknown, IsMulti extends boolean = f
16
16
  searchable?: false | 'inline' | 'menulist';
17
17
  resizable?: boolean;
18
18
  isClearable?: boolean;
19
+ skipDefaultFiltering?: boolean;
19
20
  closeMenuOnSelect?: boolean;
20
21
  hideSelectedOptions?: boolean;
21
22
  showHeaderSelectionCheckbox?: boolean;
@@ -140,6 +140,7 @@ export const Select = function (props) {
140
140
  const renderMultipleValues = props.renderMultipleValues;
141
141
  const isMulti = props.isMulti ?? Array.isArray(props.value);
142
142
  const showHeaderSelectionCheckbox = isMulti && (props.showHeaderSelectionCheckbox ?? false);
143
+ const skipDefaultFiltering = props.skipDefaultFiltering ?? false;
143
144
  let selectedOption = null;
144
145
  if (isMulti) {
145
146
  selectedOption =
@@ -194,7 +195,7 @@ export const Select = function (props) {
194
195
  },
195
196
  } }));
196
197
  };
197
- }, []);
198
+ }, [isSelectMenuOpen]);
198
199
  const resizable = props.resizable ?? false;
199
200
  const ValueContainer = React.useMemo(() => {
200
201
  return (props) => {
@@ -289,7 +290,7 @@ export const Select = function (props) {
289
290
  const MenuList = React.useMemo(() => {
290
291
  return (props) => {
291
292
  const { setValue, getValue, focusedOption, options, selectProps } = props;
292
- const { filterOption, inputValue, options: selectOptions, isLoading } = selectProps;
293
+ const { filterOption, inputValue, isLoading } = selectProps;
293
294
  // Focus the input when MenuList mounts
294
295
  React.useEffect(() => {
295
296
  if (menulistInputRef.current) {
@@ -297,7 +298,7 @@ export const Select = function (props) {
297
298
  }
298
299
  }, []);
299
300
  const filterFunction = React.useCallback(({ data }) => filterOption({ data, label: `${data.label}`, value: data.value }, inputValue), [filterOption, inputValue]);
300
- const hasFilter = inputValue !== '';
301
+ const hasFilter = inputValue !== '' && !skipDefaultFiltering;
301
302
  const filteredOptionsValues = new Set();
302
303
  const filteredOptions = !hasFilter
303
304
  ? options
@@ -454,7 +455,7 @@ export const Select = function (props) {
454
455
  }, placeholder: "Search..." }))),
455
456
  React.createElement(InfiniteTable, { header: isMulti && showHeaderSelectionCheckbox ? true : false, rowClassName: rowClassName, showZebraRows: false, rowHeight: '--ab-grid-row-height', onCellClick: isLoading ? null : onCellClick, keyboardNavigation: isLoading ? false : 'row', activeRowIndex: focusedOptionIndex, keyboardSelection: true, columns: isMulti ? INFINITE_COLUMNS_WITH_CHECKBOX : INFINITE_COLUMNS_WITH_RADIO, domProps: INFINITE_DOM_PROPS })));
456
457
  };
457
- }, [isMulti, showHeaderSelectionCheckbox]);
458
+ }, [isMulti, skipDefaultFiltering, showHeaderSelectionCheckbox]);
458
459
  const DropdownIndicator = React.useMemo(() => {
459
460
  return (dropdownIndicatorProps) => {
460
461
  return (React.createElement(components.DropdownIndicator, { ...dropdownIndicatorProps, innerProps: {
package/src/env.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export default {
2
2
  NEXT_PUBLIC_INFINITE_TABLE_LICENSE_KEY: "StartDate=2021-06-29|EndDate=2030-01-01|Owner=Adaptable|Type=distribution|TS=1624971462479|C=137829811,1004007071,2756196225,1839832928,3994409405,636616862" || '',
3
- PUBLISH_TIMESTAMP: 1756391396935 || Date.now(),
4
- VERSION: "21.0.0-canary.0" || '--current-version--',
3
+ PUBLISH_TIMESTAMP: 1756992459408 || Date.now(),
4
+ VERSION: "21.0.0-canary.2" || '--current-version--',
5
5
  };