@adaptabletools/adaptable 22.0.0-canary.2 → 22.0.0-canary.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.
Files changed (131) hide show
  1. package/index.css +64 -26
  2. package/index.css.map +1 -1
  3. package/package.json +1 -1
  4. package/src/AdaptableInterfaces/IAdaptable.d.ts +2 -2
  5. package/src/AdaptableOptions/ActionColumnOptions.d.ts +2 -2
  6. package/src/AdaptableOptions/CustomSortOptions.d.ts +5 -0
  7. package/src/AdaptableOptions/DashboardOptions.d.ts +1 -2
  8. package/src/AdaptableOptions/ToolPanelOptions.d.ts +1 -2
  9. package/src/AdaptableState/AlertState.d.ts +2 -2
  10. package/src/AdaptableState/ChartingState.d.ts +3 -3
  11. package/src/AdaptableState/Common/AdaptableAlert.d.ts +2 -2
  12. package/src/AdaptableState/Common/AdaptableButton.d.ts +2 -2
  13. package/src/AdaptableState/Common/AdaptableFlashingCell.d.ts +2 -2
  14. package/src/AdaptableState/Common/AdaptableObject.d.ts +25 -2
  15. package/src/AdaptableState/Common/AdaptableStyle.d.ts +8 -0
  16. package/src/AdaptableState/Common/RowSummary.d.ts +1 -1
  17. package/src/AdaptableState/Common/Schedule.d.ts +3 -4
  18. package/src/AdaptableState/Common/SystemStatusMessageInfo.d.ts +2 -2
  19. package/src/AdaptableState/CustomSortState.d.ts +2 -2
  20. package/src/AdaptableState/DashboardState.d.ts +2 -2
  21. package/src/AdaptableState/ExportState.d.ts +2 -2
  22. package/src/AdaptableState/FlashingCellState.d.ts +2 -2
  23. package/src/AdaptableState/FormatColumnState.d.ts +2 -10
  24. package/src/AdaptableState/LayoutState.d.ts +8 -3
  25. package/src/AdaptableState/NamedQueryState.d.ts +2 -2
  26. package/src/AdaptableState/PlusMinusState.d.ts +2 -2
  27. package/src/AdaptableState/ShortcutState.d.ts +2 -2
  28. package/src/AdaptableState/StyledColumnState.d.ts +1 -1
  29. package/src/AdaptableState/ThemeState.d.ts +2 -2
  30. package/src/Api/CustomSortApi.d.ts +6 -3
  31. package/src/Api/DataSetApi.d.ts +1 -1
  32. package/src/Api/GridApi.d.ts +3 -3
  33. package/src/Api/Implementation/CustomSortApiImpl.d.ts +5 -1
  34. package/src/Api/Implementation/CustomSortApiImpl.js +2 -2
  35. package/src/Api/Implementation/GridApiImpl.d.ts +9 -9
  36. package/src/Api/Implementation/GridApiImpl.js +16 -16
  37. package/src/Api/Implementation/LayoutHelpers.js +7 -0
  38. package/src/Api/Implementation/ScheduleApiImpl.js +1 -0
  39. package/src/Api/Internal/ColumnInternalApi.js +1 -1
  40. package/src/Api/Internal/FormatColumnInternalApi.d.ts +0 -10
  41. package/src/Api/Internal/FormatColumnInternalApi.js +1 -19
  42. package/src/Redux/ActionsReducers/LayoutRedux.d.ts +1 -1
  43. package/src/Redux/ActionsReducers/NoteRedux.js +1 -1
  44. package/src/Strategy/AlertModule.js +4 -0
  45. package/src/Strategy/CustomSortModule.js +4 -0
  46. package/src/Strategy/FlashingCellModule.js +5 -0
  47. package/src/Strategy/FormatColumnModule.js +4 -0
  48. package/src/Strategy/LayoutModule.js +4 -4
  49. package/src/Strategy/PlusMinusModule.js +4 -0
  50. package/src/Strategy/ScheduleModule.js +4 -0
  51. package/src/Strategy/ShortcutModule.js +4 -0
  52. package/src/Strategy/Utilities/FormatColumn/getFormatColumnSettingsViewItems.js +0 -3
  53. package/src/Utilities/Constants/DocumentationLinkConstants.d.ts +2 -2
  54. package/src/Utilities/Constants/DocumentationLinkConstants.js +2 -2
  55. package/src/Utilities/ExpressionFunctions/scalarExpressionFunctions.js +3 -3
  56. package/src/Utilities/Extensions/StringExtensions.d.ts +2 -0
  57. package/src/Utilities/Extensions/StringExtensions.js +16 -0
  58. package/src/Utilities/Helpers/FormatHelper.js +9 -2
  59. package/src/Utilities/Helpers/StyleHelper.js +14 -0
  60. package/src/Utilities/ObjectFactory.js +16 -3
  61. package/src/Utilities/Services/AnnotationsService.js +1 -1
  62. package/src/Utilities/Services/ModuleService.js +3 -3
  63. package/src/View/AdaptablePopover/index.d.ts +1 -0
  64. package/src/View/AdaptablePopover/index.js +1 -1
  65. package/src/View/Alert/ActiveAlertsPanel.js +8 -0
  66. package/src/View/Alert/AlertViewPanel.js +13 -9
  67. package/src/View/Alert/Utilities/getAlertButtonStyle.d.ts +1 -0
  68. package/src/View/Alert/Utilities/getAlertButtonStyle.js +8 -0
  69. package/src/View/Alert/Utilities/getDefaultAlertDefinition.d.ts +2 -1
  70. package/src/View/Alert/Wizard/AlertTypeWizardSection.d.ts +5 -2
  71. package/src/View/Alert/Wizard/AlertTypeWizardSection.js +47 -12
  72. package/src/View/Alert/Wizard/AlertWizard.js +14 -10
  73. package/src/View/BulkUpdate/BulkUpdateViewPanel.js +23 -11
  74. package/src/View/CalculatedColumn/Wizard/CalculatedColumnExpressionWizardSection.js +2 -2
  75. package/src/View/CellSummary/CellSummaryViewPanel.js +15 -17
  76. package/src/View/Components/AdaptableDateInput/index.js +1 -1
  77. package/src/View/Components/Buttons/ButtonApply.js +1 -1
  78. package/src/View/Components/Buttons/ButtonClear.d.ts +1 -0
  79. package/src/View/Components/Buttons/EntityListActionButtons.d.ts +1 -2
  80. package/src/View/Components/Buttons/SuspendToggleButton/SuspendToggleButton.d.ts +1 -2
  81. package/src/View/Components/Selectors/BulkUpdateValueSelector.js +19 -18
  82. package/src/View/Components/StyleComponent.js +20 -1
  83. package/src/View/CustomSort/Wizard/CustomSortColumnWizardSection.d.ts +2 -1
  84. package/src/View/CustomSort/Wizard/CustomSortColumnWizardSection.js +40 -14
  85. package/src/View/CustomSort/Wizard/CustomSortWizard.js +4 -4
  86. package/src/View/Dashboard/DashboardPopup.js +4 -5
  87. package/src/View/DataChangeHistory/DataChangeHistoryGrid.js +1 -0
  88. package/src/View/Export/ExportDestinationPicker.js +1 -1
  89. package/src/View/Export/ExportStatusBar.js +4 -2
  90. package/src/View/Export/ExportViewPanel.js +25 -18
  91. package/src/View/FlashingCell/Wizard/FlashingCellSettingsWizardSection.d.ts +2 -1
  92. package/src/View/FlashingCell/Wizard/FlashingCellSettingsWizardSection.js +34 -14
  93. package/src/View/FlashingCell/Wizard/FlashingCellWizard.js +14 -10
  94. package/src/View/FormatColumn/Wizard/FormatColumnSettingsWizardSection.js +46 -51
  95. package/src/View/FormatColumn/Wizard/FormatColumnStyleWizardSection.js +2 -2
  96. package/src/View/FormatColumn/Wizard/FormatColumnWizard.js +20 -9
  97. package/src/View/GridInfo/GridInfoPopup/GridInfoPopup.js +57 -65
  98. package/src/View/Layout/Wizard/sections/PivotColumnsSection.js +8 -0
  99. package/src/View/PlusMinus/Wizard/PlusMinusSettingsWizardSection.js +32 -9
  100. package/src/View/PlusMinus/Wizard/PlusMinusWizard.js +20 -15
  101. package/src/View/QuickSearch/QuickSearchPopup.js +4 -1
  102. package/src/View/Schedule/Wizard/ScheduleSettingsWizard/ScheduleSettingsIPushPull.js +12 -1
  103. package/src/View/Schedule/Wizard/ScheduleSettingsWizard/ScheduleSettingsOpenFin.js +12 -1
  104. package/src/View/Schedule/Wizard/ScheduleSettingsWizard/ScheduleSettingsReminder.js +14 -4
  105. package/src/View/Schedule/Wizard/ScheduleSettingsWizard/ScheduleSettingsReport.js +12 -1
  106. package/src/View/Schedule/Wizard/ScheduleSettingsWizard/isSettingsValid.d.ts +2 -1
  107. package/src/View/Schedule/Wizard/ScheduleSettingsWizard/isSettingsValid.js +10 -1
  108. package/src/View/Shortcut/Wizard/ShortcutSettingsWizard.d.ts +2 -1
  109. package/src/View/Shortcut/Wizard/ShortcutSettingsWizard.js +25 -4
  110. package/src/View/Shortcut/Wizard/ShortcutWizard.js +18 -14
  111. package/src/View/UIHelper.d.ts +2 -0
  112. package/src/View/UIHelper.js +15 -0
  113. package/src/agGrid/AdaptableAgGrid.d.ts +2 -2
  114. package/src/agGrid/AdaptableAgGrid.js +5 -5
  115. package/src/agGrid/AgGridColumnAdapter.js +3 -18
  116. package/src/components/Dashboard/DashboardToolbar.js +1 -1
  117. package/src/components/ExpressionEditor/EditorInput.js +19 -3
  118. package/src/components/Tree/TreeDropdown/index.js +1 -1
  119. package/src/env.js +2 -2
  120. package/src/layout-manager/src/LayoutManagerModel.d.ts +1 -0
  121. package/src/layout-manager/src/index.js +25 -7
  122. package/src/layout-manager/src/normalizeLayoutModel.js +3 -0
  123. package/src/metamodel/adaptable.metamodel.d.ts +39 -7
  124. package/src/metamodel/adaptable.metamodel.js +1 -1
  125. package/src/migration/AdaptableUpgradeHelper.js +3 -1
  126. package/src/migration/VersionUpgrade22.d.ts +21 -0
  127. package/src/migration/VersionUpgrade22.js +187 -0
  128. package/src/types.d.ts +2 -3
  129. package/tsconfig.esm.tsbuildinfo +1 -1
  130. package/src/AdaptableState/Common/SuspendableObject.d.ts +0 -10
  131. package/src/AdaptableState/Common/SuspendableObject.js +0 -1
@@ -3,20 +3,55 @@ import { Tabs } from '../../../components/Tabs';
3
3
  import { AlertType, getAlertTypeText } from '../Utilities/getAlertType';
4
4
  import { TypeRadio } from '../../Wizard/TypeRadio';
5
5
  import { Tag } from '../../../components/Tag';
6
- import { Box, Flex } from '../../../components/Flex';
6
+ import { Flex } from '../../../components/Flex';
7
+ import { useOnePageAdaptableWizardContext } from '../../Wizard/OnePageAdaptableWizard';
8
+ import FormLayout, { FormRow } from '../../../components/FormLayout';
9
+ import Input from '../../../components/Input';
10
+ import { SummaryText } from '../../Wizard/OnePageAdaptableWizard';
11
+ export const isSettingsValid = (data, api) => {
12
+ if (!data.Name?.trim()) {
13
+ return 'Name is required';
14
+ }
15
+ const allAlerts = api.alertApi.getAlertDefinitions();
16
+ const isDuplicateName = allAlerts.some((a) => a.Name === data.Name && a.Uuid !== data.Uuid);
17
+ if (isDuplicateName) {
18
+ return 'An Alert already exists with that name';
19
+ }
20
+ return true;
21
+ };
7
22
  export const renderAlertTypeSummary = (alertType) => {
23
+ const { data } = useOnePageAdaptableWizardContext();
8
24
  const text = getAlertTypeText(alertType);
9
- return (React.createElement(Box, null,
10
- React.createElement(Tag, null, text)));
25
+ return (React.createElement(React.Fragment, null,
26
+ React.createElement(SummaryText, null,
27
+ "Name ",
28
+ React.createElement(Tag, null, data.Name || 'Not specified')),
29
+ React.createElement(SummaryText, null,
30
+ "Type ",
31
+ React.createElement(Tag, null, text))));
11
32
  };
12
33
  export const AlertTypeWizardSection = (props) => {
13
- return (React.createElement(Tabs, null,
14
- React.createElement(Tabs.Tab, null, "Alert Type"),
15
- React.createElement(Tabs.Content, null,
16
- React.createElement(Flex, { flexDirection: "column" },
17
- React.createElement(TypeRadio, { text: getAlertTypeText(AlertType.DataChange), description: "A change has been made to the Grid's underlying data", checked: props.alertType === AlertType.DataChange, onClick: () => props.onAlertTypeChange(AlertType.DataChange) }),
18
- React.createElement(TypeRadio, { text: getAlertTypeText(AlertType.RowChange), description: "A Row was added or removed from the data source", checked: props.alertType === AlertType.RowChange, onClick: () => props.onAlertTypeChange(AlertType.RowChange) }),
19
- React.createElement(TypeRadio, { text: getAlertTypeText(AlertType.Aggregation), description: "A change has been made to aggregated data (i.e. from multiple Rows)", onClick: () => props.onAlertTypeChange(AlertType.Aggregation), checked: props.alertType === AlertType.Aggregation }),
20
- React.createElement(TypeRadio, { text: getAlertTypeText(AlertType.Observable), description: "A specified change (or lack of change) over time has been observed in the Grid", onClick: () => props.onAlertTypeChange(AlertType.Observable), checked: props.alertType === AlertType.Observable }),
21
- React.createElement(TypeRadio, { text: getAlertTypeText(AlertType.Validation), description: "A change has broken a data validation rule", checked: props.alertType === AlertType.Validation, onClick: () => props.onAlertTypeChange(AlertType.Validation) })))));
34
+ const { data } = useOnePageAdaptableWizardContext();
35
+ const handleNameChange = (event) => {
36
+ props.onChange({
37
+ ...data,
38
+ Name: event.target.value,
39
+ });
40
+ };
41
+ return (React.createElement(Flex, { flexDirection: "column" },
42
+ React.createElement(Tabs, null,
43
+ React.createElement(Tabs.Tab, null, "Settings"),
44
+ React.createElement(Tabs.Content, null,
45
+ React.createElement(FormLayout, null,
46
+ React.createElement(FormRow, { label: "Name" },
47
+ React.createElement(Input, { "data-name": "alert-name", className: "twa:flex-1 twa:max-w-[200px] twa:mr-3", onChange: handleNameChange, placeholder: "Enter Name", value: data.Name ?? '' }))))),
48
+ React.createElement(Tabs, { className: "twa:mt-2" },
49
+ React.createElement(Tabs.Tab, null, "Alert Type"),
50
+ React.createElement(Tabs.Content, null,
51
+ React.createElement(Flex, { flexDirection: "column" },
52
+ React.createElement(TypeRadio, { text: getAlertTypeText(AlertType.DataChange), description: "A change has been made to the Grid's underlying data", checked: props.alertType === AlertType.DataChange, onClick: () => props.onAlertTypeChange(AlertType.DataChange) }),
53
+ React.createElement(TypeRadio, { text: getAlertTypeText(AlertType.RowChange), description: "A Row was added or removed from the data source", checked: props.alertType === AlertType.RowChange, onClick: () => props.onAlertTypeChange(AlertType.RowChange) }),
54
+ React.createElement(TypeRadio, { text: getAlertTypeText(AlertType.Aggregation), description: "A change has been made to aggregated data (i.e. from multiple Rows)", onClick: () => props.onAlertTypeChange(AlertType.Aggregation), checked: props.alertType === AlertType.Aggregation }),
55
+ React.createElement(TypeRadio, { text: getAlertTypeText(AlertType.Observable), description: "A specified change (or lack of change) over time has been observed in the Grid", onClick: () => props.onAlertTypeChange(AlertType.Observable), checked: props.alertType === AlertType.Observable }),
56
+ React.createElement(TypeRadio, { text: getAlertTypeText(AlertType.Validation), description: "A change has broken a data validation rule", checked: props.alertType === AlertType.Validation, onClick: () => props.onAlertTypeChange(AlertType.Validation) }))))));
22
57
  };
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { useState } from 'react';
2
+ import { useState, useCallback } from 'react';
3
3
  import { OnePageAdaptableWizard, OnePageWizardSummary } from '../../Wizard/OnePageAdaptableWizard';
4
4
  import { cloneObject } from '../../../Utilities/Helpers/Helper';
5
5
  import { AlertScopeWizardSection } from './AlertScopeWizardSection';
@@ -15,7 +15,7 @@ import { useDispatch } from 'react-redux';
15
15
  import * as AlertRedux from '../../../Redux/ActionsReducers/AlertRedux';
16
16
  import { useAdaptable } from '../../AdaptableContext';
17
17
  import { ObjectTagsWizardSection, renderObjectTagsSummary, } from '../../Wizard/ObjectTagsWizardSection';
18
- import { AlertTypeWizardSection, renderAlertTypeSummary } from './AlertTypeWizardSection';
18
+ import { AlertTypeWizardSection, renderAlertTypeSummary, isSettingsValid, } from './AlertTypeWizardSection';
19
19
  import { AlertType, getAlertType } from '../Utilities/getAlertType';
20
20
  import { mapAlertDefinition } from '../Utilities/mapAlertDefinition';
21
21
  import { getDefaultAlertDefinition } from '../Utilities/getDefaultAlertDefinition';
@@ -25,7 +25,7 @@ export const AlertWizard = (props) => {
25
25
  const { api } = useAdaptable();
26
26
  const dispatch = useDispatch();
27
27
  const behaviourSpelling = api.internalApi.getCorrectEnglishVariant('Behaviour');
28
- const [alertDefinition, setAlertDefinition] = useState(() => {
28
+ const [alertDefinition, doSetAlertDefinition] = useState(() => {
29
29
  const alertDefinition = props.data
30
30
  ? cloneObject(props.data)
31
31
  : ObjectFactory.CreateEmptyAlertDefinition();
@@ -45,6 +45,9 @@ export const AlertWizard = (props) => {
45
45
  alertDefinition.MessageType = alertDefinition.MessageType ?? ALERT_DEFAULT_MESSAGE_TYPE;
46
46
  return alertDefinition;
47
47
  });
48
+ const setAlertDefinition = useCallback((data) => {
49
+ doSetAlertDefinition(data);
50
+ }, []);
48
51
  // Alert type is based initialy on data, but can be changed by the user
49
52
  // the default objects do not neccesary have enough information to determine the type
50
53
  const [alertType, setAlertType] = useState(() => {
@@ -59,22 +62,23 @@ export const AlertWizard = (props) => {
59
62
  }
60
63
  props.onCloseWizard();
61
64
  };
62
- const updateAlertDefinition = (newAlertDefinition) => {
63
- setAlertDefinition(mapAlertDefinition(api, newAlertDefinition));
64
- };
65
+ const updateAlertDefinition = useCallback((newAlertDefinition) => {
66
+ doSetAlertDefinition(mapAlertDefinition(api, newAlertDefinition));
67
+ }, [api]);
65
68
  const handleAlertTypeChange = (newAlertType) => {
66
69
  setAlertType(newAlertType);
67
- setAlertDefinition(getDefaultAlertDefinition(alertDefinition, newAlertType));
70
+ doSetAlertDefinition(getDefaultAlertDefinition(alertDefinition, newAlertType));
68
71
  };
69
72
  return (React.createElement(OnePageAdaptableWizard, { defaultCurrentSectionName: props.defaultCurrentSectionName, moduleInfo: props.moduleInfo, modal: props.modal, data: alertDefinition, onHide: props.onCloseWizard, onFinish: handleFinish, sections: [
70
73
  {
71
- title: 'Type',
74
+ title: 'Name & Type',
75
+ isValid: isSettingsValid,
72
76
  details: (React.createElement(React.Fragment, null,
73
- "Select ",
77
+ "Enter Name and select ",
74
78
  React.createElement("b", null, "what"),
75
79
  " type of change in AdapTable will cause the Alert to fire")),
76
80
  render: () => (React.createElement(Box, { className: "twa:p-2" },
77
- React.createElement(AlertTypeWizardSection, { alertType: alertType, onAlertTypeChange: handleAlertTypeChange }))),
81
+ React.createElement(AlertTypeWizardSection, { alertType: alertType, onAlertTypeChange: handleAlertTypeChange, onChange: setAlertDefinition }))),
78
82
  renderSummary: () => renderAlertTypeSummary(alertType),
79
83
  },
80
84
  {
@@ -38,24 +38,36 @@ class BulkUpdateViewPanelComponent extends React.Component {
38
38
  let statusColour = this.getStatusColour();
39
39
  let selectedColumn = this.props.BulkUpdateValidationResult.Column;
40
40
  let previewPanel = (React.createElement(PreviewResultsPanel, { previewInfo: this.props.PreviewInfo, api: this.props.api, selectedColumn: selectedColumn, showPanel: true, showHeader: false }));
41
- let shouldDisable = this.props.accessLevel == 'ReadOnly' ||
41
+ const valueSelectorDisabled = this.props.accessLevel == 'ReadOnly' ||
42
42
  !this.props.BulkUpdateValidationResult.IsValid ||
43
- this.props.api.layoutApi.isCurrentLayoutPivot() == true;
43
+ this.props.api.layoutApi.isCurrentLayoutPivot();
44
+ const valueOperationDisabled = valueSelectorDisabled ||
45
+ StringExtensions.IsNullOrEmpty(this.props.BulkUpdateValue) ||
46
+ (this.props.PreviewInfo != null &&
47
+ this.props.PreviewInfo.previewValidationSummary.validationResult == 'All');
44
48
  const applyStyle = {
45
49
  color: statusColour,
46
50
  fill: 'currentColor',
47
51
  };
48
- const elementType = this.props.viewType === 'Toolbar' ? 'DashboardToolbar' : 'ToolPanel';
49
- return (React.createElement(Flex, { flexDirection: "row", className: clsx(shouldDisable ? GeneralConstants.READ_ONLY_STYLE : '', `ab-${elementType}__BulkUpdate__wrap twa:min-w-[150px]`), flexWrap: this.props.viewType === 'ToolPanel' ? 'wrap' : 'nowrap' },
50
- React.createElement(Flex, null,
52
+ const isToolbar = this.props.viewType === 'Toolbar';
53
+ const elementType = isToolbar ? 'DashboardToolbar' : 'ToolPanel';
54
+ const messageStyle = UIHelper.getMessageTypeByStatusColour(statusColour);
55
+ const infoStyle = messageStyle === 'Success' ? 'Info' : messageStyle;
56
+ return (React.createElement(Flex, { className: clsx(valueSelectorDisabled ? GeneralConstants.READ_ONLY_STYLE : '', `ab-${elementType}__BulkUpdate__wrap twa:gap-1 twa:flex-row`, {
57
+ 'twa:min-w-[300px] twa:max-w-[300px] twa:w-[300px] twa:flex-nowrap': isToolbar,
58
+ 'twa:flex-1 twa:flex-wrap': !isToolbar,
59
+ }), flexWrap: isToolbar ? 'nowrap' : 'wrap' },
60
+ React.createElement(Flex, { className: clsx('twa:flex-1', {
61
+ 'twa:min-w-[100px]': !isToolbar,
62
+ 'twa:min-w-0': isToolbar,
63
+ }) },
51
64
  React.createElement(BulkUpdateValueSelector, { selectedGridCells: this.props.SelectedGridCells, newLabel: "New", existingLabel: "Existing", dropdownButtonProps: {
52
65
  listMinWidth: 160,
53
- }, className: `ab-${elementType}__BulkUpdate__select`, disabled: shouldDisable, selectedColumnValue: this.props.BulkUpdateValue, selectedColumn: selectedColumn, api: this.props.api, onColumnValueChange: (columns) => this.onColumnValueSelectedChanged(columns) })),
54
- React.createElement(Flex, null,
55
- !shouldDisable && StringExtensions.IsNotNullOrEmpty(this.props.BulkUpdateValue) && (React.createElement(ButtonApply, { className: `ab-${elementType}__BulkUpdate__apply twa:ml-2`, onClick: () => this.onApplyClick(), style: applyStyle, tooltip: "Apply Bulk Update", disabled: StringExtensions.IsNullOrEmpty(this.props.BulkUpdateValue) ||
56
- (this.props.PreviewInfo != null &&
57
- this.props.PreviewInfo.previewValidationSummary.validationResult == 'All'), accessLevel: this.props.accessLevel }, this.props.viewType === 'ToolPanel' && 'Update')),
58
- !shouldDisable && StringExtensions.IsNotNullOrEmpty(this.props.BulkUpdateValue) && (React.createElement(AdaptablePopover, { popoverMinWidth: 360, className: `ab-${elementType}__BulkUpdate__info`, headerText: "Preview Results", bodyText: [previewPanel], MessageType: UIHelper.getMessageTypeByStatusColour(statusColour), useButton: true, showEvent: 'focus', hideEvent: "blur" })))));
66
+ }, className: `ab-${elementType}__BulkUpdate__select twa:w-full`, disabled: valueSelectorDisabled, selectedColumnValue: this.props.BulkUpdateValue, selectedColumn: selectedColumn, api: this.props.api, onColumnValueChange: (columns) => this.onColumnValueSelectedChanged(columns) })),
67
+ React.createElement(Flex, { className: "twa:flex-shrink-0 twa:gap-1" },
68
+ React.createElement(Flex, { className: "twa:flex twa:box-border twa:items-center" },
69
+ React.createElement(ButtonApply, { className: `ab-${elementType}__BulkUpdate__apply twa:h-full`, onClick: () => this.onApplyClick(), style: applyStyle, tooltip: "Apply Bulk Update", disabled: valueOperationDisabled, accessLevel: this.props.accessLevel }, 'Apply')),
70
+ React.createElement(AdaptablePopover, { popoverMinWidth: 360, className: `ab-${elementType}__BulkUpdate__info`, headerText: "Preview Results", bodyText: [previewPanel], MessageType: infoStyle, useButton: true, showEvent: 'focus', hideEvent: "blur", disabled: valueSelectorDisabled || StringExtensions.IsNullOrEmpty(this.props.BulkUpdateValue) }))));
59
71
  }
60
72
  onColumnValueSelectedChanged(selectedColumnValue) {
61
73
  this.props.onBulkUpdateValueChange(selectedColumnValue);
@@ -17,11 +17,11 @@ export const isValidCalculatedColumnExpression = (data, api) => {
17
17
  const calculatedColumnExpressionService = api.internalApi.getCalculatedColumnExpressionService();
18
18
  const expression = api.expressionApi.getAdaptableQueryExpression(data.Query)?.trim();
19
19
  if (!expression) {
20
- return 'Calculated column expression cannot be empty';
20
+ return 'Calculated Column Expression cannot be empty';
21
21
  }
22
22
  const isValid = calculatedColumnExpressionService.isCalculatedColumnQueryValid(data.Query);
23
23
  if (!isValid) {
24
- return 'Calculated column expression is not valid';
24
+ return 'Calculated Column Expression is not valid';
25
25
  }
26
26
  return true;
27
27
  };
@@ -9,6 +9,7 @@ import * as InternalRedux from '../../Redux/ActionsReducers/InternalRedux';
9
9
  import { connect } from 'react-redux';
10
10
  import { Select } from '../../components/Select';
11
11
  import { Flex } from '../../components/Flex';
12
+ import clsx from 'clsx';
12
13
  class CellSummaryViewPanelComponent extends React.Component {
13
14
  cleanupEvent;
14
15
  constructor(props) {
@@ -44,30 +45,27 @@ class CellSummaryViewPanelComponent extends React.Component {
44
45
  });
45
46
  let cellSummaryPopover = React.createElement(CellSummaryPopover, { CellSummary: this.props.CellSummary });
46
47
  let shouldDisable = this.props.accessLevel == 'ReadOnly' || this.props.CellSummary == null;
47
- const renderOperationValue = () => {
48
- if (shouldDisable) {
49
- return;
50
- }
51
- const operationValue = this.getOperationValue();
52
- if (operationValue == undefined) {
53
- return;
54
- }
55
- return this.props.viewType === 'ToolPanel' ? (React.createElement(Flex, { className: `ab-${elementType}__CellSummary__value twa:rounded-standard twa:mr-2 twa:p-2 twa:text-text-on-info twa:bg-info twa:text-2` }, operationValue)) : (React.createElement(Flex, { justifyContent: "center", className: `ab-${elementType}__CellSummary__value twa:flex-1 twa:mr-2 twa:ml-1 text-text-on-primary` }, operationValue));
56
- };
57
- const elementType = this.props.viewType === 'Toolbar' ? 'DashboardToolbar' : 'ToolPanel';
58
- return (React.createElement(Flex, { flexDirection: "row", className: shouldDisable ? GeneralConstants.READ_ONLY_STYLE : `ab-${elementType}__CellSummary__wrap`, flexWrap: this.props.viewType === 'ToolPanel' ? 'wrap' : 'nowrap' },
48
+ const isToolbar = this.props.viewType === 'Toolbar';
49
+ const elementType = isToolbar ? 'DashboardToolbar' : 'ToolPanel';
50
+ const operationValue = this.getOperationValue() ?? 'N/A';
51
+ return (React.createElement(Flex, { className: clsx(shouldDisable ? GeneralConstants.READ_ONLY_STYLE : '', `ab-${elementType}__CellSummary__wrap twa:gap-2 twa:flex-row`, {
52
+ 'twa:min-w-[215px] twa:max-w-[215px] twa:w-[215px] twa:flex-nowrap': isToolbar,
53
+ 'twa:flex-1 twa:flex-wrap': !isToolbar,
54
+ }) },
59
55
  React.createElement(Flex, { className: "twa:flex-1" },
60
56
  React.createElement(Select, { "aria-label": "Cell Summary Operation Selector", className: `ab-${elementType}__CellSummary__select twa:w-full`, disabled: shouldDisable, options: [...operationMenuItems, ...operationDefinitions], onChange: (x) => this.props.onCellSummaryOperationChange(x), value: this.props.CellSummaryOperation })),
61
- React.createElement(Flex, { alignItems: "center", className: "twa:ml-2" }, React.createElement(React.Fragment, null,
62
- renderOperationValue(),
63
- this.props.CellSummary != null && this.props.CellSummary.Count > 0 && (React.createElement(AdaptablePopover, { popoverMaxWidth: 360, className: "ab-ToolPanel__CellSummary__info", bodyText: [cellSummaryPopover], useButton: true, showEvent: 'focus', hideEvent: "blur", tooltipText: 'Show Cell Summaries' }))))));
57
+ React.createElement(Flex, { className: "twa:items-center twa:gap-1" }, React.createElement(React.Fragment, null,
58
+ React.createElement(Flex, { className: clsx(`ab-${elementType}__CellSummary__value twa:min-w-[50px]`, {
59
+ 'twa:rounded-standard twa:text-color-text-on-info twa:bg-color-info twa:text-2': !isToolbar,
60
+ 'twa:flex-1 twa:text-color-text-on-primary twa:justify-center': isToolbar,
61
+ }) }, operationValue),
62
+ React.createElement(AdaptablePopover, { popoverMaxWidth: 360, className: "ab-ToolPanel__CellSummary__info", bodyText: [cellSummaryPopover], useButton: true, showEvent: 'focus', hideEvent: "blur", tooltipText: 'Show Cell Summaries', disabled: !this.props.CellSummary?.Count })))));
64
63
  }
65
64
  checkSelectedCells() {
66
65
  this.props.onCreateCellSummary();
67
66
  }
68
67
  getOperationValue() {
69
- const api = this.props.api;
70
- return api.cellSummaryApi.getCellSummaryOperationValue(this.props.CellSummaryOperation);
68
+ return this.props.api.cellSummaryApi.getCellSummaryOperationValue(this.props.CellSummaryOperation);
71
69
  }
72
70
  }
73
71
  function mapStateToProps(state, ownProps) {
@@ -8,7 +8,7 @@ const AdaptableDateInput = React.forwardRef(function AdaptableDateInputCmp(props
8
8
  const { value: _, defaultValue: __, onChange, required, disabled, showClearButton, ...inputProps } = props;
9
9
  const [value, setValue] = useProperty(props, 'value', undefined, {
10
10
  onChange: (dateString) =>
11
- // wrap date value in FormEvent in order to keep the external API unchanged
11
+ // wrap date value in ChangeEvent in order to keep the external API unchanged
12
12
  props.onChange?.({
13
13
  target: {
14
14
  // ALWAYS trigger onChange with the ISO format
@@ -2,6 +2,6 @@ import * as React from 'react';
2
2
  import SimpleButton from '../../../components/SimpleButton';
3
3
  export class ButtonApply extends React.Component {
4
4
  render() {
5
- return (React.createElement(SimpleButton, { "data-name": "apply", tooltip: "Apply", iconSize: 20, icon: "check", variant: "text", ...this.props }));
5
+ return (React.createElement(SimpleButton, { "data-name": "apply", tooltip: "Apply", iconSize: 20, icon: "check", variant: "outlined", ...this.props }));
6
6
  }
7
7
  }
@@ -3,6 +3,7 @@ import { SimpleButtonProps } from '../../../components/SimpleButton';
3
3
  export interface ClearButtonProps extends SimpleButtonProps {
4
4
  showText?: boolean;
5
5
  showIcon?: boolean;
6
+ variant?: SimpleButtonProps['variant'];
6
7
  }
7
8
  export declare class ButtonClear extends React.Component<ClearButtonProps, {}> {
8
9
  render(): React.JSX.Element;
@@ -2,8 +2,7 @@ import * as React from 'react';
2
2
  import * as Redux from 'redux';
3
3
  import { AccessLevel } from '../../../AdaptableState/Common/Entitlement';
4
4
  import { AdaptableSharedEntityConfig } from '../../../AdaptableState/TeamSharingState';
5
- import { AdaptableObject } from '../../../AdaptableState/Common/AdaptableObject';
6
- import { SuspendableObject } from '../../../AdaptableState/Common/SuspendableObject';
5
+ import { AdaptableObject, SuspendableObject } from '../../../AdaptableState/Common/AdaptableObject';
7
6
  export interface EntityListActionButtonsProps extends React.ClassAttributes<EntityListActionButtons> {
8
7
  editClick?: () => void;
9
8
  cloneClick?: () => void;
@@ -1,7 +1,6 @@
1
1
  import * as React from 'react';
2
- import { AdaptableObject } from '../../../../AdaptableState/Common/AdaptableObject';
2
+ import { AdaptableObject, SuspendableObject } from '../../../../AdaptableState/Common/AdaptableObject';
3
3
  import { AccessLevel } from '../../../../AdaptableState/Common/Entitlement';
4
- import { SuspendableObject } from '../../../../AdaptableState/Common/SuspendableObject';
5
4
  interface EntityListSuspendButtonProps {
6
5
  onSuspend: (adaptableObject: AdaptableObject) => void;
7
6
  onUnSuspend: (adaptableObject: AdaptableObject) => void;
@@ -1,13 +1,14 @@
1
1
  import * as React from 'react';
2
- import FieldWrap from '../../../components/FieldWrap';
2
+ import { useCallback } from 'react';
3
+ import DropdownButton from '../../../components/DropdownButton';
3
4
  import UIHelper from '../../UIHelper';
4
5
  import AdaptableInput from '../AdaptableInput';
5
6
  import { PermittedValuesSelector } from './PermittedValuesSelector';
6
- import { Select } from '../../../components/Select';
7
7
  import { useAdaptable } from '../../AdaptableContext';
8
- import { useCallback } from 'react';
9
8
  import clsx from 'clsx';
10
- import { Box } from '../../../components/Flex';
9
+ import { Box, Flex } from '../../../components/Flex';
10
+ import { Icon } from '../../../components/icons';
11
+ import { InputGroup } from '../../../components/InputGroup';
11
12
  export const BulkUpdateValueSelector = (props) => {
12
13
  const [valueType, setValueType] = React.useState('existing');
13
14
  const adaptable = useAdaptable();
@@ -17,8 +18,8 @@ export const BulkUpdateValueSelector = (props) => {
17
18
  // TODO = this seems to be called whenever we edit a cell
18
19
  // which is then triggering a get all values
19
20
  // not sure that we need to
20
- const permittedValueSelector = (React.createElement(Box, null,
21
- React.createElement(PermittedValuesSelector, { allowNewValues: true, searchable: 'inline', disabled: props.disabled || !props.selectedColumn, value: props.selectedColumnValue === '' ? null : props.selectedColumnValue, columnId: columnId, placeholder: isDateType ? 'Select' : 'Select or type new value', loadValues: useCallback(({ currentSearchValue }) => {
21
+ const permittedValueSelector = (React.createElement(Box, { className: 'twa:flex-1' },
22
+ React.createElement(PermittedValuesSelector, { allowNewValues: true, searchable: 'inline', disabled: props.disabled || !props.selectedColumn, value: props.selectedColumnValue === '' ? null : props.selectedColumnValue, columnId: columnId, placeholder: 'Select value', loadValues: useCallback(({ currentSearchValue }) => {
22
23
  if (!columnId || !props.selectedGridCells.length) {
23
24
  return Promise.resolve([]);
24
25
  }
@@ -41,16 +42,16 @@ export const BulkUpdateValueSelector = (props) => {
41
42
  : 'Enter Value', autoFocus: true, disabled: props.disabled, className: "twa:w-full", value: props.selectedColumnValue, onChange: (e) => {
42
43
  props.onColumnValueChange(e.target.value);
43
44
  } }));
44
- let valueTypeSelector = null;
45
- if (isDateType) {
46
- valueTypeSelector = (React.createElement(Select, { "aria-label": "Bulk Update Value Selector", options: [
47
- { label: 'New', value: 'new' },
48
- { label: 'Existing', value: 'existing' },
49
- ], value: valueType, onChange: (value) => {
50
- setValueType(value);
51
- } }));
52
- }
53
- return (React.createElement(FieldWrap, { className: clsx('twa:overflow-visible twa:max-w-full', props.className), style: props.style }, isDateType ? (React.createElement(React.Fragment, null,
54
- valueType === 'new' ? input : permittedValueSelector,
55
- valueTypeSelector)) : (permittedValueSelector)));
45
+ return (React.createElement(Flex, { className: clsx('twa:overflow-visible twa:max-w-full', props.className), style: props.style }, isDateType ? (React.createElement(React.Fragment, null,
46
+ React.createElement(InputGroup, { Component: Flex, "data-id": "bulk-update-input-wrapper", className: "twa:w-full" },
47
+ React.createElement(DropdownButton, { "aria-label": "Bulk Update Value Selector", "data-id": "bulk-update-value-type-selector", "data-value": valueType, columns: ['label'], variant: "outlined", tone: "neutral", items: [
48
+ { label: 'New', icon: React.createElement(Icon, { name: "edit" }), onClick: () => setValueType('new') },
49
+ {
50
+ label: 'Existing',
51
+ icon: React.createElement(Icon, { name: "grid" }),
52
+ onClick: () => setValueType('existing'),
53
+ },
54
+ ] },
55
+ React.createElement(React.Fragment, null, valueType === 'existing' ? React.createElement(Icon, { name: "grid" }) : React.createElement(Icon, { name: "edit" }))),
56
+ valueType === 'new' ? input : permittedValueSelector))) : (permittedValueSelector)));
56
57
  };
@@ -129,6 +129,14 @@ export const StyleComponent = (props) => {
129
129
  }
130
130
  setComponentStyle(newStyle);
131
131
  };
132
+ const onAlignmentChange = (alignment) => {
133
+ const newStyle = { ...componentStyle };
134
+ newStyle.Alignment = alignment;
135
+ if (alignment == 'Default') {
136
+ delete newStyle.Alignment;
137
+ }
138
+ setComponentStyle(newStyle);
139
+ };
132
140
  const Cmp = props.headless ? Box : Panel;
133
141
  const headerText = props.headerText ?? 'Style';
134
142
  const cmpProps = props.headless
@@ -216,7 +224,18 @@ export const StyleComponent = (props) => {
216
224
  ], value: componentStyle.FontSize?.toString() ?? '', onChange: (value) => onFontSizeChange(value) }))) : (React.createElement(Flex, { flexDirection: "row", alignItems: "center", className: "twa:gap-2 twa:flex-wrap" }, fontSizes.map((enumName) => {
217
225
  return (React.createElement(Radio, { onClick: () => onFontSizeChange(enumName), checked: (enumName == 'Default' && !componentStyle.FontSize) ||
218
226
  componentStyle.FontSize === enumName, key: enumName }, enumName));
219
- }))))))),
227
+ }))),
228
+ React.createElement("span", null, "Alignment"),
229
+ React.createElement(ToggleGroup, null,
230
+ React.createElement(Toggle, { icon: "align-left", pressed: componentStyle.Alignment === 'Left', onPressedChange: (pressed) => pressed
231
+ ? onAlignmentChange('Left')
232
+ : onAlignmentChange('Default') }),
233
+ React.createElement(Toggle, { icon: "align-center", pressed: componentStyle.Alignment === 'Center', onPressedChange: (pressed) => pressed
234
+ ? onAlignmentChange('Center')
235
+ : onAlignmentChange('Default') }),
236
+ React.createElement(Toggle, { icon: "align-right", pressed: componentStyle.Alignment === 'Right', onPressedChange: (pressed) => pressed
237
+ ? onAlignmentChange('Right')
238
+ : onAlignmentChange('Default') })))))),
220
239
  !props.hidePreview && (React.createElement(Card, { shadow: false },
221
240
  React.createElement(Card.Title, null, "Preview"),
222
241
  React.createElement(Card.Body, { className: "twa:grid twa:place-items-center" },
@@ -3,7 +3,8 @@ import { CustomSort } from '../../../AdaptableState/CustomSortState';
3
3
  export type CustomSortColumnWizardSectionProps = {
4
4
  onChange: (data: CustomSort) => void;
5
5
  isNew: boolean;
6
+ allCustomSorts: CustomSort[];
6
7
  };
7
8
  export declare const renderCustomSortColumn: (data: CustomSort) => React.JSX.Element;
8
- export declare const isValidCustomSortColumn: (data: CustomSort) => true | string;
9
+ export declare const isValidCustomSortColumn: (data: CustomSort, allCustomSorts: CustomSort[]) => true | string;
9
10
  export declare const CustomSortColumnWizardSection: (props: CustomSortColumnWizardSectionProps) => React.JSX.Element;
@@ -3,14 +3,26 @@ import { Tabs } from '../../../components/Tabs';
3
3
  import { Tag } from '../../../components/Tag';
4
4
  import { NewColumnSelector } from '../../Components/ColumnSelector';
5
5
  import { useOnePageAdaptableWizardContext } from '../../Wizard/OnePageAdaptableWizard';
6
- import { Box } from '../../../components/Flex';
6
+ import { Box, Flex } from '../../../components/Flex';
7
+ import FormLayout, { FormRow } from '../../../components/FormLayout';
8
+ import Input from '../../../components/Input';
7
9
  export const renderCustomSortColumn = (data) => {
8
10
  const { api } = useOnePageAdaptableWizardContext();
9
11
  return (React.createElement(Box, { className: "twa:text-2 twa:py-2 twa:pr-2" },
10
- "Custom sort column: ",
11
- React.createElement(Tag, null, api.columnApi.getFriendlyNameForColumnId(data.ColumnId))));
12
+ React.createElement(Tag, { className: "twa:mr-2" },
13
+ "Name: ",
14
+ data.Name),
15
+ React.createElement(Tag, null,
16
+ "Column: ",
17
+ api.columnApi.getFriendlyNameForColumnId(data.ColumnId))));
12
18
  };
13
- export const isValidCustomSortColumn = (data) => {
19
+ export const isValidCustomSortColumn = (data, allCustomSorts) => {
20
+ if (!data.Name) {
21
+ return 'Custom Sort Name cannot be blank';
22
+ }
23
+ if (allCustomSorts.some((customSort) => customSort.Name === data.Name && customSort.Uuid !== data.Uuid)) {
24
+ return 'A Custom Sort already exists with that name';
25
+ }
14
26
  if (!data.ColumnId) {
15
27
  return 'You have to select a Column for Custom Sort';
16
28
  }
@@ -42,14 +54,28 @@ export const CustomSortColumnWizardSection = (props) => {
42
54
  });
43
55
  });
44
56
  }, []);
45
- return (React.createElement(Tabs, { style: { height: '100%' } },
46
- React.createElement(Tabs.Tab, null, "Column"),
47
- React.createElement(Tabs.Content, null,
48
- React.createElement(NewColumnSelector, { availableColumns: sortableCols, selected: data.ColumnId ? [data.ColumnId] : [], singleSelect: true, onChange: (ids) => {
49
- props.onChange({
50
- ...data,
51
- SortedValues: [],
52
- ColumnId: ids[0],
53
- });
54
- }, allowReorder: false }))));
57
+ const onNameChange = (event) => {
58
+ props.onChange({
59
+ ...data,
60
+ Name: event.target.value,
61
+ });
62
+ };
63
+ return (React.createElement(Flex, { flexDirection: "column", style: { height: '100%' } },
64
+ React.createElement(Tabs, { className: "twa:mb-3" },
65
+ React.createElement(Tabs.Tab, null, "Settings"),
66
+ React.createElement(Tabs.Content, null,
67
+ React.createElement(Flex, { flexDirection: "row" },
68
+ React.createElement(FormLayout, { className: "twa:max-w-[300px] twa:w-full" },
69
+ React.createElement(FormRow, { label: "Name" },
70
+ React.createElement(Input, { className: "twa:w-full", "data-name": "custom-sort-name", onChange: onNameChange, value: data?.Name ?? '' })))))),
71
+ React.createElement(Tabs, { style: { flex: 1, minHeight: 0 } },
72
+ React.createElement(Tabs.Tab, null, "Column"),
73
+ React.createElement(Tabs.Content, null,
74
+ React.createElement(NewColumnSelector, { availableColumns: sortableCols, selected: data.ColumnId ? [data.ColumnId] : [], singleSelect: true, onChange: (ids) => {
75
+ props.onChange({
76
+ ...data,
77
+ SortedValues: [],
78
+ ColumnId: ids[0],
79
+ });
80
+ }, allowReorder: false })))));
55
81
  };
@@ -37,14 +37,14 @@ export const CustomSortWizard = (props) => {
37
37
  };
38
38
  return (React.createElement(OnePageAdaptableWizard, { defaultCurrentSectionName: props.defaultCurrentSectionName, moduleInfo: props.moduleInfo, data: customSort, onFinish: handleFinish, onHide: props.onCloseWizard, sections: [
39
39
  {
40
- isValid: isValidCustomSortColumn,
40
+ isValid: (data) => isValidCustomSortColumn(data, allCustomSorts),
41
41
  renderSummary: renderCustomSortColumn,
42
- details: 'Select a Column for Custom Sort',
42
+ details: 'Enter Name and select a Column for Custom Sort',
43
43
  render: () => {
44
44
  return (React.createElement(Box, { className: "twa:p-2 twa:h-full" },
45
- React.createElement(CustomSortColumnWizardSection, { isNew: props.isNew, onChange: setCustomSort })));
45
+ React.createElement(CustomSortColumnWizardSection, { isNew: props.isNew, onChange: setCustomSort, allCustomSorts: allCustomSorts })));
46
46
  },
47
- title: 'Column',
47
+ title: 'Name & Column',
48
48
  },
49
49
  {
50
50
  title: 'Sort Order',
@@ -69,18 +69,17 @@ class DashboardPopupComponent extends React.Component {
69
69
  React.createElement(Flex, { flexDirection: "column", className: "twa:h-full twa:gap-4" },
70
70
  areDashboardSettingsVisible && (React.createElement(React.Fragment, null,
71
71
  React.createElement(Card, null,
72
- React.createElement(Card.Title, { gap: 8 },
73
- "Display Settings",
74
- React.createElement(ToggleButton, { className: "twa:self-end", onChange: (visible) => this.props.onSetDashboardHidden(!visible), checked: !this.props.IsHidden, "data-name": "dashboard-visibility" }, this.props.IsHidden ? 'Hidden' : 'Visible')),
72
+ React.createElement(Card.Title, { gap: 8 }, "Display Settings"),
75
73
  React.createElement(Card.Body, { gap: 2, className: "twa:p-2" },
76
- React.createElement(ToggleButton, { disabled: this.props.IsFloating, className: "twa:w-24", onChange: (expanded) => this.props.onSetDashboardCollapsed(!expanded), checked: !this.props.IsCollapsed, "data-name": "expand-state" }, this.props.IsCollapsed ? 'Collapsed' : 'Expanded'),
74
+ React.createElement(ToggleButton, { className: "twa:w-24", onChange: (visible) => this.props.onSetDashboardHidden(!visible), checked: !this.props.IsHidden, "data-name": "dashboard-visibility" }, this.props.IsHidden ? 'Hidden' : 'Visible'),
75
+ this.props.DashboardState.Tabs?.length > 0 ? (React.createElement(ToggleButton, { disabled: this.props.IsFloating, className: "twa:w-24", onChange: (expanded) => this.props.onSetDashboardCollapsed(!expanded), checked: !this.props.IsCollapsed, "data-name": "expand-state" }, this.props.IsCollapsed ? 'Collapsed' : 'Expanded')) : null,
77
76
  this.props.api.optionsApi.getDashboardOptions().canFloat ? (React.createElement(ToggleButton, { className: "twa:w-24", onChange: (pinned) => this.props.onSetDashboardFloating(!pinned), checked: !this.props.IsFloating, "data-name": "floating" }, this.props.IsFloating ? 'Floating' : 'Pinned')) : null)))),
78
77
  React.createElement(Card, { className: "twa:flex-1 twa:overflow-hidden", gap: 0 },
79
78
  React.createElement(Card.Title, null, "Contents"),
80
79
  React.createElement(Card.Body, { className: "twa:p-2" },
81
80
  React.createElement(Tabs, { className: "twa:flex-1 twa:min-h-0" },
82
81
  React.createElement(Tabs.Tab, { value: "pinned-toolbars" }, "Pinned Toolbars"),
83
- React.createElement(Tabs.Tab, { value: "tabbed-toolbars" }, "Tabbed Toolbars"),
82
+ React.createElement(Tabs.Tab, { value: "tabbed-toolbars" }, "Tabs & Toolbars"),
84
83
  React.createElement(Tabs.Tab, { value: "buttons" }, "Buttons"),
85
84
  React.createElement(Tabs.Content, { value: "pinned-toolbars", className: contentCls },
86
85
  React.createElement(PinnedToolbarsSelector, null)),
@@ -160,6 +160,7 @@ const buildAdaptableOptions = (mainAdaptableInstance, adaptableContainerId, agGr
160
160
  Revision: Date.now(),
161
161
  FormatColumns: [
162
162
  {
163
+ Name: 'Changed At',
163
164
  Scope: {
164
165
  ColumnIds: ['changeInfo.changedAt'],
165
166
  },
@@ -12,7 +12,7 @@ export const ExportDestinationPicker = ({ reportName, reportFormat, viewType, })
12
12
  };
13
13
  const supportedDestinations = exportApi.getSupportedExportDestinations(reportFormat);
14
14
  if (supportedDestinations.length === 0 || supportedDestinations.length === 1) {
15
- return (React.createElement(ButtonExport, { className: clsx(viewType !== 'StatusBar' ? 'twa:mr-[20px]' : undefined, 'twa:pr-0'), onClick: () => handleExport(supportedDestinations[0]), tooltip: "Export Report", disabled: reportName == undefined || reportFormat == undefined }));
15
+ return (React.createElement(ButtonExport, { className: clsx(viewType !== 'StatusBar' ? '' : undefined, ''), onClick: () => handleExport(supportedDestinations[0]), tooltip: "Export Report", disabled: reportName == undefined || reportFormat == undefined }));
16
16
  }
17
17
  const destinationItems = supportedDestinations.map((destination) => ({
18
18
  label: destination,
@@ -4,13 +4,15 @@ import { ReportNameSelector } from './ReportNameSelector';
4
4
  import { ReportFormatSelector } from './ReportFormatSelector';
5
5
  import { ExportDestinationPicker } from './ExportDestinationPicker';
6
6
  import { useAdaptable } from '../AdaptableContext';
7
+ import { Flex } from '../../components/Flex';
7
8
  export const ExportStatusBar = () => {
8
9
  const adaptable = useAdaptable();
9
10
  const exportApi = adaptable.api.exportApi;
10
11
  const currentReportName = useSelector((state) => state.Export.CurrentReport);
11
12
  const currentFormat = useSelector((state) => state.Export.CurrentFormat);
12
13
  return (React.createElement(React.Fragment, null,
13
- React.createElement(ReportNameSelector, { viewType: "StatusBar", size: 'small', reportName: currentReportName, onReportNameSelected: (reportName) => exportApi.selectReport(reportName) }),
14
- React.createElement(ReportFormatSelector, { viewType: "StatusBar", size: 'small', reportName: currentReportName, reportFormat: currentFormat, onReportFormatSelected: (reportFormat) => exportApi.selectFormat(reportFormat) }),
14
+ React.createElement(Flex, { className: "twa:gap-1" },
15
+ React.createElement(ReportNameSelector, { viewType: "StatusBar", reportName: currentReportName, onReportNameSelected: (reportName) => exportApi.selectReport(reportName) }),
16
+ React.createElement(ReportFormatSelector, { viewType: "StatusBar", reportName: currentReportName, reportFormat: currentFormat, onReportFormatSelected: (reportFormat) => exportApi.selectFormat(reportFormat) })),
15
17
  React.createElement(ExportDestinationPicker, { viewType: "StatusBar", reportName: currentReportName, reportFormat: currentFormat })));
16
18
  };