@adaptabletools/adaptable 22.0.10 → 22.1.0-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 (71) hide show
  1. package/index.css +33 -1
  2. package/index.css.map +1 -1
  3. package/package.json +3 -4
  4. package/src/AdaptableState/Common/AdaptablePredicate.js +1 -1
  5. package/src/AdaptableState/InitialState.d.ts +2 -2
  6. package/src/AdaptableState/LayoutState.d.ts +47 -0
  7. package/src/Api/CalendarApi.d.ts +15 -0
  8. package/src/Api/ColumnScopeApi.d.ts +5 -0
  9. package/src/Api/DataChangeHistoryApi.d.ts +7 -2
  10. package/src/Api/Implementation/CalendarApiImpl.d.ts +3 -0
  11. package/src/Api/Implementation/CalendarApiImpl.js +10 -0
  12. package/src/Api/Implementation/ColumnScopeApiImpl.d.ts +1 -0
  13. package/src/Api/Implementation/ColumnScopeApiImpl.js +12 -0
  14. package/src/Api/Implementation/DataChangeHistoryApiImpl.d.ts +2 -1
  15. package/src/Api/Implementation/DataChangeHistoryApiImpl.js +7 -0
  16. package/src/Api/Implementation/LayoutHelpers.js +12 -0
  17. package/src/Api/Internal/AlertInternalApi.js +4 -1
  18. package/src/Api/Internal/FormatColumnInternalApi.js +3 -3
  19. package/src/Strategy/FlashingCellModule.js +1 -0
  20. package/src/Strategy/PlusMinusModule.js +3 -3
  21. package/src/Utilities/Constants/GeneralConstants.js +2 -1
  22. package/src/Utilities/ExpressionFunctions/booleanExpressionFunctions.d.ts +1 -1
  23. package/src/Utilities/ExpressionFunctions/booleanExpressionFunctions.js +41 -2
  24. package/src/Utilities/ExpressionFunctions/scalarExpressionFunctions.d.ts +1 -1
  25. package/src/Utilities/ExpressionFunctions/scalarExpressionFunctions.js +31 -2
  26. package/src/Utilities/Helpers/AdaptableHelper.js +30 -4
  27. package/src/Utilities/Services/Interface/IQueryLanguageService.d.ts +1 -0
  28. package/src/Utilities/Services/MetamodelService.js +18 -18
  29. package/src/Utilities/Services/QueryLanguageService.d.ts +2 -0
  30. package/src/Utilities/Services/QueryLanguageService.js +20 -8
  31. package/src/Utilities/Services/ValidationService.js +3 -1
  32. package/src/View/Components/EntityRulesEditor/index.js +1 -1
  33. package/src/View/Components/ModuleValueSelector/index.js +9 -1
  34. package/src/View/Components/ReorderDraggable/index.js +22 -36
  35. package/src/View/Components/ValueSelector/index.js +46 -50
  36. package/src/View/Dashboard/PinnedToolbarsSelector.js +1 -1
  37. package/src/View/Layout/Wizard/LayoutWizard.js +16 -1
  38. package/src/View/Layout/Wizard/sections/RowSelectionSection.d.ts +8 -0
  39. package/src/View/Layout/Wizard/sections/RowSelectionSection.js +141 -0
  40. package/src/View/NamedQuery/Wizard/NamedQuerySettingsWizardSection.js +0 -1
  41. package/src/agGrid/AdaptableAgGrid.js +10 -0
  42. package/src/components/Dashboard/Dashboard.js +1 -1
  43. package/src/components/DragAndDropContext/ModuleManager.d.ts +1 -0
  44. package/src/components/DragAndDropContext/ModuleManager.js +12 -37
  45. package/src/components/DragAndDropContext/TabList.d.ts +11 -6
  46. package/src/components/DragAndDropContext/TabList.js +78 -36
  47. package/src/components/DragAndDropContext/UnusedPanel.js +10 -21
  48. package/src/components/ExpressionEditor/BaseEditorInput.d.ts +2 -0
  49. package/src/components/ExpressionEditor/BaseEditorInput.js +4 -0
  50. package/src/components/ExpressionEditor/EditorInput.d.ts +3 -1
  51. package/src/components/ExpressionEditor/EditorInput.js +20 -9
  52. package/src/components/ExpressionEditor/QueryBuilder/QueryBuilder.d.ts +2 -1
  53. package/src/components/ExpressionEditor/QueryBuilder/QueryBuilder.js +3 -12
  54. package/src/components/ExpressionEditor/QueryBuilder/QueryPredicateBuilder.js +17 -19
  55. package/src/components/ExpressionEditor/index.d.ts +2 -1
  56. package/src/components/ExpressionEditor/index.js +1 -1
  57. package/src/components/Tree/TreeDropdown/index.js +38 -27
  58. package/src/components/dnd/index.d.ts +3 -13
  59. package/src/components/dnd/index.js +4 -55
  60. package/src/env.js +2 -2
  61. package/src/layout-manager/src/LayoutManagerModel.d.ts +2 -1
  62. package/src/layout-manager/src/index.d.ts +9 -0
  63. package/src/layout-manager/src/index.js +97 -1
  64. package/src/layout-manager/src/normalizeLayoutModel.js +8 -0
  65. package/src/layout-manager/src/simplifyLayoutModel.js +6 -0
  66. package/src/metamodel/adaptable-metamodel-model.d.ts +22 -13
  67. package/src/metamodel/adaptable.metamodel.d.ts +3773 -5143
  68. package/src/metamodel/adaptable.metamodel.js +1 -1
  69. package/src/parser/src/parser.js +55 -1218
  70. package/src/parser/src/types.d.ts +5 -0
  71. package/tsconfig.esm.tsbuildinfo +1 -1
@@ -1,65 +1,107 @@
1
1
  import * as React from 'react';
2
- import { Draggable, Droppable } from '../dnd';
2
+ import { defaultDragProxyMove, DragList } from '../dnd';
3
3
  import { Icon } from '../icons';
4
4
  import SimpleButton from '../SimpleButton';
5
5
  import { DragAndDropContext } from './DragAndDropContext';
6
6
  import { Box, Flex } from '../Flex';
7
- export function TabList({ tabs, onRemoveTab, onRemoveToolbar, onChangeTabName, disabled, onNewTab, }) {
8
- return (React.createElement(Droppable, { droppableId: "MAIN", type: "TAB", direction: "horizontal" }, (provided) => (React.createElement("div", { ...provided.droppableProps, className: "ab-ModuleSelector__TabList twa:flex twa:flex-1 twa:overflow-auto", ref: provided.innerRef, "data-name": "dashboard-tabs" },
9
- tabs.map((tab, tabIndex) => (React.createElement(TabItem, { disabled: disabled, key: tabIndex, tabIndex: tabIndex, tab: tab, onRemove: () => onRemoveTab(tabIndex), onRemoveToolbar: (toolbarIndex) => onRemoveToolbar(tabIndex, toolbarIndex), onChangeTabName: (tabName) => onChangeTabName(tabIndex, tabName) }))),
7
+ import clsx from 'clsx';
8
+ export function TabList({ tabs, onTabsChange, onRemoveTab, onRemoveToolbar, onChangeTabName, disabled, onNewTab, }) {
9
+ const tabIdsRef = React.useRef(new WeakMap());
10
+ const nextTabIdRef = React.useRef(0);
11
+ const getTabStableId = React.useCallback((tab) => {
12
+ const existingId = tabIdsRef.current.get(tab);
13
+ if (existingId) {
14
+ return existingId;
15
+ }
16
+ const newId = `dashboard-tab-${String(nextTabIdRef.current++)}`;
17
+ tabIdsRef.current.set(tab, newId);
18
+ return newId;
19
+ }, []);
20
+ return (React.createElement(DragList, { dragListId: "TABS", orientation: "horizontal", dragStrategy: "proxy", preserveDragSpace: true, onDragProxyMove: defaultDragProxyMove, onDrop: (sortedIndexes) => {
21
+ const newTabs = sortedIndexes.map((i) => tabs[i]);
22
+ onTabsChange(newTabs);
23
+ } }, (listDomProps) => (React.createElement("div", { ...listDomProps, className: clsx('ab-ModuleSelector__TabList twa:flex twa:flex-1 twa:overflow-auto', listDomProps.className), "data-name": "dashboard-tabs" },
24
+ tabs.map((tab, tabIndex) => {
25
+ const tabId = getTabStableId(tab);
26
+ return (React.createElement(TabItem, { disabled: disabled, key: tabIndex, tabId: tabId, tabIndex: tabIndex, tabs: tabs, onTabsChange: onTabsChange, tab: tab, onRemove: () => onRemoveTab(tabIndex), onRemoveToolbar: (toolbarIndex) => onRemoveToolbar(tabIndex, toolbarIndex), onChangeTabName: (tabName) => onChangeTabName(tabIndex, tabName) }));
27
+ }),
10
28
  !disabled && onNewTab ? (React.createElement(Flex, { alignItems: "center", justifyContent: "center", className: "ab-ModuleSelector__TabItem twa:min-w-32 twa:border-dashed twa:cursor-pointer twa:bg-primarylight twa:text-primary-foreground twa:hover:bg-primary", onClick: onNewTab },
11
29
  React.createElement("div", { className: "twa:text-8 twa:flex twa:flex-col twa:gap-4 twa:items-center twa:italic" },
12
30
  React.createElement(Icon, { name: "plus", size: 32 }),
13
- "Click to add tab"))) : null,
14
- provided.placeholder))));
31
+ "Click to add tab"))) : null))));
15
32
  }
16
- export function TabItem({ tab, tabIndex, onRemove, onRemoveToolbar, onChangeTabName, disabled, }) {
33
+ export function TabItem({ tab, tabId, tabIndex, tabs, onTabsChange, onRemove, onRemoveToolbar, onChangeTabName, disabled, }) {
17
34
  const context = React.useContext(DragAndDropContext);
18
35
  const isDragDisabled = disabled || !context.permittedActions.dragAndDropTab;
19
- return (React.createElement(Draggable, { isDragDisabled: isDragDisabled, draggableId: String(tabIndex), index: tabIndex }, (provided) => {
36
+ return (React.createElement(DragList.DraggableItem, { dragListId: "TABS", id: tabId }, (itemDomProps) => {
37
+ const { onPointerDown, ...restDomProps } = itemDomProps;
20
38
  let showHeader = true;
21
39
  if (tab.Name === '' &&
22
40
  !context.permittedActions.editTabName &&
23
41
  !context.permittedActions.deleteTab) {
24
42
  showHeader = false;
25
43
  }
26
- return (React.createElement("div", { className: "ab-ModuleSelector__TabItem twa:min-w-32", "data-name": "dashboard-tab", ref: provided.innerRef, ...provided.draggableProps, style: {
27
- ...(isDragDisabled ? {} : provided.draggableProps.style),
28
- } },
44
+ return (React.createElement("div", { ...restDomProps, className: clsx('twa:bg-defaultbackground', 'twa:select-none', 'ab-ModuleSelector__TabItem twa:min-w-32', restDomProps.className), "data-name": "dashboard-tab" },
29
45
  showHeader ? (React.createElement("div", { className: "ab-ModuleSelector__TabItem__header" },
30
- React.createElement("div", { ...(disabled ? {} : provided.dragHandleProps), style: context.permittedActions.dragAndDropTab
31
- ? {}
32
- : {
33
- display: 'none',
34
- } },
46
+ React.createElement("div", { ...(!isDragDisabled ? { onPointerDown } : {}), style: context.permittedActions.dragAndDropTab ? {} : { display: 'none' } },
35
47
  React.createElement(Icon, { name: "drag" })),
36
48
  context.permittedActions.editTabName ? (React.createElement("input", { className: "ab-ModuleSelector__TabItem__header-input", type: "text", disabled: disabled, value: tab.Name, onChange: (event) => {
37
49
  onChangeTabName(event.target.value);
38
50
  } })) : (tab.Name),
39
51
  context.permittedActions.deleteTab && (React.createElement(SimpleButton, { disabled: disabled, icon: "delete", variant: "text", onClick: onRemove })))) : null,
40
- React.createElement(ToolbarList, { disabled: disabled, toolbars: tab.Items, droppableId: String(tabIndex), onRemove: onRemoveToolbar })));
52
+ React.createElement(ToolbarList, { disabled: disabled, toolbars: tab.Items, tabIndex: tabIndex, tabs: tabs, onTabsChange: onTabsChange, onRemove: onRemoveToolbar })));
41
53
  }));
42
54
  }
43
- export function ToolbarList({ toolbars, droppableId, onRemove, disabled, }) {
44
- return (React.createElement(Droppable, { droppableId: droppableId, type: "TOOLBAR" }, (provided, snapshot) => (React.createElement(Box, { className: "ab-ModuleSelector__ToolbarList", ref: provided.innerRef, ...(disabled ? {} : provided.droppableProps), "data-name": "dashboard-toolbar-drop-target", style: {
45
- backgroundColor: snapshot.isDraggingOver
46
- ? 'var(--ab-dashboard-tab-drop-target__background)'
47
- : '',
48
- } },
49
- toolbars?.map((toolbar, toolbarIndex) => (React.createElement(ToolbarItem, { disabled: disabled, key: toolbar, toolbar: toolbar, toolbarIndex: toolbarIndex, onRemove: () => onRemove(toolbarIndex) }))),
50
- toolbars.length === 0 ? (React.createElement("div", { className: "ab-ModuleSelector__ToolbarList__placeholder twa:flex twa:items-center twa:justify-center twa:h-full twa:italic twa:text-center" }, "Drag and drop toolbar here")) : null,
51
- provided.placeholder))));
55
+ export function ToolbarList({ toolbars, tabIndex, tabs, onTabsChange, onRemove, disabled, }) {
56
+ const acceptDropsFrom = React.useMemo(() => {
57
+ const sources = ['UNUSED'];
58
+ tabs.forEach((_, i) => {
59
+ if (i !== tabIndex)
60
+ sources.push(String(i));
61
+ });
62
+ return sources;
63
+ }, [tabIndex, tabs]);
64
+ return (React.createElement(DragList, { dragListId: String(tabIndex), orientation: "vertical", acceptDropsFrom: [...acceptDropsFrom, String(tabIndex)], onDragProxyMove: defaultDragProxyMove,
65
+ // this is called when reordering inside the same list
66
+ onDrop: (sortedIndexes) => {
67
+ const newItems = sortedIndexes.map((i) => toolbars[i]);
68
+ onTabsChange(tabs.map((t, i) => (i === tabIndex ? { ...t, Items: newItems } : t)));
69
+ }, shouldAcceptDrop: ({ dragItem, dragSourceListId }) => {
70
+ const dragItemId = dragItem.id;
71
+ // if the tab contains an item with the same id, don't accept the drop
72
+ if (dragSourceListId != String(tabIndex) && tabs[tabIndex].Items.includes(dragItemId)) {
73
+ return false;
74
+ }
75
+ return true;
76
+ },
77
+ // this is called when dropping an item from a different list
78
+ onAcceptDrop: ({ dragItemId, dragSourceListId, dropIndex }) => {
79
+ const newTabs = tabs.map((tab, i) => {
80
+ let items = [...tab.Items];
81
+ if (dragSourceListId !== 'UNUSED' && i === Number(dragSourceListId)) {
82
+ items = items.filter((item) => item !== dragItemId);
83
+ }
84
+ if (i === tabIndex) {
85
+ items.splice(dropIndex, 0, dragItemId);
86
+ }
87
+ return { ...tab, Items: items };
88
+ });
89
+ onTabsChange(newTabs);
90
+ } }, (listDomProps, context) => (React.createElement(Box, { ...listDomProps, className: clsx('ab-ModuleSelector__ToolbarList', listDomProps.className, {
91
+ 'twa:bg-(--ab-dashboard-tab-drop-target__background) ab-ModuleSelector__ToolbarList--accent-drop': context.dropTargetListId === String(tabIndex) && context.status === 'accepted',
92
+ 'twa:bg-error/30 ab-ModuleSelector__ToolbarList--reject-drop': context.dropTargetListId === String(tabIndex) && context.status === 'rejected',
93
+ }), "data-name": "dashboard-toolbar-drop-target" },
94
+ toolbars?.map((toolbar, toolbarIndex) => (React.createElement(ToolbarItem, { disabled: disabled, key: toolbar, toolbar: toolbar, onRemove: () => onRemove(toolbarIndex) }))),
95
+ toolbars.length === 0 ? (React.createElement("div", { className: "ab-ModuleSelector__ToolbarList__placeholder twa:flex twa:items-center twa:justify-center twa:h-full twa:italic twa:text-center" }, "Drag and drop toolbar here")) : null))));
52
96
  }
53
- export function ToolbarItem({ toolbar, toolbarIndex, onRemove, disabled, }) {
97
+ export function ToolbarItem({ toolbar, onRemove, disabled, }) {
54
98
  const { availableItems } = React.useContext(DragAndDropContext);
55
- let currentItem = availableItems.find((t) => t.Id === toolbar);
99
+ const currentItem = availableItems.find((t) => t.Id === toolbar);
56
100
  const title = currentItem ? currentItem.Title : toolbar;
57
- return (React.createElement(Draggable, { isDragDisabled: disabled, draggableId: toolbar, index: toolbarIndex }, (provided, snapshot) => (React.createElement(Flex, { className: `ab-ModuleSelector__ToolbarItem twa:mb-1 twa:pl-1`, alignItems: "center", ref: provided.innerRef, ...provided.draggableProps, ...provided.dragHandleProps, style: {
58
- ...provided.draggableProps.style,
59
- backgroundColor: snapshot.isDragging
60
- ? 'var(--ab-dashboard-toolbar-drag__background)'
61
- : 'var(--ab-color-primarylight)',
62
- } },
63
- React.createElement("div", { className: "twa:flex-1" }, title),
64
- React.createElement(SimpleButton, { disabled: disabled, icon: "close", variant: "text", className: "twa:p-1", onClick: onRemove })))));
101
+ return (React.createElement(DragList.DraggableItem, { id: toolbar }, (itemDomProps) => {
102
+ const { onPointerDown, ...restDomProps } = itemDomProps;
103
+ return (React.createElement(Flex, { ...restDomProps, ...(disabled ? {} : { onPointerDown }), className: clsx('ab-ModuleSelector__ToolbarItem twa:mb-1 twa:pl-1 twa:text-3', 'twa:bg-primarylight', restDomProps.className), alignItems: "center" },
104
+ React.createElement("div", { className: "twa:flex-1" }, title),
105
+ React.createElement(SimpleButton, { disabled: disabled, icon: "close", variant: "text", className: "twa:p-1", onClick: onRemove })));
106
+ }));
65
107
  }
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { Draggable, Droppable } from '../dnd';
2
+ import { defaultDragProxyMove, DragList } from '../dnd';
3
3
  import { DragAndDropContext } from './DragAndDropContext';
4
4
  import { Box } from '../Flex';
5
5
  import clsx from 'clsx';
@@ -12,29 +12,18 @@ export function UnusedPanel({ items, disabled, title, dragItemText, }) {
12
12
  ")"),
13
13
  React.createElement(UnusedItemList, { disabled: disabled, items: items })));
14
14
  }
15
+ const EMPTY_ARRAY = [];
15
16
  function UnusedItemList({ items, disabled }) {
16
- return (React.createElement(Droppable, { droppableId: "UNUSED", type: "TOOLBAR", isDropDisabled: true, direction: "horizontal" }, (provided) => (React.createElement("div", { ref: provided.innerRef, "data-name": "unusedpanel-items-list", ...provided.droppableProps, className: 'twa:px-2 twa:flex-wrap twa:flex twa:flex-row twa:gap-1' },
17
- items.map((unusedItem, unusedItemIndex) => (React.createElement(UnusedItem, { disabled: disabled, key: unusedItem, unusedItem: unusedItem, unusedItemIndex: unusedItemIndex }))),
18
- provided.placeholder))));
17
+ return (React.createElement(DragList, { dragStrategy: "proxy", preserveDragSpace: true, dragListId: "UNUSED", orientation: "horizontal", onDragProxyMove: defaultDragProxyMove, acceptDropsFrom: EMPTY_ARRAY, onDragProxySetup: ({ proxyElement }) => {
18
+ proxyElement.classList.add('twa:shadow-md');
19
+ }, onDrop: () => { } }, (listDomProps) => (React.createElement("div", { ...listDomProps, "data-name": "unusedpanel-items-list", className: clsx('twa:px-2 twa:flex-wrap twa:flex twa:flex-row twa:gap-1', listDomProps.className) }, items.map((unusedItem) => (React.createElement(UnusedItem, { disabled: disabled, key: unusedItem, unusedItem: unusedItem })))))));
19
20
  }
20
- function UnusedItem({ unusedItem, unusedItemIndex, disabled, }) {
21
+ function UnusedItem({ unusedItem, disabled }) {
21
22
  const { availableItems } = React.useContext(DragAndDropContext);
22
- let currentItem = availableItems.find((t) => t.Id === unusedItem);
23
+ const currentItem = availableItems.find((t) => t.Id === unusedItem);
23
24
  const title = currentItem ? currentItem.Title : unusedItem;
24
- return (React.createElement(Draggable, { isDragDisabled: disabled, draggableId: unusedItem, index: unusedItemIndex }, (provided, snapshot) => {
25
- const eventHandlers = disabled
26
- ? {}
27
- : {
28
- ...provided.draggableProps,
29
- ...provided.dragHandleProps,
30
- };
31
- const dragStyle = disabled ? {} : provided.draggableProps.style;
32
- return (React.createElement("div", { "data-name": "unused-item", ref: provided.innerRef, ...eventHandlers, className: clsx('twa:rounded-md twa:text-sm twa:text-text-on-primary twa:p-2'), style: {
33
- ...dragStyle,
34
- border: '1px solid var(--ab-color-primary)',
35
- backgroundColor: snapshot.isDragging
36
- ? 'var(--ab-dashboard-toolbar-drag__background)'
37
- : 'var(--ab-color-primary)',
38
- } }, title));
25
+ return (React.createElement(DragList.DraggableItem, { id: unusedItem }, (itemDomProps) => {
26
+ const { onPointerDown, ...restDomProps } = itemDomProps;
27
+ return (React.createElement("div", { "data-name": "unused-item", ...restDomProps, ...(disabled ? {} : { onPointerDown }), className: clsx('twa:rounded-md twa:text-sm twa:text-text-on-primary twa:p-2 twa:select-none', 'twa:bg-primary', restDomProps.className) }, title));
39
28
  }));
40
29
  }
@@ -2,6 +2,7 @@ import * as React from 'react';
2
2
  import { ExpressionFunction, ExpressionFunctionMap } from '../../parser/src/types';
3
3
  import { AdaptableApi } from '../../Api/AdaptableApi';
4
4
  import { CSSProperties } from 'react';
5
+ import { ColumnScope } from '../../types';
5
6
  interface BaseEditorInputProps {
6
7
  type: 'main' | 'secondary';
7
8
  value: string;
@@ -16,6 +17,7 @@ interface BaseEditorInputProps {
16
17
  hideResultPreview?: boolean;
17
18
  api: AdaptableApi;
18
19
  style?: CSSProperties;
20
+ columnScope?: ColumnScope;
19
21
  }
20
22
  export interface OperatorEditorButton {
21
23
  functionName: string;
@@ -202,6 +202,9 @@ export function BaseEditorInput(props) {
202
202
  // clone the class instance to still keep the prototype methods
203
203
  return Object.assign(Object.create(Object.getPrototypeOf(firstRowNode)), firstRowNode);
204
204
  }, []);
205
+ const scopeColumnId = useMemo(() => {
206
+ return props.api.columnScopeApi.getAnyColumnIdForScope(props.columnScope);
207
+ }, [props.columnScope]);
205
208
  try {
206
209
  // explicitly parsing & evaluating the expression because we need full control of the resulted AST
207
210
  const expr = parser.parse(props.value || '');
@@ -218,6 +221,7 @@ export function BaseEditorInput(props) {
218
221
  functions: expressionFunctions,
219
222
  evaluateCustomQueryVariable: props.api.internalApi.getQueryLanguageService().evaluateCustomQueryVariable,
220
223
  dataChangedEvent,
224
+ columnScope: scopeColumnId,
221
225
  ...props.api.internalApi.buildBaseContext(),
222
226
  });
223
227
  }
@@ -1,14 +1,16 @@
1
1
  import * as React from 'react';
2
2
  import { AdaptableApi } from '../../Api/AdaptableApi';
3
3
  import { AdaptableModule } from '../../AdaptableState/Common/Types';
4
+ import { ColumnScope } from '../../AdaptableState/Common/ColumnScope';
4
5
  interface EditorInputProps {
5
6
  type: 'boolean' | 'scalar' | 'aggregatedScalar' | 'cumulativeAggregatedScalar' | 'quantileAggregatedScalar';
6
7
  module: AdaptableModule;
7
8
  value: string;
8
9
  onChange: (value: string) => void;
10
+ api: AdaptableApi;
9
11
  testData: any;
10
12
  isFullExpression?: boolean;
11
- api: AdaptableApi;
13
+ columnScope?: ColumnScope;
12
14
  }
13
15
  declare function EditorInput(props: EditorInputProps): React.JSX.Element;
14
16
  export default EditorInput;
@@ -38,15 +38,26 @@ function EditorInput(props) {
38
38
  }, {});
39
39
  };
40
40
  const expressionFunctions = useMemo(() => {
41
- return props.type === 'aggregatedScalar' ||
41
+ if (props.type === 'aggregatedScalar' ||
42
42
  props.type === 'cumulativeAggregatedScalar' ||
43
- props.type === 'quantileAggregatedScalar'
44
- ? getFilteredAggregatedExpressionFunctions(moduleExpressionFunctions.aggregatedScalarFunctions, props.type)
45
- : {
46
- ...moduleExpressionFunctions.booleanFunctions,
47
- ...moduleExpressionFunctions.scalarFunctions,
48
- };
49
- }, [props.type]);
43
+ props.type === 'quantileAggregatedScalar') {
44
+ return getFilteredAggregatedExpressionFunctions(moduleExpressionFunctions.aggregatedScalarFunctions, props.type);
45
+ }
46
+ let booleanAndScalarFunctions = {
47
+ ...moduleExpressionFunctions.booleanFunctions,
48
+ ...moduleExpressionFunctions.scalarFunctions,
49
+ };
50
+ if (!props.columnScope) {
51
+ // filter out $SCOPE function if no columnScope is provided
52
+ booleanAndScalarFunctions = Object.keys(booleanAndScalarFunctions)
53
+ .filter((key) => key !== '$SCOPE')
54
+ .reduce((obj, key) => {
55
+ obj[key] = booleanAndScalarFunctions[key];
56
+ return obj;
57
+ }, {});
58
+ }
59
+ return booleanAndScalarFunctions;
60
+ }, [props.type, props.columnScope]);
50
61
  const { setSelectedFunction } = useExpressionEditor();
51
62
  let queryName;
52
63
  switch (props.type) {
@@ -74,6 +85,6 @@ function EditorInput(props) {
74
85
  ? editorButtonsQuantileAggregatedScalar
75
86
  : editorButtonsSearch, testData: props.testData, isFullExpression: props.isFullExpression, hideResultPreview: props.type === 'aggregatedScalar' ||
76
87
  props.type === 'cumulativeAggregatedScalar' ||
77
- props.type === 'quantileAggregatedScalar', api: props.api }));
88
+ props.type === 'quantileAggregatedScalar', api: props.api, columnScope: props.columnScope }));
78
89
  }
79
90
  export default EditorInput;
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { AdaptableColumnDataType, AdaptableModule, BooleanFunctionName } from '../../../types';
2
+ import { AdaptableColumnDataType, AdaptableModule, BooleanFunctionName, ColumnScope } from '../../../types';
3
3
  interface QueryBuilderProps {
4
4
  query: string;
5
5
  getColumns: (type?: AdaptableColumnDataType) => {
@@ -14,6 +14,7 @@ interface QueryBuilderProps {
14
14
  }[];
15
15
  onChange: (query: string) => void;
16
16
  module: AdaptableModule;
17
+ columnScope?: ColumnScope;
17
18
  }
18
19
  export declare function useQueryBuilderContext(): {
19
20
  getColumns: QueryBuilderProps["getColumns"];
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { DragDropContext } from '../../dnd';
2
+ import { DragDropProvider } from '../../dnd';
3
3
  import { mapExpressionToQlPredicate, } from '../../../parser/src/predicate';
4
4
  import { mapQlPredicateToExpression } from '../../../parser/src/predicate/mapQlPredicateToExpression';
5
5
  import { useAdaptable } from '../../../View/AdaptableContext';
@@ -9,7 +9,7 @@ import Panel from '../../Panel';
9
9
  import SimpleButton from '../../SimpleButton';
10
10
  import { WarningBox } from '../../WarningBox';
11
11
  import { QueryPredicateBuilder } from './QueryPredicateBuilder';
12
- import { getFunctionsForColumnType, getUnsuportedExpressionFromQlPredicate, reorder, } from './utils';
12
+ import { getFunctionsForColumnType, getUnsuportedExpressionFromQlPredicate } from './utils';
13
13
  import { Box, Flex } from '../../Flex';
14
14
  const QUERY_BUILDER_CLASSNAME = 'ab-QueryBuilder';
15
15
  const QueryBuilderContext = React.createContext(null);
@@ -86,7 +86,6 @@ export const QueryBuilder = (props) => {
86
86
  }
87
87
  else if (qlPredicate && !('errorMessage' in qlPredicate)) {
88
88
  errorOrEditor = (React.createElement(QueryPredicateBuilder, { isRoot: true, index: 0, id: "0", predicate: qlPredicate, onNewPredicate: (type) => {
89
- // add to its children
90
89
  const newPredicate = {
91
90
  operator: type === 'filter' ? undefined : 'AND',
92
91
  args: [],
@@ -99,15 +98,7 @@ export const QueryBuilder = (props) => {
99
98
  handleQlPredicateChange(predicate);
100
99
  } }));
101
100
  }
102
- return (React.createElement(DragDropContext, { onDragEnd: (result) => {
103
- if (!result.destination) {
104
- return;
105
- }
106
- const toPath = `${result.destination.droppableId}/${result.destination.index}`;
107
- const fromPath = result.draggableId;
108
- const predicate = reorder(qlPredicate, fromPath, toPath);
109
- handleQlPredicateChange(predicate);
110
- } },
101
+ return (React.createElement(DragDropProvider, null,
111
102
  React.createElement(QueryBuilderContext.Provider, { value: context },
112
103
  React.createElement(Box, { className: QUERY_BUILDER_CLASSNAME },
113
104
  React.createElement(HelpBlock, { "data-name": "query-builder-help", className: "twa:my-2 twa:p-2 twa:text-3" }, "Build the Grid Filter by adding Column Conditions and AND / OR Groups as required"),
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { Draggable, Droppable } from '../../dnd';
2
+ import { defaultDragProxyMove, DragList } from '../../dnd';
3
3
  import { isArgumentColumnOrField, isQlLogicalOperator, } from '../../../parser/src/predicate';
4
4
  import { mapColumnDataTypeToExpressionFunctionType } from '../../../Utilities/adaptableQlUtils';
5
5
  import { booleanExpressionFunctions } from '../../../Utilities/ExpressionFunctions/booleanExpressionFunctions';
@@ -11,6 +11,7 @@ import SimpleButton from '../../SimpleButton';
11
11
  import { CombinatorSelector, ExpressionSelector, PrimitiveValueInput, PrimitiveColumnOrFieldSelector, PrimitiveMultiValueInput, } from './QueryBuilderInputs';
12
12
  import { getOperatorMatchingInputs as getFunctionMatchingInputTypes, mapExpressionToFieldValue, } from './utils';
13
13
  import { Box, Flex } from '../../Flex';
14
+ import clsx from 'clsx';
14
15
  const ITEM_HEIGHT = 40;
15
16
  const BASE_CLASS_NAME = 'ab-QueryBuilder-predicate-editor';
16
17
  const Handle = (props) => (React.createElement(Flex, { className: `${BASE_CLASS_NAME}__handle twa:mr-1`, style: { height: ITEM_HEIGHT }, alignItems: "center", ...props },
@@ -35,8 +36,12 @@ const LogicalFunctionEditor = (props) => {
35
36
  ${props.lastChild ? `${BASE_CLASS_NAME}--last-child` : ''}
36
37
  ${props.isRoot ? `${BASE_CLASS_NAME}--root` : `${BASE_CLASS_NAME}--child`}
37
38
  `;
38
- const getCombinatorEl = (handleProps, className) => (React.createElement(Droppable, { droppableId: props.id, type: props.id }, (provided, snapshot) => {
39
- return (React.createElement("div", { ...provided.droppableProps, ref: provided.innerRef, className: className },
39
+ const handleDrop = (sortedIndexes) => {
40
+ const newArgs = sortedIndexes.map((i) => props.predicate.args[i]);
41
+ props.onChange({ ...props.predicate, args: newArgs });
42
+ };
43
+ const getCombinatorEl = (handleProps) => (React.createElement(DragList, { dragListId: props.id, orientation: "vertical", onDrop: handleDrop, onDragProxyMove: defaultDragProxyMove }, (listDomProps) => {
44
+ return (React.createElement("div", { ...listDomProps, className: clsx(listDomProps.className) },
40
45
  React.createElement(Flex, null,
41
46
  props.isRoot ? null : React.createElement(Handle, { ...handleProps }),
42
47
  React.createElement(Flex, { className: "twa:flex-1", alignItems: "center", height: ITEM_HEIGHT },
@@ -94,21 +99,18 @@ const LogicalFunctionEditor = (props) => {
94
99
  });
95
100
  } }));
96
101
  }),
97
- provided.placeholder,
98
102
  React.createElement("div", { className: `${BASE_CLASS_NAME}__root-actions` },
99
103
  React.createElement(QueryPredicateButtons, { ...props, hideDelete: true })))));
100
104
  }));
101
105
  if (props.isRoot) {
102
- return getCombinatorEl({ className: className });
103
- }
104
- else {
105
- return (React.createElement(Draggable, { key: props.id, draggableId: props.id, index: props.index }, (provided, snapshot) => {
106
- return (React.createElement("div", { ...provided.draggableProps, ref: provided.innerRef, className: className }, getCombinatorEl(provided.dragHandleProps)));
107
- }));
106
+ return getCombinatorEl({ className });
108
107
  }
108
+ return (React.createElement(DragList.DraggableItem, { id: props.id }, (itemDomProps) => {
109
+ const { onPointerDown, ...restDomProps } = itemDomProps;
110
+ return (React.createElement("div", { ...restDomProps, className: clsx(className, restDomProps.className) }, getCombinatorEl({ onPointerDown })));
111
+ }));
109
112
  };
110
113
  const PrimitiveFunctionEditor = (props) => {
111
- // [handle] [column] [operator-dropdown] [...args] [delete-button] [plus-button]
112
114
  const adaptable = useAdaptable();
113
115
  const [columnOrFieldExpression, ...restOfArgs] = props.predicate.args;
114
116
  const columnOrField = columnOrFieldExpression;
@@ -116,15 +118,12 @@ const PrimitiveFunctionEditor = (props) => {
116
118
  let columnOrFieldDataType = null;
117
119
  let columnInputDataType = null;
118
120
  let functionInputInputDataTypes = null;
119
- // Thsese are the type of inputs ommiting the column
120
- // [[column-data-type], number, number]
121
121
  let restOfFunctionInputDataTypes = [];
122
122
  if (columnOrField) {
123
123
  if (!isArgumentColumnOrField(columnOrField)) {
124
124
  return React.createElement(ErrorBox, null, "Expression must start with a column or a filed!");
125
125
  }
126
126
  if (columnOrField.includes('FIELD')) {
127
- // we let the full expression so we can difirienciate between column and field
128
127
  columnOrFieldId = columnOrField;
129
128
  const fieldValue = mapExpressionToFieldValue(columnOrField);
130
129
  columnOrFieldDataType = adaptable.api.expressionApi.internalApi.getFieldType(fieldValue);
@@ -141,9 +140,10 @@ const PrimitiveFunctionEditor = (props) => {
141
140
  : [];
142
141
  }
143
142
  const level = props.id.split('/').length - 1;
144
- return (React.createElement(Draggable, { key: props.id, draggableId: props.id, index: props.index }, (provided) => {
145
- return (React.createElement(Flex, { className: `twa:pb-2 ${BASE_CLASS_NAME} ${BASE_CLASS_NAME}-level-${level} ${BASE_CLASS_NAME}-primitive ${props.lastChild ? `${BASE_CLASS_NAME}--last-child` : ''} `, ref: provided.innerRef, ...provided.draggableProps, style: { ...provided.draggableProps.style, minHeight: ITEM_HEIGHT } },
146
- React.createElement(Handle, { ...provided.dragHandleProps }),
143
+ return (React.createElement(DragList.DraggableItem, { id: props.id }, (itemDomProps) => {
144
+ const { onPointerDown, ...restDomProps } = itemDomProps;
145
+ return (React.createElement(Flex, { ...restDomProps, className: clsx(`twa:pb-2 ${BASE_CLASS_NAME} ${BASE_CLASS_NAME}-level-${level} ${BASE_CLASS_NAME}-primitive ${props.lastChild ? `${BASE_CLASS_NAME}--last-child` : ''}`, restDomProps.className), style: { minHeight: ITEM_HEIGHT } },
146
+ React.createElement(Handle, { onPointerDown: onPointerDown }),
147
147
  React.createElement(Flex, { alignItems: "center", style: { height: ITEM_HEIGHT } },
148
148
  React.createElement(Box, { className: "twa:mr-2" },
149
149
  React.createElement(PrimitiveColumnOrFieldSelector, { onChange: (colOrField) => {
@@ -161,7 +161,6 @@ const PrimitiveFunctionEditor = (props) => {
161
161
  props.onChange({
162
162
  ...props.predicate,
163
163
  operator,
164
- // discard arguments
165
164
  args,
166
165
  });
167
166
  }, value: props.predicate.operator })),
@@ -182,7 +181,6 @@ const PrimitiveFunctionEditor = (props) => {
182
181
  }
183
182
  return (React.createElement(PrimitiveValueInput, { ...commonProps, key: key, value: restOfArgs[index] ?? null, onChange: (value) => {
184
183
  const args = [...props.predicate.args];
185
- // +1 because col is the first argument
186
184
  args[index + 1] = value;
187
185
  props.onChange({
188
186
  ...props.predicate,
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { AdaptableApi, AdaptableColumn, AdaptableField, AdaptableModule, NamedQuery } from '../../types';
2
+ import { AdaptableApi, AdaptableColumn, AdaptableField, AdaptableModule, ColumnScope, NamedQuery } from '../../types';
3
3
  export type ExpressionEditorType = 'boolean' | 'scalar' | 'observable' | 'aggregatedBoolean' | 'aggregatedScalar' | 'cumulativeAggregatedScalar' | 'quantileAggregatedScalar';
4
4
  interface ExpressionEditorProps {
5
5
  value: string;
@@ -19,6 +19,7 @@ interface ExpressionEditorProps {
19
19
  api: AdaptableApi;
20
20
  showQueryBuilder?: boolean;
21
21
  showExpressionEditor?: boolean;
22
+ columnScope?: ColumnScope;
22
23
  }
23
24
  export declare const baseClassName = "ab-ExpressionEditor";
24
25
  export declare function ExpressionEditor(props: ExpressionEditorProps): React.JSX.Element;
@@ -35,7 +35,7 @@ export function ExpressionEditor(props) {
35
35
  // 'boolean','scalar','aggregatedScalar'/'cumulativeAggregatedScalar'/'quantileAggregatedScalar'
36
36
  (React.createElement(
37
37
  EditorInput,
38
- { type: type, module: module, value: props.value, onChange: (value) => {
38
+ { type: type, module: module, columnScope: props.columnScope, value: props.value, onChange: (value) => {
39
39
  setExpressionText(value);
40
40
  props.onChange(value);
41
41
  }, testData: props.initialData, isFullExpression: props.isFullExpression, api: props.api }
@@ -5,7 +5,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
5
5
  import OverlayTrigger from '../../OverlayTrigger';
6
6
  import NotifyResize from '../../NotifyResize';
7
7
  import Input from '../../Input';
8
- import { TreeSelectionState, withSelectedLeafNodesOnly, } from '../../InfiniteTable';
8
+ import { TreeSelectionState, useDataSourceState, withSelectedLeafNodesOnly, } from '../../InfiniteTable';
9
9
  import SimpleButton from '../../SimpleButton';
10
10
  import { CheckBox } from '../../CheckBox';
11
11
  import { useLatest } from '../../utils/useLatest';
@@ -59,35 +59,46 @@ const getLabelColumn = (field, { includeExpandCollapseButton }) => {
59
59
  } }));
60
60
  },
61
61
  renderHeader: ({ dataSourceApi, api, allRowsSelected, someRowsSelected }) => {
62
- const { treeApi } = dataSourceApi;
63
- const allFirstLevelCollapsed = dataSourceApi
64
- .getOriginalDataArray()
65
- .every((item) => !treeApi.isNodeExpanded([item.id]));
66
- return (React.createElement(Flex, { flexDirection: 'row', alignItems: 'center', className: "twa:w-full", onMouseDown: (e) => {
67
- // so we can keep the focus on the Grid
68
- e.preventDefault();
69
- } },
70
- React.createElement(CheckBox, { checked: someRowsSelected && !allRowsSelected ? null : allRowsSelected, className: "twa:mr-2", onChange: () => {
71
- if (allRowsSelected) {
72
- dataSourceApi.treeApi.deselectAll();
73
- }
74
- else {
75
- dataSourceApi.treeApi.selectAll();
76
- }
77
- api.focus();
78
- } }, allRowsSelected ? '(Deselect All)' : '(Select All)'),
79
- React.createElement(Flex, { className: "twa:flex-1" }),
80
- includeExpandCollapseButton ? (React.createElement(SimpleButton, { label: "toggle-expand-collapse", icon: allFirstLevelCollapsed ? 'expand-all' : 'collapse-all', onMouseDown: () => {
81
- if (allFirstLevelCollapsed) {
82
- dataSourceApi.treeApi.expandAll();
83
- }
84
- else {
85
- dataSourceApi.treeApi.collapseAll();
86
- }
87
- }, iconPosition: "end" })) : null));
62
+ return (React.createElement(CustomHeader, { dataSourceApi: dataSourceApi, api: api, allRowsSelected: allRowsSelected, someRowsSelected: someRowsSelected, includeExpandCollapseButton: includeExpandCollapseButton }));
88
63
  },
89
64
  };
90
65
  };
66
+ function useAllFirstLevelCollapsed(treeApi) {
67
+ const { originalDataArray } = useDataSourceState((state) => {
68
+ return {
69
+ originalDataArray: state.originalDataArray,
70
+ treeExpandState: state.treeExpandState,
71
+ };
72
+ });
73
+ return originalDataArray.every((item) => !treeApi.isNodeExpanded([item.id]));
74
+ }
75
+ function CustomHeader({ dataSourceApi, api, allRowsSelected, someRowsSelected, includeExpandCollapseButton, }) {
76
+ const { treeApi } = dataSourceApi;
77
+ const allFirstLevelCollapsed = useAllFirstLevelCollapsed(treeApi);
78
+ const checked = someRowsSelected && !allRowsSelected ? null : allRowsSelected;
79
+ return (React.createElement(Flex, { flexDirection: 'row', alignItems: 'center', className: "twa:w-full", onMouseDown: (e) => {
80
+ // so we can keep the focus on the Grid
81
+ e.preventDefault();
82
+ } },
83
+ React.createElement(CheckBox, { checked: checked, className: "twa:mr-2", onChange: () => {
84
+ if (allRowsSelected) {
85
+ dataSourceApi.treeApi.deselectAll();
86
+ }
87
+ else {
88
+ dataSourceApi.treeApi.selectAll();
89
+ }
90
+ api.focus();
91
+ } }, allRowsSelected ? '(Deselect All)' : '(Select All)'),
92
+ React.createElement(Flex, { className: "twa:flex-1" }),
93
+ includeExpandCollapseButton ? (React.createElement(SimpleButton, { label: "toggle-expand-collapse", icon: allFirstLevelCollapsed ? 'expand-all' : 'collapse-all', onMouseDown: () => {
94
+ if (allFirstLevelCollapsed) {
95
+ dataSourceApi.treeApi.expandAll();
96
+ }
97
+ else {
98
+ dataSourceApi.treeApi.collapseAll();
99
+ }
100
+ }, iconPosition: "end" })) : null));
101
+ }
91
102
  const sizeFull = {
92
103
  width: '100%',
93
104
  height: '100%',
@@ -1,13 +1,3 @@
1
- import * as React from 'react';
2
- import { DropResult, Draggable, DroppableProps, DragDropContextProps } from '@adaptabletools/react-beautiful-dnd';
3
- /**
4
- * We're doing all this because the placeholder is not correctly displayed in react-beautiful-dnd
5
- * with React 19.
6
- * So we make sure it properly occupies the space of the dragged item, so the
7
- * container won't flicker when we're dragging an item (as the drag item receives
8
- * position: fixed while dragging, so content does not have the initial height anymore, therefore,
9
- * the placeholder is included, with the computed height of the dragging element)
10
- */
11
- declare const Droppable: (props: DroppableProps) => React.JSX.Element;
12
- declare const DragDropContext: (props: DragDropContextProps) => React.JSX.Element;
13
- export { type DropResult, Draggable, Droppable, DragDropContext };
1
+ import { DragProxyMoveParams } from '@infinite-table/infinite-react';
2
+ export { DragDropProvider, DragList, useDragDropProvider, useDragListContext, DRAG_ITEM_ATTRIBUTE, type DragListProps, type DragDropSourceAndTarget, } from '@infinite-table/infinite-react';
3
+ export declare function defaultDragProxyMove({ proxyElement, dx, dy }: DragProxyMoveParams): void;