@adaptabletools/adaptable 15.0.0-canary.0 → 15.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 (108) hide show
  1. package/bundle.cjs.js +247 -262
  2. package/package.json +2 -2
  3. package/publishTimestamp.d.ts +1 -1
  4. package/publishTimestamp.js +1 -1
  5. package/src/AdaptableInterfaces/IAdaptable.d.ts +42 -42
  6. package/src/AdaptableOptions/ActionOptions.d.ts +31 -31
  7. package/src/AdaptableOptions/AdaptableOptions.d.ts +13 -13
  8. package/src/AdaptableOptions/AdaptableQLOptions.d.ts +4 -4
  9. package/src/AdaptableOptions/AlertOptions.d.ts +14 -14
  10. package/src/AdaptableOptions/ChartingOptions.d.ts +2 -3
  11. package/src/AdaptableOptions/DataChangeHistoryOptions.d.ts +6 -6
  12. package/src/AdaptableOptions/EditOptions.d.ts +8 -8
  13. package/src/AdaptableOptions/ExportOptions.d.ts +1 -1
  14. package/src/AdaptableOptions/ExpressionOptions.d.ts +1 -1
  15. package/src/AdaptableOptions/FilterOptions.d.ts +3 -3
  16. package/src/AdaptableOptions/GeneralOptions.d.ts +9 -9
  17. package/src/AdaptableOptions/MenuOptions.d.ts +3 -3
  18. package/src/AdaptableOptions/PredicateOptions.d.ts +1 -1
  19. package/src/AdaptableOptions/SearchOptions.d.ts +2 -2
  20. package/src/AdaptableOptions/UserInterfaceOptions.d.ts +25 -25
  21. package/src/Api/ChartingApi.d.ts +22 -18
  22. package/src/Api/ColumnApi.d.ts +3 -3
  23. package/src/Api/EventApi.d.ts +13 -1
  24. package/src/Api/Events/ActionRowSubmitted.d.ts +8 -8
  25. package/src/Api/Events/GridDataChanged.d.ts +4 -4
  26. package/src/Api/Events/ThemeChanged.d.ts +6 -0
  27. package/src/Api/FilterApi.d.ts +2 -2
  28. package/src/Api/FinanceApi.d.ts +9 -9
  29. package/src/Api/FormatColumnApi.d.ts +6 -6
  30. package/src/Api/FreeTextColumnApi.d.ts +3 -3
  31. package/src/Api/GridApi.d.ts +30 -30
  32. package/src/Api/Implementation/ChartingApiImpl.d.ts +2 -1
  33. package/src/Api/Implementation/ChartingApiImpl.js +4 -1
  34. package/src/Api/Implementation/ColumnApiImpl.d.ts +4 -4
  35. package/src/Api/Implementation/FilterApiImpl.d.ts +2 -2
  36. package/src/Api/Implementation/FormatColumnApiImpl.d.ts +6 -6
  37. package/src/Api/Implementation/FreeTextColumnApiImpl.d.ts +3 -3
  38. package/src/Api/Implementation/GridApiImpl.d.ts +29 -29
  39. package/src/Api/Implementation/ThemeApiImpl.d.ts +4 -0
  40. package/src/Api/Implementation/ThemeApiImpl.js +14 -0
  41. package/src/Api/Internal/ActionInternalApi.d.ts +3 -3
  42. package/src/Api/Internal/AdaptableInternalApi.d.ts +3 -3
  43. package/src/Api/Internal/AlertInternalApi.d.ts +3 -3
  44. package/src/Api/Internal/FilterInternalApi.d.ts +2 -2
  45. package/src/Api/Internal/FormatColumnInternalApi.d.ts +7 -7
  46. package/src/Api/Internal/GridInternalApi.d.ts +4 -4
  47. package/src/Api/Internal/StyledColumnInternalApi.d.ts +3 -3
  48. package/src/Api/OptionsApi.d.ts +1 -1
  49. package/src/Api/ThemeApi.d.ts +18 -0
  50. package/src/PredefinedConfig/Common/AdaptableAlert.d.ts +7 -7
  51. package/src/PredefinedConfig/Common/AdaptableColumn.d.ts +2 -2
  52. package/src/PredefinedConfig/Common/AdaptableComparerFunction.d.ts +5 -6
  53. package/src/PredefinedConfig/Common/AdaptablePredicate.d.ts +2 -2
  54. package/src/PredefinedConfig/Common/CellDataChangedInfo.d.ts +5 -5
  55. package/src/PredefinedConfig/Common/CellSummary.d.ts +4 -4
  56. package/src/PredefinedConfig/Common/Menu.d.ts +9 -9
  57. package/src/PredefinedConfig/Selection/GridCell.d.ts +4 -4
  58. package/src/PredefinedConfig/Selection/GridRow.d.ts +4 -4
  59. package/src/PredefinedConfig/Selection/SelectedCellInfo.d.ts +3 -3
  60. package/src/PredefinedConfig/Selection/SelectedRowInfo.d.ts +2 -2
  61. package/src/PredefinedConfig/StatusBarState.d.ts +1 -1
  62. package/src/PredefinedConfig/StatusBarState.js +1 -1
  63. package/src/PredefinedConfig/SystemState.d.ts +1 -2
  64. package/src/PredefinedConfig/ThemeState.d.ts +4 -0
  65. package/src/Redux/ActionsReducers/GridRedux.d.ts +5 -5
  66. package/src/Redux/ActionsReducers/ThemeRedux.d.ts +27 -0
  67. package/src/Redux/ActionsReducers/ThemeRedux.js +63 -1
  68. package/src/Strategy/ExportModule.js +1 -1
  69. package/src/Utilities/Constants/GeneralConstants.d.ts +1 -0
  70. package/src/Utilities/Constants/GeneralConstants.js +3 -2
  71. package/src/Utilities/Defaults/DefaultAdaptableOptions.js +1 -1
  72. package/src/Utilities/Defaults/DefaultSettingsPanel.js +2 -2
  73. package/src/Utilities/ExpressionFunctions/aggregatedScalarExpressionFunctions.d.ts +3 -3
  74. package/src/Utilities/Interface/Preview.d.ts +2 -2
  75. package/src/Utilities/ObjectFactory.d.ts +5 -3
  76. package/src/Utilities/ObjectFactory.js +10 -1
  77. package/src/Utilities/Services/AggregatedScalarLiveValue.d.ts +2 -2
  78. package/src/Utilities/Services/CalculatedColumnExpressionService.d.ts +2 -2
  79. package/src/Utilities/Services/Interface/ICalculatedColumnExpressionService.d.ts +2 -2
  80. package/src/Utilities/Services/Interface/IQueryLanguageService.d.ts +3 -3
  81. package/src/Utilities/Services/Interface/IReportService.d.ts +3 -3
  82. package/src/Utilities/Services/Interface/IThemeService.d.ts +3 -0
  83. package/src/Utilities/Services/Interface/IThemeService.js +2 -0
  84. package/src/Utilities/Services/MetamodelService.d.ts +2 -0
  85. package/src/Utilities/Services/MetamodelService.js +26 -19
  86. package/src/Utilities/Services/QueryLanguageService.d.ts +2 -2
  87. package/src/Utilities/Services/ReportService.d.ts +4 -4
  88. package/src/Utilities/Services/ThemeService.d.ts +12 -0
  89. package/src/Utilities/Services/ThemeService.js +49 -0
  90. package/src/View/AdaptableWizardView/AdaptableConfigurationDialog/AdaptableOptionsForm.js +5 -5
  91. package/src/View/Charting/ShowChartButton.js +2 -1
  92. package/src/View/Charting/useChartingElements.js +2 -1
  93. package/src/View/Components/FilterForm/QuickFilterForm.js +1 -1
  94. package/src/View/Components/ToolPanel/AdaptableToolPanel.js +1 -1
  95. package/src/View/DataChangeHistory/buildActionColumnButton.d.ts +2 -2
  96. package/src/View/Theme/ThemeEditor.d.ts +7 -0
  97. package/src/View/Theme/ThemeEditor.js +186 -0
  98. package/src/View/Theme/ThemePopup.d.ts +3 -0
  99. package/src/View/Theme/ThemePopup.js +30 -6
  100. package/src/agGrid/ActionColumnRenderer.js +1 -0
  101. package/src/agGrid/Adaptable.d.ts +42 -41
  102. package/src/agGrid/Adaptable.js +20 -27
  103. package/src/agGrid/createAgStatusPanelComponent.js +1 -1
  104. package/src/metamodel/adaptable-metamodel-model.d.ts +9 -9
  105. package/src/metamodel/adaptable.metamodel.d.ts +1698 -3141
  106. package/src/metamodel/adaptable.metamodel.js +1 -1
  107. package/version.d.ts +1 -1
  108. package/version.js +1 -1
@@ -12,7 +12,7 @@ const StringExtensions_1 = tslib_1.__importDefault(require("../../../Utilities/E
12
12
  const MetamodelService_1 = require("../../../Utilities/Services/MetamodelService");
13
13
  const AdaptablePopover_1 = require("../../AdaptablePopover");
14
14
  const LABEL_WIDTH = 250;
15
- const SUPPORTED_PRIMITEVE_TYPES = ['string', 'number', 'boolean'];
15
+ const SUPPORTED_PRIMITEVE_TYPES = ['s', 'n', 'b'];
16
16
  const OptionInput = (props) => {
17
17
  const { name, defaultValue, value, description, uiLabel } = props.option;
18
18
  const label = uiLabel !== null && uiLabel !== void 0 ? uiLabel : StringExtensions_1.default.Humanize(name);
@@ -54,13 +54,13 @@ const OptionInput = (props) => {
54
54
  }
55
55
  else {
56
56
  switch (option.kind) {
57
- case 'number':
57
+ case 'n':
58
58
  input = React.createElement(Input_1.default, Object.assign({ type: "number", onChange: handleInputChange }, inputProps));
59
59
  break;
60
- case 'string':
60
+ case 's':
61
61
  input = React.createElement(Input_1.default, Object.assign({ type: "text", onChange: handleInputChange }, inputProps));
62
62
  break;
63
- case 'boolean':
63
+ case 'b':
64
64
  input = (React.createElement(CheckBox_1.CheckBox, { onChange: handleCheckboxChange, checked: Boolean(value), type: "date" }, label));
65
65
  break;
66
66
  }
@@ -71,7 +71,7 @@ const OptionInput = (props) => {
71
71
  " ",
72
72
  info),
73
73
  input));
74
- if (option.kind === 'boolean') {
74
+ if (option.kind === 'b') {
75
75
  content = (React.createElement(rebass_1.Flex, { alignItems: "center" },
76
76
  input,
77
77
  " ",
@@ -7,6 +7,7 @@ const SimpleButton_1 = tslib_1.__importDefault(require("../../components/SimpleB
7
7
  const AdaptableContext_1 = require("../AdaptableContext");
8
8
  const DropdownButton_1 = tslib_1.__importDefault(require("../../components/DropdownButton"));
9
9
  const useChartState_1 = require("./useChartState");
10
+ const GeneralConstants_1 = require("../../Utilities/Constants/GeneralConstants");
10
11
  const ShowChartButton = (props) => {
11
12
  var _a, _b;
12
13
  const adaptable = (0, AdaptableContext_1.useAdaptable)();
@@ -21,7 +22,7 @@ const ShowChartButton = (props) => {
21
22
  }
22
23
  const containerOptions = [
23
24
  {
24
- label: (_b = chartingOptions.agGridContainerName) !== null && _b !== void 0 ? _b : 'Ag Grid Window',
25
+ label: (_b = chartingOptions.agGridContainerName) !== null && _b !== void 0 ? _b : GeneralConstants_1.AG_GRID_CHART_WINDOW,
25
26
  onClick: () => {
26
27
  showChart(null);
27
28
  },
@@ -12,6 +12,7 @@ const AdaptableHelper_1 = tslib_1.__importDefault(require("../../Utilities/Helpe
12
12
  const useChartState_1 = require("./useChartState");
13
13
  const DeleteChartButton_1 = require("./DeleteChartButton");
14
14
  const EditChartButton_1 = require("./EditChartButton");
15
+ const GeneralConstants_1 = require("../../Utilities/Constants/GeneralConstants");
15
16
  const useChartingElements = ({ elementType, accessLevel, size = 'normal', }) => {
16
17
  var _a, _b;
17
18
  const adaptable = (0, AdaptableContext_1.useAdaptable)();
@@ -75,7 +76,7 @@ const useChartingElements = ({ elementType, accessLevel, size = 'normal', }) =>
75
76
  iconSize = 15;
76
77
  }
77
78
  const chartSelector = (React.createElement(DropdownButton_1.default, { style: style, width: "100%", columns: ['label'], className: `ab-${elementType}__Chart__select`, items: options, disabled: !hasCharts }, content));
78
- const containerSelector = Boolean(chartContainers === null || chartContainers === void 0 ? void 0 : chartContainers.length) && (React.createElement(DropdownButton_1.default, { style: style, width: "100%", columns: ['label'], items: containerOptions, disabled: !isSelectedChart }, (selectedContainer === null || selectedContainer === void 0 ? void 0 : selectedContainer.name) || chartingOptions.agGridContainerName || 'Ag Grid Window'));
79
+ const containerSelector = Boolean(chartContainers === null || chartContainers === void 0 ? void 0 : chartContainers.length) && (React.createElement(DropdownButton_1.default, { style: style, width: "100%", columns: ['label'], items: containerOptions, disabled: !isSelectedChart }, (selectedContainer === null || selectedContainer === void 0 ? void 0 : selectedContainer.name) || chartingOptions.agGridContainerName || GeneralConstants_1.AG_GRID_CHART_WINDOW));
79
80
  const chartButton = (React.createElement(SimpleButton_1.default, { style: style, mr: 1, onClick: () => (isOpen ? closeChart() : showChart(selectedContainer)), disabled: !Boolean(selectedChart), variant: 'text', tone: 'neutral', icon: isOpen ? 'visibility-off' : 'visibility', tooltip: isOpen ? 'Hide Chart' : 'Show Chart' }));
80
81
  const deleteButton = (React.createElement(DeleteChartButton_1.DeleteChartButton, { iconSize: iconSize, chart: selectedChart, accessLevel: chartAccessLevel }));
81
82
  const editButton = (React.createElement(EditChartButton_1.EditChartButton, { iconSize: iconSize, chart: selectedChart, accessLevel: chartAccessLevel, isOpen: isOpen }));
@@ -206,7 +206,7 @@ class QuickFilterFormComponent extends React.Component {
206
206
  var _a, _b;
207
207
  return (React.createElement(AdaptableInput_1.default, { disabled: this.isFilterDisabled(), key: index, type: predicateInput.type === 'number' ? 'text' : predicateInput.type,
208
208
  // autoFocus has to be FALSE because if the input receives focus in the init phase,
209
- // it may scroll the ag-grid header viewport into view and de-synchronize it (relative to the content viewport)
209
+ // it may scroll the AG Grid header viewport into view and de-synchronize it (relative to the content viewport)
210
210
  autoFocus: false, value: (_b = (_a = filter.Predicate.Inputs) === null || _a === void 0 ? void 0 : _a[index]) !== null && _b !== void 0 ? _b : '', onChange: (e) => this.changeColumnPredicateInput(e.target.value, index), onKeyDownCapture: (e) => {
211
211
  if (e.nativeEvent.key === 'Escape') {
212
212
  e.nativeEvent.preventDefault();
@@ -244,7 +244,7 @@ const getAdaptableToolPanelAgGridComponent = (adaptable) => {
244
244
  const api = adaptable.api;
245
245
  this.gui = document.createElement('div');
246
246
  this.gui.id = getContainerId();
247
- // preserve ag-grid naming convention
247
+ // preserve AG Grid naming convention
248
248
  this.gui.className = 'ag-adaptable-panel';
249
249
  Object.keys(toolPanelContainerStyle).forEach((key) => {
250
250
  //@ts-ignore
@@ -1,3 +1,3 @@
1
- import { RowNode } from '@ag-grid-community/core';
1
+ import { IRowNode } from '@ag-grid-community/core';
2
2
  import { ActionColumnContext, AdaptableButton, DataChangeHistoryOptions } from '../../types';
3
- export declare const buildActionColumnButton: (options: DataChangeHistoryOptions, undoRowNode: (rowNode: RowNode) => void) => AdaptableButton<ActionColumnContext>[];
3
+ export declare const buildActionColumnButton: (options: DataChangeHistoryOptions, undoRowNode: (rowNode: IRowNode) => void) => AdaptableButton<ActionColumnContext<any>>[];
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+ import { AccessLevel } from '../../types';
3
+ export interface ThemeEditorProps {
4
+ theme: string;
5
+ accessLevel: AccessLevel;
6
+ }
7
+ export declare const ThemeEditor: React.FunctionComponent<ThemeEditorProps>;
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ThemeEditor = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const React = tslib_1.__importStar(require("react"));
6
+ const ColorPicker_1 = require("../../components/ColorPicker");
7
+ const FormLayout_1 = tslib_1.__importStar(require("../../components/FormLayout"));
8
+ const StyleHelper_1 = require("../../Utilities/Helpers/StyleHelper");
9
+ const AdaptableContext_1 = require("../AdaptableContext");
10
+ const AdaptableInput_1 = tslib_1.__importDefault(require("../Components/AdaptableInput"));
11
+ const throttle_1 = tslib_1.__importDefault(require("lodash/throttle"));
12
+ const SimpleButton_1 = tslib_1.__importDefault(require("../../components/SimpleButton"));
13
+ const rebass_1 = require("rebass");
14
+ const Panel_1 = tslib_1.__importDefault(require("../../components/Panel"));
15
+ const fields = [
16
+ {
17
+ name: 'Primary Color',
18
+ type: 'color',
19
+ variable: '--ab-color-primary',
20
+ },
21
+ {
22
+ name: 'Primary Dark Color',
23
+ type: 'color',
24
+ variable: '--ab-color-primarydark',
25
+ },
26
+ {
27
+ name: 'Primary Light Color',
28
+ type: 'color',
29
+ variable: '--ab-color-primarylight',
30
+ },
31
+ {
32
+ name: 'Text on Primary Color',
33
+ type: 'color',
34
+ variable: '--ab-color-text-on-primary',
35
+ },
36
+ {
37
+ name: 'Text on Primary Dark Color',
38
+ type: 'color',
39
+ variable: '--ab-color-text-on-primarydark',
40
+ },
41
+ {
42
+ name: 'Secondary Color',
43
+ type: 'color',
44
+ variable: '--ab-color-secondary',
45
+ },
46
+ {
47
+ name: 'Secondary Dark Color',
48
+ type: 'color',
49
+ variable: '--ab-color-secondarydark',
50
+ },
51
+ {
52
+ name: 'Secondary Light Color',
53
+ type: 'color',
54
+ variable: '--ab-color-secondarylight',
55
+ },
56
+ {
57
+ name: 'Text on Secondary Color',
58
+ type: 'color',
59
+ variable: '--ab-color-text-on-secondary',
60
+ },
61
+ {
62
+ name: 'Text on Secondary Light Color',
63
+ type: 'color',
64
+ variable: '--ab-color-text-on-secondarylight',
65
+ },
66
+ {
67
+ name: 'Default background',
68
+ type: 'color',
69
+ variable: '--ab-color-defaultbackground',
70
+ },
71
+ {
72
+ name: 'Text Color on Default Background',
73
+ type: 'color',
74
+ variable: '--ab-color-text-on-defaultbackground',
75
+ },
76
+ ];
77
+ const Field = (props) => {
78
+ const adaptable = (0, AdaptableContext_1.useAdaptable)();
79
+ let input = null;
80
+ let value = props.value;
81
+ const throttledOnChange = React.useMemo(() => {
82
+ return (0, throttle_1.default)((value) => {
83
+ props.onChange(value);
84
+ }, 300);
85
+ }, []);
86
+ if (value === undefined) {
87
+ value = (0, StyleHelper_1.getVariableColor)(`var(${props.variable})`);
88
+ }
89
+ switch (props.type) {
90
+ case 'number':
91
+ input = (React.createElement(AdaptableInput_1.default, { disabled: props.disabled, type: "number", onChange: (event) => throttledOnChange(event.target.value), value: value }));
92
+ break;
93
+ case 'color':
94
+ input = (React.createElement(ColorPicker_1.ColorPicker, { disabled: props.disabled, includeAlpha: false, api: adaptable.api, value: value, onChange: (color) => throttledOnChange(color) }));
95
+ break;
96
+ }
97
+ return (React.createElement(FormLayout_1.FormRow, { label: props.name },
98
+ React.createElement(rebass_1.Flex, null,
99
+ input,
100
+ ' ',
101
+ React.createElement(SimpleButton_1.default, { disabled: props.value === undefined, onClick: () => props.onChange(false) }, "Clear"))));
102
+ };
103
+ const ThemeEditor = (props) => {
104
+ var _a, _b;
105
+ const adaptable = (0, AdaptableContext_1.useAdaptable)();
106
+ const allThemes = adaptable.api.themeApi.getUserThemes();
107
+ const disabled = props.accessLevel === 'ReadOnly';
108
+ const [currentThemeObject, setCurrentThemeObject] = React.useState(() => {
109
+ return adaptable.api.themeApi.getCurrentThemeObject();
110
+ });
111
+ // THEME variables
112
+ const themeVariables = currentThemeObject === null || currentThemeObject === void 0 ? void 0 : currentThemeObject.CSSVariables;
113
+ const valuesFromTheme = fields.reduce((acc, field) => {
114
+ if (themeVariables === null || themeVariables === void 0 ? void 0 : themeVariables[field.variable]) {
115
+ acc[field.variable] = themeVariables === null || themeVariables === void 0 ? void 0 : themeVariables[field.variable];
116
+ }
117
+ return acc;
118
+ }, {});
119
+ React.useEffect(() => {
120
+ setCurrentThemeObject(adaptable.api.themeApi.getCurrentThemeObject());
121
+ }, [props.theme]);
122
+ // This is needed when clearing variables, so the new value is pickedup up from the document
123
+ React.useEffect(() => {
124
+ const updateTheme = () => {
125
+ const theme = adaptable.api.themeApi.getCurrentThemeObject();
126
+ setCurrentThemeObject(Object.assign({}, theme));
127
+ };
128
+ const themeChangedUnsubscribe = adaptable.api.eventApi.on('ThemeChanged', updateTheme);
129
+ const themeEditedUnsubscribe = adaptable.api.eventApi.on('ThemeEdited', updateTheme);
130
+ return () => {
131
+ themeChangedUnsubscribe();
132
+ themeEditedUnsubscribe();
133
+ };
134
+ }, []);
135
+ const handleNameDescriptionChangeThrottled = React.useMemo(() => {
136
+ return (0, throttle_1.default)((key, value) => {
137
+ const theme = adaptable.api.themeApi.getCurrentThemeObject();
138
+ const newTheme = Object.assign(Object.assign({}, theme), { [key]: value });
139
+ adaptable.api.themeApi.editTheme(newTheme);
140
+ }, 600);
141
+ }, []);
142
+ const handleDescriptionChange = React.useCallback((key, value) => {
143
+ setCurrentThemeObject((prev) => (Object.assign(Object.assign({}, prev), { [key]: value })));
144
+ handleNameDescriptionChangeThrottled(key, value);
145
+ }, []);
146
+ const handleDeleteTheme = React.useCallback(() => {
147
+ adaptable.api.themeApi.loadLightTheme();
148
+ adaptable.api.themeApi.deleteUserTheme(currentThemeObject);
149
+ }, []);
150
+ const handleSaveName = () => {
151
+ const name = currentThemeObject.Name;
152
+ setCurrentThemeObject((prev) => (Object.assign(Object.assign({}, prev), { Name: name })));
153
+ handleNameDescriptionChangeThrottled('Name', name);
154
+ };
155
+ const nameHasChanged = currentThemeObject.Name !== props.theme;
156
+ const nameIsNotUnique = allThemes.some((theme) => theme.Uuid !== currentThemeObject.Uuid && currentThemeObject.Name === theme.Name);
157
+ const saveNameDisabled = !nameHasChanged || nameIsNotUnique || currentThemeObject.Name === '';
158
+ return (React.createElement(Panel_1.default, { header: React.createElement(rebass_1.Flex, { alignItems: "center", width: "100%" },
159
+ React.createElement(rebass_1.Box, { flex: 1 }, " Edit Custom Theme"),
160
+ React.createElement(SimpleButton_1.default, { "data-name": "delete", disabled: props.accessLevel !== 'Full', icon: "trash", onClick: handleDeleteTheme, variant: "text" })) },
161
+ React.createElement(FormLayout_1.default, null,
162
+ React.createElement(FormLayout_1.FormRow, { label: "Theme Name" },
163
+ React.createElement(AdaptableInput_1.default, { mr: 2, onChange: (event) => setCurrentThemeObject(Object.assign(Object.assign({}, currentThemeObject), { Name: event.target.value.replace(/ /g, '-') })), value: (_a = currentThemeObject.Name) !== null && _a !== void 0 ? _a : '' }),
164
+ React.createElement(SimpleButton_1.default, { onClick: handleSaveName, disabled: saveNameDisabled, icon: "save" }),
165
+ React.createElement(rebass_1.Text, { fontSize: 2, marginTop: 1 }, "The name cannot contain spaces."),
166
+ nameIsNotUnique && (React.createElement(rebass_1.Text, { fontSize: 2, color: "var(--ab-color-error)" }, "Name must be unique."))),
167
+ React.createElement(FormLayout_1.FormRow, { label: "Description" },
168
+ React.createElement(AdaptableInput_1.default, { onChange: (event) => handleDescriptionChange('Description', event.target.value), value: (_b = currentThemeObject === null || currentThemeObject === void 0 ? void 0 : currentThemeObject.Description) !== null && _b !== void 0 ? _b : '' })),
169
+ fields.map((field) => {
170
+ return (React.createElement(Field, { disabled: disabled, key: field.name, type: field.type, name: field.name, value: valuesFromTheme[field.variable], variable: field.variable, onChange: (val) => {
171
+ // needs a fresh copy
172
+ const currentThemeObject = adaptable.api.themeApi.getCurrentThemeObject();
173
+ let newTheme = null;
174
+ if (val === false) {
175
+ newTheme = Object.assign(Object.assign({}, currentThemeObject), { CSSVariables: Object.assign({}, currentThemeObject === null || currentThemeObject === void 0 ? void 0 : currentThemeObject.CSSVariables) });
176
+ delete newTheme.CSSVariables[field.variable];
177
+ }
178
+ else {
179
+ newTheme = Object.assign(Object.assign({}, currentThemeObject), { CSSVariables: Object.assign(Object.assign({}, currentThemeObject === null || currentThemeObject === void 0 ? void 0 : currentThemeObject.CSSVariables), { [field.variable]: val }) });
180
+ }
181
+ setCurrentThemeObject(newTheme);
182
+ adaptable.api.themeApi.editTheme(newTheme);
183
+ } }));
184
+ }))));
185
+ };
186
+ exports.ThemeEditor = ThemeEditor;
@@ -1,13 +1,16 @@
1
1
  import * as React from 'react';
2
2
  import * as ThemeRedux from '../../Redux/ActionsReducers/ThemeRedux';
3
3
  import { ModuleViewPopupProps } from '../Components/SharedProps/ModuleViewPopupProps';
4
+ import { AdaptableTheme } from '../../PredefinedConfig/ThemeState';
4
5
  interface ThemePopupProps extends ModuleViewPopupProps<ThemePopupComponent> {
5
6
  CurrentTheme: string;
7
+ UserThemes: AdaptableTheme[];
6
8
  SelectTheme: (newTheme: string) => ThemeRedux.ThemeSelectAction;
7
9
  }
8
10
  declare class ThemePopupComponent extends React.Component<ThemePopupProps, {}> {
9
11
  render(): JSX.Element;
10
12
  onChangeTheme(value: string): void;
13
+ handleCreateNewTheme: () => void;
11
14
  }
12
15
  export declare let ThemePopup: import("react-redux").ConnectedComponent<typeof ThemePopupComponent, any>;
13
16
  export {};
@@ -8,11 +8,31 @@ const ThemeRedux = tslib_1.__importStar(require("../../Redux/ActionsReducers/The
8
8
  const PopupPanel_1 = require("../Components/Popups/AdaptablePopup/PopupPanel");
9
9
  const FormLayout_1 = tslib_1.__importStar(require("../../components/FormLayout"));
10
10
  const DropdownButton_1 = tslib_1.__importDefault(require("../../components/DropdownButton"));
11
+ const ThemeEditor_1 = require("./ThemeEditor");
12
+ const rebass_1 = require("rebass");
13
+ const ButtonNew_1 = require("../Components/Buttons/ButtonNew");
14
+ const ObjectFactory_1 = tslib_1.__importDefault(require("../../Utilities/ObjectFactory"));
11
15
  class ThemePopupComponent extends React.Component {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.handleCreateNewTheme = () => {
19
+ let nthItem = this.props.UserThemes.length + 1;
20
+ let name = 'Custom-Theme-' + nthItem;
21
+ // make sure it is unique
22
+ while (this.props.UserThemes.some((theme) => theme.Name === name)) {
23
+ nthItem++;
24
+ name = 'Custom-Theme-' + nthItem;
25
+ }
26
+ const newTheme = ObjectFactory_1.default.CreateEmptyTheme(name);
27
+ this.props.api.themeApi.addUserTheme(newTheme);
28
+ this.props.api.themeApi.loadTheme(newTheme.Name);
29
+ };
30
+ }
12
31
  render() {
13
32
  const availableThemes = this.props.api.themeApi.getThemes();
14
- let currentThemeDescription = '';
15
- let optionThemes = availableThemes.map((theme) => {
33
+ const theme = this.props.api.themeApi.getCurrentThemeObject();
34
+ const currentThemeDescription = theme.Description || theme.Name;
35
+ const optionThemes = availableThemes.map((theme) => {
16
36
  if (typeof theme === 'string') {
17
37
  // protection against old state, which could be string
18
38
  theme = {
@@ -20,19 +40,22 @@ class ThemePopupComponent extends React.Component {
20
40
  Description: theme,
21
41
  };
22
42
  }
23
- if (theme.Name === this.props.CurrentTheme) {
24
- currentThemeDescription = theme.Description;
25
- }
26
43
  return {
27
44
  value: theme.Name,
28
45
  label: theme.Description,
29
46
  onClick: () => this.onChangeTheme(theme.Name),
30
47
  };
31
48
  });
49
+ const isCustomTheme = this.props.api.themeApi
50
+ .getUserThemes()
51
+ .some((theme) => theme.Name === this.props.CurrentTheme);
32
52
  return (React.createElement(PopupPanel_1.PopupPanel, { headerText: this.props.moduleInfo.FriendlyName, glyphicon: this.props.moduleInfo.Glyph, infoLink: this.props.moduleInfo.HelpPage, infoLinkDisabled: !this.props.api.internalApi.isDocumentationLinksDisplayed() },
33
53
  React.createElement(FormLayout_1.default, null,
34
54
  React.createElement(FormLayout_1.FormRow, { label: "Current Theme:" },
35
- React.createElement(DropdownButton_1.default, { "data-name": "select-theme-dropdown", columns: ['label'], style: { width: '50%', minWidth: 200 }, placeholder: "Select theme", value: this.props.CurrentTheme, items: optionThemes, accessLevel: this.props.accessLevel }, currentThemeDescription)))));
55
+ React.createElement(DropdownButton_1.default, { "data-name": "select-theme-dropdown", columns: ['label'], style: { width: '50%', minWidth: 200 }, placeholder: "Select theme", value: this.props.CurrentTheme, items: optionThemes, accessLevel: this.props.accessLevel }, currentThemeDescription),
56
+ React.createElement(ButtonNew_1.ButtonNew, { ml: 2, onClick: this.handleCreateNewTheme, accessLevel: this.props.accessLevel }))),
57
+ isCustomTheme && (React.createElement(rebass_1.Box, { mt: 3 },
58
+ React.createElement(ThemeEditor_1.ThemeEditor, { accessLevel: this.props.accessLevel, theme: this.props.CurrentTheme })))));
36
59
  }
37
60
  onChangeTheme(value) {
38
61
  this.props.SelectTheme(value);
@@ -41,6 +64,7 @@ class ThemePopupComponent extends React.Component {
41
64
  function mapStateToProps(state, ownProps) {
42
65
  return {
43
66
  CurrentTheme: state.Theme.CurrentTheme,
67
+ UserThemes: state.Theme.UserThemes,
44
68
  };
45
69
  }
46
70
  function mapDispatchToProps(dispatch) {
@@ -61,6 +61,7 @@ const ReactActionColumnRenderer = (props) => {
61
61
  if (!actionColumn || !actionButtons.length) {
62
62
  return null;
63
63
  }
64
+ // TODO: see why types do not match
64
65
  if (adaptable.api.gridApi.isGroupRowNode(props.node) && !actionColumn.includeGroupedRows) {
65
66
  return null;
66
67
  }
@@ -1,4 +1,4 @@
1
- import { ChartRef, ColDef, ColGroupDef, Column, ColumnRowGroupChangedEvent, ExcelStyle, GridOptions, Module, ModuleNames, RowNode } from '@ag-grid-community/core';
1
+ import { ChartRef, ColDef, ColGroupDef, Column, ColumnRowGroupChangedEvent, ExcelStyle, GridOptions, Module, ModuleNames, IRowNode } from '@ag-grid-community/core';
2
2
  import { AdaptableNoCodeWizardOptions, IAdaptableNoCodeWizard } from '../AdaptableInterfaces/AdaptableNoCodeWizard';
3
3
  import { AdaptableVariant, IAdaptable } from '../AdaptableInterfaces/IAdaptable';
4
4
  import { AdaptableOptions } from '../AdaptableOptions/AdaptableOptions';
@@ -61,6 +61,7 @@ export declare class Adaptable implements IAdaptable {
61
61
  RowEditService: IRowEditService;
62
62
  private LicenseService;
63
63
  private ChartingService;
64
+ private ThemeService;
64
65
  embedColumnMenu: boolean;
65
66
  gridOptions: GridOptions;
66
67
  isInitialised: boolean;
@@ -149,9 +150,9 @@ export declare class Adaptable implements IAdaptable {
149
150
  private filterOnEditDataChange;
150
151
  private filterOnTickingDataChange;
151
152
  applyGridFiltering(): void;
152
- isGroupRowNode(rowNode: RowNode): boolean;
153
- isVisibleNode(rowNode: RowNode): boolean;
154
- isPinnedRowNode(rowNode: RowNode): boolean;
153
+ isGroupRowNode(rowNode: IRowNode): boolean;
154
+ isVisibleNode(rowNode: IRowNode): boolean;
155
+ isPinnedRowNode(rowNode: IRowNode): boolean;
155
156
  clearGridFiltering(): void;
156
157
  clearColumnFiltering(columnIds: string[]): void;
157
158
  hideFilterFormPopup: Function;
@@ -180,7 +181,7 @@ export declare class Adaptable implements IAdaptable {
180
181
  private getEditableCellClass;
181
182
  private getReadonlyCellClass;
182
183
  private isQuickSearchActive;
183
- getPrimaryKeyValueFromRowNode(rowNode: RowNode): any;
184
+ getPrimaryKeyValueFromRowNode(rowNode: IRowNode): any;
184
185
  private getSortedColumnStateForVisibleColumns;
185
186
  setColumnOrder(VisibleColumnList: string[]): void;
186
187
  private persistLayout;
@@ -189,59 +190,59 @@ export declare class Adaptable implements IAdaptable {
189
190
  private updateLayoutFromGrid;
190
191
  setSelectedCells(): SelectedCellInfo | undefined;
191
192
  setSelectedRows(): SelectedRowInfo | undefined;
192
- setDataValue(value: any, column: AdaptableColumn, primaryKeyValue: any, rowNode?: RowNode): void;
193
+ setDataValue(value: any, column: AdaptableColumn, primaryKeyValue: any, rowNode?: IRowNode): void;
193
194
  setCellValue(cellDataChangedInfo: CellDataChangedInfo): void;
194
195
  cancelEdit(): void;
195
- isCellEditable(rowNode: RowNode, column: Column): boolean;
196
- getDistinctValuesForColumn(column: AdaptableColumn, visibleRowsOnly: boolean, skipRowNode?: RowNode, permittedValues?: any[]): GridCell[];
197
- getDistinctFilterValuesForColumn(column: AdaptableColumn, visibleRowsOnly: boolean, filter: string, skipRowNode?: RowNode): Promise<{
196
+ isCellEditable(rowNode: IRowNode, column: Column): boolean;
197
+ getDistinctValuesForColumn(column: AdaptableColumn, visibleRowsOnly: boolean, skipRowNode?: IRowNode, permittedValues?: any[]): GridCell[];
198
+ getDistinctFilterValuesForColumn(column: AdaptableColumn, visibleRowsOnly: boolean, filter: string, skipRowNode?: IRowNode): Promise<{
198
199
  suppressClientSideFilter?: boolean;
199
200
  gridCells: GridCell[];
200
201
  }>;
201
- getDistinctCustomSortValuesForColumn(column: AdaptableColumn, visibleRowsOnly: boolean, skipRowNode?: RowNode): Promise<GridCell[]>;
202
- getDistinctBulkUpdateValuesForColumn(column: AdaptableColumn, visibleRowsOnly: boolean, selectedGridCells: GridCell[], skipRowNode?: RowNode): Promise<GridCell[]>;
202
+ getDistinctCustomSortValuesForColumn(column: AdaptableColumn, visibleRowsOnly: boolean, skipRowNode?: IRowNode): Promise<GridCell<any>[]>;
203
+ getDistinctBulkUpdateValuesForColumn(column: AdaptableColumn, visibleRowsOnly: boolean, selectedGridCells: GridCell[], skipRowNode?: IRowNode): Promise<GridCell<any>[]>;
203
204
  getColumnValueDisplayValuePairList(columnId: string, visibleRowsOnly: boolean, onlyIncludeIds?: {
204
205
  [key: string]: boolean;
205
206
  }): GridCell[];
206
207
  private addDistinctColumnValue;
207
208
  getDisplayValue(primaryKey: any, columnId: string): string | undefined;
208
- getGridCellFromRowNode(rowNode: RowNode, columnId: string): GridCell | undefined;
209
- getDisplayValueFromRowNode(rowNode: RowNode, columnId: string): string | undefined;
210
- getDisplayValueFromRawValue(rowNode: RowNode, columnId: string, rawValue: any): string | undefined;
209
+ getGridCellFromRowNode(rowNode: IRowNode, columnId: string): GridCell | undefined;
210
+ getDisplayValueFromRowNode(rowNode: IRowNode, columnId: string): string | undefined;
211
+ getDisplayValueFromRawValue(rowNode: IRowNode, columnId: string, rawValue: any): string | undefined;
211
212
  private getFormattedValue;
212
213
  getNormalisedValueFromRawValue(rawValue: any, column: AdaptableColumn): string | number | boolean | Date | unknown;
213
- getRawValueFromRowNode(rowNode: RowNode, columnId: string): any;
214
- getDataRowFromRowNode(rowNode: RowNode): any;
214
+ getRawValueFromRowNode(rowNode: IRowNode, columnId: string): any;
215
+ getDataRowFromRowNode(rowNode: IRowNode): any;
215
216
  getRowNodeForPrimaryKey(primaryKeyValue: any): any;
216
- getRowNodeByIndex(index: number): RowNode;
217
+ getRowNodeByIndex(index: number): IRowNode;
217
218
  getRowNodesForPrimaryKeys(primaryKeyValues: any[]): any[];
218
- forAllRowNodesDo(func: (rowNode: RowNode) => void, config?: {
219
+ forAllRowNodesDo(func: (rowNode: IRowNode) => void, config?: {
219
220
  includeGroupRows?: boolean;
220
- filterFn?: (rowNode: RowNode) => boolean;
221
+ filterFn?: (rowNode: IRowNode) => boolean;
221
222
  }): void;
222
- forAllVisibleRowNodesDo(func: (rowNode: RowNode, rowIndex: number) => void): void;
223
- getVisibleRowNodes(): RowNode[];
223
+ forAllVisibleRowNodesDo(func: (rowNode: IRowNode, rowIndex: number) => void): void;
224
+ getVisibleRowNodes(): IRowNode[];
224
225
  getAllRowNodes(config?: {
225
226
  includeGroupRows?: boolean;
226
- filterFn?: (rowNode: RowNode) => boolean;
227
- }): RowNode[];
228
- getRowsInViewport(): RowNode[];
229
- selectNodes(rowNodes: RowNode[], clearSelection: boolean): void;
230
- deSelectNodes(rowNodes: RowNode[], clearSelection: boolean): void;
231
- selectNode(rowNode: RowNode, clearSelection: boolean): void;
232
- deSelectNode(rowNode: RowNode, clearSelection: boolean): void;
233
- selectCells(columnIds: string[], startNode: RowNode, endNode: RowNode, clearSelection?: boolean): void;
234
- isRowNodeVisible(rowNode: RowNode): boolean;
227
+ filterFn?: (rowNode: IRowNode) => boolean;
228
+ }): IRowNode[];
229
+ getRowsInViewport(): IRowNode[];
230
+ selectNodes(rowNodes: IRowNode[], clearSelection: boolean): void;
231
+ deSelectNodes(rowNodes: IRowNode[], clearSelection: boolean): void;
232
+ selectNode(rowNode: IRowNode, clearSelection: boolean): void;
233
+ deSelectNode(rowNode: IRowNode, clearSelection: boolean): void;
234
+ selectCells(columnIds: string[], startNode: IRowNode, endNode: IRowNode, clearSelection?: boolean): void;
235
+ isRowNodeVisible(rowNode: IRowNode): boolean;
235
236
  redrawBody(): void;
236
237
  redrawRenderedRows(): void;
237
238
  redrawHeader(): void;
238
- redrawRow(rowNode: RowNode): void;
239
- redrawRows(rowNodes: RowNode[]): void;
240
- refreshCells(rowNodes: RowNode[], columns: (string | Column)[], forceUpdate: boolean, suppressFlash?: boolean): void;
239
+ redrawRow(rowNode: IRowNode): void;
240
+ redrawRows(rowNodes: IRowNode[]): void;
241
+ refreshCells(rowNodes: IRowNode[], columns: (string | Column)[], forceUpdate: boolean, suppressFlash?: boolean): void;
241
242
  refreshColumns(columns: (string | Column)[], forceUpdate: boolean, suppressFlash?: boolean): void;
242
- jumpToRow(rowNode: RowNode): void;
243
+ jumpToRow(rowNode: IRowNode): void;
243
244
  jumpToColumn(columnId: string): void;
244
- jumpToCell(columnId: string, rowNode: RowNode): void;
245
+ jumpToCell(columnId: string, rowNode: IRowNode): void;
245
246
  /**
246
247
  * This creates a clone of the current column definitions. If config.removeEmpty is true, will also remove empty column groups
247
248
  *
@@ -260,8 +261,8 @@ export declare class Adaptable implements IAdaptable {
260
261
  getColDefs(): ColDef[];
261
262
  getGroupedColDefs(): ColDef[];
262
263
  getColumnDefsWithCorrectVisibility: () => ColDef[];
263
- getFirstRowNode(): RowNode;
264
- getFirstDisplayedRowNode(): RowNode;
264
+ getFirstRowNode(): IRowNode;
265
+ getFirstDisplayedRowNode(): IRowNode;
265
266
  destroy(config?: {
266
267
  unmount: boolean;
267
268
  destroyApi?: boolean;
@@ -345,9 +346,9 @@ export declare class Adaptable implements IAdaptable {
345
346
  getGridData(): any[];
346
347
  getFilteredData(): any[];
347
348
  loadDataSource(dataSource: any[]): void;
348
- updateRows(dataRows: any[], dataUpdateConfig?: DataUpdateConfig): Promise<RowNode[]>;
349
- addRows(dataRows: any[], dataUpdateConfig?: DataUpdateConfig): Promise<RowNode[]>;
350
- deleteRows(dataRows: any[], dataUpdateConfig?: DataUpdateConfig): Promise<RowNode[]>;
349
+ updateRows(dataRows: any[], dataUpdateConfig?: DataUpdateConfig): Promise<IRowNode[]>;
350
+ addRows(dataRows: any[], dataUpdateConfig?: DataUpdateConfig): Promise<IRowNode[]>;
351
+ deleteRows(dataRows: any[], dataUpdateConfig?: DataUpdateConfig): Promise<IRowNode[]>;
351
352
  getFirstGroupedColumn(): AdaptableColumn | undefined;
352
353
  private checkColumnsDataTypeSet;
353
354
  private updateColumnDataTypeIfRowDataIsEmpty;
@@ -362,7 +363,7 @@ export declare class Adaptable implements IAdaptable {
362
363
  showQuickFilter(): void;
363
364
  hideQuickFilter(): void;
364
365
  getAgGridColumnType(columnId: string): string | string[];
365
- getActiveColumnComparator(columnId: string, customSort?: CustomSort, customSortComparer?: ColumnValuesComparer): (valueA: any, valueB: any, nodeA?: RowNode, nodeB?: RowNode, isInverted?: boolean) => number | undefined;
366
+ getActiveColumnComparator(columnId: string, customSort?: CustomSort, customSortComparer?: ColumnValuesComparer): (valueA: any, valueB: any, nodeA?: IRowNode, nodeB?: IRowNode, isInverted?: boolean) => number | undefined;
366
367
  getAgGridLightThemeName(): string;
367
368
  getAgGridCurrentThemeName(): string;
368
369
  applyAdaptableTheme(theme: AdaptableTheme | string): void;