@adaptabletools/adaptable 22.1.0 → 22.1.1-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/index.css +8 -9
  2. package/package.json +1 -1
  3. package/src/AdaptableInterfaces/IAdaptable.d.ts +2 -2
  4. package/src/AdaptableOptions/AdaptableOptions.d.ts +2 -21
  5. package/src/AdaptableOptions/AlertOptions.d.ts +0 -5
  6. package/src/AdaptableOptions/CellSummaryOptions.d.ts +2 -0
  7. package/src/AdaptableOptions/ChartingOptions.d.ts +2 -0
  8. package/src/AdaptableOptions/ColumnOptions.d.ts +0 -2
  9. package/src/AdaptableOptions/CommentOptions.d.ts +6 -0
  10. package/src/AdaptableOptions/ContainerOptions.d.ts +0 -6
  11. package/src/AdaptableOptions/DashboardOptions.d.ts +0 -2
  12. package/src/AdaptableOptions/DataChangeHistoryOptions.d.ts +0 -2
  13. package/src/AdaptableOptions/DataSetOptions.d.ts +2 -0
  14. package/src/AdaptableOptions/DefaultAdaptableOptions.js +35 -3
  15. package/src/AdaptableOptions/EditOptions.d.ts +0 -1
  16. package/src/AdaptableOptions/EntitlementOptions.d.ts +0 -2
  17. package/src/AdaptableOptions/ExportOptions.d.ts +1 -7
  18. package/src/AdaptableOptions/ExpressionOptions.d.ts +0 -18
  19. package/src/AdaptableOptions/Fdc3Options.d.ts +5 -1
  20. package/src/AdaptableOptions/FilterOptions.d.ts +3 -18
  21. package/src/AdaptableOptions/NoteOptions.d.ts +6 -0
  22. package/src/AdaptableOptions/NotificationsOptions.d.ts +0 -10
  23. package/src/AdaptableOptions/PredicateOptions.d.ts +12 -1
  24. package/src/AdaptableOptions/QuickSearchOptions.d.ts +0 -4
  25. package/src/AdaptableOptions/SettingsPanelOptions.d.ts +15 -5
  26. package/src/AdaptableOptions/TeamSharingOptions.d.ts +0 -4
  27. package/src/AdaptableOptions/ToolPanelOptions.d.ts +0 -1
  28. package/src/AdaptableOptions/UserInterfaceOptions.d.ts +6 -7
  29. package/src/AdaptableState/Common/AdaptableFormat.d.ts +9 -0
  30. package/src/AdaptableState/Common/AdaptableFormatPresets.d.ts +31 -0
  31. package/src/AdaptableState/Common/AdaptableFormatPresets.js +181 -0
  32. package/src/AdaptableState/Common/Menu.d.ts +1 -1
  33. package/src/AdaptableState/Common/Menu.js +2 -0
  34. package/src/AdaptableState/FormatColumnState.d.ts +6 -3
  35. package/src/Api/EventApi.d.ts +6 -6
  36. package/src/Api/Implementation/EntitlementApiImpl.js +5 -4
  37. package/src/Api/Implementation/FormatColumnApiImpl.js +8 -3
  38. package/src/Api/Implementation/GridApiImpl.js +1 -12
  39. package/src/Api/Internal/FormatColumnInternalApi.js +4 -2
  40. package/src/Api/Internal/LayoutInternalApi.js +5 -2
  41. package/src/Redux/Store/AdaptableStore.js +4 -4
  42. package/src/Strategy/AdaptableModuleBase.js +8 -7
  43. package/src/Strategy/AlertModule.d.ts +1 -1
  44. package/src/Strategy/BulkUpdateModule.d.ts +1 -1
  45. package/src/Strategy/BulkUpdateModule.js +2 -1
  46. package/src/Strategy/CalculatedColumnModule.d.ts +1 -1
  47. package/src/Strategy/CellSummaryModule.d.ts +1 -1
  48. package/src/Strategy/CellSummaryModule.js +2 -1
  49. package/src/Strategy/ColumnFilterModule.js +2 -1
  50. package/src/Strategy/ColumnInfoModule.d.ts +1 -1
  51. package/src/Strategy/ColumnInfoModule.js +2 -1
  52. package/src/Strategy/CommentModule.d.ts +1 -1
  53. package/src/Strategy/CommentModule.js +12 -2
  54. package/src/Strategy/ExportModule.d.ts +1 -1
  55. package/src/Strategy/Fdc3Module.d.ts +1 -1
  56. package/src/Strategy/FlashingCellModule.d.ts +1 -1
  57. package/src/Strategy/GridFilterModule.js +2 -1
  58. package/src/Strategy/GridInfoModule.d.ts +1 -1
  59. package/src/Strategy/GridInfoModule.js +2 -1
  60. package/src/Strategy/LayoutModule.d.ts +1 -1
  61. package/src/Strategy/NamedQueryModule.js +0 -16
  62. package/src/Strategy/NoteModule.d.ts +1 -1
  63. package/src/Strategy/NoteModule.js +16 -3
  64. package/src/Strategy/PlusMinusModule.js +8 -2
  65. package/src/Strategy/ScheduleModule.js +5 -4
  66. package/src/Strategy/SettingsPanelModule.d.ts +1 -1
  67. package/src/Strategy/ShortcutModule.js +5 -4
  68. package/src/Strategy/SmartEditModule.d.ts +1 -1
  69. package/src/Strategy/SmartEditModule.js +4 -4
  70. package/src/Strategy/SystemStatusModule.d.ts +1 -1
  71. package/src/Utilities/Constants/GeneralConstants.d.ts +4 -0
  72. package/src/Utilities/Constants/GeneralConstants.js +4 -0
  73. package/src/Utilities/Extensions/NumberExtensions.d.ts +2 -0
  74. package/src/Utilities/Extensions/NumberExtensions.js +8 -0
  75. package/src/Utilities/Helpers/AdaptableHelper.js +3 -2
  76. package/src/Utilities/Helpers/FormatHelper.js +26 -15
  77. package/src/Utilities/Services/AnnotationsService.js +10 -1
  78. package/src/Utilities/Services/Interface/IMetamodelService.d.ts +0 -1
  79. package/src/Utilities/Services/MetamodelService.d.ts +0 -2
  80. package/src/Utilities/Services/MetamodelService.js +6 -12
  81. package/src/View/AdaptableWizardView/AdaptableConfigurationDialog/EntitlementsForm.js +7 -6
  82. package/src/View/Alert/AlertEmptyView.js +2 -1
  83. package/src/View/BulkUpdate/BulkUpdateViewPanel.js +1 -1
  84. package/src/View/CellSummary/CellSummaryViewPanel.js +2 -1
  85. package/src/View/Comments/CommentsEditor.js +2 -1
  86. package/src/View/Comments/CommentsPopup.js +3 -1
  87. package/src/View/Components/Buttons/ButtonBase/index.js +3 -2
  88. package/src/View/Components/Buttons/EntityListActionButtons.js +7 -6
  89. package/src/View/Components/Buttons/SuspendToggleButton/SuspendToggleButton.js +2 -1
  90. package/src/View/Components/ColumnFilter/components/ColumnFilterInput.js +3 -2
  91. package/src/View/Components/ColumnFilter/components/ColumnFilterInputList.js +4 -1
  92. package/src/View/Components/Panels/PanelDashboard/index.js +2 -1
  93. package/src/View/Components/Popups/AdaptablePopup/AdaptablePopup.js +4 -2
  94. package/src/View/Components/Popups/AdaptablePopup/AdaptablePopupModuleView.js +2 -1
  95. package/src/View/Components/ToolPanel/AdaptableToolPanel.js +3 -2
  96. package/src/View/Components/ToolPanel/CustomToolPanelContent.js +2 -1
  97. package/src/View/Dashboard/CustomDashboardButton.js +3 -2
  98. package/src/View/Dashboard/Dashboard.js +3 -2
  99. package/src/View/Dashboard/DashboardPopup.js +3 -2
  100. package/src/View/Dashboard/PinnedToolbarsSelector.js +2 -1
  101. package/src/View/DataChangeHistory/DataChangeHistoryGrid.js +2 -1
  102. package/src/View/Export/ExportViewPanel.js +3 -1
  103. package/src/View/Filter/FilterViewPanel.js +2 -1
  104. package/src/View/FormatColumn/Wizard/FormatColumnFormatWizardSection.js +137 -181
  105. package/src/View/FormatColumn/Wizard/FormatColumnWizard.js +20 -8
  106. package/src/View/GridFilter/GridFilterPopupUI/index.d.ts +3 -2
  107. package/src/View/GridFilter/GridFilterPopupUI/index.js +2 -1
  108. package/src/View/GridFilter/GridFilterViewPanel.js +3 -2
  109. package/src/View/GridInfo/GridInfoPopup/GridInfoPopup.js +179 -6
  110. package/src/View/Layout/LayoutCloneButton.js +2 -1
  111. package/src/View/Layout/LayoutViewPanel.js +3 -1
  112. package/src/View/Layout/TransposedPopup.js +2 -1
  113. package/src/View/Note/NotePopup.js +3 -1
  114. package/src/View/SmartEdit/SmartEditViewPanel.js +2 -1
  115. package/src/View/StateManagement/StateManagementViewPanel.js +3 -1
  116. package/src/View/StatusBar/StatusBarPopup.js +2 -1
  117. package/src/View/Theme/ThemeEditor.js +2 -1
  118. package/src/View/Theme/ThemePopup.js +2 -1
  119. package/src/View/Theme/ThemeSelector.js +3 -1
  120. package/src/View/Theme/ThemeViewPanel.js +3 -1
  121. package/src/View/Wizard/OnePageWizards.js +3 -2
  122. package/src/agGrid/AdaptableAgGrid.d.ts +2 -2
  123. package/src/agGrid/AdaptableAgGrid.js +7 -29
  124. package/src/agGrid/AgGridAdapter.js +2 -2
  125. package/src/agGrid/AgGridColumnAdapter.js +11 -4
  126. package/src/agGrid/AgGridExportAdapter.js +4 -2
  127. package/src/agGrid/cellRenderers/ActionColumnRenderer.js +2 -1
  128. package/src/components/Dashboard/Dashboard.js +2 -1
  129. package/src/components/Dashboard/DashboardToolbar.js +2 -1
  130. package/src/components/Datepicker/index.js +2 -1
  131. package/src/components/ExpressionEditor/QueryBuilder/QueryBuilderInputs.js +1 -1
  132. package/src/components/Select/Select.js +4 -3
  133. package/src/components/SimpleButton/index.js +3 -2
  134. package/src/env.js +2 -2
  135. package/src/metamodel/adaptable-metamodel-model.d.ts +0 -2
  136. package/src/metamodel/adaptable.metamodel.d.ts +10 -197
  137. package/src/metamodel/adaptable.metamodel.js +1 -1
  138. package/src/types.d.ts +2 -0
  139. package/src/types.js +1 -0
  140. package/themes/dark.css +3 -1
  141. package/tsconfig.esm.tsbuildinfo +1 -1
  142. package/index.css.map +0 -1
@@ -7,6 +7,7 @@ import Panel from '../../../components/Panel';
7
7
  import { Tabs } from '../../../components/Tabs';
8
8
  import { PopupPanel } from '../../Components/Popups/AdaptablePopup/PopupPanel';
9
9
  import { AdaptableObjectsSummary } from './AdaptableObjectsSummary';
10
+ import { getDefaultAdaptableOptions } from '../../../AdaptableOptions/DefaultAdaptableOptions';
10
11
  import clsx from 'clsx';
11
12
  const adaptableVersion = ADAPTABLE_VERSION;
12
13
  const agGridVersion = AG_GRID_VERSION;
@@ -36,6 +37,7 @@ export const GridInfoPopup = (props) => {
36
37
  if (api.optionsApi.getUserInterfaceOptions()?.showAgGridVersion) {
37
38
  keyValuePairs.push({ Key: 'AG Grid Version', Value: agGridVersion });
38
39
  }
40
+ keyValuePairs.push({ Key: 'License Key', Value: api.optionsApi.getAdaptableOptions().licenseKey });
39
41
  keyValuePairs.push({ Key: 'Sorted Columns', Value: ArrayExtensions.IsNotNullOrEmpty(sorts) ? sorts.join('; ') : 'None' });
40
42
  keyValuePairs.push({ Key: 'Column Filters', Value: columnFilterDescription });
41
43
  keyValuePairs.push({ Key: 'Grid Filter', Value: gridFilterExpression });
@@ -68,16 +70,187 @@ export const GridInfoPopup = (props) => {
68
70
  Key: { field: 'Key', header: 'Property', defaultFlex: 1 },
69
71
  Value: { field: 'Value', header: 'Value', defaultFlex: 3 },
70
72
  };
73
+ // Variant used by the Grid Options tab — the Value column allows newlines
74
+ // in the rendered string (preserved via `white-space: pre-line`), so a
75
+ // nested *Options object can show one `"key": value` per line.
76
+ const optionsColumnsMap = {
77
+ Key: { field: 'Key', header: 'Property', defaultFlex: 1 },
78
+ Value: {
79
+ field: 'Value',
80
+ header: 'Value',
81
+ defaultFlex: 3,
82
+ render: ({ value }) => (React.createElement("span", { style: {
83
+ whiteSpace: 'pre-wrap',
84
+ wordBreak: 'break-word',
85
+ overflowWrap: 'anywhere',
86
+ display: 'block',
87
+ lineHeight: '18px',
88
+ paddingTop: 4,
89
+ paddingBottom: 4,
90
+ } }, String(value ?? ''))),
91
+ },
92
+ };
93
+ // ---- Grid Options tab: build one InfiniteTableGrid section per non-empty
94
+ // ---- options group on the AdaptableOptions object.
95
+ const titleCase = (camel) => camel
96
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
97
+ .replace(/^./, (c) => c.toUpperCase())
98
+ .replace(/\s./g, (c) => c.toUpperCase());
99
+ // Renders a single primitive / function / array / nested-object value
100
+ // (used for the inner key:value pairs when expanding a nested options
101
+ // object). Short objects/arrays stay on one line; longer ones get
102
+ // pretty-printed across multiple lines so they don't blow past the cell.
103
+ const ONE_LINE_MAX = 60;
104
+ const fnReplacer = (_k, val) => typeof val === 'function' ? '[Function]' : val;
105
+ const formatValuePart = (v) => {
106
+ if (typeof v === 'function')
107
+ return '[Function]';
108
+ if (v === undefined)
109
+ return 'undefined';
110
+ if (v === null)
111
+ return 'null';
112
+ if (typeof v === 'string')
113
+ return JSON.stringify(v);
114
+ if (Array.isArray(v) || typeof v === 'object') {
115
+ try {
116
+ const oneLine = JSON.stringify(v, fnReplacer);
117
+ if (oneLine !== undefined && oneLine.length <= ONE_LINE_MAX)
118
+ return oneLine;
119
+ return JSON.stringify(v, fnReplacer, 2);
120
+ }
121
+ catch {
122
+ return String(v);
123
+ }
124
+ }
125
+ return String(v);
126
+ };
127
+ const displayValue = (v) => {
128
+ if (typeof v === 'function')
129
+ return '[Function]';
130
+ if (v === undefined)
131
+ return '(undefined)';
132
+ if (v === null)
133
+ return '(null)';
134
+ if (Array.isArray(v)) {
135
+ // Top-level array values (e.g. `colorPalette`, `systemFilterPredicates`).
136
+ // Short arrays stay on one line; longer ones get pretty-printed across
137
+ // multiple lines so they don't blow past the cell.
138
+ return formatValuePart(v);
139
+ }
140
+ if (typeof v === 'object') {
141
+ // Nested options-style object → render as one `key: value` per line.
142
+ // `undefined` entries are filtered out so empty defaults don't show up.
143
+ const entries = Object.entries(v).filter(([, val]) => val !== undefined);
144
+ if (entries.length === 0)
145
+ return '{}';
146
+ return entries.map(([k, val]) => `${k}: ${formatValuePart(val)}`).join('\n');
147
+ }
148
+ return String(v);
149
+ };
150
+ const gridOptionsSections = (() => {
151
+ const opts = api.optionsApi.getAdaptableOptions();
152
+ const defaults = getDefaultAdaptableOptions();
153
+ const baseRows = [];
154
+ const groupSections = [];
155
+ // A function value should only be displayed when it has been explicitly
156
+ // provided by the user. AdapTable ships a handful of identity-function
157
+ // defaults (e.g. `stateOptions.applyState`) that are not interesting to
158
+ // surface here — we suppress those by reference-comparing against the
159
+ // values returned from `getDefaultAdaptableOptions()`.
160
+ const isUserProvidedFunction = (groupKey, propKey, fn) => {
161
+ if (typeof fn !== 'function')
162
+ return false;
163
+ const defaultGroup = defaults[groupKey];
164
+ if (!defaultGroup || typeof defaultGroup !== 'object')
165
+ return true;
166
+ return defaultGroup[propKey] !== fn;
167
+ };
168
+ Object.keys(opts).forEach((key) => {
169
+ if (key === 'licenseKey' || key === 'initialState')
170
+ return;
171
+ const value = opts[key];
172
+ if (value == null)
173
+ return;
174
+ if (typeof value === 'object' && !Array.isArray(value)) {
175
+ const rows = Object.keys(value)
176
+ .filter((sk) => {
177
+ const sv = value[sk];
178
+ // skip empties (undefined / null)
179
+ if (sv == null)
180
+ return false;
181
+ // suppress AdapTable's default callback implementations — keep
182
+ // only user-provided overrides
183
+ if (typeof sv === 'function' && !isUserProvidedFunction(key, sk, sv)) {
184
+ return false;
185
+ }
186
+ return true;
187
+ })
188
+ .map((sk) => ({ Key: sk, Value: displayValue(value[sk]) }));
189
+ if (rows.length === 0)
190
+ return;
191
+ groupSections.push({ title: titleCase(key), rows });
192
+ }
193
+ else {
194
+ // top-level function defaults aren't a concern (none exist on the
195
+ // root of `AdaptableOptions`), but apply the same rule for safety
196
+ if (typeof value === 'function' && defaults[key] === value)
197
+ return;
198
+ baseRows.push({ Key: key, Value: displayValue(value) });
199
+ }
200
+ });
201
+ const sections = [];
202
+ if (baseRows.length > 0)
203
+ sections.push({ title: 'Base Properties', rows: baseRows });
204
+ sections.push(...groupSections);
205
+ return sections;
206
+ })();
207
+ // Variable row height for Grid Options sections — counts the number of
208
+ // lines in the formatted value string (including visual wraps for very
209
+ // long unbroken lines) and grows the row to fit.
210
+ const VALUE_CHARS_PER_LINE = 70; // rough estimate at the Value column width
211
+ const visualLineCount = (text) => {
212
+ if (!text)
213
+ return 1;
214
+ return text
215
+ .split('\n')
216
+ .reduce((acc, line) => acc + Math.max(1, Math.ceil(line.length / VALUE_CHARS_PER_LINE)), 0);
217
+ };
218
+ const calculateRowHeight = (row) => {
219
+ const lines = visualLineCount(String(row?.Value ?? ''));
220
+ if (lines <= 1)
221
+ return 32;
222
+ return lines * 18 + 12;
223
+ };
224
+ const sectionHeight = (rows) => {
225
+ const total = rows.reduce((acc, r) => acc + calculateRowHeight(r), 0);
226
+ // 40px header, capped so a single huge group can't dominate the popup
227
+ return Math.min(total + 40, 400);
228
+ };
229
+ // Which tabs the user has opted in to. Falls back to all three (matching
230
+ // the default in `DefaultAdaptableOptions`) when the option isn't set.
231
+ const enabledTabs = api.optionsApi.getSettingsPanelOptions()?.gridInfoTabs ??
232
+ ['Grid Options', 'Grid Summary', 'Grid State'];
233
+ const showSummary = enabledTabs.includes('Grid Summary');
234
+ const showState = enabledTabs.includes('Grid State');
235
+ const showOptions = enabledTabs.includes('Grid Options');
71
236
  const baseClassName = 'ab-GridInfo';
72
237
  return (React.createElement(PopupPanel, { className: clsx(baseClassName), headerText: 'Grid Info', glyphicon: 'info', scrollable: false },
73
238
  React.createElement(Panel, { className: "twa:flex-1 twa:border-none twa:shadow-md twa:overflow-hidden" },
74
239
  React.createElement(Panel.FlexBody, null,
75
240
  React.createElement(Tabs, { className: "twa:flex-1 twa:min-h-0" },
76
- React.createElement(Tabs.Tab, null, "Grid Summary"),
77
- React.createElement(Tabs.Tab, null, "Grid State"),
78
- React.createElement(Tabs.Content, null,
241
+ showSummary ? React.createElement(Tabs.Tab, null, "Grid Summary") : null,
242
+ showState ? React.createElement(Tabs.Tab, null, "Grid State") : null,
243
+ showOptions ? React.createElement(Tabs.Tab, null, "Grid Options") : null,
244
+ showSummary ? (React.createElement(Tabs.Content, null,
79
245
  React.createElement(DataSource, { data: keyValuePairs, primaryKey: "Key" },
80
- React.createElement(InfiniteTableGrid, { domProps: domProps, columns: columnsMap }))),
81
- React.createElement(Tabs.Content, null,
82
- React.createElement(AdaptableObjectsSummary, { className: "twa:min-h-0 twa:overflow-auto twa:p-2" })))))));
246
+ React.createElement(InfiniteTableGrid, { domProps: domProps, columns: columnsMap })))) : null,
247
+ showState ? (React.createElement(Tabs.Content, null,
248
+ React.createElement(AdaptableObjectsSummary, { className: "twa:min-h-0 twa:overflow-auto twa:p-2" }))) : null,
249
+ showOptions ? (React.createElement(Tabs.Content, null,
250
+ React.createElement("div", { className: "twa:min-h-0 twa:overflow-auto twa:p-2 twa:flex twa:flex-col twa:gap-4" }, gridOptionsSections.map((section) => (React.createElement("div", { key: section.title },
251
+ React.createElement("h4", { className: "twa:font-semibold twa:mb-1" }, section.title),
252
+ React.createElement(DataSource, { data: section.rows, primaryKey: "Key" },
253
+ React.createElement(InfiniteTableGrid, { domProps: {
254
+ style: { height: sectionHeight(section.rows), width: '100%' },
255
+ }, rowHeight: (rowInfo) => calculateRowHeight(rowInfo.data), columns: optionsColumnsMap })))))))) : null)))));
83
256
  };
@@ -2,9 +2,10 @@ import * as React from 'react';
2
2
  import SimpleButton from '../../components/SimpleButton';
3
3
  import { useAdaptable } from '../AdaptableContext';
4
4
  import { isPivotLayout } from '../../Utilities/isPivotLayout';
5
+ import { ACCESS_LEVEL_READ_ONLY } from '../../Utilities/Constants/GeneralConstants';
5
6
  export const LayoutCloneButton = ({ data, accessLevel }) => {
6
7
  const adaptable = useAdaptable();
7
- const isDisabled = accessLevel === 'ReadOnly';
8
+ const isDisabled = accessLevel === ACCESS_LEVEL_READ_ONLY;
8
9
  const handleClick = React.useCallback(() => {
9
10
  adaptable.api.layoutApi.showLayoutEditor(data.Name, isPivotLayout(data) ? 'pivot' : 'table', 'Clone');
10
11
  }, []);
@@ -41,7 +41,9 @@ const LayoutViewPanelComponent = (props) => {
41
41
  return (React.createElement(Flex, { flexDirection: "row", className: `ab-${elementType}__Layout__wrap`, flexWrap: viewType === 'ToolPanel' ? 'wrap' : 'nowrap' },
42
42
  React.createElement(Flex, { style: layoutSelectStyle, className: "twa:flex-1" },
43
43
  React.createElement(Select, { "aria-label": 'Select Layout', disabled: isErrorLayout, style: { width: '100%' }, options: availableLayoutOptions, className: `ab-${elementType}__Layout__select`, value: layoutEntity ? layoutEntity.Name : null, onChange: (layout) => onSelectLayout(layout) })),
44
- React.createElement(Flex, { flexDirection: "row", className: join(accessLevel === 'ReadOnly' ? GeneralConstants.READ_ONLY_STYLE : '', `ab-${elementType}__Layout__wrap`) },
44
+ React.createElement(Flex, { flexDirection: "row", className: join(accessLevel === GeneralConstants.ACCESS_LEVEL_READ_ONLY
45
+ ? GeneralConstants.READ_ONLY_STYLE
46
+ : '', `ab-${elementType}__Layout__wrap`) },
45
47
  React.createElement(ButtonEdit, { disabled: isErrorLayout, onClick: () => api.layoutApi.showLayoutEditor(layoutEntity.Name), tooltip: LAYOUT_EDIT_TOOLTIP, className: `ab-${elementType}__Layout__edit`, accessLevel: entityAccessLevel }),
46
48
  React.createElement(ButtonClone, { disabled: isErrorLayout, onClick: () => api.layoutApi.showLayoutEditor(layoutEntity.Name, isPivotLayout(layoutEntity) ? 'pivot' : 'table', 'Clone'), tooltip: LAYOUT_CLONE_TOOLTIP, className: `ab-${elementType}__Layout__clone`, tone: "neutral", variant: "text", children: null, accessLevel: cloneAccessLevel }),
47
49
  React.createElement(DropdownButton, { variant: "text", tooltip: LAYOUT_NEW_TABLE_OR_PIVOT_TOOLTIP, columns: ['label'], "data-name": "new", items: [
@@ -5,6 +5,7 @@ import { useAdaptable } from '../AdaptableContext';
5
5
  import { ColumnSelector } from '../Components/Selectors/ColumnSelector';
6
6
  import { AdaptableAgGrid } from '../../agGrid/AdaptableAgGrid';
7
7
  import { Box, Flex } from '../../components/Flex';
8
+ import { ACCESS_LEVEL_HIDDEN } from '../../Utilities/Constants/GeneralConstants';
8
9
  import { ExportModuleId } from '../../Utilities/Constants/ModuleConstants';
9
10
  import StringExtensions from '../../Utilities/Extensions/StringExtensions';
10
11
  const ADAPTABLE_CONTAINER_ID = 'transposed-adaptable-container';
@@ -23,7 +24,7 @@ function buildTransposedAdaptableOptions({ hostOptions, transposedRowsAndColumns
23
24
  adaptableContainer: ADAPTABLE_CONTAINER_ID,
24
25
  agGridContainer: AG_GRID_CONTAINER_ID,
25
26
  },
26
- entitlementOptions: { defaultAccessLevel: 'Hidden' },
27
+ entitlementOptions: { defaultAccessLevel: ACCESS_LEVEL_HIDDEN },
27
28
  initialState: {
28
29
  Layout: {
29
30
  Revision: Date.now(),
@@ -7,6 +7,7 @@ import { AdaptableButtonComponent } from '../Components/AdaptableButton';
7
7
  import { PopupPanel } from '../Components/Popups/AdaptablePopup/PopupPanel';
8
8
  import StringExtensions from '../../Utilities/Extensions/StringExtensions';
9
9
  import FormatHelper from '../../Utilities/Helpers/FormatHelper';
10
+ import { ACCESS_LEVEL_READ_ONLY } from '../../Utilities/Constants/GeneralConstants';
10
11
  const tableDOMProps = {
11
12
  style: {
12
13
  height: '100%',
@@ -31,7 +32,8 @@ export const NotePopup = (props) => {
31
32
  ? adaptable.api.columnApi.getFriendlyNameForColumnId(adaptable.api.columnApi.getPrimaryKeyColumn().columnId)
32
33
  : StringExtensions.Humanize(adaptable.adaptableOptions.primaryKey);
33
34
  const allNotes = useSelector((state) => GetAllNotesSelector(state.Note));
34
- const isReadOnlyModule = adaptable.api.entitlementApi.getEntitlementAccessLevelForModule('Note') === 'ReadOnly';
35
+ const isReadOnlyModule = adaptable.api.entitlementApi.getEntitlementAccessLevelForModule('Note') ===
36
+ ACCESS_LEVEL_READ_ONLY;
35
37
  const formatDate = (date, format) => {
36
38
  return FormatHelper.DateFormatter(date, { Pattern: format });
37
39
  };
@@ -6,6 +6,7 @@ import { StringExtensions } from '../../Utilities/Extensions/StringExtensions';
6
6
  import { PreviewResultsPanel } from '../Components/PreviewResultsPanel';
7
7
  import { EnumExtensions } from '../../Utilities/Extensions/EnumExtensions';
8
8
  import Input from '../../components/Input';
9
+ import { ACCESS_LEVEL_READ_ONLY } from '../../Utilities/Constants/GeneralConstants';
9
10
  import { ButtonApply } from '../Components/Buttons/ButtonApply';
10
11
  import { AdaptablePopover } from '../AdaptablePopover';
11
12
  import { UIHelper } from '../UIHelper';
@@ -62,7 +63,7 @@ class SmartEditViewPanelComponent extends React.Component {
62
63
  color: statusColour,
63
64
  fill: 'currentColor',
64
65
  };
65
- let shouldDisable = this.props.accessLevel == 'ReadOnly' ||
66
+ let shouldDisable = this.props.accessLevel == ACCESS_LEVEL_READ_ONLY ||
66
67
  !this.props.IsValidSelection ||
67
68
  this.props.api.layoutApi.isCurrentLayoutPivot() == true;
68
69
  const elementType = this.props.viewType === 'Toolbar' ? 'DashboardToolbar' : 'ToolPanel';
@@ -8,7 +8,9 @@ import { Flex } from '../../components/Flex';
8
8
  export const StateManagementViewPanel = (props) => {
9
9
  const isToolbar = props.viewType === 'Toolbar';
10
10
  const elementType = isToolbar ? 'DashboardToolbar' : 'ToolPanel';
11
- return (React.createElement(Flex, { flexDirection: isToolbar ? 'row' : 'column', className: join(props.accessLevel == 'ReadOnly' ? GeneralConstants.READ_ONLY_STYLE : '', `ab-${elementType}__StateManagement__wrap twa:min-h-input`) },
11
+ return (React.createElement(Flex, { flexDirection: isToolbar ? 'row' : 'column', className: join(props.accessLevel == GeneralConstants.ACCESS_LEVEL_READ_ONLY
12
+ ? GeneralConstants.READ_ONLY_STYLE
13
+ : '', `ab-${elementType}__StateManagement__wrap twa:min-h-input`) },
12
14
  React.createElement(Flex, { flexDirection: "row" },
13
15
  React.createElement(LoadButton, { tooltip: "Load Initial Adaptable State", variant: "text", icon: "upload", onLoad: (json) => props.api.stateApi.reloadInitialState(json), accessLevel: props.accessLevel }, !isToolbar && 'Load'),
14
16
  React.createElement(ClearButton, { icon: "delete", tooltip: "Clear User State", variant: "text", onClick: () => props.api.stateApi.reloadInitialState(), accessLevel: props.accessLevel }, !isToolbar && 'Clear')),
@@ -6,6 +6,7 @@ import { ALL_STATUS_SUB_PANELS } from '../../AdaptableState/Common/Types';
6
6
  import { getStatusPanelsSelector } from '../../Redux/ActionsReducers/StatusBarRedux';
7
7
  import { useAdaptable } from '../AdaptableContext';
8
8
  import { PopupPanel } from '../Components/Popups/AdaptablePopup/PopupPanel';
9
+ import { ACCESS_LEVEL_READ_ONLY } from '../../Utilities/Constants/GeneralConstants';
9
10
  export const StatusBarPopup = (props) => {
10
11
  const statusPanels = useSelector(getStatusPanelsSelector);
11
12
  const adaptable = useAdaptable();
@@ -32,7 +33,7 @@ export const StatusBarPopup = (props) => {
32
33
  const module = adaptable.ModuleService.getModuleById(panel);
33
34
  return { Id: panel, Title: module.moduleInfo.FriendlyName };
34
35
  });
35
- const disabled = props.accessLevel === 'ReadOnly';
36
+ const disabled = props.accessLevel === ACCESS_LEVEL_READ_ONLY;
36
37
  return (React.createElement(PopupPanel, { headerText: props.moduleInfo.FriendlyName, glyphicon: props.moduleInfo.Glyph, infoLink: props.moduleInfo.HelpPage, infoLinkDisabled: !props.api.internalApi.isDocumentationLinksDisplayed() }, statusPanels.length ? (React.createElement(ModuleManager, { permittedActions: {
37
38
  createTab: false,
38
39
  dragAndDropTab: false,
@@ -8,6 +8,7 @@ import Panel from '../../components/Panel';
8
8
  import { Field } from './ThemeField';
9
9
  import { VariantSelector } from './VariantSelector';
10
10
  import { getAccessLevelForObject } from '../../Utilities/Helpers/AdaptableHelper';
11
+ import { ACCESS_LEVEL_FULL } from '../../Utilities/Constants/GeneralConstants';
11
12
  import { Box, Flex } from '../../components/Flex';
12
13
  const fields = [
13
14
  {
@@ -53,7 +54,7 @@ export const ThemeEditor = (props) => {
53
54
  return adaptable.api.themeApi.getCurrentThemeObject();
54
55
  });
55
56
  const currentThemeAccessLevel = getAccessLevelForObject(currentThemeObject, props.accessLevel);
56
- const currentThemeIsReadOnly = currentThemeAccessLevel !== 'Full';
57
+ const currentThemeIsReadOnly = currentThemeAccessLevel !== ACCESS_LEVEL_FULL;
57
58
  // THEME variables
58
59
  const themeVariables = currentThemeObject?.CSSVariables;
59
60
  const valuesFromTheme = fields.reduce((acc, field) => {
@@ -6,6 +6,7 @@ import FormLayout, { FormRow } from '../../components/FormLayout';
6
6
  import DropdownButton from '../../components/DropdownButton';
7
7
  import { ThemeEditor } from './ThemeEditor';
8
8
  import ObjectFactory from '../../Utilities/ObjectFactory';
9
+ import { ACCESS_LEVEL_READ_ONLY } from '../../Utilities/Constants/GeneralConstants';
9
10
  import SimpleButton from '../../components/SimpleButton';
10
11
  import { Icon } from '../../components/icons';
11
12
  import { ThemeSelector } from './ThemeSelector';
@@ -15,7 +16,7 @@ class ThemePopupComponent extends React.Component {
15
16
  const isCustomTheme = this.props.api.themeApi
16
17
  .getUserThemes()
17
18
  .some((theme) => theme.Name === this.props.CurrentTheme);
18
- const disabled = this.props.accessLevel === 'ReadOnly';
19
+ const disabled = this.props.accessLevel === ACCESS_LEVEL_READ_ONLY;
19
20
  const newButton = (React.createElement(DropdownButton, { className: "twa:ml-2", disabled: disabled, tone: "accent", variant: "raised", columns: ['label'], items: [
20
21
  {
21
22
  label: 'Dark',
@@ -2,6 +2,7 @@ import * as React from 'react';
2
2
  import { useDispatch, useSelector } from 'react-redux';
3
3
  import { Select } from '../../components/Select';
4
4
  import * as ThemeRedux from '../../Redux/ActionsReducers/ThemeRedux';
5
+ import { ACCESS_LEVEL_READ_ONLY } from '../../Utilities/Constants/GeneralConstants';
5
6
  import { ThemeModuleId } from '../../Utilities/Constants/ModuleConstants';
6
7
  import { useAdaptable } from '../AdaptableContext';
7
8
  export const ThemeSelector = (props) => {
@@ -9,7 +10,8 @@ export const ThemeSelector = (props) => {
9
10
  const dispatch = useDispatch();
10
11
  const availableThemes = adaptable.api.themeApi.getThemes();
11
12
  const currentTheme = useSelector((state) => state.Theme.CurrentTheme);
12
- const disabled = adaptable.api.entitlementApi.getEntitlementAccessLevelForModule(ThemeModuleId) === 'ReadOnly';
13
+ const disabled = adaptable.api.entitlementApi.getEntitlementAccessLevelForModule(ThemeModuleId) ===
14
+ ACCESS_LEVEL_READ_ONLY;
13
15
  const optionThemes = availableThemes.map((theme) => {
14
16
  if (typeof theme === 'string') {
15
17
  // protection against old state, which could be string
@@ -4,6 +4,8 @@ import * as GeneralConstants from '../../Utilities/Constants/GeneralConstants';
4
4
  import { ThemeSelector } from './ThemeSelector';
5
5
  export const ThemeViewPanelControl = (props) => {
6
6
  const elementType = props.viewType === 'Toolbar' ? 'DashboardToolbar' : 'ToolPanel';
7
- return (React.createElement("div", { className: join(props.accessLevel == 'ReadOnly' ? GeneralConstants.READ_ONLY_STYLE : '', `ab-${elementType}__Theme__wrap`) },
7
+ return (React.createElement("div", { className: join(props.accessLevel == GeneralConstants.ACCESS_LEVEL_READ_ONLY
8
+ ? GeneralConstants.READ_ONLY_STYLE
9
+ : '', `ab-${elementType}__Theme__wrap`) },
8
10
  React.createElement(ThemeSelector, null)));
9
11
  };
@@ -5,6 +5,7 @@ import Dialog from '../../components/Dialog';
5
5
  import SimpleButton from '../../components/SimpleButton';
6
6
  import useProperty from '../../components/utils/useProperty';
7
7
  import { isMacLike } from '../../Utilities/isMacLike';
8
+ import { ACCESS_LEVEL_FULL } from '../../Utilities/Constants/GeneralConstants';
8
9
  import { KeyHint } from '../KeyHint';
9
10
  import { Icon } from '../../components/icons';
10
11
  import { useResizeObserver } from '../../components/ResizeObserver';
@@ -176,8 +177,8 @@ export const OnePageWizard = (props) => {
176
177
  "to navigate")),
177
178
  React.createElement(Flex, { flexDirection: "column", className: "ab-OnePageWizard__section-container twa:min-h-0 twa:min-w-0 twa:flex-1" }, renderSection(currentSection))),
178
179
  React.createElement(Flex, { flexDirection: "row", alignItems: "center", className: "ab-WizardDialog__footer ab-OnePageWizard__footer twa:p-2" },
179
- React.createElement(SimpleButton, { tone: "neutral", variant: "text", "data-name": "close", onClick: () => props.onHide?.(), tooltip: props.closeTooltip ?? 'Close wizard', accessLevel: 'Full' }, props.closeText ?? 'CLOSE'),
180
+ React.createElement(SimpleButton, { tone: "neutral", variant: "text", "data-name": "close", onClick: () => props.onHide?.(), tooltip: props.closeTooltip ?? 'Close wizard', accessLevel: ACCESS_LEVEL_FULL }, props.closeText ?? 'CLOSE'),
180
181
  React.createElement(KeyHint, { className: "twa:ml-2" }, "Esc"),
181
182
  React.createElement(Box, { className: "ab-OnePageWizard__error twa:text-2 twa:mr-3 twa:flex-1 twa:text-error twa:text-end" }, firstErrorMessage),
182
- React.createElement(SimpleButton, { tone: "accent", "data-name": "finish", variant: "raised", disabled: canFinish !== true, onClick: () => handleClickFinish(), icon: 'check', accessLevel: 'Full' }, props.finishText ?? 'Finish')))))));
183
+ React.createElement(SimpleButton, { tone: "accent", "data-name": "finish", variant: "raised", disabled: canFinish !== true, onClick: () => handleClickFinish(), icon: 'check', accessLevel: ACCESS_LEVEL_FULL }, props.finishText ?? 'Finish')))))));
183
184
  };
@@ -26,7 +26,7 @@ import { RenderReactRootFn } from '../renderReactRoot';
26
26
  import { AgGridOptionsService } from './AgGridOptionsService';
27
27
  import { AgGridColumnAdapter } from './AgGridColumnAdapter';
28
28
  import { RowFormService } from '../Utilities/Services/RowFormService';
29
- import { GridCellWithChildren, GridCellWithCount } from '../AdaptableState/Selection/GridCell';
29
+ import { CellUpdateRequest, GridCellWithChildren, GridCellWithCount } from '../AdaptableState/Selection/GridCell';
30
30
  import { FlashingCellService } from '../Utilities/Services/FlashingCellService';
31
31
  import { AgGridExportAdapter } from './AgGridExportAdapter';
32
32
  import { PivotLayoutModel, TableLayoutModel } from '../layout-manager/src/LayoutManagerModel';
@@ -300,7 +300,7 @@ export declare class AdaptableAgGrid implements IAdaptable {
300
300
  getRowNodesForPrimaryKeys(primaryKeyValues: any[]): any[];
301
301
  getRowNodeByIndex(index: number): IRowNode;
302
302
  getAgGridStatusPanels(): StatusPanelDef[];
303
- setDataValue(value: any, column: AdaptableColumn, primaryKeyValue: any, rowNode?: IRowNode): void;
303
+ updateCell(cellUpdateRequest: CellUpdateRequest): void;
304
304
  forAllRowNodesDo(func: (rowNode: IRowNode, rowIndex: number) => void, config?: {
305
305
  includeGroupRows?: boolean;
306
306
  filterFn?: (rowNode: IRowNode) => boolean;
@@ -3301,38 +3301,16 @@ export class AdaptableAgGrid {
3301
3301
  getAgGridStatusPanels() {
3302
3302
  return this.agGridAdapter.getGridOption('statusBar')?.statusPanels ?? [];
3303
3303
  }
3304
- setDataValue(value, column, primaryKeyValue, rowNode) {
3304
+ updateCell(cellUpdateRequest) {
3305
3305
  // note: because we use RowNode.setDataValue() this will cause Validation to fire
3306
3306
  // see https://www.ag-grid.com/javascript-data-grid/change-detection/#triggering-value-change-detection
3307
- let newValue;
3308
- let dataType = column.dataType;
3309
- newValue = dataType == 'number' ? Number(value) : value;
3310
- if (dataType == undefined) {
3311
- return; // no point continuing as probably a wrong column
3312
- }
3313
- if (rowNode) {
3314
- rowNode.setDataValue(column.columnId, newValue);
3315
- }
3316
- else {
3317
- if (this.useRowNodeLookUp) {
3318
- const rowNode = this.agGridAdapter.getAgGridApi().getRowNode(primaryKeyValue);
3319
- if (rowNode != null) {
3320
- rowNode.setDataValue(column.columnId, newValue);
3321
- }
3322
- }
3323
- else {
3324
- let isUpdated = false;
3325
- // prefer not to use this method but if we do then at least we can prevent further lookups once we find
3326
- this.agGridAdapter.getAgGridApi().forEachNode((rowNode) => {
3327
- if (!isUpdated) {
3328
- if (primaryKeyValue == this.getPrimaryKeyValueFromRowNode(rowNode)) {
3329
- rowNode.setDataValue(column.columnId, newValue);
3330
- isUpdated = true;
3331
- }
3332
- }
3333
- });
3334
- }
3307
+ const rowNode = cellUpdateRequest.rowNode ?? this.getRowNodeForPrimaryKey(cellUpdateRequest.primaryKeyValue);
3308
+ if (!rowNode) {
3309
+ this.logger.warn(`updateCell() - rowNode not found for primaryKeyValue: ${cellUpdateRequest.primaryKeyValue}`);
3310
+ return;
3335
3311
  }
3312
+ // update the row node and set it as an edit (for AG Grid Cell Change Detection)
3313
+ rowNode.setDataValue(cellUpdateRequest.columnId, cellUpdateRequest.newValue, 'edit');
3336
3314
  }
3337
3315
  forAllRowNodesDo(func, config) {
3338
3316
  this.agGridAdapter.getAgGridApi().forEachNode((rowNode, rowIndex) => {
@@ -1,6 +1,6 @@
1
1
  import { ColumnApiModule, } from 'ag-grid-enterprise';
2
2
  import { ACTION_COLUMN_TYPE, CALCULATED_COLUMN_TYPE, FDC3_COLUMN_TYPE, FREE_TEXT_COLUMN_TYPE, } from '../AdaptableState/Common/AdaptableColumn';
3
- import { ADAPTABLE_FDC3_ACTION_COLUMN_FRIENDLY_NAME } from '../Utilities/Constants/GeneralConstants';
3
+ import { ACCESS_LEVEL_HIDDEN, ADAPTABLE_FDC3_ACTION_COLUMN_FRIENDLY_NAME, } from '../Utilities/Constants/GeneralConstants';
4
4
  import { createUuid } from '../AdaptableState/Uuid';
5
5
  import ArrayExtensions from '../Utilities/Extensions/ArrayExtensions';
6
6
  import * as ModuleConstants from '../Utilities/Constants/ModuleConstants';
@@ -746,7 +746,7 @@ export class AgGridAdapter {
746
746
  }
747
747
  isColumnFilterable(colDef) {
748
748
  // follow agGrid logic which is that ONLY filterable if explicitly set
749
- if (this.adaptableApi.entitlementApi.getEntitlementAccessLevelForModule(ModuleConstants.ColumnFilterModuleId) == 'Hidden') {
749
+ if (this.adaptableApi.entitlementApi.getEntitlementAccessLevelForModule(ModuleConstants.ColumnFilterModuleId) == ACCESS_LEVEL_HIDDEN) {
750
750
  return false;
751
751
  }
752
752
  return colDef != null && colDef.filter != null && colDef.filter != false;
@@ -1,4 +1,5 @@
1
1
  import kebabCase from '../Utilities/utils/kebabCase';
2
+ import { resolveDisplayFormat } from '../AdaptableState/Common/AdaptableFormatPresets';
2
3
  import merge from '../Utilities/utils/merge';
3
4
  import { convertAdaptableStyleToCSS, getVariableColor, normalizeStyleForAgGrid, } from '../Utilities/Helpers/StyleHelper';
4
5
  import StringExtensions from '../Utilities/Extensions/StringExtensions';
@@ -730,8 +731,14 @@ export class AgGridColumnAdapter {
730
731
  // ALL FormatColumns are conditional and NONE of them are relevant for this row
731
732
  return value;
732
733
  }
733
- const formatterOptions = mostRelevantFormatColumn.DisplayFormat.Options;
734
- if (mostRelevantFormatColumn.DisplayFormat.Formatter === 'NumberFormatter') {
734
+ // Resolve once: a preset name (e.g. 'Dollar') is materialised
735
+ // into the concrete AdaptableFormat for this render call.
736
+ const resolvedDisplayFormat = resolveDisplayFormat(mostRelevantFormatColumn.DisplayFormat);
737
+ if (!resolvedDisplayFormat) {
738
+ return value;
739
+ }
740
+ const formatterOptions = resolvedDisplayFormat.Options;
741
+ if (resolvedDisplayFormat.Formatter === 'NumberFormatter') {
735
742
  // change the Number format - if the scope allows it
736
743
  if (this.adaptableApi.columnScopeApi.isColumnInNumericScope(abColumn, mostRelevantFormatColumn.Scope)) {
737
744
  let cellValue = params.value;
@@ -743,7 +750,7 @@ export class AgGridColumnAdapter {
743
750
  return this.adaptableApi.formatColumnApi.internalApi.getNumberFormattedValue(cellValue, params.node, abColumn, formatterOptions);
744
751
  }
745
752
  }
746
- if (mostRelevantFormatColumn.DisplayFormat.Formatter === 'DateFormatter') {
753
+ if (resolvedDisplayFormat.Formatter === 'DateFormatter') {
747
754
  // change the Date format - if the scope allows it
748
755
  if (this.adaptableApi.columnScopeApi.isColumnInDateScope(abColumn, mostRelevantFormatColumn.Scope)) {
749
756
  let cellValue = params.value;
@@ -755,7 +762,7 @@ export class AgGridColumnAdapter {
755
762
  return this.adaptableApi.formatColumnApi.internalApi.getDateFormattedValue(cellValue, params.node, abColumn, formatterOptions);
756
763
  }
757
764
  }
758
- if (mostRelevantFormatColumn.DisplayFormat.Formatter === 'StringFormatter') {
765
+ if (resolvedDisplayFormat.Formatter === 'StringFormatter') {
759
766
  // change the String format - if the scope allows it
760
767
  if (this.adaptableApi.columnScopeApi.isColumnInTextScope(abColumn, mostRelevantFormatColumn.Scope)) {
761
768
  let cellValue = params.value;
@@ -1,5 +1,6 @@
1
1
  import tinycolor from 'tinycolor2';
2
2
  import { inferSchema, initParser } from 'udsv';
3
+ import { resolveDisplayFormat } from '../AdaptableState/Common/AdaptableFormatPresets';
3
4
  import { createUuid } from '../AdaptableState/Uuid';
4
5
  import { AG_GRID_GROUPED_COLUMN, AG_GRID_SELECTION_COLUMN, } from '../Utilities/Constants/GeneralConstants';
5
6
  import { ExportModuleId } from '../Utilities/Constants/ModuleConstants';
@@ -639,9 +640,10 @@ export class AgGridExportAdapter {
639
640
  const abColumn = getAdaptableColumnWithColumnId(column.getColId());
640
641
  if (!dateFormatPattern) {
641
642
  const mostRelevantFormatColumn = this.adaptableApi.formatColumnApi.internalApi.getMostRelevantFormatColumnForColumn(getFormatColumnsWithDisplayFormatForColumn(column.getColId()), abColumn, { node, value: rawValue });
643
+ const resolvedDisplayFormat = resolveDisplayFormat(mostRelevantFormatColumn?.DisplayFormat);
642
644
  dateFormatPattern =
643
- mostRelevantFormatColumn?.DisplayFormat?.Formatter === 'DateFormatter' &&
644
- mostRelevantFormatColumn?.DisplayFormat?.Options?.Pattern;
645
+ resolvedDisplayFormat?.Formatter === 'DateFormatter' &&
646
+ resolvedDisplayFormat?.Options?.Pattern;
645
647
  }
646
648
  if (dateFormatPattern) {
647
649
  const customDateFormatPattern = typeof dateFormatPattern === 'function'
@@ -3,6 +3,7 @@ import * as React from 'react';
3
3
  import { useRerender } from '../../components/utils/useRerender';
4
4
  import { renderWithAdaptableContext } from '../../View/renderWithAdaptableContext';
5
5
  import { LAYOUT_SELECT } from '../../Redux/ActionsReducers/LayoutRedux';
6
+ import { ACCESS_LEVEL_FULL } from '../../Utilities/Constants/GeneralConstants';
6
7
  const ActionButtons = (props) => {
7
8
  const { buttons, adaptableApi, context, rerender } = props;
8
9
  return (React.createElement(React.Fragment, null, buttons.map((button, index) => {
@@ -30,7 +31,7 @@ const ActionButtons = (props) => {
30
31
  button.icon?.name ??
31
32
  button.tooltip ??
32
33
  `${index + 1}`;
33
- return (React.createElement(SimpleButton, { key: button.Uuid, "data-name": `action-button-${identifier}`, variant: buttonStyle?.variant ?? 'text', disabled: disabled, tooltip: buttonTooltip, icon: buttonIcon, tone: buttonStyle?.tone ?? 'none', onClick: handleClick, className: buttonStyle?.className, accessLevel: 'Full' }, buttonLabel));
34
+ return (React.createElement(SimpleButton, { key: button.Uuid, "data-name": `action-button-${identifier}`, variant: buttonStyle?.variant ?? 'text', disabled: disabled, tooltip: buttonTooltip, icon: buttonIcon, tone: buttonStyle?.tone ?? 'none', onClick: handleClick, className: buttonStyle?.className, accessLevel: ACCESS_LEVEL_FULL }, buttonLabel));
34
35
  })));
35
36
  };
36
37
  export const ReactActionColumnRenderer = (props) => {
@@ -4,6 +4,7 @@ import join from '../utils/join';
4
4
  import useProperty from '../utils/useProperty';
5
5
  import { DashboardToolbar } from './DashboardToolbar';
6
6
  import DropdownButton from '../DropdownButton';
7
+ import { ACCESS_LEVEL_FULL } from '../../Utilities/Constants/GeneralConstants';
7
8
  export function Dashboard(props) {
8
9
  const { title, children, left, right, onShowDashboardPopup } = props;
9
10
  const [activeTabIndex, setActiveTabIndex] = useProperty(props, 'activeTabIndex', 0);
@@ -64,7 +65,7 @@ export function Dashboard(props) {
64
65
  !floating && renderTabs()),
65
66
  floating ? (React.createElement("div", { className: "ab-Dashboard__title", ref: handleRef, key: "title-drag", style: { cursor: 'move' } }, title)) : (React.createElement("div", { className: "ab-Dashboard__title", key: "title" }, title)),
66
67
  React.createElement("div", { className: "ab-Dashboard__header-right" }, right)));
67
- const renderHomeToolbar = () => (React.createElement(DashboardToolbar, { onConfigure: onShowDashboardPopup, className: "ab-Dashboard__home-toolbar", title: title, tooltip: `Configure Dashboard`, showConfigure: true, showClose: false, accessLevel: 'Full' },
68
+ const renderHomeToolbar = () => (React.createElement(DashboardToolbar, { onConfigure: onShowDashboardPopup, className: "ab-Dashboard__home-toolbar", title: title, tooltip: `Configure Dashboard`, showConfigure: true, showClose: false, accessLevel: ACCESS_LEVEL_FULL },
68
69
  left,
69
70
  right,
70
71
  children && children.length > 1,
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import SimpleButton from '../SimpleButton';
3
3
  import join from '../utils/join';
4
+ import { ACCESS_LEVEL_READ_ONLY } from '../../Utilities/Constants/GeneralConstants';
4
5
  import { Flex } from '../Flex';
5
6
  export function DashboardToolbar(props) {
6
7
  return (React.createElement("div", { className: join('ab-Dashboard__toolbar', props.className) },
@@ -8,5 +9,5 @@ export function DashboardToolbar(props) {
8
9
  React.createElement(Flex, { className: "ab-Dashboard__toolbar-title twa:items-center twa:justify-center twa:px-2 twa:pb-1 twa:opacity-70", flexDirection: "row" },
9
10
  React.createElement("span", { className: "twa:text-2" }, props.title),
10
11
  props.showConfigure && (React.createElement(SimpleButton, { "aria-label": `Configure ${props.title}`, icon: "spanner", variant: "text", tone: "none", "data-name": "configure", iconSize: 16, className: "twa:ml-1", tooltip: props.tooltip || `Configure ${props.title}`, onClick: () => props.onConfigure() })),
11
- props.showClose && (React.createElement(SimpleButton, { "aria-label": `Close ${props.title}`, style: { alignSelf: 'flex-end' }, disabled: props.accessLevel == 'ReadOnly', "data-name": "close", icon: "close", variant: "text", tone: "none", iconSize: 16, className: "twa:ml-1", tooltip: props.tooltip || `Close ${props.title} Toolbar`, onClick: () => props.onClose?.() })))));
12
+ props.showClose && (React.createElement(SimpleButton, { "aria-label": `Close ${props.title}`, style: { alignSelf: 'flex-end' }, disabled: props.accessLevel == ACCESS_LEVEL_READ_ONLY, "data-name": "close", icon: "close", variant: "text", tone: "none", iconSize: 16, className: "twa:ml-1", tooltip: props.tooltip || `Close ${props.title} Toolbar`, onClick: () => props.onClose?.() })))));
12
13
  }