@adaptabletools/adaptable 20.2.7 → 20.2.9

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.
@@ -6,6 +6,7 @@ import { ColumnInternalApi } from '../Internal/ColumnInternalApi';
6
6
  import { AUTO_GROUP_COLUMN_ID__MULTI_PREFIX, AUTO_GROUP_COLUMN_ID__SINGLE, } from '../../layout-manager/src/normalizeLayoutModel';
7
7
  import ArrayExtensions from '../../Utilities/Extensions/ArrayExtensions';
8
8
  import { isPivotColumnTotal } from '../../layout-manager/src/isPivotColumnTotal';
9
+ import { isPivotLayout } from './LayoutHelpers';
9
10
  const ROW_GROUP_COLUMN_DEFAULTS = {
10
11
  columnId: '',
11
12
  isTreeColumn: false,
@@ -121,13 +122,17 @@ export class ColumnApiImpl extends ApiBase {
121
122
  }
122
123
  getVisibleColumns() {
123
124
  const layout = this.getLayoutApi().getCurrentLayout();
125
+ const allcols = this.getColumns();
126
+ if (isPivotLayout(layout)) {
127
+ return allcols;
128
+ }
124
129
  const visibleCols = layout.TableColumns.reduce((acc, colId) => {
125
130
  if (layout.ColumnVisibility?.[colId] !== false) {
126
131
  acc.add(colId);
127
132
  }
128
133
  return acc;
129
134
  }, new Set());
130
- return this.getColumns().filter((c) => visibleCols.has(c.columnId));
135
+ return allcols.filter((c) => visibleCols.has(c.columnId));
131
136
  }
132
137
  selectColumn(columnId) {
133
138
  this._adaptable.selectColumn(columnId);
@@ -38,12 +38,8 @@ export declare class LayoutApiImpl extends ApiBase implements LayoutApi {
38
38
  showChangeColumnCaption(column: AdaptableColumn): void;
39
39
  openLayoutSettingsPanel(): void;
40
40
  showLayoutEditor(layoutName?: string, layoutType?: 'table' | 'pivot', action?: ModuleParams['action']): void;
41
- isCurrentLayoutReadOnly(): boolean;
42
41
  deleteLayout(layout: Layout): void;
43
42
  deleteLayoutByName(layoutName: string): void;
44
43
  removeColumnFromCurrentLayout(columnId: string): void;
45
- removeColumnFromAllLayouts(columnId: string): void;
46
- removeColumnFromLayout(columnId: string, layoutName: string): void;
47
- addColumnToTableLayout(columnId: string, layoutName: string): void;
48
- addColumnToCurrentTableLayout(columnId: string): void;
44
+ addColumnToCurrentLayout(columnId: string): void;
49
45
  }
@@ -1,5 +1,4 @@
1
1
  import * as LayoutRedux from '../../Redux/ActionsReducers/LayoutRedux';
2
- import { LayoutSetColumnCaption } from '../../Redux/ActionsReducers/LayoutRedux';
3
2
  import * as ModuleConstants from '../../Utilities/Constants/ModuleConstants';
4
3
  import { ApiBase } from './ApiBase';
5
4
  import StringExtensions from '../../Utilities/Extensions/StringExtensions';
@@ -207,10 +206,11 @@ export class LayoutApiImpl extends ApiBase {
207
206
  }
208
207
  setColumnCaption(columnId, caption) {
209
208
  if (StringExtensions.IsNotNullOrEmpty(columnId) && StringExtensions.IsNotNullOrEmpty(caption)) {
210
- const currentLayoutName = this.getCurrentLayoutName();
211
- if (StringExtensions.IsNotNullOrEmpty(currentLayoutName)) {
212
- this.dispatchAction(LayoutRedux.LayoutSetColumnCaption(currentLayoutName, columnId, caption));
213
- }
209
+ this.updateCurrentLayout((layout) => {
210
+ layout.ColumnHeaders = { ...layout.ColumnHeaders };
211
+ layout.ColumnHeaders[columnId] = caption;
212
+ return layout;
213
+ });
214
214
  }
215
215
  }
216
216
  createOrUpdateLayout(layout) {
@@ -222,13 +222,18 @@ export class LayoutApiImpl extends ApiBase {
222
222
  }
223
223
  }
224
224
  showChangeColumnCaption(column) {
225
- const customHeader = this.getCurrentLayout().ColumnHeaders?.[column.columnId] ?? column.friendlyName;
225
+ const currentLayout = this.getCurrentLayout();
226
+ const customHeader = currentLayout.ColumnHeaders?.[column.columnId] ?? column.friendlyName;
226
227
  this.dispatchAction(PopupShowPrompt({
227
228
  Header: `Change caption for '${column.friendlyName}'`,
228
229
  Msg: '',
229
230
  DefaultValue: customHeader,
230
- ConfirmActionCreator: (inputText) => inputText !== customHeader &&
231
- LayoutSetColumnCaption(this.getCurrentLayoutName(), column.columnId, inputText),
231
+ ConfirmActionCreator: (inputText) => {
232
+ if (inputText !== customHeader) {
233
+ this.setColumnCaption(column.columnId, inputText);
234
+ }
235
+ return { type: 'NOOP' };
236
+ },
232
237
  }));
233
238
  }
234
239
  openLayoutSettingsPanel() {
@@ -253,13 +258,6 @@ export class LayoutApiImpl extends ApiBase {
253
258
  },
254
259
  });
255
260
  }
256
- isCurrentLayoutReadOnly() {
257
- const currentLayout = this.getCurrentLayout();
258
- if (currentLayout) {
259
- return currentLayout.IsReadOnly;
260
- }
261
- return true;
262
- }
263
261
  deleteLayout(layout) {
264
262
  const layoutCount = this.getLayouts().length;
265
263
  if (layoutCount === 1) {
@@ -277,38 +275,39 @@ export class LayoutApiImpl extends ApiBase {
277
275
  return this.deleteLayout(layout);
278
276
  }
279
277
  removeColumnFromCurrentLayout(columnId) {
280
- this.removeColumnFromLayout(columnId, this.getCurrentLayoutName());
281
- }
282
- removeColumnFromAllLayouts(columnId) {
283
- this.getLayouts().forEach((layout) => {
284
- this.removeColumnFromLayout(columnId, layout.Name);
285
- });
286
- }
287
- removeColumnFromLayout(columnId, layoutName) {
288
278
  const column = this.getColumnApi().getColumnWithColumnId(columnId);
289
279
  if (column) {
290
- const layout = this.getLayoutByName(layoutName);
291
- if (layout && !isPivotLayout(layout)) {
292
- if (layout.TableColumns.includes(columnId)) {
293
- this.dispatchAction(LayoutRedux.LayoutRemoveColumn(layoutName, columnId));
294
- this.getColumnApi().hideColumn(columnId);
295
- }
280
+ const layout = this.getCurrentLayout();
281
+ if (!isPivotLayout(layout)) {
282
+ this.updateCurrentLayout((layout) => {
283
+ layout.TableColumns = layout.TableColumns.filter((c) => c !== columnId);
284
+ return layout;
285
+ });
286
+ }
287
+ else {
288
+ this.updateCurrentLayout((layout) => {
289
+ layout.PivotColumns = layout.PivotColumns.filter((c) => c !== columnId);
290
+ return layout;
291
+ });
296
292
  }
297
293
  }
298
294
  }
299
- addColumnToTableLayout(columnId, layoutName) {
295
+ addColumnToCurrentLayout(columnId) {
300
296
  const column = this.getColumnApi().getColumnWithColumnId(columnId);
301
297
  if (column) {
302
- const layout = this.getLayoutByName(layoutName);
303
- if (layout && !isPivotLayout(layout)) {
304
- if (!layout.TableColumns.includes(columnId)) {
305
- this.dispatchAction(LayoutRedux.LayoutAddColumn(layoutName, columnId));
306
- this.getColumnApi().showColumn(columnId);
307
- }
298
+ const layout = this.getCurrentLayout();
299
+ if (!isPivotLayout(layout)) {
300
+ this.updateCurrentLayout((layout) => {
301
+ layout.TableColumns.push(columnId);
302
+ return layout;
303
+ });
304
+ }
305
+ else {
306
+ this.updateCurrentLayout((layout) => {
307
+ layout.PivotColumns.push(columnId);
308
+ return layout;
309
+ });
308
310
  }
309
311
  }
310
312
  }
311
- addColumnToCurrentTableLayout(columnId) {
312
- this.addColumnToTableLayout(columnId, this.getCurrentLayoutName());
313
- }
314
313
  }
@@ -226,7 +226,6 @@ export const pivotLayoutToPivotLayoutModel = (pivotLayout) => {
226
226
  Name: pivotLayout.Name,
227
227
  SuppressAggFuncInHeader: pivotLayout.SuppressAggFuncInHeader,
228
228
  ColumnWidths: pivotLayout.ColumnWidths,
229
- ColumnVisibility: pivotLayout.ColumnVisibility,
230
229
  ColumnSorts: pivotLayout.ColumnSorts,
231
230
  PivotGroupedColumns: pivotLayout.PivotGroupedColumns,
232
231
  ColumnPinning: pivotLayout.ColumnPinning,
@@ -399,7 +398,6 @@ export const pivotLayoutModelToPivotLayout = (layoutModel) => {
399
398
  PivotColumns: layoutModel.PivotColumns,
400
399
  TableColumns: layoutModel.TableColumns,
401
400
  ColumnWidths: layoutModel.ColumnWidths,
402
- ColumnVisibility: layoutModel.ColumnVisibility,
403
401
  ColumnSorts: layoutModel.ColumnSorts,
404
402
  ColumnPinning: layoutModel.ColumnPinning,
405
403
  PivotExpandLevel: layoutModel.PivotExpandLevel,
@@ -4,6 +4,7 @@ import { CellDataChangedInfo } from '../../AdaptableState/Common/CellDataChanged
4
4
  import { AdaptableAlert, AdaptableFlashingCell, AdaptablePersistentState, AdaptableSharedEntity, AdaptableState, AdaptableTheme, CalculatedColumn, CreatedRowInfo, DashboardState, DataImportedInfo, DataSet, DeletedRowInfo, EditedRowInfo, LayoutState, RowDataChangedInfo, SystemStatusMessageInfo } from '../../types';
5
5
  import { ApiBase } from '../Implementation/ApiBase';
6
6
  import { BaseSchedule } from '../../AdaptableState/Common/Schedule';
7
+ import { LayoutChangedAction } from '../Events/LayoutChanged';
7
8
  export declare class EventInternalApi extends ApiBase {
8
9
  fireGridSortedEvent(): void;
9
10
  fireCellChangedEvent(cellDataChangedInfo: CellDataChangedInfo): void;
@@ -11,7 +12,7 @@ export declare class EventInternalApi extends ApiBase {
11
12
  fireDashboardChangedEvent(trigger: string, oldDashboardState: DashboardState, newDashboardState: DashboardState): void;
12
13
  fireAlertFiredEvent(alertToFire: AdaptableAlert): void;
13
14
  fireThemeChangedEvent(theme: AdaptableTheme, trigger: 'ThemeSelected' | 'ThemeEdited'): void;
14
- fireLayoutChangedEvent(trigger: string, oldState: LayoutState, newState: LayoutState): void;
15
+ fireLayoutChangedEvent(trigger: LayoutChangedAction, oldState: LayoutState, newState: LayoutState): void;
15
16
  fireScheduleTriggeredEvent(schedule: BaseSchedule): void;
16
17
  fireDataSetSelectedEvent(dataSet: DataSet): void;
17
18
  fireSystemStatusMessageDisplayedEvent(systemStatusMessageInfo: SystemStatusMessageInfo): void;
@@ -88,26 +88,26 @@ export interface LayoutApi {
88
88
  */
89
89
  updateCurrentLayout(updateFn: (layout: TableLayout | PivotLayout) => TableLayout | PivotLayout): void;
90
90
  /**
91
- * Creates new Layout in Adaptable State
91
+ * Creates a new Layout
92
92
  * @param layoutToCreate Layout to create
93
93
  * @returns created Layout object or `false` if Layout with the same name/Uuid already exists
94
94
  */
95
95
  createLayout(layoutToCreate: Layout): Layout | false;
96
96
  /**
97
- * Creates new Layout in the state and then loads it into Grid
97
+ * Creates new Layout and loads it into Grid
98
98
  * @param layoutToCreate Layout to create
99
99
  * @returns created Layout object or `false` if creation failed
100
100
  */
101
101
  createAndSetLayout(layoutToCreate: Layout): Layout | false;
102
102
  /**
103
- * Creates new Layout based on given Layout but with name provided
103
+ * Creates new Layout by cloning a given Layout
104
104
  * @param layoutToClone Layout to clone
105
- * @param layoutName name to use for new Layout
105
+ * @param layoutName name of new Layout
106
106
  * @returns created Layout object or `false` if creation failed
107
107
  */
108
108
  cloneLayout(layoutToClone: Layout, layoutName: string): Layout | false;
109
109
  /**
110
- * Creates new Layout based on given Layout but with name provided and then loads it into Grid
110
+ * Creates new Layout by cloning a given Layout and then loads it into Grid
111
111
  * @param layoutToClone Layout to clone
112
112
  * @param layoutName name to use for new Layout
113
113
  * @returns created Layout object or `false` if creation failed
@@ -148,40 +148,19 @@ export interface LayoutApi {
148
148
  * @param layout Name of the Layout to delete
149
149
  */
150
150
  deleteLayoutByName(layoutName: string): void;
151
- /**
152
- * Specifies where Current Layout is editable
153
- */
154
- isCurrentLayoutReadOnly(): boolean;
155
151
  /**
156
152
  * Opens Change Column Caption popup
157
153
  * @param column Column to open Popup for
158
154
  */
159
155
  showChangeColumnCaption(column: AdaptableColumn): void;
160
156
  /**
161
- * Removes a Column from the Current Layout
157
+ * Removes a Column from Current Table or Pivot Layout
162
158
  * @param columnId Column to remove
163
159
  */
164
160
  removeColumnFromCurrentLayout(columnId: string): void;
165
161
  /**
166
- * Removes a Column from all Layouts
167
- * @param columnId Column to remove
168
- */
169
- removeColumnFromAllLayouts(columnId: string): void;
170
- /**
171
- * Removes a Column from a given Layout
172
- * @param columnId Column to remove
173
- * @param layoutName layout from which to remove Column
174
- */
175
- removeColumnFromLayout(columnId: string, layoutName: string): void;
176
- /**
177
- * Adds a Column to a given Table Layout
178
- * @param columnId Column to add
179
- * @param layoutName layout to which to add Column
180
- */
181
- addColumnToTableLayout(columnId: string, layoutName: string): void;
182
- /**
183
- * Adds a Column to Current (Table) Layout
162
+ * Adds a Column to Current Table or Pivot Layout
184
163
  * @param columnId Column to add
185
164
  */
186
- addColumnToCurrentTableLayout(columnId: string): void;
165
+ addColumnToCurrentLayout(columnId: string): void;
187
166
  }
@@ -2,10 +2,6 @@ import * as Redux from 'redux';
2
2
  import { AdaptableState } from '../../../types';
3
3
  import { LayoutState, Layout } from '../../AdaptableState/LayoutState';
4
4
  import { ColumnFilter } from '../../types';
5
- /**
6
- * @ReduxAction A new caption / header has been set for a Column in the Layout
7
- */
8
- export declare const LAYOUT_COLUMN_SET_CAPTION = "LAYOUT_COLUMN_SET_CAPTION";
9
5
  /**
10
6
  * @ReduxAction Layout Module is ready
11
7
  */
@@ -30,14 +26,6 @@ export declare const LAYOUT_SELECT = "LAYOUT_SELECT";
30
26
  * @ReduxAction A Layout has been (auto)saved
31
27
  */
32
28
  export declare const LAYOUT_SAVE = "LAYOUT_SAVE";
33
- /**
34
- * @ReduxAction A Column has been added
35
- */
36
- export declare const LAYOUT_COLUMN_ADD = "LAYOUT_COLUMN_ADD";
37
- /**
38
- * @ReduxAction A Column has been removed
39
- */
40
- export declare const LAYOUT_COLUMN_REMOVE = "LAYOUT_COLUMN_REMOVE";
41
29
  /**
42
30
  * @ReduxAction A Column Filter has been added
43
31
  */
@@ -83,7 +71,7 @@ export declare const LAYOUT_GRID_FILTER_SUSPEND = "LAYOUT_GRID_FILTER_SUSPEND";
83
71
  */
84
72
  export declare const LAYOUT_GRID_FILTER_UNSUSPEND = "LAYOUT_GRID_FILTER_UNSUSPEND";
85
73
  /**
86
- * @ReduxAction Edit Grid filter
74
+ * @ReduxAction The Grid Filter has been edited
87
75
  */
88
76
  export declare const LAYOUT_GRID_FILTER_SET = "LAYOUT_GRID_FILTER_SET";
89
77
  /**
@@ -171,9 +159,6 @@ export interface LayoutReadyAction extends Redux.Action {
171
159
  export declare const LayoutAdd: (layout: Layout) => LayoutAddAction;
172
160
  export declare const LayoutDelete: (layout: Layout) => LayoutDeleteAction;
173
161
  export declare const LayoutSave: (layout: Layout) => LayoutSaveAction;
174
- export declare const LayoutSetColumnCaption: (layoutName: string, columnId: string, caption: string) => LayoutSetColumnCaptionAction;
175
- export declare const LayoutAddColumn: (layoutName: string, columnId: string) => LayoutAddColumnAction;
176
- export declare const LayoutRemoveColumn: (layoutName: string, columnId: string) => LayoutRemoveColumnAction;
177
162
  export declare const LayoutSelect: (layoutName: string) => LayoutSelectAction;
178
163
  export declare const LayoutReady: (layoutState: LayoutState) => LayoutReadyAction;
179
164
  export declare const getColumnFiltersSelector: (state: AdaptableState) => ColumnFilter[];
@@ -1,10 +1,6 @@
1
1
  import { EMPTY_STRING } from '../../Utilities/Constants/GeneralConstants';
2
2
  import AdaptableHelper from '../../Utilities/Helpers/AdaptableHelper';
3
3
  import { normalizeLayout } from '../../Api/Implementation/LayoutHelpers';
4
- /**
5
- * @ReduxAction A new caption / header has been set for a Column in the Layout
6
- */
7
- export const LAYOUT_COLUMN_SET_CAPTION = 'LAYOUT_COLUMN_SET_CAPTION';
8
4
  /**
9
5
  * @ReduxAction Layout Module is ready
10
6
  */
@@ -29,14 +25,6 @@ export const LAYOUT_SELECT = 'LAYOUT_SELECT';
29
25
  * @ReduxAction A Layout has been (auto)saved
30
26
  */
31
27
  export const LAYOUT_SAVE = 'LAYOUT_SAVE';
32
- /**
33
- * @ReduxAction A Column has been added
34
- */
35
- export const LAYOUT_COLUMN_ADD = 'LAYOUT_COLUMN_ADD';
36
- /**
37
- * @ReduxAction A Column has been removed
38
- */
39
- export const LAYOUT_COLUMN_REMOVE = 'LAYOUT_COLUMN_REMOVE';
40
28
  /**
41
29
  * @ReduxAction A Column Filter has been added
42
30
  */
@@ -82,7 +70,7 @@ export const LAYOUT_GRID_FILTER_SUSPEND = 'LAYOUT_GRID_FILTER_SUSPEND';
82
70
  */
83
71
  export const LAYOUT_GRID_FILTER_UNSUSPEND = 'LAYOUT_GRID_FILTER_UNSUSPEND';
84
72
  /**
85
- * @ReduxAction Edit Grid filter
73
+ * @ReduxAction The Grid Filter has been edited
86
74
  */
87
75
  export const LAYOUT_GRID_FILTER_SET = 'LAYOUT_GRID_FILTER_SET';
88
76
  /**
@@ -148,22 +136,6 @@ export const LayoutSave = (layout) => ({
148
136
  type: LAYOUT_SAVE,
149
137
  layout: normalizeLayout(layout),
150
138
  });
151
- export const LayoutSetColumnCaption = (layoutName, columnId, caption) => ({
152
- type: LAYOUT_COLUMN_SET_CAPTION,
153
- layoutName,
154
- columnId,
155
- caption,
156
- });
157
- export const LayoutAddColumn = (layoutName, columnId) => ({
158
- type: LAYOUT_COLUMN_ADD,
159
- layoutName,
160
- columnId,
161
- });
162
- export const LayoutRemoveColumn = (layoutName, columnId) => ({
163
- type: LAYOUT_COLUMN_REMOVE,
164
- layoutName,
165
- columnId,
166
- });
167
139
  export const LayoutSelect = (layoutName) => ({
168
140
  type: LAYOUT_SELECT,
169
141
  layoutName,
@@ -243,52 +215,6 @@ export const LayoutReducer = (state = initialState, action) => {
243
215
  Layouts: newLayouts,
244
216
  };
245
217
  }
246
- case LAYOUT_COLUMN_SET_CAPTION: {
247
- const setColumnCaptionAction = action;
248
- const currentLayoutName = setColumnCaptionAction.layoutName;
249
- let currentLayout = state.Layouts.find((l) => l.Name === currentLayoutName);
250
- if (currentLayout) {
251
- if (!currentLayout.ColumnHeaders) {
252
- currentLayout.ColumnHeaders = {};
253
- }
254
- currentLayout.ColumnHeaders[setColumnCaptionAction.columnId] =
255
- setColumnCaptionAction.caption;
256
- return Object.assign({}, state, {
257
- Layouts: state.Layouts.map((abObject) => abObject.Uuid === currentLayout.Uuid ? currentLayout : abObject),
258
- });
259
- }
260
- return state;
261
- }
262
- case LAYOUT_COLUMN_ADD: {
263
- const addColumnAction = action;
264
- const layoutname = addColumnAction.layoutName;
265
- const colToAdd = addColumnAction.columnId;
266
- let layoutToUpdate = state.Layouts.find((l) => l.Name === layoutname);
267
- if (layoutToUpdate) {
268
- layoutToUpdate.TableColumns.push(colToAdd);
269
- return {
270
- ...state,
271
- Layouts: state.Layouts.map((abObject) => abObject.Uuid === layoutToUpdate.Uuid ? layoutToUpdate : abObject),
272
- };
273
- }
274
- return state;
275
- }
276
- case LAYOUT_COLUMN_REMOVE: {
277
- const removeColumnAction = action;
278
- const layoutname = removeColumnAction.layoutName;
279
- const colToRemove = removeColumnAction.columnId;
280
- let layoutToUpdate = state.Layouts.find((l) => l.Name === layoutname);
281
- if (layoutToUpdate) {
282
- layoutToUpdate.TableColumns = layoutToUpdate.TableColumns.filter((col) => {
283
- return col !== colToRemove;
284
- });
285
- return {
286
- ...state,
287
- Layouts: state.Layouts.map((abObject) => abObject.Uuid === layoutToUpdate.Uuid ? layoutToUpdate : abObject),
288
- };
289
- }
290
- return state;
291
- }
292
218
  case LAYOUT_COLUMN_FILTER_SET: {
293
219
  let columnFilters = currentLayout.ColumnFilters ?? [];
294
220
  const columnFilterAction = action.columnFilter;
@@ -881,7 +881,6 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
881
881
  case LayoutRedux.LAYOUT_EDIT:
882
882
  case LayoutRedux.LAYOUT_SAVE:
883
883
  case LayoutRedux.LAYOUT_DELETE:
884
- case LayoutRedux.LAYOUT_COLUMN_SET_CAPTION:
885
884
  case LayoutRedux.LAYOUT_SELECT: {
886
885
  const oldLayoutState = middlewareAPI.getState().Layout;
887
886
  // this must be called before 'next(action)'
@@ -907,8 +906,7 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
907
906
  adaptable.applyFiltering();
908
907
  }
909
908
  if (returnAction.type == LayoutRedux.LAYOUT_SELECT ||
910
- returnAction.type == LayoutRedux.LAYOUT_DELETE ||
911
- returnAction.type == LayoutRedux.LAYOUT_COLUMN_SET_CAPTION) {
909
+ returnAction.type == LayoutRedux.LAYOUT_DELETE) {
912
910
  // tell AdapTable the Layout has been selected
913
911
  if (newLayout) {
914
912
  adaptable.updateLayoutInManagerAfterStoreHasChanged(newLayout);
@@ -24,4 +24,5 @@ export declare class LayoutModule extends AdaptableModuleBase implements IModule
24
24
  getViewProperties(): AdaptableModuleView;
25
25
  handleLayoutSelection(): void;
26
26
  getReferencedNamedQueryNames(layout: Layout): string[];
27
+ isCurrentLayoutReadOnly(): boolean;
27
28
  }
@@ -42,7 +42,7 @@ export class LayoutModule extends AdaptableModuleBase {
42
42
  }
43
43
  getExplicitlyReferencedColumnIds(layout) {
44
44
  const columnIds = [];
45
- if (layout.TableColumns) {
45
+ if (!isPivotLayout(layout) && layout.TableColumns) {
46
46
  const visibility = layout.ColumnVisibility || {};
47
47
  columnIds.push(...layout.TableColumns.filter((colId) => {
48
48
  return visibility[colId] !== false;
@@ -125,7 +125,7 @@ export class LayoutModule extends AdaptableModuleBase {
125
125
  return;
126
126
  }
127
127
  let returnColumnMenuItems = [];
128
- const isReadOnlyLayout = this.api.layoutApi.isCurrentLayoutReadOnly();
128
+ const isReadOnlyLayout = this.isCurrentLayoutReadOnly();
129
129
  if (!isReadOnlyLayout) {
130
130
  returnColumnMenuItems.push(this.createMenuItemShowPopup('layout-edit', 'Edit Layout', this.moduleInfo.Popup, 'edit-table', {
131
131
  action: 'Edit',
@@ -164,7 +164,7 @@ export class LayoutModule extends AdaptableModuleBase {
164
164
  }
165
165
  createContextMenuItems(menuContext) {
166
166
  let returnColumnMenuItems = [];
167
- if (this.isModuleEditable() && !this.api.layoutApi.isCurrentLayoutReadOnly()) {
167
+ if (this.isModuleEditable() && !this.isCurrentLayoutReadOnly()) {
168
168
  returnColumnMenuItems.push(this.createMenuItemShowPopup('layout-edit', 'Edit Layout', this.moduleInfo.Popup, 'edit-table', {
169
169
  action: 'Edit',
170
170
  source: 'ColumnMenu',
@@ -450,4 +450,11 @@ export class LayoutModule extends AdaptableModuleBase {
450
450
  }
451
451
  return this.api.namedQueryApi.internalApi.getReferencedNamedQueryNames(layout.GridFilter.Expression);
452
452
  }
453
+ isCurrentLayoutReadOnly() {
454
+ const currentLayout = this.api.layoutApi.getCurrentLayout();
455
+ if (currentLayout) {
456
+ return currentLayout.IsReadOnly;
457
+ }
458
+ return true;
459
+ }
453
460
  }
@@ -75,7 +75,44 @@ export const FloatingFilterValues = (props) => {
75
75
  columnId: props.columnId,
76
76
  searchValueRef,
77
77
  });
78
- useEffect(triggerValuesLoad, []);
78
+ const valueRef = React.useRef(props.value);
79
+ useEffect(() => {
80
+ // we used to load values initially on mount, without any condition
81
+ const value = valueRef.current;
82
+ // but we now optimize it - if there are no values to show (for which we would need a label)
83
+ // then we skip it altogether, so we'll only load onMenuOpen
84
+ if (!value || !Array.isArray(value) || value.length === 0) {
85
+ return;
86
+ }
87
+ // however, if the `value` prop is a non-empty array, we need to load the values
88
+ // so we know which labels to show
89
+ triggerValuesLoad();
90
+ }, []);
91
+ const quickFilterValuesRef = React.useRef(quickFilterValues);
92
+ quickFilterValuesRef.current = quickFilterValues;
93
+ useEffect(() => {
94
+ // since we did the optimization above,
95
+ // we now hit a scenario where the value is set via an API method
96
+ // so we also need to account for that - so whenever props.value changes, we need to check
97
+ // and if we previously didn't have a valid array
98
+ // and now we do, we need to load the values - if they are not already loaded
99
+ if (quickFilterValuesRef.current.values.length > 0 ||
100
+ quickFilterValuesRef.current.dataLoadIsComplete) {
101
+ // values have already been loaded, so we can skip
102
+ return;
103
+ }
104
+ const currentValue = props.value;
105
+ const prevValue = valueRef.current;
106
+ valueRef.current = currentValue;
107
+ const prevValid = Array.isArray(prevValue) && prevValue.length > 0;
108
+ const currentValid = Array.isArray(currentValue) && currentValue.length > 0;
109
+ if (!currentValid) {
110
+ return;
111
+ }
112
+ if (!prevValid && currentValid) {
113
+ triggerValuesLoad();
114
+ }
115
+ }, [props.value]);
79
116
  const onMenuOpen = triggerValuesLoad;
80
117
  const onInputChange = React.useCallback((value) => {
81
118
  searchValueRef.current = value;
@@ -23,6 +23,7 @@ import { AdaptableFormControlTextClear } from '../../../Components/Forms/Adaptab
23
23
  import { sortColumnIdsByOrder } from '../../../../layout-manager/src/sortColumnIdsByOrder';
24
24
  import HelpBlock from '../../../../components/HelpBlock';
25
25
  import { AG_GRID_SELECTION_COLUMN } from '../../../../Utilities/Constants/GeneralConstants';
26
+ import { isPivotLayout } from '../../../../Utilities/isPivotLayout';
26
27
  const PropertyOrderText = (props) => (React.createElement(Text, { fontWeight: 600, fontSize: 2 }, props.children));
27
28
  const columnTypes = {
28
29
  default: {
@@ -156,7 +157,8 @@ const ColumnRow = (props) => {
156
157
  const { column } = props;
157
158
  // width
158
159
  const columnWidth = props.layout.ColumnWidths?.[column.columnId];
159
- const visible = (props.layout.TableColumns.includes(column.columnId) &&
160
+ const visible = (!isPivotLayout(props.layout) &&
161
+ props.layout.TableColumns.includes(column.columnId) &&
160
162
  props.layout.ColumnVisibility?.[column.columnId] !== false) ||
161
163
  isRowGroupColumn;
162
164
  return (React.createElement(Box, { "data-name": props.column.columnId, className: "ab-Layout-Wizard__ColumnRow" },
@@ -3127,6 +3127,7 @@ You need to define at least one Layout!`);
3127
3127
  }
3128
3128
  }
3129
3129
  }
3130
+ const prevLayout = this._prevLayout;
3130
3131
  this._prevLayout = layout;
3131
3132
  const perfSetLayout = this.logger.beginPerf(`setLayout(${layout.Name})`);
3132
3133
  const isPivot = isPivotLayout(layout);
@@ -3149,7 +3150,10 @@ You need to define at least one Layout!`);
3149
3150
  // need to refresh the header,
3150
3151
  // as the Layout.ColumnHeaders state property is not implemented in the LayoutManager
3151
3152
  // and is specific to Adaptable, therefore we need to refresh it manually
3152
- this.refreshHeader();
3153
+ if (!prevLayout ||
3154
+ JSON.stringify(prevLayout.ColumnHeaders) !== JSON.stringify(layout.ColumnHeaders)) {
3155
+ this.refreshHeader();
3156
+ }
3153
3157
  const layoutModel = layoutStateToLayoutModel(layout);
3154
3158
  this.layoutManager?.setLayout(layoutModel, {
3155
3159
  skipApplyRowGroupsExpandedState: !shouldUpdateExpandState,
@@ -1,11 +1,24 @@
1
1
  import * as React from 'react';
2
+ import { useCallback, useEffect } from 'react';
2
3
  import { Box, Flex } from 'rebass';
4
+ import debounce from 'lodash/debounce';
3
5
  import Input from '../Input';
4
6
  import { getVariableColor } from '../../Utilities/Helpers/StyleHelper';
5
7
  import tinycolor from 'tinycolor2';
6
8
  export const ColorPicker = React.forwardRef((props, ref) => {
7
9
  const ColorPalette = props.api.userInterfaceApi.getColorPalette();
8
10
  let { api, value, includeAlpha = true, ...restProps } = props;
11
+ // Create a debounced version of onChange
12
+ // we need this because moving the mouse A LOT in the custom color picker can break the React rendering
13
+ const debouncedOnChange = useCallback(debounce((color) => {
14
+ props.onChange(color);
15
+ }, 30), [props.onChange]);
16
+ // Clean up the debounce on unmount
17
+ useEffect(() => {
18
+ return () => {
19
+ debouncedOnChange.cancel();
20
+ };
21
+ }, [debouncedOnChange]);
9
22
  const optionsMap = ColorPalette.reduce((acc, colorItem) => ({ ...acc, [getVariableColor(colorItem)]: colorItem }), {});
10
23
  const ABcolorChoicesOptions = Object.keys(optionsMap).map((x) => {
11
24
  return (React.createElement("option", { key: x, value: x }, x));
@@ -27,7 +40,7 @@ export const ColorPicker = React.forwardRef((props, ref) => {
27
40
  * The value is not in the map when the color is not in the palette.
28
41
  */
29
42
  const color = optionsMap[event.target.value] ?? event.target.value;
30
- props.onChange(color);
43
+ debouncedOnChange(color);
31
44
  }, value: preparedValue, ref: ref, type: "color", style: {
32
45
  width: 70,
33
46
  padding: 0 /* we need this to be 0, since otherwise on Windows browsers, the chosen color cannot be seen */,
@@ -37,6 +50,6 @@ export const ColorPicker = React.forwardRef((props, ref) => {
37
50
  React.createElement(Box, { mr: 1 }, "Opacity"),
38
51
  React.createElement(Input, { disabled: props.disabled, className: "ab-ColorPicker-range", style: { background: rangeBackround }, value: alpha, onChange: (event) => {
39
52
  const color = tinycolor(value).setAlpha(event.target.value).toRgbString();
40
- props.onChange(color);
53
+ debouncedOnChange(color);
41
54
  }, min: 0, max: 1, step: 0.01, type: "range" })))));
42
55
  });
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: 1751978297635 || Date.now(),
4
- VERSION: "20.2.7" || '--current-version--',
3
+ PUBLISH_TIMESTAMP: 1752564875397 || Date.now(),
4
+ VERSION: "20.2.9" || '--current-version--',
5
5
  };
@@ -5644,13 +5644,13 @@ export declare const ADAPTABLE_METAMODEL: {
5644
5644
  kind: string;
5645
5645
  desc: string;
5646
5646
  isOpt: boolean;
5647
- ref?: undefined;
5647
+ ref: string;
5648
5648
  } | {
5649
5649
  name: string;
5650
5650
  kind: string;
5651
5651
  desc: string;
5652
5652
  isOpt: boolean;
5653
- ref: string;
5653
+ ref?: undefined;
5654
5654
  } | {
5655
5655
  name: string;
5656
5656
  kind: string;