@adaptabletools/adaptable 12.0.3 → 12.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptabletools/adaptable",
3
- "version": "12.0.3",
3
+ "version": "12.0.4",
4
4
  "description": "Powerful data-agnostic HTML5 datagrid add-on that sits on top of an underlying grid component and provides all the rich functionality that advanced users expect from their DataGrids and Data Tables",
5
5
  "keywords": [
6
6
  "web-components",
@@ -1,2 +1,2 @@
1
- declare const _default: 1656962682750;
1
+ declare const _default: 1657113089379;
2
2
  export default _default;
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = 1656962682750;
3
+ exports.default = 1657113089379;
@@ -7,7 +7,7 @@ import { ColumnFilter, DataSet } from '../../types';
7
7
  */
8
8
  export interface SearchChangedInfo extends BaseEventInfo {
9
9
  /**
10
- * What search-related change caused the event to fire
10
+ * How Search was changed: 'CurrentQuery', 'Filter', 'DataChange' or 'Sort'
11
11
  */
12
12
  searchChangedTrigger: 'CurrentQuery' | 'Filter' | 'DataChange' | 'Sort';
13
13
  /**
@@ -199,4 +199,9 @@ export interface FormatColumnApi {
199
199
  * @param options formatter options
200
200
  */
201
201
  getDateFormattedValue(value: any, node: RowNode, abColumn: AdaptableColumn, options: AdaptableFormat['Options']): string;
202
+ /**
203
+ * Checks if a Format Column contains a Custom Display Formatter
204
+ * @param formatColumn Format Column
205
+ */
206
+ hasCustomDisplayFormatter(formatColumn: FormatColumn): boolean;
202
207
  }
@@ -48,4 +48,5 @@ export declare class FormatColumnApiImpl extends ApiBase implements FormatColumn
48
48
  getNumberFormattedValue(value: any, node: RowNode, abColumn: AdaptableColumn, options: AdaptableFormat['Options']): string;
49
49
  getStringFormattedValue(value: any, node: RowNode, abColumn: AdaptableColumn, options: AdaptableFormat['Options']): string;
50
50
  getDateFormattedValue(value: any, node: RowNode, abColumn: AdaptableColumn, options: AdaptableFormat['Options']): string;
51
+ hasCustomDisplayFormatter(formatColumn: FormatColumn): boolean;
51
52
  }
@@ -293,6 +293,9 @@ class FormatColumnApiImpl extends ApiBase_1.ApiBase {
293
293
  }, customDisplayFormatterContext);
294
294
  }
295
295
  getNumberFormattedValue(value, node, abColumn, options) {
296
+ if (!value) {
297
+ return undefined;
298
+ }
296
299
  const preparedValue = this.applyCustomFormatters(value, node, abColumn, options);
297
300
  return FormatHelper_1.default.NumberFormatter(preparedValue, options);
298
301
  }
@@ -301,8 +304,27 @@ class FormatColumnApiImpl extends ApiBase_1.ApiBase {
301
304
  return FormatHelper_1.default.StringFormatter(preparedValue, options);
302
305
  }
303
306
  getDateFormattedValue(value, node, abColumn, options) {
307
+ if (!value) {
308
+ return undefined;
309
+ }
304
310
  const preparedValue = this.applyCustomFormatters(value, node, abColumn, options);
305
- return FormatHelper_1.default.DateFormatter(preparedValue, options);
311
+ const dateFormatterOptions = options;
312
+ // only use DateFormatter if we have a pattern
313
+ return dateFormatterOptions.Pattern
314
+ ? FormatHelper_1.default.DateFormatter(preparedValue, options)
315
+ : preparedValue;
316
+ }
317
+ hasCustomDisplayFormatter(formatColumn) {
318
+ var _a;
319
+ if (!formatColumn || !formatColumn.DisplayFormat || !formatColumn.DisplayFormat.Options) {
320
+ return false;
321
+ }
322
+ const options = formatColumn.DisplayFormat.Options;
323
+ const columnCustomFormatters = (_a = options === null || options === void 0 ? void 0 : options.CustomDisplayFormats) !== null && _a !== void 0 ? _a : [];
324
+ if (!(columnCustomFormatters === null || columnCustomFormatters === void 0 ? void 0 : columnCustomFormatters.length)) {
325
+ return false;
326
+ }
327
+ return true;
306
328
  }
307
329
  }
308
330
  exports.FormatColumnApiImpl = FormatColumnApiImpl;
@@ -14,6 +14,7 @@ export declare class LayoutApiImpl extends ApiBase implements LayoutApi {
14
14
  fireLayoutChangedEvent(trigger: string, oldSate: LayoutState, newState: LayoutState): void;
15
15
  getCurrentLayout(): Layout;
16
16
  getCurrentLayoutColumnSort(columnId: string): ColumnSort['SortOrder'] | null;
17
+ areDraftAndCurrentLayoutEqual(): boolean;
17
18
  getCurrentLayoutName(): string;
18
19
  getLayoutByName(layoutName: string): Layout | null;
19
20
  getAllLayout(): Layout[];
@@ -76,6 +76,12 @@ class LayoutApiImpl extends ApiBase_1.ApiBase {
76
76
  const currentLayout = this.getCurrentLayout();
77
77
  return ((_d = (_c = (_b = (_a = currentLayout === null || currentLayout === void 0 ? void 0 : currentLayout.ColumnSorts) === null || _a === void 0 ? void 0 : _a.find) === null || _b === void 0 ? void 0 : _b.call(_a, (sort) => sort.ColumnId === columnId)) === null || _c === void 0 ? void 0 : _c.SortOrder) !== null && _d !== void 0 ? _d : null);
78
78
  }
79
+ areDraftAndCurrentLayoutEqual() {
80
+ const state = this.getAdaptableState();
81
+ const currentLayout = this.getLayoutByName(state.Layout.CurrentLayout);
82
+ const draftLayout = state.Grid.CurrentLayout;
83
+ return this.areLayoutsEqual(currentLayout, draftLayout);
84
+ }
79
85
  getCurrentLayoutName() {
80
86
  return this.getAdaptableState().Layout.CurrentLayout;
81
87
  }
@@ -198,4 +198,9 @@ export interface LayoutApi {
198
198
  * @param layoutName layout from which to remove Column
199
199
  */
200
200
  removeColumnFromLayout(columnId: string, layoutName: string): void;
201
+ /**
202
+ * Checks if the draft layout and the current layout are the same.
203
+ * Useful when `autoSaveLayouts=true`
204
+ */
205
+ areDraftAndCurrentLayoutEqual(): boolean;
201
206
  }
@@ -10,7 +10,7 @@ export interface ChartDefinition {
10
10
  model: ChartModel;
11
11
  }
12
12
  /**
13
- * Predefined Configuration for Quick Search Module
13
+ * Used for persisting AG Grids in Adaptable State
14
14
  */
15
15
  export interface ChartingState extends ConfigState {
16
16
  /**
@@ -682,12 +682,18 @@ const adaptableMiddleware = (adaptable) => function (middlewareAPI) {
682
682
  if (adaptable.adaptableOptions.searchOptions.filterResultsAfterQuickSearch) {
683
683
  const actionTyped = action;
684
684
  const searchText = actionTyped.quickSearchText;
685
+ // const gridOptions = adaptable.api.gridApi.getAgGridInstance();
685
686
  if (StringExtensions_1.StringExtensions.IsNotNullOrEmpty(searchText)) {
687
+ // Currently using this but any searchable would allow us to limit the cols checked
686
688
  const queryText = 'ANY_CONTAINS("' + searchText + '") ';
689
+ // const queryText = 'ANY_SEARCHABLE_CONTAINS("' + searchText + '") ';
687
690
  adaptable.api.queryApi.setCurrentQuery(queryText);
691
+ // Better still would be to use ag grid if that is possible?
692
+ // gridOptions.api.setQuickFilter(searchText);
688
693
  }
689
694
  else {
690
695
  adaptable.api.queryApi.clearCurrentQuery();
696
+ // gridOptions.api.setQuickFilter('');
691
697
  }
692
698
  }
693
699
  return returnAction;
@@ -247,7 +247,7 @@ class FormatColumnModule extends AdaptableModuleBase_1.AdaptableModuleBase {
247
247
  },
248
248
  {
249
249
  name: 'Display Format',
250
- values: [FormatColumnFormatWizardSection_1.getFormatColumnFormatSummaryValue(formatColumn, this.api.formatColumnApi)],
250
+ values: [FormatColumnFormatWizardSection_1.getFormatColumnFormatSummaryValue(formatColumn, this.api)],
251
251
  },
252
252
  getFormatColumnSettingsViewItems_1.getFormatColumnSettingsViewItems(formatColumn),
253
253
  getObjectTagsViewItems_1.getObjectTagsViewItems(formatColumn, this.api),
@@ -10,6 +10,7 @@ const LayoutRadioSelector_1 = require("../View/Layout/LayoutRadioSelector");
10
10
  const LayoutStatusBarSubPanelPopover_1 = require("../View/Layout/LayoutStatusBarSubPanelPopover");
11
11
  const EditCurrentLayoutButton_1 = require("../View/Layout/EditCurrentLayoutButton");
12
12
  const LayoutCloneButton_1 = require("../View/Layout/LayoutCloneButton");
13
+ const SaveLayoutButton_1 = require("../View/Layout/SaveLayoutButton");
13
14
  class LayoutModule extends AdaptableModuleBase_1.AdaptableModuleBase {
14
15
  constructor(api) {
15
16
  super(ModuleConstants.LayoutModuleId, 'Layout', 'layout', 'LayoutPopup', 'Named sets of column visibility, order, groupings, aggregation, pivots etc.', api);
@@ -293,7 +294,7 @@ class LayoutModule extends AdaptableModuleBase_1.AdaptableModuleBase {
293
294
  content: text,
294
295
  popover: popover,
295
296
  popoverMinWidth: 150,
296
- extraActions: [EditCurrentLayoutButton_1.EditCurrentLayoutButton],
297
+ extraActions: [EditCurrentLayoutButton_1.EditCurrentLayoutButton, SaveLayoutButton_1.SaveLayoutButton],
297
298
  };
298
299
  },
299
300
  };
@@ -28,6 +28,7 @@ export declare const AG_GRID_GROUPED_COLUMN: string;
28
28
  export declare const AG_GRID_PIVOT_COLUMN: string;
29
29
  export declare const ADAPTABLE_ROW_ACTION_BUTTONS = "adaptableRowActionButtons";
30
30
  export declare const ADAPTABLE_ROW_ACTION_BUTTONS_FRIENDLY_NAME = "(ActionRowButtons)";
31
+ export declare const DEFAULT_DATE_FORMAT_PATTERN = "dd-MM-yyyy";
31
32
  export declare const SYSTEM_STATUS_DEFAULT_MAX_MESSAGES_IN_STORE: number;
32
33
  export declare const QUICK_SEARCH_DEFAULT_BACK_COLOR: string;
33
34
  export declare const QUICK_SEARCH_DEFAULT_FORE_COLOR: string;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.VISUAL_DATA_REPORT = exports.SYSTEM_THEMES = exports.SMART_EDIT_MATH_OPERATION_STATE_PROPERTY = exports.SMART_EDIT_VALUE_STATE_PROPERTY = exports.QUICK_SEARCH_STYLE_STATE_PROPERTY = exports.QUICK_SEARCH_TEXT_STATE_PROPERTY = exports.CURRENT_THEME_STATE_PROPERTY = exports.FLASHING_CELL_DEFAULT_DURATION_STATE_PROPERTY = exports.FLASHING_CELL_DEFAULT_DOWN_COLOR_STATE_PROPERTY = exports.FLASHING_CELL_DEFAULT_UP_COLOR_STATE_PROPERTY = exports.CURRENT_REPORT_STATE_PROPERTY = exports.CURRENT_LAYOUT_STATE_PROPERTY = exports.SUMMARY_OPERATION_STATE_PROPERTY = exports.ALERT_DEFAULT_SHOW_POPUP = exports.ALERT_DEFAULT_MESSAGE_TYPE = exports.PLUS_MINUS_DEFAULT_NUDGE_VALUE = exports.DEFAULT_LIVE_REPORT_THROTTLE_TIME = exports.THEME_DEFAULT_CURRENT_THEME = exports.SYSTEM_DEFAULT_SYSTEM_STATUS_TYPE = exports.CELL_SUMMARY_DEFAULT_OPERATION = exports.QUICK_SEARCH_DEBOUNCE_TIME = exports.QUICK_SEARCH_DEFAULT_FORE_COLOR = exports.QUICK_SEARCH_DEFAULT_BACK_COLOR = exports.SYSTEM_STATUS_DEFAULT_MAX_MESSAGES_IN_STORE = exports.ADAPTABLE_ROW_ACTION_BUTTONS_FRIENDLY_NAME = exports.ADAPTABLE_ROW_ACTION_BUTTONS = exports.AG_GRID_PIVOT_COLUMN = exports.AG_GRID_GROUPED_COLUMN = exports.HALF_SECOND = exports.AB_SPECIAL_COLUMN = exports.EMPTY_ARRAY = exports.EMPTY_STRING = exports.FILTER_THROTTLE = exports.FILTER_NEVER = exports.FILTER_ALWAYS = exports.ALL_COLUMN_VALUES = exports.READ_ONLY_STYLE = exports.MENU_PREFIX = exports.AGGRID_TOOLPANEL_COLUMNS = exports.AGGRID_TOOLPANEL_FILTERS = exports.ADAPTABLE_TOOLPANEL_COMPONENT = exports.ADAPTABLE_TOOLPANEL_ID = exports.ADAPTABLE = exports.ADAPTABLE_ID = exports.USER_NAME = exports.DARK_THEME = exports.LIGHT_THEME = exports.DEFAULT_LAYOUT = exports.MISSING_COLUMN = exports.AUTOGENERATED_PK_COLUMN = void 0;
4
- exports.THEME_STYLE = exports.SELECTED_ROWS_REPORT = exports.SELECTED_CELLS_REPORT = exports.CURRENT_DATA_REPORT = exports.ALL_DATA_REPORT = void 0;
3
+ exports.SYSTEM_THEMES = exports.SMART_EDIT_MATH_OPERATION_STATE_PROPERTY = exports.SMART_EDIT_VALUE_STATE_PROPERTY = exports.QUICK_SEARCH_STYLE_STATE_PROPERTY = exports.QUICK_SEARCH_TEXT_STATE_PROPERTY = exports.CURRENT_THEME_STATE_PROPERTY = exports.FLASHING_CELL_DEFAULT_DURATION_STATE_PROPERTY = exports.FLASHING_CELL_DEFAULT_DOWN_COLOR_STATE_PROPERTY = exports.FLASHING_CELL_DEFAULT_UP_COLOR_STATE_PROPERTY = exports.CURRENT_REPORT_STATE_PROPERTY = exports.CURRENT_LAYOUT_STATE_PROPERTY = exports.SUMMARY_OPERATION_STATE_PROPERTY = exports.ALERT_DEFAULT_SHOW_POPUP = exports.ALERT_DEFAULT_MESSAGE_TYPE = exports.PLUS_MINUS_DEFAULT_NUDGE_VALUE = exports.DEFAULT_LIVE_REPORT_THROTTLE_TIME = exports.THEME_DEFAULT_CURRENT_THEME = exports.SYSTEM_DEFAULT_SYSTEM_STATUS_TYPE = exports.CELL_SUMMARY_DEFAULT_OPERATION = exports.QUICK_SEARCH_DEBOUNCE_TIME = exports.QUICK_SEARCH_DEFAULT_FORE_COLOR = exports.QUICK_SEARCH_DEFAULT_BACK_COLOR = exports.SYSTEM_STATUS_DEFAULT_MAX_MESSAGES_IN_STORE = exports.DEFAULT_DATE_FORMAT_PATTERN = exports.ADAPTABLE_ROW_ACTION_BUTTONS_FRIENDLY_NAME = exports.ADAPTABLE_ROW_ACTION_BUTTONS = exports.AG_GRID_PIVOT_COLUMN = exports.AG_GRID_GROUPED_COLUMN = exports.HALF_SECOND = exports.AB_SPECIAL_COLUMN = exports.EMPTY_ARRAY = exports.EMPTY_STRING = exports.FILTER_THROTTLE = exports.FILTER_NEVER = exports.FILTER_ALWAYS = exports.ALL_COLUMN_VALUES = exports.READ_ONLY_STYLE = exports.MENU_PREFIX = exports.AGGRID_TOOLPANEL_COLUMNS = exports.AGGRID_TOOLPANEL_FILTERS = exports.ADAPTABLE_TOOLPANEL_COMPONENT = exports.ADAPTABLE_TOOLPANEL_ID = exports.ADAPTABLE = exports.ADAPTABLE_ID = exports.USER_NAME = exports.DARK_THEME = exports.LIGHT_THEME = exports.DEFAULT_LAYOUT = exports.MISSING_COLUMN = exports.AUTOGENERATED_PK_COLUMN = void 0;
4
+ exports.THEME_STYLE = exports.SELECTED_ROWS_REPORT = exports.SELECTED_CELLS_REPORT = exports.CURRENT_DATA_REPORT = exports.ALL_DATA_REPORT = exports.VISUAL_DATA_REPORT = void 0;
5
5
  const Enums_1 = require("../../PredefinedConfig/Common/Enums");
6
6
  const UIHelper_1 = require("../../View/UIHelper");
7
7
  exports.AUTOGENERATED_PK_COLUMN = '__ADAPTABLE_PK__';
@@ -31,6 +31,7 @@ exports.AG_GRID_GROUPED_COLUMN = 'ag-Grid-AutoColumn';
31
31
  exports.AG_GRID_PIVOT_COLUMN = 'pivot_';
32
32
  exports.ADAPTABLE_ROW_ACTION_BUTTONS = 'adaptableRowActionButtons';
33
33
  exports.ADAPTABLE_ROW_ACTION_BUTTONS_FRIENDLY_NAME = '(ActionRowButtons)';
34
+ exports.DEFAULT_DATE_FORMAT_PATTERN = 'dd-MM-yyyy';
34
35
  /*
35
36
  Redux / State Defaults
36
37
  Try to put all our Redux / State defaults here and ONLY reference from here - avoid magic numbers / strings.
@@ -233,10 +233,32 @@ exports.booleanExpressionFunctions = {
233
233
  });
234
234
  },
235
235
  isPredicate: true,
236
- description: 'Returns true if any column contains input',
236
+ description: 'Returns true if any Column contains input',
237
237
  signatures: ['ANY_CONTAINS(value)'],
238
238
  examples: ['ANY_CONTAINS("abc")'],
239
239
  },
240
+ /*
241
+ ANY_SEARCHABLE_CONTAINS: {
242
+ handler(args, context) {
243
+ const searchTerm = getStringValue(context, String(args[0]));
244
+ return context.api?.columnApi
245
+ .getVisibleColumns()
246
+ .filter((c) => !c.isExcludedFromQuickSearch)
247
+ .some((column) => {
248
+ const value = context.api?.gridApi.getDisplayValueFromRowNode(
249
+ context.node,
250
+ column.columnId
251
+ );
252
+ const columnValue = getStringValue(context, String(value));
253
+ return columnValue.indexOf(searchTerm) !== -1;
254
+ });
255
+ },
256
+ isPredicate: true,
257
+ description: 'Returns true if any Searchable Column contains input',
258
+ signatures: ['ANY_SEARCHABLE_CONTAINS(value)'],
259
+ examples: ['ANY_SEARCHABLE_CONTAINS("abc")'],
260
+ },
261
+ */
240
262
  QUERY: {
241
263
  handler(args, context) {
242
264
  var _a, _b;
@@ -6,6 +6,7 @@ const tslib_1 = require("tslib");
6
6
  // import dateFnsFormat from 'date-fns/format';
7
7
  const format_1 = tslib_1.__importDefault(require("date-fns/format"));
8
8
  const sentence_case_1 = require("sentence-case");
9
+ const GeneralConstants_1 = require("../Constants/GeneralConstants");
9
10
  function Format(input, format) {
10
11
  if (format.Formatter === 'NumberFormatter') {
11
12
  return NumberFormatter(input, format.Options);
@@ -79,7 +80,7 @@ function DateFormatter(input, options) {
79
80
  if (typeof input === 'string') {
80
81
  input = new Date(input);
81
82
  }
82
- return format_1.default(input, options.Pattern || '');
83
+ return format_1.default(input, (options === null || options === void 0 ? void 0 : options.Pattern) || GeneralConstants_1.DEFAULT_DATE_FORMAT_PATTERN);
83
84
  }
84
85
  catch (error) {
85
86
  return input;
@@ -3,7 +3,6 @@ import { FormatColumn } from '../../../PredefinedConfig/FormatColumnState';
3
3
  import { AdaptableFormat } from '../../../PredefinedConfig/Common/AdaptableFormat';
4
4
  import { AdaptableScope } from '../../../PredefinedConfig/Common/AdaptableScope';
5
5
  import { AdaptableApi } from '../../../Api/AdaptableApi';
6
- import { FormatColumnApi } from '../../../types';
7
6
  export declare type FormatColumnFormatWizardSectionProps = {
8
7
  onChange: (data: FormatColumn) => void;
9
8
  };
@@ -11,7 +10,7 @@ export interface FormatColumnFormatWizardState {
11
10
  DisplayFormat: AdaptableFormat;
12
11
  NumericFormat?: 'Percent' | 'Thousand' | 'Million' | 'Dollar' | 'Sterling' | undefined;
13
12
  }
14
- export declare const getFormatColumnFormatSummaryValue: (data: FormatColumn, formattedColumnApi: FormatColumnApi) => string;
13
+ export declare const getFormatColumnFormatSummaryValue: (data: FormatColumn, api: AdaptableApi) => string;
15
14
  export declare const renderFormatColumnFormatSummary: (data: FormatColumn, api: AdaptableApi) => JSX.Element;
16
15
  export declare const getFormatDisplayTypeForScope: (scope: AdaptableScope, api: AdaptableApi) => 'Number' | 'Date' | 'String' | undefined;
17
16
  export declare const FormatColumnFormatWizardSection: (props: FormatColumnFormatWizardSectionProps) => JSX.Element;
@@ -78,7 +78,7 @@ const DateFormatPresets = [
78
78
  'yyyyMMdd',
79
79
  'HH:mm:ss',
80
80
  ];
81
- const getFormatColumnFormatSummaryValue = (data, formattedColumnApi) => {
81
+ const getFormatColumnFormatSummaryValue = (data, api) => {
82
82
  let content = 'N/A';
83
83
  if (!data.DisplayFormat) {
84
84
  content = 'N/A';
@@ -86,24 +86,17 @@ const getFormatColumnFormatSummaryValue = (data, formattedColumnApi) => {
86
86
  else {
87
87
  if (data.DisplayFormat.Formatter === 'NumberFormatter') {
88
88
  content = FormatHelper_1.default.NumberFormatter(12345.6789, data.DisplayFormat.Options);
89
- //formattedColumnApi.getNumberFormattedValue(12345.6789, data.DisplayFormat.Options);
90
89
  }
91
90
  if (data.DisplayFormat.Formatter === 'DateFormatter') {
92
- content = FormatHelper_1.default.DateFormatter(new Date(), data.DisplayFormat.Options);
93
- //formattedColumnApi.getDateFormattedValue(new Date(), data.DisplayFormat.Options);
91
+ content = FormatHelper_1.default.DateFormatter(new Date(2022, 0, 1), data.DisplayFormat.Options);
94
92
  }
95
93
  if (data.DisplayFormat.Formatter === 'StringFormatter') {
96
94
  content = FormatHelper_1.default.StringFormatter('Hello World ', data.DisplayFormat.Options);
97
- //formattedColumnApi.getStringFormattedValue('Hello World ', data.DisplayFormat.Options);
98
95
  }
99
96
  }
100
97
  return content;
101
98
  };
102
99
  exports.getFormatColumnFormatSummaryValue = getFormatColumnFormatSummaryValue;
103
- function splitArrayInTwo(arr) {
104
- const half = Math.floor(arr.length - 1 / 2);
105
- return [arr.slice(0, half), arr.slice(half)];
106
- }
107
100
  const renderCustomFormatter = (data, customFormatter, setFormatOption) => {
108
101
  var _a, _b, _c;
109
102
  return (React.createElement(FormLayout_1.FormRow, { key: customFormatter.id, label: (_a = customFormatter.label) !== null && _a !== void 0 ? _a : customFormatter.id },
@@ -120,7 +113,7 @@ const renderCustomFormatter = (data, customFormatter, setFormatOption) => {
120
113
  } })));
121
114
  };
122
115
  const renderFormatColumnFormatSummary = (data, api) => {
123
- return React.createElement(Tag_1.Tag, null, exports.getFormatColumnFormatSummaryValue(data, api.formatColumnApi));
116
+ return React.createElement(Tag_1.Tag, null, exports.getFormatColumnFormatSummaryValue(data, api));
124
117
  };
125
118
  exports.renderFormatColumnFormatSummary = renderFormatColumnFormatSummary;
126
119
  const getFormatDisplayTypeForScope = (scope, api) => {
@@ -157,7 +150,7 @@ const getFormatDisplayTypeForScope = (scope, api) => {
157
150
  return undefined;
158
151
  };
159
152
  exports.getFormatDisplayTypeForScope = getFormatDisplayTypeForScope;
160
- const renderDateFormat = (data, _onChange, setFormatOption, customFormatters, formatColumnApi) => {
153
+ const renderDateFormat = (data, _onChange, setFormatOption, scopedCustomFormatters, formatColumnApi) => {
161
154
  if (data.DisplayFormat.Formatter !== 'DateFormatter') {
162
155
  return null;
163
156
  }
@@ -173,9 +166,12 @@ const renderDateFormat = (data, _onChange, setFormatOption, customFormatters, fo
173
166
  React.createElement(FormLayout_1.default, null,
174
167
  React.createElement(FormLayout_1.FormRow, { label: "Pattern" },
175
168
  React.createElement(Input_1.default, { value: data.DisplayFormat.Options.Pattern, onChange: (e) => setFormatOption('Pattern', e.currentTarget.value), mr: 2 }),
176
- React.createElement("span", null, FormatHelper_1.default.DateFormatter(new Date(), data.DisplayFormat.Options))),
177
- customFormatters.map((formatter) => renderCustomFormatter(data, formatter, setFormatOption))))),
178
- React.createElement(Tabs_1.Tabs, { marginTop: 2 },
169
+ React.createElement("span", null, FormatHelper_1.default.DateFormatter(new Date(), data.DisplayFormat.Options)))))),
170
+ scopedCustomFormatters.length > 0 && (React.createElement(Tabs_1.Tabs, { marginTop: 2, keyboardNavigation: false },
171
+ React.createElement(Tabs_1.Tabs.Tab, null, "Custom Formats"),
172
+ React.createElement(Tabs_1.Tabs.Content, null,
173
+ React.createElement(FormLayout_1.default, null, scopedCustomFormatters.map((formatter) => renderCustomFormatter(data, formatter, setFormatOption)))))),
174
+ React.createElement(Tabs_1.Tabs, { marginTop: 2, keyboardNavigation: false },
179
175
  React.createElement(Tabs_1.Tabs.Tab, null, "Presets"),
180
176
  React.createElement(Tabs_1.Tabs.Content, null,
181
177
  React.createElement(AdaptableObjectRow_1.AdaptableObjectRow, { style: { fontWeight: 'bold' }, colItems: [
@@ -195,7 +191,7 @@ const renderDateFormat = (data, _onChange, setFormatOption, customFormatters, fo
195
191
  },
196
192
  ] })))))));
197
193
  };
198
- const renderNumberFormat = (data, onChange, setFormatOption, customFormatters, formatColumnApi) => {
194
+ const renderNumberFormat = (data, onChange, setFormatOption, scopedCustomFormatters, formatColumnApi) => {
199
195
  if (data.DisplayFormat.Formatter !== 'NumberFormatter') {
200
196
  return null;
201
197
  }
@@ -247,7 +243,6 @@ const renderNumberFormat = (data, onChange, setFormatOption, customFormatters, f
247
243
  data.DisplayFormat.Options.Multiplier === MILLION_OPTIONS.Multiplier; //isEqual(data.DisplayFormat.Options, MILLION_OPTIONS);
248
244
  const IS_DOLLAR = data.DisplayFormat.Options.Prefix === '$'; //isEqual(data.DisplayFormat.Options, DOLLAR_OPTIONS);
249
245
  const IS_STERLING = data.DisplayFormat.Options.Prefix === '£'; //isEqual(data.DisplayFormat, STERLING_OPTIONS);
250
- const [leftCustomFormatters, rightCustomFormatters] = splitArrayInTwo(customFormatters);
251
246
  return (React.createElement(rebass_1.Box, { "data-name": 'format-column-display-format', padding: 2 },
252
247
  React.createElement(Tabs_1.Tabs, null,
253
248
  React.createElement(Tabs_1.Tabs.Tab, null, "Format"),
@@ -261,8 +256,7 @@ const renderNumberFormat = (data, onChange, setFormatOption, customFormatters, f
261
256
  React.createElement(FormLayout_1.FormRow, { label: "Prefix" },
262
257
  React.createElement(Input_1.default, { value: data.DisplayFormat.Options.Prefix, onChange: (e) => setFormatOption('Prefix', e.currentTarget.value) })),
263
258
  React.createElement(FormLayout_1.FormRow, { label: "Suffix" },
264
- React.createElement(Input_1.default, { value: data.DisplayFormat.Options.Suffix, onChange: (e) => setFormatOption('Suffix', e.currentTarget.value) })),
265
- leftCustomFormatters.map((formatter) => renderCustomFormatter(data, formatter, setFormatOption))),
259
+ React.createElement(Input_1.default, { value: data.DisplayFormat.Options.Suffix, onChange: (e) => setFormatOption('Suffix', e.currentTarget.value) }))),
266
260
  React.createElement(FormLayout_1.default, null,
267
261
  React.createElement(FormLayout_1.FormRow, { label: "Fraction Digits" },
268
262
  React.createElement(Input_1.default, { type: "number", min: "0",
@@ -279,8 +273,12 @@ const renderNumberFormat = (data, onChange, setFormatOption, customFormatters, f
279
273
  React.createElement(FormLayout_1.FormRow, { label: "Parentheses" },
280
274
  React.createElement(CheckBox_1.CheckBox, { checked: data.DisplayFormat.Options.Parentheses, onChange: (checked) => setFormatOption('Parentheses', checked) })),
281
275
  React.createElement(FormLayout_1.FormRow, { label: "Truncate" },
282
- React.createElement(CheckBox_1.CheckBox, { checked: data.DisplayFormat.Options.Truncate, onChange: (checked) => setFormatOption('Truncate', checked) })),
283
- rightCustomFormatters.map((formatter) => renderCustomFormatter(data, formatter, setFormatOption)))))),
276
+ React.createElement(CheckBox_1.CheckBox, { checked: data.DisplayFormat.Options.Truncate, onChange: (checked) => setFormatOption('Truncate', checked) })))))),
277
+ scopedCustomFormatters.length > 0 && (React.createElement(Tabs_1.Tabs, { marginTop: 2, keyboardNavigation: false },
278
+ React.createElement(Tabs_1.Tabs.Tab, null, "Custom Formats"),
279
+ React.createElement(Tabs_1.Tabs.Content, null,
280
+ React.createElement(rebass_1.Flex, { flexDirection: "row" },
281
+ React.createElement(FormLayout_1.default, null, scopedCustomFormatters.map((formatter) => renderCustomFormatter(data, formatter, setFormatOption))))))),
284
282
  React.createElement(Tabs_1.Tabs, { marginTop: 2, autoFocus: false, keyboardNavigation: false },
285
283
  React.createElement(Tabs_1.Tabs.Tab, null, "Presets"),
286
284
  React.createElement(Tabs_1.Tabs.Content, null,
@@ -322,10 +320,11 @@ const renderNumberFormat = (data, onChange, setFormatOption, customFormatters, f
322
320
  },
323
321
  ] })))));
324
322
  };
325
- const renderStringFormat = (data, _onChange, setFormatOption, customFormatters, formatColumnApi) => {
323
+ const renderStringFormat = (data, _onChange, setFormatOption, scopedCustomFormatters, formatColumnApi) => {
326
324
  if (data.DisplayFormat.Formatter !== 'StringFormatter') {
327
325
  return null;
328
326
  }
327
+ console.log('formatters', scopedCustomFormatters);
329
328
  return (React.createElement(rebass_1.Box, { "data-name": 'format-column-display-format', padding: 2 },
330
329
  React.createElement(Tabs_1.Tabs, null,
331
330
  React.createElement(Tabs_1.Tabs.Tab, null, "Format"),
@@ -341,8 +340,12 @@ const renderStringFormat = (data, _onChange, setFormatOption, customFormatters,
341
340
  React.createElement(FormLayout_1.FormRow, { label: "Prefix" },
342
341
  React.createElement(Input_1.default, { value: data.DisplayFormat.Options.Prefix, onChange: (e) => setFormatOption('Prefix', e.currentTarget.value) })),
343
342
  React.createElement(FormLayout_1.FormRow, { label: "Suffix" },
344
- React.createElement(Input_1.default, { value: data.DisplayFormat.Options.Suffix, onChange: (e) => setFormatOption('Suffix', e.currentTarget.value) })),
345
- customFormatters.map((formatter) => renderCustomFormatter(data, formatter, setFormatOption)))))),
343
+ React.createElement(Input_1.default, { value: data.DisplayFormat.Options.Suffix, onChange: (e) => setFormatOption('Suffix', e.currentTarget.value) })))))),
344
+ scopedCustomFormatters.length > 0 && (React.createElement(Tabs_1.Tabs, { marginTop: 2, keyboardNavigation: false },
345
+ React.createElement(Tabs_1.Tabs.Tab, null, "Custom Formats"),
346
+ React.createElement(Tabs_1.Tabs.Content, null,
347
+ React.createElement(rebass_1.Flex, { flexDirection: "column" },
348
+ React.createElement(FormLayout_1.default, { mr: 3 }, scopedCustomFormatters.map((formatter) => renderCustomFormatter(data, formatter, setFormatOption))))))),
346
349
  React.createElement(Tabs_1.Tabs, { marginTop: 2, keyboardNavigation: false },
347
350
  React.createElement(Tabs_1.Tabs.Tab, null, "Example"),
348
351
  React.createElement(Tabs_1.Tabs.Content, null,
@@ -376,15 +379,15 @@ const FormatColumnFormatWizardSection = (props) => {
376
379
  update({ DisplayFormat });
377
380
  };
378
381
  const Type = data.DisplayFormat && data.DisplayFormat.Formatter;
379
- const customNumberFormatters = customDisplayFormatters.filter((displayFormatter) => adaptable.api.scopeApi.isScopeInScope(displayFormatter.scope, data.Scope));
382
+ const customScopedFormatters = customDisplayFormatters.filter((displayFormatter) => adaptable.api.scopeApi.isScopeInScope(displayFormatter.scope, data.Scope));
380
383
  if (Type === 'NumberFormatter') {
381
- return renderNumberFormat(data, update, setFormatOption, customNumberFormatters, formatColumnApi);
384
+ return renderNumberFormat(data, update, setFormatOption, customScopedFormatters, formatColumnApi);
382
385
  }
383
386
  if (Type === 'DateFormatter') {
384
- return renderDateFormat(data, update, setFormatOption, customNumberFormatters, formatColumnApi);
387
+ return renderDateFormat(data, update, setFormatOption, customScopedFormatters, formatColumnApi);
385
388
  }
386
389
  if (Type === 'StringFormatter') {
387
- return renderStringFormat(data, update, setFormatOption, customNumberFormatters, formatColumnApi);
390
+ return renderStringFormat(data, update, setFormatOption, customScopedFormatters, formatColumnApi);
388
391
  }
389
392
  return (React.createElement(HelpBlock_1.default, { margin: 3 },
390
393
  "Setting a Display Format is only available if ",
@@ -1,7 +1,7 @@
1
+ import * as React from 'react';
1
2
  import { ViewPanelProps } from '../Components/SharedProps/ViewPanelProps';
2
- import * as LayoutRedux from '../../Redux/ActionsReducers/LayoutRedux';
3
3
  import { Layout } from '../../PredefinedConfig/LayoutState';
4
- import * as React from 'react';
4
+ import * as LayoutRedux from '../../Redux/ActionsReducers/LayoutRedux';
5
5
  export declare const COMPONENT_LAYOUT_POPUP_NAME = "LayoutEditorStandalonePopup";
6
6
  export interface LayoutViewPanelComponentProps extends ViewPanelProps {
7
7
  onSelectLayout: (layoutName: string) => LayoutRedux.LayoutSelectAction;
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LayoutViewPanelControl = exports.COMPONENT_LAYOUT_POPUP_NAME = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const LayoutRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/LayoutRedux"));
6
5
  const React = tslib_1.__importStar(require("react"));
6
+ const react_redux_1 = require("react-redux");
7
7
  const AdaptableHelper_1 = tslib_1.__importDefault(require("../../Utilities/Helpers/AdaptableHelper"));
8
8
  const rebass_1 = require("rebass");
9
9
  const DropdownButton_1 = tslib_1.__importDefault(require("../../components/DropdownButton"));
@@ -13,9 +13,9 @@ const ButtonSave_1 = require("../Components/Buttons/ButtonSave");
13
13
  const ButtonEdit_1 = require("../Components/Buttons/ButtonEdit");
14
14
  const ButtonNew_1 = require("../Components/Buttons/ButtonNew");
15
15
  const ButtonDelete_1 = require("../Components/Buttons/ButtonDelete");
16
- const react_redux_1 = require("react-redux");
17
16
  const ButtonClone_1 = require("../Components/Buttons/ButtonClone");
18
17
  const GridRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/GridRedux"));
18
+ const LayoutRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/LayoutRedux"));
19
19
  exports.COMPONENT_LAYOUT_POPUP_NAME = 'LayoutEditorStandalonePopup';
20
20
  class LayoutViewPanelComponent extends React.Component {
21
21
  render() {
@@ -55,8 +55,7 @@ function mapStateToProps(state, ownProps) {
55
55
  CurrentLayoutName,
56
56
  CurrentDraftLayout: state.Grid.CurrentLayout || selectedLayout,
57
57
  Layouts,
58
- CanSave: state.Grid.CurrentLayout &&
59
- !api.layoutApi.areLayoutsEqual(selectedLayout, state.Grid.CurrentLayout),
58
+ CanSave: state.Grid.CurrentLayout && !api.layoutApi.areDraftAndCurrentLayoutEqual(),
60
59
  };
61
60
  }
62
61
  function mapDispatchToProps(dispatch) {
@@ -0,0 +1,2 @@
1
+ import * as React from 'react';
2
+ export declare const SaveLayoutButton: React.FunctionComponent;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SaveLayoutButton = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const React = tslib_1.__importStar(require("react"));
6
+ const react_redux_1 = require("react-redux");
7
+ const AdaptableContext_1 = require("../AdaptableContext");
8
+ const ButtonSave_1 = require("../Components/Buttons/ButtonSave");
9
+ const GridRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/GridRedux"));
10
+ const LayoutRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/LayoutRedux"));
11
+ const ModuleConstants = tslib_1.__importStar(require("../../Utilities/Constants/ModuleConstants"));
12
+ const SaveLayoutButton = () => {
13
+ const adaptable = AdaptableContext_1.useAdaptable();
14
+ const accessLevel = adaptable.api.internalApi
15
+ .getEntitlementService()
16
+ .getEntitlementAccessLevelForModule(ModuleConstants.LayoutModuleId);
17
+ const dispatch = react_redux_1.useDispatch();
18
+ const currentDraftLayout = react_redux_1.useSelector((state) => state.Grid.CurrentLayout);
19
+ const isManualSaveLayout = !adaptable.api.layoutApi.shouldAutoSaveLayout(currentDraftLayout);
20
+ const handleSave = React.useCallback((layout) => {
21
+ dispatch(LayoutRedux.LayoutSave(layout));
22
+ dispatch(GridRedux.LayoutUpdateCurrentDraft(null));
23
+ }, []);
24
+ const isSaveEnabled = currentDraftLayout && !adaptable.api.layoutApi.areDraftAndCurrentLayoutEqual();
25
+ if (!isManualSaveLayout) {
26
+ return React.createElement(React.Fragment, null);
27
+ }
28
+ return (React.createElement(ButtonSave_1.ButtonSave, { ml: 1, variant: "text", iconSize: 15, onClick: () => handleSave(currentDraftLayout), tooltip: "Save Changes to Current Layout", disabled: !isSaveEnabled, accessLevel: accessLevel }));
29
+ };
30
+ exports.SaveLayoutButton = SaveLayoutButton;
@@ -2760,7 +2760,7 @@ class Adaptable {
2760
2760
  all_modules_1.Events.EVENT_ROW_GROUP_OPENED,
2761
2761
  all_modules_1.Events.EVENT_COLUMN_VALUE_CHANGED,
2762
2762
  ];
2763
- // no need to add filter event, it is handled by AdaptableStore side-effects
2763
+ // ADD filter event
2764
2764
  this.gridOptions.api.addGlobalListener((this.listenerGlobalColumnEventsThatTriggerAutoLayoutSave = (type) => {
2765
2765
  if (columnEventsThatTriggersAutoLayoutSave.indexOf(type) > -1) {
2766
2766
  this.debouncedSaveGridLayout();