@adaptabletools/adaptable 23.0.5 → 23.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.css +10 -1
- package/package.json +1 -1
- package/src/AdaptableOptions/AdaptableOptions.d.ts +9 -0
- package/src/AdaptableOptions/DataChangeHistoryOptions.d.ts +7 -0
- package/src/AdaptableOptions/DefaultAdaptableOptions.d.ts +17 -0
- package/src/AdaptableOptions/DefaultAdaptableOptions.js +8 -46
- package/src/AdaptableOptions/EditOptions.d.ts +10 -2
- package/src/AdaptableOptions/SettingsPanelOptions.d.ts +3 -28
- package/src/AdaptableOptions/WizardOptions.d.ts +25 -0
- package/src/AdaptableOptions/WizardOptions.js +1 -0
- package/src/AdaptableState/Common/CustomWindowConfig.d.ts +2 -14
- package/src/AdaptableState/Common/Window.d.ts +33 -0
- package/src/AdaptableState/Common/Window.js +1 -0
- package/src/AdaptableState/InitialState.d.ts +2 -1
- package/src/AdaptableState/PlusMinusState.d.ts +12 -2
- package/src/Api/Implementation/DataChangeHistoryApiImpl.js +10 -9
- package/src/Redux/ActionsReducers/InternalRedux.d.ts +2 -1
- package/src/Redux/ActionsReducers/InternalRedux.js +25 -27
- package/src/Strategy/DataChangeHistoryModule.js +1 -1
- package/src/Strategy/PlusMinusModule.js +5 -3
- package/src/Utilities/Extensions/ObjectExtensions.d.ts +16 -0
- package/src/Utilities/Extensions/ObjectExtensions.js +41 -0
- package/src/Utilities/Helpers/PlusMinusHelper.d.ts +62 -9
- package/src/Utilities/Helpers/PlusMinusHelper.js +180 -25
- package/src/View/Components/Popups/AdaptablePopup/AdaptablePopup.js +5 -1
- package/src/View/Components/Popups/AdaptablePopup/AdaptablePopupDialog.js +7 -3
- package/src/View/Components/Popups/Utilities.d.ts +11 -0
- package/src/View/Components/Popups/Utilities.js +8 -0
- package/src/View/DataChangeHistory/DataChangeHistoryViewPanel.js +3 -4
- package/src/View/DataChangeHistory/dataChangeHistoryHelpers.js +1 -1
- package/src/View/PlusMinus/Wizard/KeyComboCaptureInput.d.ts +30 -0
- package/src/View/PlusMinus/Wizard/KeyComboCaptureInput.js +161 -0
- package/src/View/PlusMinus/Wizard/PlusMinusSettingsWizardSection.js +30 -60
- package/src/View/Wizard/OnePageWizards.js +27 -2
- package/src/agGrid/AdaptableAgGrid.js +2 -0
- package/src/components/ui/input-group.js +0 -1
- package/src/env.js +2 -2
- package/src/migration/DeprecatedStateKeys.d.ts +37 -0
- package/src/migration/DeprecatedStateKeys.js +42 -0
- package/src/migration/VersionUpgrade23.d.ts +9 -0
- package/src/migration/VersionUpgrade23.js +1 -2
- package/src/types.d.ts +4 -2
- package/tsconfig.esm.tsbuildinfo +1 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { cn } from '../../../lib/utils';
|
|
4
|
+
import { Box, Flex } from '../../../components/Flex';
|
|
5
|
+
import SimpleButton from '../../../components/SimpleButton';
|
|
6
|
+
import { capturePlusMinusTriggerFromEvent, plusMinusKeyLabel, plusMinusTriggerDisplayParts, } from '../../../Utilities/Helpers/PlusMinusHelper';
|
|
7
|
+
import { targetOwn } from '../../../components/twUtils';
|
|
8
|
+
const Kbd = ({ children }) => (_jsx(Box, { as: "kbd", className: "twa:px-2 twa:py-[2px] twa:rounded-standard twa:bg-primary twa:text-2 twa:leading-none twa:font-medium twa:whitespace-nowrap", children: children }));
|
|
9
|
+
const renderTokens = (tokens) => tokens.map((token, index) => (_jsxs(React.Fragment, { children: [index > 0 ? _jsx(Box, { className: "twa:opacity-50 twa:text-2", children: "+" }) : null, _jsx(Kbd, { children: token })] }, `${token}-${index}`)));
|
|
10
|
+
export const KeyComboCaptureInput = (props) => {
|
|
11
|
+
const { value, isUsingDefault, placeholder, disabled, onCapture, onReset, validateCapture } = props;
|
|
12
|
+
const ref = React.useRef(null);
|
|
13
|
+
const [focused, setFocused] = React.useState(false);
|
|
14
|
+
const [editing, setEditing] = React.useState(false);
|
|
15
|
+
const [pendingModifiers, setPendingModifiers] = React.useState([]);
|
|
16
|
+
const [staged, setStaged] = React.useState(undefined);
|
|
17
|
+
const [error, setError] = React.useState(undefined);
|
|
18
|
+
const stopEditing = React.useCallback(() => {
|
|
19
|
+
setEditing(false);
|
|
20
|
+
setPendingModifiers([]);
|
|
21
|
+
setStaged(undefined);
|
|
22
|
+
}, []);
|
|
23
|
+
const handleKeyDown = (event) => {
|
|
24
|
+
if (disabled) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!editing) {
|
|
28
|
+
if (event.key === 'Enter') {
|
|
29
|
+
event.preventDefault();
|
|
30
|
+
event.stopPropagation();
|
|
31
|
+
setError(undefined);
|
|
32
|
+
setPendingModifiers([]);
|
|
33
|
+
setStaged(undefined);
|
|
34
|
+
setEditing(true);
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (event.key === 'Escape') {
|
|
39
|
+
event.preventDefault();
|
|
40
|
+
event.stopPropagation();
|
|
41
|
+
setError(undefined);
|
|
42
|
+
stopEditing();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (event.key === 'Tab') {
|
|
46
|
+
if (staged && !validateCapture?.(staged)) {
|
|
47
|
+
onCapture(staged);
|
|
48
|
+
}
|
|
49
|
+
stopEditing();
|
|
50
|
+
setError(undefined);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
event.stopPropagation();
|
|
55
|
+
const noModifiers = !event.ctrlKey && !event.altKey && !event.metaKey && !event.shiftKey;
|
|
56
|
+
if (event.key === 'Enter' && noModifiers) {
|
|
57
|
+
if (!staged) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const validationError = validateCapture?.(staged);
|
|
61
|
+
if (validationError) {
|
|
62
|
+
setError(validationError);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const confirmed = staged;
|
|
66
|
+
setError(undefined);
|
|
67
|
+
stopEditing();
|
|
68
|
+
onCapture(confirmed);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const result = capturePlusMinusTriggerFromEvent({
|
|
72
|
+
key: event.key,
|
|
73
|
+
ctrlKey: event.ctrlKey,
|
|
74
|
+
altKey: event.altKey,
|
|
75
|
+
metaKey: event.metaKey,
|
|
76
|
+
shiftKey: event.shiftKey,
|
|
77
|
+
});
|
|
78
|
+
if (result.kind === 'pending') {
|
|
79
|
+
setPendingModifiers(result.modifiers);
|
|
80
|
+
setError(undefined);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (result.kind === 'invalid') {
|
|
84
|
+
setPendingModifiers([]);
|
|
85
|
+
setStaged(undefined);
|
|
86
|
+
setError(result.reason);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const validationError = validateCapture?.(result.trigger);
|
|
90
|
+
if (validationError) {
|
|
91
|
+
setPendingModifiers([]);
|
|
92
|
+
setStaged(undefined);
|
|
93
|
+
setError(validationError);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
setPendingModifiers([]);
|
|
97
|
+
setError(undefined);
|
|
98
|
+
setStaged(result.trigger);
|
|
99
|
+
};
|
|
100
|
+
const handleReset = (event) => {
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
event.stopPropagation();
|
|
103
|
+
setError(undefined);
|
|
104
|
+
stopEditing();
|
|
105
|
+
onReset?.();
|
|
106
|
+
};
|
|
107
|
+
const handleEnterEdit = (event) => {
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
event.stopPropagation();
|
|
110
|
+
setError(undefined);
|
|
111
|
+
setPendingModifiers([]);
|
|
112
|
+
setStaged(undefined);
|
|
113
|
+
setEditing(true);
|
|
114
|
+
ref.current?.focus();
|
|
115
|
+
};
|
|
116
|
+
const valueParts = plusMinusTriggerDisplayParts(value);
|
|
117
|
+
let content;
|
|
118
|
+
if (editing) {
|
|
119
|
+
if (staged) {
|
|
120
|
+
content = (_jsx(Flex, { className: "twa:items-center twa:gap-1", children: renderTokens(plusMinusTriggerDisplayParts(staged)) }));
|
|
121
|
+
}
|
|
122
|
+
else if (pendingModifiers.length) {
|
|
123
|
+
content = (_jsxs(Flex, { className: "twa:items-center twa:gap-1", children: [renderTokens(pendingModifiers.map(plusMinusKeyLabel)), _jsx(Box, { className: "twa:opacity-50 twa:text-2", children: "+ \u2026" })] }));
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
content = _jsx(Box, { className: "twa:opacity-60 twa:text-2", children: "Press a key combination\u2026" });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else if (valueParts.length) {
|
|
130
|
+
content = (_jsxs(Flex, { className: "twa:items-center twa:gap-1", children: [renderTokens(valueParts), isUsingDefault ? (_jsx(Box, { className: "twa:opacity-60 twa:text-2 twa:ml-1", children: "(default)" })) : null] }));
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
content = _jsx(Box, { className: "twa:opacity-60 twa:text-2", children: placeholder ?? 'Hit Enter to edit' });
|
|
134
|
+
}
|
|
135
|
+
return (_jsxs(Flex, { flexDirection: "column", className: "twa:gap-1 twa:max-w-[300px] twa:w-full", children: [_jsxs(Flex, { ref: ref, role: "button", tabIndex: disabled ? -1 : 0, "data-name": props['data-name'], "aria-label": "Record keyboard shortcut", onFocus: () => {
|
|
136
|
+
if (!disabled) {
|
|
137
|
+
setFocused(true);
|
|
138
|
+
}
|
|
139
|
+
}, onBlur: (event) => {
|
|
140
|
+
if (ref.current && event.relatedTarget && ref.current.contains(event.relatedTarget)) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (editing && staged && !validateCapture?.(staged)) {
|
|
144
|
+
onCapture(staged);
|
|
145
|
+
}
|
|
146
|
+
setFocused(false);
|
|
147
|
+
stopEditing();
|
|
148
|
+
setError(undefined);
|
|
149
|
+
}, onClick: () => ref.current?.focus(), onKeyDown: handleKeyDown, className: cn('twa:min-h-input twa:rounded-input twa:px-2 twa:items-center twa:gap-2 twa:w-full', 'twa:border-input twa:border', targetOwn.focusWithinOutline, disabled
|
|
150
|
+
? 'twa:opacity-60 twa:cursor-not-allowed'
|
|
151
|
+
: 'twa:cursor-pointer twa:bg-input-background', editing ? 'twa:border-accent' : '', error ? 'twa:border-destructive' : ''), children: [_jsx(Flex, { className: "twa:flex-1 twa:flex-wrap twa:items-center twa:gap-1 twa:py-1", children: content }), !disabled && !editing ? (onReset && !isUsingDefault ? (_jsx(SimpleButton, { variant: "text", icon: "undo", tooltip: "Revert to default", "data-name": "plus-minus-reset-key", tabIndex: -1, onMouseDown: handleReset, onKeyDown: (event) => {
|
|
152
|
+
if (event.key === 'Enter') {
|
|
153
|
+
handleReset(event);
|
|
154
|
+
ref.current?.focus();
|
|
155
|
+
}
|
|
156
|
+
} })) : (_jsx(SimpleButton, { variant: "text", icon: "edit", tooltip: "Edit keyboard shortcut", "data-name": "plus-minus-edit-key", tabIndex: -1, onMouseDown: handleEnterEdit, onKeyDown: (event) => {
|
|
157
|
+
if (event.key === 'Enter') {
|
|
158
|
+
handleEnterEdit(event);
|
|
159
|
+
}
|
|
160
|
+
} }))) : null] }), _jsx(Box, { "data-name": error ? 'key-capture-error' : 'key-capture-hint', className: cn('twa:text-2', error ? 'twa:text-destructive' : 'twa:opacity-60', !focused && !error ? 'twa:invisible' : ''), children: error ? error : editing ? 'ENTER to confirm, ESCAPE to cancel' : 'Hit Enter to edit' })] }));
|
|
161
|
+
};
|
|
@@ -5,7 +5,8 @@ import { SummaryText, useOnePageAdaptableWizardContext, } from '../../Wizard/One
|
|
|
5
5
|
import { Tag } from '../../../components/Tag';
|
|
6
6
|
import { Box, Flex } from '../../../components/Flex';
|
|
7
7
|
import { Card } from '../../../components/Card';
|
|
8
|
-
import { plusMinusDecrementKeyFromOptionsOnly, plusMinusIncrementKeyFromOptionsOnly, plusMinusResolvedKeysConflict, plusMinusTriggerSameAsBaseline, resolvePlusMinusTriggerKeysForNudge, } from '../../../Utilities/Helpers/PlusMinusHelper';
|
|
8
|
+
import { normalizePlusMinusTrigger, plusMinusDecrementKeyFromOptionsOnly, plusMinusIncrementKeyFromOptionsOnly, plusMinusResolvedKeysConflict, plusMinusTriggerSameAsBaseline, resolvePlusMinusTriggerKeysForNudge, } from '../../../Utilities/Helpers/PlusMinusHelper';
|
|
9
|
+
import { KeyComboCaptureInput } from './KeyComboCaptureInput';
|
|
9
10
|
export const PlusMinusSettingsSummary = () => {
|
|
10
11
|
const { data, api } = useOnePageAdaptableWizardContext();
|
|
11
12
|
const { incrementKey, decrementKey } = resolvePlusMinusTriggerKeysForNudge(data, api.optionsApi.getEditOptions().plusMinusOptions ?? {});
|
|
@@ -36,42 +37,35 @@ export const PlusMinusSettingsWizardSection = (props) => {
|
|
|
36
37
|
const pmOpts = api.optionsApi.getEditOptions().plusMinusOptions ?? {};
|
|
37
38
|
const incrementBaseline = plusMinusIncrementKeyFromOptionsOnly(pmOpts);
|
|
38
39
|
const decrementBaseline = plusMinusDecrementKeyFromOptionsOnly(pmOpts);
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const decrementDisplayValue = decrementEdit !== undefined
|
|
51
|
-
? decrementEdit
|
|
52
|
-
: data.DecrementKey?.trim()
|
|
53
|
-
? (data.DecrementKey ?? '').trim()
|
|
54
|
-
: decrementBaseline;
|
|
55
|
-
const commitIncrementKey = React.useCallback((raw) => {
|
|
56
|
-
const trimmed = raw.trim();
|
|
57
|
-
const next = trimmed === '' || plusMinusTriggerSameAsBaseline(trimmed, incrementBaseline)
|
|
58
|
-
? undefined
|
|
59
|
-
: trimmed;
|
|
60
|
-
const prev = data.IncrementKey?.trim() || undefined;
|
|
61
|
-
if (next !== prev) {
|
|
62
|
-
props.onChange({ ...data, IncrementKey: next });
|
|
63
|
-
}
|
|
40
|
+
const incrementUsingDefault = !data.IncrementKey?.trim();
|
|
41
|
+
const decrementUsingDefault = !data.DecrementKey?.trim();
|
|
42
|
+
const incrementDisplayValue = incrementUsingDefault
|
|
43
|
+
? incrementBaseline
|
|
44
|
+
: (data.IncrementKey ?? '').trim();
|
|
45
|
+
const decrementDisplayValue = decrementUsingDefault
|
|
46
|
+
? decrementBaseline
|
|
47
|
+
: (data.DecrementKey ?? '').trim();
|
|
48
|
+
const commitIncrementKey = React.useCallback((trigger) => {
|
|
49
|
+
const next = plusMinusTriggerSameAsBaseline(trigger, incrementBaseline) ? undefined : trigger;
|
|
50
|
+
props.onChange({ ...data, IncrementKey: next });
|
|
64
51
|
}, [data, incrementBaseline, props.onChange]);
|
|
65
|
-
const commitDecrementKey = React.useCallback((
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
? undefined
|
|
69
|
-
: trimmed;
|
|
70
|
-
const prev = data.DecrementKey?.trim() || undefined;
|
|
71
|
-
if (next !== prev) {
|
|
72
|
-
props.onChange({ ...data, DecrementKey: next });
|
|
73
|
-
}
|
|
52
|
+
const commitDecrementKey = React.useCallback((trigger) => {
|
|
53
|
+
const next = plusMinusTriggerSameAsBaseline(trigger, decrementBaseline) ? undefined : trigger;
|
|
54
|
+
props.onChange({ ...data, DecrementKey: next });
|
|
74
55
|
}, [data, decrementBaseline, props.onChange]);
|
|
56
|
+
const resetIncrementKey = React.useCallback(() => {
|
|
57
|
+
props.onChange({ ...data, IncrementKey: undefined });
|
|
58
|
+
}, [data, props.onChange]);
|
|
59
|
+
const resetDecrementKey = React.useCallback(() => {
|
|
60
|
+
props.onChange({ ...data, DecrementKey: undefined });
|
|
61
|
+
}, [data, props.onChange]);
|
|
62
|
+
const SAME_KEYS_MESSAGE = 'Increment and decrement keys cannot be the same.';
|
|
63
|
+
const validateIncrementCapture = React.useCallback((trigger) => normalizePlusMinusTrigger(trigger) === normalizePlusMinusTrigger(decrementDisplayValue)
|
|
64
|
+
? SAME_KEYS_MESSAGE
|
|
65
|
+
: undefined, [decrementDisplayValue]);
|
|
66
|
+
const validateDecrementCapture = React.useCallback((trigger) => normalizePlusMinusTrigger(trigger) === normalizePlusMinusTrigger(incrementDisplayValue)
|
|
67
|
+
? SAME_KEYS_MESSAGE
|
|
68
|
+
: undefined, [incrementDisplayValue]);
|
|
75
69
|
const handleNameChange = (event) => {
|
|
76
70
|
props.onChange({
|
|
77
71
|
...data,
|
|
@@ -85,29 +79,5 @@ export const PlusMinusSettingsWizardSection = (props) => {
|
|
|
85
79
|
NudgeValue: isNaN(newValue) ? '' : newValue,
|
|
86
80
|
});
|
|
87
81
|
};
|
|
88
|
-
|
|
89
|
-
setIncrementEdit(data.IncrementKey?.trim() ? (data.IncrementKey ?? '').trim() : incrementBaseline);
|
|
90
|
-
};
|
|
91
|
-
const handleIncrementKeyChange = (event) => {
|
|
92
|
-
const raw = event.target.value;
|
|
93
|
-
setIncrementEdit(raw);
|
|
94
|
-
commitIncrementKey(raw);
|
|
95
|
-
};
|
|
96
|
-
const handleIncrementKeyBlur = (event) => {
|
|
97
|
-
commitIncrementKey(event.target.value);
|
|
98
|
-
setIncrementEdit(undefined);
|
|
99
|
-
};
|
|
100
|
-
const handleDecrementKeyFocus = () => {
|
|
101
|
-
setDecrementEdit(data.DecrementKey?.trim() ? (data.DecrementKey ?? '').trim() : decrementBaseline);
|
|
102
|
-
};
|
|
103
|
-
const handleDecrementKeyChange = (event) => {
|
|
104
|
-
const raw = event.target.value;
|
|
105
|
-
setDecrementEdit(raw);
|
|
106
|
-
commitDecrementKey(raw);
|
|
107
|
-
};
|
|
108
|
-
const handleDecrementKeyBlur = (event) => {
|
|
109
|
-
commitDecrementKey(event.target.value);
|
|
110
|
-
setDecrementEdit(undefined);
|
|
111
|
-
};
|
|
112
|
-
return (_jsx(Box, { "data-name": "plus-minus-column-settings", children: _jsxs(Flex, { flexDirection: "column", className: "twa:gap-3 twa:p-3", children: [_jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Name" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Provide a unique name for the Plus/Minus Nudge" })] }), _jsx(Card.Body, { className: "twa:p-1", children: _jsx(Input, { "data-name": "plus-minus-name", className: "twa:max-w-[300px] twa:w-full", onChange: handleNameChange, placeholder: "Enter Name", value: data.Name ?? '' }) })] }), _jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Nudge Value" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Amount added to or subtracted from the cell value when Plus/Minus is used" })] }), _jsx(Card.Body, { className: "twa:p-1", children: _jsx(Input, { "data-name": "nudge-value", className: "twa:max-w-[300px] twa:w-full", onChange: handleNudgeValueChange, placeholder: "Enter Number", type: "number", value: data.NudgeValue ?? '' }) })] }), _jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Trigger Keys" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Keyboard keys that trigger increment and decrement" })] }), _jsx(Card.Body, { className: "twa:p-1", children: _jsxs(Flex, { flexDirection: "column", className: "twa:gap-3", children: [_jsxs(Box, { children: [_jsx(Box, { className: "twa:text-2 twa:mb-1 twa:opacity-80", children: "Increment key" }), _jsx(Input, { "data-name": "plus-minus-increment-key", className: "twa:max-w-[300px] twa:w-full", onBlur: handleIncrementKeyBlur, onChange: handleIncrementKeyChange, onFocus: handleIncrementKeyFocus, value: incrementDisplayValue })] }), _jsxs(Box, { children: [_jsx(Box, { className: "twa:text-2 twa:mb-1 twa:opacity-80", children: "Decrement key" }), _jsx(Input, { "data-name": "plus-minus-decrement-key", className: "twa:max-w-[300px] twa:w-full", onBlur: handleDecrementKeyBlur, onChange: handleDecrementKeyChange, onFocus: handleDecrementKeyFocus, value: decrementDisplayValue })] })] }) })] })] }) }));
|
|
82
|
+
return (_jsx(Box, { "data-name": "plus-minus-column-settings", children: _jsxs(Flex, { flexDirection: "column", className: "twa:gap-3 twa:p-3", children: [_jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Name" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Provide a unique name for the Plus / Minus Nudge" })] }), _jsx(Card.Body, { className: "twa:p-1", children: _jsx(Input, { "data-name": "plus-minus-name", className: "twa:max-w-[300px] twa:w-full", onChange: handleNameChange, placeholder: "Enter Name", value: data.Name ?? '' }) })] }), _jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Nudge Value" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Amount added to or subtracted from the cell value when Plus / Minus is used" })] }), _jsx(Card.Body, { className: "twa:p-1", children: _jsx(Input, { "data-name": "nudge-value", className: "twa:max-w-[300px] twa:w-full", onChange: handleNudgeValueChange, placeholder: "Enter Number", type: "number", value: data.NudgeValue ?? '' }) })] }), _jsxs(Card, { shadow: false, children: [_jsxs(Card.Title, { children: [_jsx(Box, { className: "twa:font-medium", children: "Trigger Keys" }), _jsx(Box, { className: "twa:text-xs twa:opacity-70 twa:font-normal twa:max-w-[520px]", children: "Click a field and press the keys that should trigger increment / decrement." })] }), _jsx(Card.Body, { className: "twa:p-1", children: _jsxs(Flex, { flexDirection: "column", className: "twa:gap-3", children: [_jsxs(Box, { children: [_jsx(Box, { className: "twa:text-2 twa:mb-1 twa:opacity-80", children: "Increment key" }), _jsx(KeyComboCaptureInput, { "data-name": "plus-minus-increment-key", value: incrementDisplayValue, isUsingDefault: incrementUsingDefault, onCapture: commitIncrementKey, onReset: resetIncrementKey, validateCapture: validateIncrementCapture })] }), _jsxs(Box, { children: [_jsx(Box, { className: "twa:text-2 twa:mb-1 twa:opacity-80", children: "Decrement key" }), _jsx(KeyComboCaptureInput, { "data-name": "plus-minus-decrement-key", value: decrementDisplayValue, isUsingDefault: decrementUsingDefault, onCapture: commitDecrementKey, onReset: resetDecrementKey, validateCapture: validateDecrementCapture })] })] }) })] })] }) }));
|
|
113
83
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { useState, useRef } from 'react';
|
|
4
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
4
5
|
import { cn } from '../../lib/utils';
|
|
5
6
|
import Dialog from '../../components/Dialog';
|
|
6
7
|
import SimpleButton from '../../components/SimpleButton';
|
|
@@ -15,6 +16,9 @@ import { useKeyboardNavigation } from './useKeyboardNavigation';
|
|
|
15
16
|
import { Box, Flex } from '../../components/Flex';
|
|
16
17
|
import { twMerge } from '../../twMerge';
|
|
17
18
|
import { targetOwn } from '../../components/twUtils';
|
|
19
|
+
import { useAdaptable } from '../AdaptableContext';
|
|
20
|
+
import { getMiddlePosition, getWizardSize } from '../Components/Popups/Utilities';
|
|
21
|
+
import { SettingsPanelSet } from '../../Redux/ActionsReducers/InternalRedux';
|
|
18
22
|
const ONE_PAGE_WIZARD_SECTION_GRID = 'twa:grid twa:grid-cols-[minmax(160px,14rem)_minmax(0,1fr)]';
|
|
19
23
|
export const SummaryTag = (props) => (_jsx(Box, { ...props }));
|
|
20
24
|
export const SummaryText = (props) => (_jsx(Box, { ...props, className: twMerge('twa:text-2 twa:mb-3', props.className) }));
|
|
@@ -113,7 +117,28 @@ export const OnePageWizard = (props) => {
|
|
|
113
117
|
const canFinish = !invalidCount;
|
|
114
118
|
const activeSection = visibleSections[currentSection];
|
|
115
119
|
const activeSectionDetails = activeSection !== '-' ? activeSection?.details : undefined;
|
|
116
|
-
|
|
120
|
+
const adaptable = useAdaptable();
|
|
121
|
+
const wizardOptions = adaptable.adaptableOptions.wizardOptions;
|
|
122
|
+
const isWindowMode = wizardOptions?.popupType === 'window' && props.modal !== false;
|
|
123
|
+
const wizardSettingsKey = `wizard-${props.name || 'unnamed'}`;
|
|
124
|
+
const dispatch = useDispatch();
|
|
125
|
+
const persistedWizardSettings = useSelector((state) => state?.Internal?.SettingsPanel?.[wizardSettingsKey]);
|
|
126
|
+
let windowModalProps;
|
|
127
|
+
if (isWindowMode) {
|
|
128
|
+
const size = persistedWizardSettings?.size ?? wizardOptions?.size ?? getWizardSize();
|
|
129
|
+
const position = persistedWizardSettings?.position ?? wizardOptions?.position ?? getMiddlePosition(size);
|
|
130
|
+
windowModalProps = {
|
|
131
|
+
handleSelector: '.ab-OnePageWizard__header',
|
|
132
|
+
minHeight: 460,
|
|
133
|
+
minWidth: 400,
|
|
134
|
+
size,
|
|
135
|
+
position,
|
|
136
|
+
onChange: (settings) => {
|
|
137
|
+
dispatch(SettingsPanelSet(wizardSettingsKey, settings));
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return (_jsx(NamedQueryContext.Provider, { value: { namedQuery, setNamedQuery }, children: _jsx(OnePageWizardContext.Provider, { value: contextValue, children: _jsx(Dialog, { modal: isWindowMode ? false : props.modal ?? true, windowModal: isWindowMode, windowModalProps: windowModalProps, fixed: !isWindowMode, isOpen: true, showCloseButton: false, focusOnBrowserVisible: true, className: cn('twa:rounded-standard twa:overflow-hidden', isWindowMode ? 'twa:h-full' : 'twa:h-[90vh]'), ref: dialogRef, onDismiss: () => props.onHide?.(), onKeyDown: (event) => {
|
|
117
142
|
if (event.metaKey || event.ctrlKey) {
|
|
118
143
|
const { key } = event;
|
|
119
144
|
if (!isNaN(Number(key))) {
|
|
@@ -129,7 +154,7 @@ export const OnePageWizard = (props) => {
|
|
|
129
154
|
}
|
|
130
155
|
}
|
|
131
156
|
}
|
|
132
|
-
}, children: _jsxs(Box, { className: cn('ab-OnePageWizard twa:flex twa:flex-col twa:h-full twa:w-[90vw] twa:max-w-[1200px]', 'twa:bg-primarylight twa:text-primary-foreground'), "data-name": props.name, style: props.style, children: [(props.moduleName || activeSectionDetails) && (_jsxs(Box, { className: cn('ab-OnePageWizard__header', ONE_PAGE_WIZARD_SECTION_GRID, 'twa:items-start twa:my-3 twa:px-2'), children: [_jsx(Box, { className: "ab-OnePageWizard__module-name twa:min-w-0 twa:pl-3 twa:font-bold", children: props.moduleName }), _jsx(Box, { className: "ab-OnePageWizard__details twa:min-w-0 twa:pr-2 twa:text-4", children: activeSectionDetails })] })), _jsx(Box, { as: "hr", className: "ab-OnePageWizard__module-separator twa:w-full twa:border-0 twa:border-t twa:border-t-input-border twa:mb-2" }), _jsxs(Box, { className: cn(ONE_PAGE_WIZARD_SECTION_GRID, 'twa:flex-1 twa:min-h-0 twa:overflow-auto twa:items-stretch'), children: [_jsxs(Flex, { flexDirection: "column", className: "ab-OnePageWizard__section-title-container twa:min-h-0 twa:min-w-0 twa:overflow-auto twa:p-3 twa:relative", ref: sizeOwnerRef, style: props.titleContainerStyle, children: [visibleSections.map((section, index) => {
|
|
157
|
+
}, children: _jsxs(Box, { className: cn('ab-OnePageWizard twa:flex twa:flex-col twa:h-full', isWindowMode ? 'twa:w-full' : 'twa:w-[90vw] twa:max-w-[1200px]', 'twa:bg-primarylight twa:text-primary-foreground'), "data-name": props.name, style: props.style, children: [(props.moduleName || activeSectionDetails) && (_jsxs(Box, { className: cn('ab-OnePageWizard__header', ONE_PAGE_WIZARD_SECTION_GRID, 'twa:items-start twa:my-3 twa:px-2'), children: [_jsx(Box, { className: "ab-OnePageWizard__module-name twa:min-w-0 twa:pl-3 twa:font-bold", children: props.moduleName }), _jsx(Box, { className: "ab-OnePageWizard__details twa:min-w-0 twa:pr-2 twa:text-4", children: activeSectionDetails })] })), _jsx(Box, { as: "hr", className: "ab-OnePageWizard__module-separator twa:w-full twa:border-0 twa:border-t twa:border-t-input-border twa:mb-2" }), _jsxs(Box, { className: cn(ONE_PAGE_WIZARD_SECTION_GRID, 'twa:flex-1 twa:min-h-0 twa:overflow-auto twa:items-stretch'), children: [_jsxs(Flex, { flexDirection: "column", className: "ab-OnePageWizard__section-title-container twa:min-h-0 twa:min-w-0 twa:overflow-auto twa:p-3 twa:relative", ref: sizeOwnerRef, style: props.titleContainerStyle, children: [visibleSections.map((section, index) => {
|
|
133
158
|
if (section === '-') {
|
|
134
159
|
return (_jsx(Box, { as: "hr", className: "ab-OnePageWizard__section-separator twa:mt-2 twa:w-full twa:border-t twa:border-t-input-border" }, `${index}-`));
|
|
135
160
|
}
|
|
@@ -81,6 +81,7 @@ import { ONLY_AGG_FN_NAME, WEIGHTED_AVERAGE_AGG_FN_NAME, } from '../AdaptableSta
|
|
|
81
81
|
import { RowFormService } from '../Utilities/Services/RowFormService';
|
|
82
82
|
import { ADAPTABLE_PUBLISH_TIMESTAMP } from '../EnvVars';
|
|
83
83
|
import { AdaptableUpgradeHelper } from '../migration/AdaptableUpgradeHelper';
|
|
84
|
+
import { stripDeprecatedStateKeys } from '../migration/DeprecatedStateKeys';
|
|
84
85
|
import { ensureLoadingScreenPortalElement } from '../components/Modal';
|
|
85
86
|
import { AdaptableLoadingScreen } from '../View/Components/Popups/AdaptableLoadingScreen';
|
|
86
87
|
import { createElement } from 'react';
|
|
@@ -521,6 +522,7 @@ export class AdaptableAgGrid {
|
|
|
521
522
|
});
|
|
522
523
|
}
|
|
523
524
|
normalizeAdaptableState(state, agGridOptions) {
|
|
525
|
+
state = stripDeprecatedStateKeys(state, this.logger);
|
|
524
526
|
state = this.normaliseLayoutState(state, agGridOptions);
|
|
525
527
|
state = this.normaliseToolPanelState(state);
|
|
526
528
|
return state;
|
package/src/env.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
NEXT_PUBLIC_INFINITE_TABLE_LICENSE_KEY: "StartDate=2021-06-29|EndDate=2030-01-01|Owner=Adaptable|Type=distribution|TS=1624971462479|C=137829811,1004007071,2756196225,1839832928,3994409405,636616862" || '',
|
|
3
|
-
PUBLISH_TIMESTAMP:
|
|
4
|
-
VERSION: "23.0.
|
|
3
|
+
PUBLISH_TIMESTAMP: 1782993623253 || Date.now(),
|
|
4
|
+
VERSION: "23.0.7" || '--current-version--',
|
|
5
5
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { AdaptableLogger } from '../agGrid/AdaptableLogger';
|
|
2
|
+
export interface DeprecatedStateKeyInfo {
|
|
3
|
+
/** AdapTable major version in which the key was removed from `AdaptableState`. */
|
|
4
|
+
removedInVersion: number;
|
|
5
|
+
/**
|
|
6
|
+
* Optional short pointer to the replacement feature(s). Only appended to the
|
|
7
|
+
* info message when the deprecated slice actually had content (i.e. the
|
|
8
|
+
* value is a non-empty object). Empty slices — e.g. someone leaving
|
|
9
|
+
* `Schedule: {}` in their `initialState` — get the base message only, since
|
|
10
|
+
* they have nothing to migrate.
|
|
11
|
+
*/
|
|
12
|
+
replacement?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Top-level `AdaptableState` keys that used to exist but have since been
|
|
16
|
+
* removed from AdapTable's state shape.
|
|
17
|
+
*
|
|
18
|
+
* On load, `stripDeprecatedStateKeys` quietly removes any of these keys from
|
|
19
|
+
* the incoming state and logs a single friendly `info` line per key — instead
|
|
20
|
+
* of letting Redux's `combineReducers` surface its more alarming
|
|
21
|
+
* `Unexpected key "…" found in previous state received by the reducer` warning.
|
|
22
|
+
*
|
|
23
|
+
* When you drop a top-level state slice, add it here so upgrading users with
|
|
24
|
+
* either an older persisted state or a stale `initialState` block in their
|
|
25
|
+
* `AdaptableOptions` see a soft, actionable message rather than a raw Redux
|
|
26
|
+
* dev-tools warning.
|
|
27
|
+
*/
|
|
28
|
+
export declare const DEPRECATED_TOP_LEVEL_STATE_KEYS: Readonly<Record<string, DeprecatedStateKeyInfo>>;
|
|
29
|
+
/**
|
|
30
|
+
* Remove any known-deprecated top-level keys from an incoming state object and
|
|
31
|
+
* log a friendly `info` message per stripped key. Unknown keys are left alone
|
|
32
|
+
* so Redux still surfaces genuinely unexpected state entries.
|
|
33
|
+
*
|
|
34
|
+
* Returns a shallow-cloned state with the deprecated keys removed, or the
|
|
35
|
+
* original state reference when nothing needed stripping.
|
|
36
|
+
*/
|
|
37
|
+
export declare function stripDeprecatedStateKeys<T extends Record<string, any>>(state: T, logger?: Pick<AdaptableLogger, 'consoleInfo'>): T;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const DEPRECATED_TOP_LEVEL_STATE_KEYS = {
|
|
2
|
+
Schedule: {
|
|
3
|
+
removedInVersion: 23,
|
|
4
|
+
replacement: 'Use Scheduled Alerts for time-based triggers, or move Report schedules onto Export state.',
|
|
5
|
+
},
|
|
6
|
+
};
|
|
7
|
+
const INTERNAL_STATE_METADATA_KEYS = new Set([
|
|
8
|
+
'Uuid',
|
|
9
|
+
'AdaptableVersion',
|
|
10
|
+
'Source',
|
|
11
|
+
'Revision',
|
|
12
|
+
]);
|
|
13
|
+
export function stripDeprecatedStateKeys(state, logger) {
|
|
14
|
+
if (!state || typeof state !== 'object') {
|
|
15
|
+
return state;
|
|
16
|
+
}
|
|
17
|
+
let cleanedState = state;
|
|
18
|
+
let didStrip = false;
|
|
19
|
+
for (const [key, info] of Object.entries(DEPRECATED_TOP_LEVEL_STATE_KEYS)) {
|
|
20
|
+
const value = state[key];
|
|
21
|
+
if (value === undefined) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (!didStrip) {
|
|
25
|
+
cleanedState = { ...state };
|
|
26
|
+
didStrip = true;
|
|
27
|
+
}
|
|
28
|
+
delete cleanedState[key];
|
|
29
|
+
const hasContent = value !== null &&
|
|
30
|
+
typeof value === 'object' &&
|
|
31
|
+
Object.keys(value).some((k) => !INTERNAL_STATE_METADATA_KEYS.has(k));
|
|
32
|
+
const message = `Deprecated state key "${key}" was removed in AdapTable v${info.removedInVersion} and will be ignored.` +
|
|
33
|
+
(hasContent && info.replacement ? ` ${info.replacement}` : '');
|
|
34
|
+
if (logger?.consoleInfo) {
|
|
35
|
+
logger.consoleInfo(message);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
console.info(message);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return cleanedState;
|
|
42
|
+
}
|
|
@@ -2,6 +2,15 @@ import { VersionUpgrade } from './VersionUpgrade';
|
|
|
2
2
|
import { AdaptableState } from '../AdaptableState/AdaptableState';
|
|
3
3
|
export declare class VersionUpgrade23 extends VersionUpgrade {
|
|
4
4
|
migrateState(state: AdaptableState): AdaptableState;
|
|
5
|
+
/**
|
|
6
|
+
* Logs a one-line summary of each populated sub-collection on the legacy
|
|
7
|
+
* `Schedule` slice so users can see exactly what they had before v23 removed
|
|
8
|
+
* the slice. The actual key removal is done later by
|
|
9
|
+
* `stripDeprecatedStateKeys` (in `normalizeAdaptableState`) so that the
|
|
10
|
+
* friendly "Schedule was removed…" info line always fires whenever `Schedule`
|
|
11
|
+
* is present — even when the slice is empty (e.g. someone left
|
|
12
|
+
* `Schedule: {}` in their `initialState`) or when `autoMigrateState` is off.
|
|
13
|
+
*/
|
|
5
14
|
private migrateSchedulingState;
|
|
6
15
|
/**
|
|
7
16
|
* v22 Percent Bar stored cell-text overlay settings as flat
|
|
@@ -43,8 +43,7 @@ export class VersionUpgrade23 extends VersionUpgrade {
|
|
|
43
43
|
if (removedReminderCount > 0) {
|
|
44
44
|
this.logger.info(`Removed ${removedReminderCount} legacy Reminders from Schedule state.`);
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
return stateWithoutSchedule;
|
|
46
|
+
return state;
|
|
48
47
|
}
|
|
49
48
|
migratePercentBarCellText(state) {
|
|
50
49
|
const columns = state.StyledColumn?.StyledColumns;
|
package/src/types.d.ts
CHANGED
|
@@ -51,7 +51,8 @@ export type { ToolPanelOptions, CustomToolPanel, ToolPanelButtonContext, CustomT
|
|
|
51
51
|
export type { UserInterfaceOptions, LoadingScreenOptions, ObjectTagsContext, CustomIcon, } from './AdaptableOptions/UserInterfaceOptions';
|
|
52
52
|
export type { ContextMenuOptions, AdaptableSystemContextMenuItem, CustomContextMenuContext, CustomContextMenuItem, UserContextMenuItem, AgGridContextMenuItemType, DefaultAdaptableMenuStructure, DefaultAgGridMenuStructure, CustomGroupContextMenuItem, } from './AdaptableOptions/ContextMenuOptions';
|
|
53
53
|
export type { ColumnMenuOptions, CustomColumnMenuContext, CustomColumnMenuItem, UserColumnMenuItem, AdaptableSystemColumnMenuItem, AgGridColumnMenuItemType, CustomGroupColumnMenuItem, } from './AdaptableOptions/ColumnMenuOptions';
|
|
54
|
-
export type { CustomSettingsPanel, SettingsPanelOptions, SettingsPanelNavigation, SettingsPanelNavigationGroup, SettingsPanelNavigationContext, SettingsPanelNavigationConfigurer, LegacyFlatSettingsPanelNavigation,
|
|
54
|
+
export type { CustomSettingsPanel, SettingsPanelOptions, SettingsPanelNavigation, SettingsPanelNavigationGroup, SettingsPanelNavigationContext, SettingsPanelNavigationConfigurer, LegacyFlatSettingsPanelNavigation, PopupType, } from './AdaptableOptions/SettingsPanelOptions';
|
|
55
|
+
export type { WizardOptions } from './AdaptableOptions/WizardOptions';
|
|
55
56
|
export type { EntitlementOptions, EntitlementContext, DefaultAccessLevelContext, } from './AdaptableOptions/EntitlementOptions';
|
|
56
57
|
export type { EvaluateExpressionExternallyContext, ExpressionOptions, ModuleExpressionFunctions, ModuleExpressionFunctionsMap, GlobalExpressionFunctionsContext, ModuleExpressionFunctionsContext, CustomQueryVariableContext, QueryableColumnContext, AdaptableFieldContext, } from './AdaptableOptions/ExpressionOptions';
|
|
57
58
|
export type { PredicateOptions, SystemPredicatesContext, } from './AdaptableOptions/PredicateOptions';
|
|
@@ -231,5 +232,6 @@ export type { Fdc3Options, GridDataContextMapping, ActionColumnDefaultConfigurat
|
|
|
231
232
|
export type { CommentState, CommentThread, AdaptableComment } from './AdaptableState/CommentState';
|
|
232
233
|
export type { UpgradeConfig } from '../agGrid';
|
|
233
234
|
export type { ProgressIndicatorConfig } from './AdaptableState/Common/ProgressIndicatorConfig';
|
|
234
|
-
export type { CustomWindowConfig
|
|
235
|
+
export type { CustomWindowConfig } from './AdaptableState/Common/CustomWindowConfig';
|
|
236
|
+
export type { WindowPosition, WindowSize } from './AdaptableState/Common/Window';
|
|
235
237
|
export type { TransposeConfig } from './AdaptableState/Common/TransposeConfig';
|