@gravity-ui/dashkit 8.9.1 → 8.10.1
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/README.md +4 -0
- package/build/cjs/components/DashKit/DashKit.d.ts +5 -0
- package/build/cjs/components/GridItem/GridItem.js +30 -2
- package/build/cjs/components/GridLayout/GridLayout.js +2 -2
- package/build/cjs/components/Item/Item.d.ts +2 -0
- package/build/cjs/components/Item/Item.js +13 -2
- package/build/cjs/hocs/prepareItem.d.ts +2 -0
- package/build/cjs/hocs/prepareItem.js +6 -3
- package/build/cjs/hocs/withContext.js +4 -0
- package/build/cjs/hooks/useCalcLayout.d.ts +2 -2
- package/build/cjs/plugins/Text/Text.d.ts +1 -0
- package/build/cjs/plugins/Text/Text.js +2 -0
- package/build/cjs/typings/plugin.d.ts +1 -0
- package/build/cjs/utils/__tests__/update-manager.test.js +98 -0
- package/build/cjs/utils/register-manager.d.ts +2 -2
- package/build/cjs/utils/update-manager.d.ts +2 -2
- package/build/cjs/utils/update-manager.js +4 -3
- package/build/esm/components/DashKit/DashKit.d.ts +5 -0
- package/build/esm/components/GridItem/GridItem.js +30 -2
- package/build/esm/components/GridLayout/GridLayout.js +2 -2
- package/build/esm/components/Item/Item.d.ts +2 -0
- package/build/esm/components/Item/Item.js +13 -2
- package/build/esm/hocs/prepareItem.d.ts +2 -0
- package/build/esm/hocs/prepareItem.js +6 -3
- package/build/esm/hocs/withContext.js +4 -0
- package/build/esm/hooks/useCalcLayout.d.ts +2 -2
- package/build/esm/plugins/Text/Text.d.ts +1 -0
- package/build/esm/plugins/Text/Text.js +2 -0
- package/build/esm/typings/plugin.d.ts +1 -0
- package/build/esm/utils/__tests__/update-manager.test.js +98 -0
- package/build/esm/utils/register-manager.d.ts +2 -2
- package/build/esm/utils/update-manager.d.ts +2 -2
- package/build/esm/utils/update-manager.js +4 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,6 +30,8 @@ interface DashKitProps {
|
|
|
30
30
|
onItemEdit: ({id}: {id: string}) => void;
|
|
31
31
|
onChange: (data: {config: Config; itemsStateAndParams: ItemsStateAndParams}) => void;
|
|
32
32
|
onDrop: (dropProps: ItemDropProps) => void;
|
|
33
|
+
onItemMountChange: (item: ConfigItem, state: {isAsync: boolead; isMounted: boolean}) => void;
|
|
34
|
+
onItemRender: (item: ConfigItem) => void;
|
|
33
35
|
defaultGlobalParams: GlobalParams;
|
|
34
36
|
globalParams: GlobalParams;
|
|
35
37
|
itemsStateAndParams: ItemsStateAndParams;
|
|
@@ -48,6 +50,8 @@ interface DashKitProps {
|
|
|
48
50
|
- **onItemEdit**: Called when you click to edit a widget.
|
|
49
51
|
- **onChange**: Called when config or [itemsStateAndParams](#temsStateAndParams) are changed.
|
|
50
52
|
- **onDrop**: Called when item dropped from ActionPanel using (#DashKitDnDWrapper)
|
|
53
|
+
- **onItemMountChange**: Called when item mount state changed
|
|
54
|
+
- **onItemRender**: Called when item render complete
|
|
51
55
|
- **defaultGlobalParams**, **globalParams**: [Parameters](#Params) that affect all widgets. In DataLens, `defaultGlobalParams` are global parameters set in the dashboard settings. `globalParams` are globals parameters that can be set in the url.
|
|
52
56
|
- **itemsStateAndParams**: [itemsStateAndParams](#temsStateAndParams).
|
|
53
57
|
- **settings**: DashKit settings.
|
|
@@ -18,6 +18,11 @@ interface DashKitDefaultProps {
|
|
|
18
18
|
groups?: DashKitGroup[];
|
|
19
19
|
}) => void;
|
|
20
20
|
onDrop: (dropProps: ItemDropProps) => void;
|
|
21
|
+
onItemMountChange?: (item: ConfigItem, state: {
|
|
22
|
+
isAsync: boolean;
|
|
23
|
+
isMounted: boolean;
|
|
24
|
+
}) => void;
|
|
25
|
+
onItemRender?: (item: ConfigItem) => void;
|
|
21
26
|
defaultGlobalParams: GlobalParams;
|
|
22
27
|
globalParams: GlobalParams;
|
|
23
28
|
itemsStateAndParams: ItemsStateAndParams;
|
|
@@ -38,6 +38,7 @@ const windowFocusObserver = new WindowFocusObserver();
|
|
|
38
38
|
class GridItem extends react_1.default.PureComponent {
|
|
39
39
|
constructor() {
|
|
40
40
|
super(...arguments);
|
|
41
|
+
this._isAsyncItem = false;
|
|
41
42
|
this.state = {
|
|
42
43
|
isFocused: false,
|
|
43
44
|
};
|
|
@@ -56,6 +57,33 @@ class GridItem extends react_1.default.PureComponent {
|
|
|
56
57
|
this.controller = null;
|
|
57
58
|
});
|
|
58
59
|
};
|
|
60
|
+
this.onMountChange = (isMounted) => {
|
|
61
|
+
var _a, _b, _c, _d, _e, _f;
|
|
62
|
+
if (isMounted) {
|
|
63
|
+
this._inited = true;
|
|
64
|
+
(_b = (_a = this.props).onItemMountChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item, {
|
|
65
|
+
isAsync: this._isAsyncItem,
|
|
66
|
+
isMounted: isMounted,
|
|
67
|
+
});
|
|
68
|
+
if (!this._isAsyncItem) {
|
|
69
|
+
(_d = (_c = this.props).onItemRender) === null || _d === void 0 ? void 0 : _d.call(_c, this.props.item);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
(_f = (_e = this.props).onItemMountChange) === null || _f === void 0 ? void 0 : _f.call(_e, this.props.item, {
|
|
74
|
+
isAsync: this._isAsyncItem,
|
|
75
|
+
isMounted: isMounted,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
this.onBeforeLoad = () => {
|
|
80
|
+
this._isAsyncItem = true;
|
|
81
|
+
return this.onLoad;
|
|
82
|
+
};
|
|
83
|
+
this.onLoad = () => {
|
|
84
|
+
var _a, _b;
|
|
85
|
+
(_b = (_a = this.props).onItemRender) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item);
|
|
86
|
+
};
|
|
59
87
|
}
|
|
60
88
|
renderOverlay() {
|
|
61
89
|
const { isPlaceholder } = this.props;
|
|
@@ -71,7 +99,7 @@ class GridItem extends react_1.default.PureComponent {
|
|
|
71
99
|
render() {
|
|
72
100
|
// из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
|
|
73
101
|
// https://github.com/STRML/react-grid-layout/issues/721
|
|
74
|
-
const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, isPlaceholder, } = this.props;
|
|
102
|
+
const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, isPlaceholder = false, } = this.props;
|
|
75
103
|
const { editMode } = this.context;
|
|
76
104
|
const width = Number.parseInt(style.width, 10);
|
|
77
105
|
const height = Number.parseInt(style.height, 10);
|
|
@@ -96,7 +124,7 @@ class GridItem extends react_1.default.PureComponent {
|
|
|
96
124
|
}
|
|
97
125
|
: {})),
|
|
98
126
|
react_1.default.createElement("div", { className: b('item', { editMode: editMode && !_editActive && !noOverlay }) },
|
|
99
|
-
react_1.default.createElement(Item_1.default, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, isPlaceholder: isPlaceholder, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef })),
|
|
127
|
+
react_1.default.createElement(Item_1.default, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, isPlaceholder: isPlaceholder, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef, onMountChange: this.onMountChange, onBeforeLoad: this.onBeforeLoad })),
|
|
100
128
|
!noOverlay && this.renderOverlay(),
|
|
101
129
|
preparedChildren));
|
|
102
130
|
}
|
|
@@ -287,7 +287,7 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
287
287
|
return (react_1.default.createElement(GridItem_1.default, { key: id, id: id, item: { id, type, data: {} }, layout: temporaryLayout.data, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, isPlaceholder: true, noOverlay: noOverlay, withCustomHandle: Boolean(draggableHandleClassName) }));
|
|
288
288
|
}
|
|
289
289
|
renderGroup(group, renderLayout, renderItems, offset = 0, groupGridProperties) {
|
|
290
|
-
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
290
|
+
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, onItemMountChange, onItemRender, } = this.context;
|
|
291
291
|
const { currentDraggingElement, draggedOverGroup } = this.state;
|
|
292
292
|
const properties = groupGridProperties
|
|
293
293
|
? groupGridProperties(Object.assign({}, registerManager.gridLayout))
|
|
@@ -310,7 +310,7 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
310
310
|
}
|
|
311
311
|
: null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
312
312
|
renderItems.map((item, i) => {
|
|
313
|
-
return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName) }));
|
|
313
|
+
return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), onItemMountChange: onItemMountChange, onItemRender: onItemRender }));
|
|
314
314
|
}),
|
|
315
315
|
this.renderTemporaryPlaceholder()));
|
|
316
316
|
}
|
|
@@ -61,7 +61,9 @@ declare const _default: {
|
|
|
61
61
|
height: PropTypes.Requireable<number>;
|
|
62
62
|
transform: PropTypes.Requireable<string>;
|
|
63
63
|
isPlaceholder: PropTypes.Requireable<boolean>;
|
|
64
|
+
onBeforeLoad: PropTypes.Requireable<(...args: any[]) => any>;
|
|
64
65
|
forwardedPluginRef: PropTypes.Requireable<any>;
|
|
66
|
+
onMountChange: PropTypes.Requireable<(...args: any[]) => any>;
|
|
65
67
|
};
|
|
66
68
|
contextType: React.Context<any>;
|
|
67
69
|
};
|
|
@@ -7,9 +7,18 @@ const prepareItem_1 = require("../../hocs/prepareItem");
|
|
|
7
7
|
const cn_1 = require("../../utils/cn");
|
|
8
8
|
const b = (0, cn_1.cn)('dashkit-item');
|
|
9
9
|
// TODO: getDerivedStateFromError и заглушка с ошибкой
|
|
10
|
-
const Item = ({ registerManager, rendererProps, type, isPlaceholder, forwardedPluginRef }) => {
|
|
10
|
+
const Item = ({ registerManager, rendererProps, type, isPlaceholder, forwardedPluginRef, onMountChange, }) => {
|
|
11
11
|
var _a, _b;
|
|
12
|
-
|
|
12
|
+
const isRegisteredType = registerManager.check(type);
|
|
13
|
+
react_1.default.useLayoutEffect(() => {
|
|
14
|
+
if (isRegisteredType && !isPlaceholder) {
|
|
15
|
+
onMountChange === null || onMountChange === void 0 ? void 0 : onMountChange(true);
|
|
16
|
+
return () => {
|
|
17
|
+
onMountChange === null || onMountChange === void 0 ? void 0 : onMountChange(false);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}, []);
|
|
21
|
+
if (!isRegisteredType) {
|
|
13
22
|
console.warn(`type [${type}] не зарегистрирован`);
|
|
14
23
|
return null;
|
|
15
24
|
}
|
|
@@ -25,5 +34,7 @@ Item.propTypes = {
|
|
|
25
34
|
registerManager: prop_types_1.default.object,
|
|
26
35
|
type: prop_types_1.default.string,
|
|
27
36
|
isPlaceholder: prop_types_1.default.bool,
|
|
37
|
+
onMountChange: prop_types_1.default.func,
|
|
38
|
+
onBeforeLoad: prop_types_1.default.func,
|
|
28
39
|
};
|
|
29
40
|
exports.default = (0, prepareItem_1.prepareItem)(Item);
|
|
@@ -61,7 +61,9 @@ export function prepareItem(Component: any): {
|
|
|
61
61
|
height: PropTypes.Requireable<number>;
|
|
62
62
|
transform: PropTypes.Requireable<string>;
|
|
63
63
|
isPlaceholder: PropTypes.Requireable<boolean>;
|
|
64
|
+
onBeforeLoad: PropTypes.Requireable<(...args: any[]) => any>;
|
|
64
65
|
forwardedPluginRef: PropTypes.Requireable<any>;
|
|
66
|
+
onMountChange: PropTypes.Requireable<(...args: any[]) => any>;
|
|
65
67
|
};
|
|
66
68
|
contextType: React.Context<any>;
|
|
67
69
|
};
|
|
@@ -15,7 +15,7 @@ function prepareItem(Component) {
|
|
|
15
15
|
};
|
|
16
16
|
this._currentRenderProps = {};
|
|
17
17
|
this.getRenderProps = () => {
|
|
18
|
-
const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder } = this.props;
|
|
18
|
+
const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder, onBeforeLoad, } = this.props;
|
|
19
19
|
const { itemsState, itemsParams, registerManager, settings, context, editMode } = this.context;
|
|
20
20
|
const { data, defaults, namespace } = item;
|
|
21
21
|
const rendererProps = {
|
|
@@ -24,6 +24,7 @@ function prepareItem(Component) {
|
|
|
24
24
|
params: itemsParams[id],
|
|
25
25
|
state: itemsState[id],
|
|
26
26
|
onStateAndParamsChange: this._onStateAndParamsChange,
|
|
27
|
+
onBeforeLoad,
|
|
27
28
|
width,
|
|
28
29
|
height,
|
|
29
30
|
id,
|
|
@@ -55,10 +56,10 @@ function prepareItem(Component) {
|
|
|
55
56
|
return true;
|
|
56
57
|
}
|
|
57
58
|
render() {
|
|
58
|
-
const { item, isPlaceholder } = this.props;
|
|
59
|
+
const { item, isPlaceholder, forwardedPluginRef, onMountChange } = this.props;
|
|
59
60
|
const { registerManager } = this.context;
|
|
60
61
|
const { type } = item;
|
|
61
|
-
return (react_1.default.createElement(Component, { forwardedPluginRef:
|
|
62
|
+
return (react_1.default.createElement(Component, { forwardedPluginRef: forwardedPluginRef, rendererProps: this.getRenderProps(), registerManager: registerManager, type: type, isPlaceholder: isPlaceholder, onMountChange: onMountChange }));
|
|
62
63
|
}
|
|
63
64
|
},
|
|
64
65
|
_a.propTypes = {
|
|
@@ -71,7 +72,9 @@ function prepareItem(Component) {
|
|
|
71
72
|
height: prop_types_1.default.number,
|
|
72
73
|
transform: prop_types_1.default.string,
|
|
73
74
|
isPlaceholder: prop_types_1.default.bool,
|
|
75
|
+
onBeforeLoad: prop_types_1.default.func,
|
|
74
76
|
forwardedPluginRef: prop_types_1.default.any,
|
|
77
|
+
onMountChange: prop_types_1.default.func,
|
|
75
78
|
},
|
|
76
79
|
_a.contextType = DashKitContext_1.DashKitContext,
|
|
77
80
|
_a;
|
|
@@ -320,6 +320,8 @@ function useMemoStateContext(props) {
|
|
|
320
320
|
onItemStateAndParamsChange,
|
|
321
321
|
onDrop,
|
|
322
322
|
onDropDragOver,
|
|
323
|
+
onItemMountChange: props.onItemMountChange,
|
|
324
|
+
onItemRender: props.onItemRender,
|
|
323
325
|
layoutChange: onLayoutChange,
|
|
324
326
|
getItemsMeta,
|
|
325
327
|
reloadItems,
|
|
@@ -347,6 +349,8 @@ function useMemoStateContext(props) {
|
|
|
347
349
|
onDrop,
|
|
348
350
|
onDropDragOver,
|
|
349
351
|
onLayoutChange,
|
|
352
|
+
props.onItemMountChange,
|
|
353
|
+
props.onItemRender,
|
|
350
354
|
getItemsMeta,
|
|
351
355
|
reloadItems,
|
|
352
356
|
memorizeOriginalLayout,
|
|
@@ -7,8 +7,8 @@ export declare const useCalcPropsLayout: (config: Config, registerManager: Regis
|
|
|
7
7
|
x: number;
|
|
8
8
|
y: number;
|
|
9
9
|
parent?: string | undefined;
|
|
10
|
-
minW
|
|
11
|
-
minH
|
|
10
|
+
minW?: number | undefined;
|
|
11
|
+
minH?: number | undefined;
|
|
12
12
|
maxW?: number | undefined;
|
|
13
13
|
maxH?: number | undefined;
|
|
14
14
|
}[];
|
|
@@ -80,6 +80,7 @@ class PluginText extends react_1.default.PureComponent {
|
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
82
82
|
this.setState({ status: LoadStatus.Pending });
|
|
83
|
+
const onLoadComplete = this.props.onBeforeLoad();
|
|
83
84
|
try {
|
|
84
85
|
let htmlText = '';
|
|
85
86
|
if (this.state.text && this.state.text.trim()) {
|
|
@@ -100,6 +101,7 @@ class PluginText extends react_1.default.PureComponent {
|
|
|
100
101
|
}
|
|
101
102
|
this.setState({ status: LoadStatus.Fail });
|
|
102
103
|
}
|
|
104
|
+
onLoadComplete();
|
|
103
105
|
}
|
|
104
106
|
get withMarkdown() {
|
|
105
107
|
return typeof this.props.apiHandler === 'function';
|
|
@@ -8,6 +8,7 @@ export interface PluginWidgetProps<T = StringParams> {
|
|
|
8
8
|
params: T;
|
|
9
9
|
state: ItemState;
|
|
10
10
|
onStateAndParamsChange: (stateAndParams: ItemStateAndParams, options?: ItemStateAndParamsChangeOptions) => void;
|
|
11
|
+
onBeforeLoad: () => () => void;
|
|
11
12
|
width: number;
|
|
12
13
|
height: number;
|
|
13
14
|
data: ConfigItem['data'];
|
|
@@ -188,6 +188,104 @@ beforeEach(() => {
|
|
|
188
188
|
jest.spyOn(console, 'warn').mockImplementation(jest.fn());
|
|
189
189
|
});
|
|
190
190
|
describe('UpdateManager', () => {
|
|
191
|
+
describe('addItem', () => {
|
|
192
|
+
it('add new item', () => {
|
|
193
|
+
expect(update_manager_1.UpdateManager.addItem({
|
|
194
|
+
item: {
|
|
195
|
+
data: {},
|
|
196
|
+
type: 'widget',
|
|
197
|
+
},
|
|
198
|
+
namespace: 'default',
|
|
199
|
+
layout: { h: 4, w: 4, x: 0, y: 0 },
|
|
200
|
+
config: config,
|
|
201
|
+
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 15, items: [
|
|
202
|
+
...config.items,
|
|
203
|
+
{
|
|
204
|
+
id: 'EZ',
|
|
205
|
+
data: {},
|
|
206
|
+
type: 'widget',
|
|
207
|
+
namespace: 'default',
|
|
208
|
+
},
|
|
209
|
+
], layout: [...config.layout, { h: 4, w: 4, x: 0, y: 32, i: 'EZ' }] }));
|
|
210
|
+
});
|
|
211
|
+
it('add new item excludeIds', () => {
|
|
212
|
+
expect(update_manager_1.UpdateManager.addItem({
|
|
213
|
+
item: {
|
|
214
|
+
data: {},
|
|
215
|
+
type: 'widget',
|
|
216
|
+
},
|
|
217
|
+
namespace: 'default',
|
|
218
|
+
layout: { h: 4, w: 4, x: 0, y: 0 },
|
|
219
|
+
config: config,
|
|
220
|
+
options: {
|
|
221
|
+
excludeIds: ['EZ'],
|
|
222
|
+
},
|
|
223
|
+
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 16, items: [
|
|
224
|
+
...config.items,
|
|
225
|
+
{
|
|
226
|
+
id: '1n',
|
|
227
|
+
data: {},
|
|
228
|
+
type: 'widget',
|
|
229
|
+
namespace: 'default',
|
|
230
|
+
},
|
|
231
|
+
], layout: [...config.layout, { h: 4, w: 4, x: 0, y: 32, i: '1n' }] }));
|
|
232
|
+
});
|
|
233
|
+
it('add new item with layout update', () => {
|
|
234
|
+
const updateLayout = [
|
|
235
|
+
{ h: 4, i: 'al', w: 4, x: 8, y: 4 },
|
|
236
|
+
{ h: 16, i: 'Q8', w: 12, x: 12, y: 4 },
|
|
237
|
+
{ h: 2, i: 'L5', w: 8, x: 0, y: 6 },
|
|
238
|
+
{ h: 2, i: 'C8', w: 8, x: 10, y: 34 },
|
|
239
|
+
{ h: 2, i: 'lko', w: 8, x: 0, y: 16 },
|
|
240
|
+
{ h: 2, i: 'qY', w: 8, x: 0, y: 28 },
|
|
241
|
+
];
|
|
242
|
+
expect(update_manager_1.UpdateManager.addItem({
|
|
243
|
+
item: {
|
|
244
|
+
data: {},
|
|
245
|
+
type: 'widget',
|
|
246
|
+
},
|
|
247
|
+
namespace: 'default',
|
|
248
|
+
layout: { h: 4, w: 12, x: 0, y: 0 },
|
|
249
|
+
config: config,
|
|
250
|
+
options: {
|
|
251
|
+
updateLayout,
|
|
252
|
+
},
|
|
253
|
+
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 15, items: [
|
|
254
|
+
...config.items,
|
|
255
|
+
{
|
|
256
|
+
id: 'EZ',
|
|
257
|
+
data: {},
|
|
258
|
+
type: 'widget',
|
|
259
|
+
namespace: 'default',
|
|
260
|
+
},
|
|
261
|
+
], layout: [...updateLayout, { h: 4, w: 12, x: 0, y: 0, i: 'EZ' }] }));
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
describe('removeItem', () => {
|
|
265
|
+
it('remove item by id', () => {
|
|
266
|
+
const deleteId = 'lko';
|
|
267
|
+
expect(update_manager_1.UpdateManager.removeItem({ id: deleteId, config, itemsStateAndParams: {} })).toEqual({
|
|
268
|
+
config: Object.assign(Object.assign({}, config), { items: config.items.filter(({ id }) => id !== deleteId), layout: config.layout.filter(({ i }) => i !== deleteId) }),
|
|
269
|
+
itemsStateAndParams: {
|
|
270
|
+
__meta__: { queue: [], version: 2 },
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
it('remove item when items and layout not sorted', () => {
|
|
275
|
+
const deleteId = 'lko';
|
|
276
|
+
const configCopy = Object.assign(Object.assign({}, config), { layout: config.layout.reverse() });
|
|
277
|
+
expect(update_manager_1.UpdateManager.removeItem({
|
|
278
|
+
id: deleteId,
|
|
279
|
+
config: configCopy,
|
|
280
|
+
itemsStateAndParams: {},
|
|
281
|
+
})).toEqual({
|
|
282
|
+
config: Object.assign(Object.assign({}, config), { items: config.items.filter(({ id }) => id !== deleteId), layout: config.layout.filter(({ i }) => i !== deleteId) }),
|
|
283
|
+
itemsStateAndParams: {
|
|
284
|
+
__meta__: { queue: [], version: 2 },
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
});
|
|
191
289
|
describe('changeStateAndParams', () => {
|
|
192
290
|
it('control adds params to empty itemsStateAndParams: common control', () => {
|
|
193
291
|
expect(update_manager_1.UpdateManager.changeStateAndParams({
|
|
@@ -5,8 +5,8 @@ interface RegisterManagerDefaultLayout {
|
|
|
5
5
|
y: number;
|
|
6
6
|
w: number;
|
|
7
7
|
h: number;
|
|
8
|
-
minW
|
|
9
|
-
minH
|
|
8
|
+
minW?: number;
|
|
9
|
+
minH?: number;
|
|
10
10
|
}
|
|
11
11
|
export type RegisterManagerPluginLayout = RegisterManagerDefaultLayout & PluginDefaultLayout;
|
|
12
12
|
export interface RegisterManagerPlugin extends Omit<Plugin, 'defaultLayout'> {
|
|
@@ -26,13 +26,13 @@ export declare class UpdateManager {
|
|
|
26
26
|
namespace: string;
|
|
27
27
|
layout: RegisterManagerPluginLayout;
|
|
28
28
|
config: Config;
|
|
29
|
-
options
|
|
29
|
+
options?: SetNewItemOptions;
|
|
30
30
|
}): Config;
|
|
31
31
|
static editItem({ item, namespace, config, options, }: {
|
|
32
32
|
item: ConfigItem;
|
|
33
33
|
namespace: string;
|
|
34
34
|
config: Config;
|
|
35
|
-
options
|
|
35
|
+
options?: SetItemOptions;
|
|
36
36
|
}): Config;
|
|
37
37
|
static removeItem({ id, config, itemsStateAndParams }: RemoveItemArg): {
|
|
38
38
|
config: Config;
|
|
@@ -227,7 +227,7 @@ function changeGroupParams({ groupItemIds, initiatorId, initiatorItem, itemsStat
|
|
|
227
227
|
return (0, immutability_helper_1.default)(itemsStateAndParams, obj);
|
|
228
228
|
}
|
|
229
229
|
class UpdateManager {
|
|
230
|
-
static addItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, layout, config, options, }) {
|
|
230
|
+
static addItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, layout, config, options = {}, }) {
|
|
231
231
|
const salt = config.salt;
|
|
232
232
|
const newItemData = getNewItemData({ item, config, salt, counter: config.counter, options });
|
|
233
233
|
let counter = newItemData.counter;
|
|
@@ -260,7 +260,7 @@ class UpdateManager {
|
|
|
260
260
|
});
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
|
-
static editItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, config, options, }) {
|
|
263
|
+
static editItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, config, options = {}, }) {
|
|
264
264
|
const itemIndex = config.items.findIndex(({ id }) => item.id === id);
|
|
265
265
|
const { counter, data } = getNewItemData({
|
|
266
266
|
item,
|
|
@@ -279,6 +279,7 @@ class UpdateManager {
|
|
|
279
279
|
return removeItemVersion1({ id, config, itemsStateAndParams });
|
|
280
280
|
}
|
|
281
281
|
const itemIndex = config.items.findIndex((item) => item.id === id);
|
|
282
|
+
const layoutIndex = config.layout.findIndex((item) => item.i === id);
|
|
282
283
|
const item = config.items[itemIndex];
|
|
283
284
|
let itemIds = [id];
|
|
284
285
|
if ((0, shared_1.isItemWithTabs)(item)) {
|
|
@@ -294,7 +295,7 @@ class UpdateManager {
|
|
|
294
295
|
$splice: [[itemIndex, 1]],
|
|
295
296
|
},
|
|
296
297
|
layout: {
|
|
297
|
-
$splice: [[
|
|
298
|
+
$splice: [[layoutIndex, 1]],
|
|
298
299
|
},
|
|
299
300
|
connections: {
|
|
300
301
|
$set: connections,
|
|
@@ -18,6 +18,11 @@ interface DashKitDefaultProps {
|
|
|
18
18
|
groups?: DashKitGroup[];
|
|
19
19
|
}) => void;
|
|
20
20
|
onDrop: (dropProps: ItemDropProps) => void;
|
|
21
|
+
onItemMountChange?: (item: ConfigItem, state: {
|
|
22
|
+
isAsync: boolean;
|
|
23
|
+
isMounted: boolean;
|
|
24
|
+
}) => void;
|
|
25
|
+
onItemRender?: (item: ConfigItem) => void;
|
|
21
26
|
defaultGlobalParams: GlobalParams;
|
|
22
27
|
globalParams: GlobalParams;
|
|
23
28
|
itemsStateAndParams: ItemsStateAndParams;
|
|
@@ -36,6 +36,7 @@ const windowFocusObserver = new WindowFocusObserver();
|
|
|
36
36
|
class GridItem extends React.PureComponent {
|
|
37
37
|
constructor() {
|
|
38
38
|
super(...arguments);
|
|
39
|
+
this._isAsyncItem = false;
|
|
39
40
|
this.state = {
|
|
40
41
|
isFocused: false,
|
|
41
42
|
};
|
|
@@ -54,6 +55,33 @@ class GridItem extends React.PureComponent {
|
|
|
54
55
|
this.controller = null;
|
|
55
56
|
});
|
|
56
57
|
};
|
|
58
|
+
this.onMountChange = (isMounted) => {
|
|
59
|
+
var _a, _b, _c, _d, _e, _f;
|
|
60
|
+
if (isMounted) {
|
|
61
|
+
this._inited = true;
|
|
62
|
+
(_b = (_a = this.props).onItemMountChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item, {
|
|
63
|
+
isAsync: this._isAsyncItem,
|
|
64
|
+
isMounted: isMounted,
|
|
65
|
+
});
|
|
66
|
+
if (!this._isAsyncItem) {
|
|
67
|
+
(_d = (_c = this.props).onItemRender) === null || _d === void 0 ? void 0 : _d.call(_c, this.props.item);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
(_f = (_e = this.props).onItemMountChange) === null || _f === void 0 ? void 0 : _f.call(_e, this.props.item, {
|
|
72
|
+
isAsync: this._isAsyncItem,
|
|
73
|
+
isMounted: isMounted,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
this.onBeforeLoad = () => {
|
|
78
|
+
this._isAsyncItem = true;
|
|
79
|
+
return this.onLoad;
|
|
80
|
+
};
|
|
81
|
+
this.onLoad = () => {
|
|
82
|
+
var _a, _b;
|
|
83
|
+
(_b = (_a = this.props).onItemRender) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item);
|
|
84
|
+
};
|
|
57
85
|
}
|
|
58
86
|
renderOverlay() {
|
|
59
87
|
const { isPlaceholder } = this.props;
|
|
@@ -69,7 +97,7 @@ class GridItem extends React.PureComponent {
|
|
|
69
97
|
render() {
|
|
70
98
|
// из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
|
|
71
99
|
// https://github.com/STRML/react-grid-layout/issues/721
|
|
72
|
-
const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, isPlaceholder, } = this.props;
|
|
100
|
+
const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, isPlaceholder = false, } = this.props;
|
|
73
101
|
const { editMode } = this.context;
|
|
74
102
|
const width = Number.parseInt(style.width, 10);
|
|
75
103
|
const height = Number.parseInt(style.height, 10);
|
|
@@ -94,7 +122,7 @@ class GridItem extends React.PureComponent {
|
|
|
94
122
|
}
|
|
95
123
|
: {})),
|
|
96
124
|
React.createElement("div", { className: b('item', { editMode: editMode && !_editActive && !noOverlay }) },
|
|
97
|
-
React.createElement(Item, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, isPlaceholder: isPlaceholder, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef })),
|
|
125
|
+
React.createElement(Item, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, isPlaceholder: isPlaceholder, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef, onMountChange: this.onMountChange, onBeforeLoad: this.onBeforeLoad })),
|
|
98
126
|
!noOverlay && this.renderOverlay(),
|
|
99
127
|
preparedChildren));
|
|
100
128
|
}
|
|
@@ -284,7 +284,7 @@ class GridLayout extends React.PureComponent {
|
|
|
284
284
|
return (React.createElement(GridItem, { key: id, id: id, item: { id, type, data: {} }, layout: temporaryLayout.data, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, isPlaceholder: true, noOverlay: noOverlay, withCustomHandle: Boolean(draggableHandleClassName) }));
|
|
285
285
|
}
|
|
286
286
|
renderGroup(group, renderLayout, renderItems, offset = 0, groupGridProperties) {
|
|
287
|
-
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
287
|
+
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, onItemMountChange, onItemRender, } = this.context;
|
|
288
288
|
const { currentDraggingElement, draggedOverGroup } = this.state;
|
|
289
289
|
const properties = groupGridProperties
|
|
290
290
|
? groupGridProperties(Object.assign({}, registerManager.gridLayout))
|
|
@@ -307,7 +307,7 @@ class GridLayout extends React.PureComponent {
|
|
|
307
307
|
}
|
|
308
308
|
: null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
309
309
|
renderItems.map((item, i) => {
|
|
310
|
-
return (React.createElement(GridItem, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName) }));
|
|
310
|
+
return (React.createElement(GridItem, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), onItemMountChange: onItemMountChange, onItemRender: onItemRender }));
|
|
311
311
|
}),
|
|
312
312
|
this.renderTemporaryPlaceholder()));
|
|
313
313
|
}
|
|
@@ -61,7 +61,9 @@ declare const _default: {
|
|
|
61
61
|
height: PropTypes.Requireable<number>;
|
|
62
62
|
transform: PropTypes.Requireable<string>;
|
|
63
63
|
isPlaceholder: PropTypes.Requireable<boolean>;
|
|
64
|
+
onBeforeLoad: PropTypes.Requireable<(...args: any[]) => any>;
|
|
64
65
|
forwardedPluginRef: PropTypes.Requireable<any>;
|
|
66
|
+
onMountChange: PropTypes.Requireable<(...args: any[]) => any>;
|
|
65
67
|
};
|
|
66
68
|
contextType: React.Context<any>;
|
|
67
69
|
};
|
|
@@ -5,9 +5,18 @@ import { cn } from '../../utils/cn';
|
|
|
5
5
|
import './Item.css';
|
|
6
6
|
const b = cn('dashkit-item');
|
|
7
7
|
// TODO: getDerivedStateFromError и заглушка с ошибкой
|
|
8
|
-
const Item = ({ registerManager, rendererProps, type, isPlaceholder, forwardedPluginRef }) => {
|
|
8
|
+
const Item = ({ registerManager, rendererProps, type, isPlaceholder, forwardedPluginRef, onMountChange, }) => {
|
|
9
9
|
var _a, _b;
|
|
10
|
-
|
|
10
|
+
const isRegisteredType = registerManager.check(type);
|
|
11
|
+
React.useLayoutEffect(() => {
|
|
12
|
+
if (isRegisteredType && !isPlaceholder) {
|
|
13
|
+
onMountChange === null || onMountChange === void 0 ? void 0 : onMountChange(true);
|
|
14
|
+
return () => {
|
|
15
|
+
onMountChange === null || onMountChange === void 0 ? void 0 : onMountChange(false);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}, []);
|
|
19
|
+
if (!isRegisteredType) {
|
|
11
20
|
console.warn(`type [${type}] не зарегистрирован`);
|
|
12
21
|
return null;
|
|
13
22
|
}
|
|
@@ -23,5 +32,7 @@ Item.propTypes = {
|
|
|
23
32
|
registerManager: PropTypes.object,
|
|
24
33
|
type: PropTypes.string,
|
|
25
34
|
isPlaceholder: PropTypes.bool,
|
|
35
|
+
onMountChange: PropTypes.func,
|
|
36
|
+
onBeforeLoad: PropTypes.func,
|
|
26
37
|
};
|
|
27
38
|
export default prepareItem(Item);
|
|
@@ -61,7 +61,9 @@ export function prepareItem(Component: any): {
|
|
|
61
61
|
height: PropTypes.Requireable<number>;
|
|
62
62
|
transform: PropTypes.Requireable<string>;
|
|
63
63
|
isPlaceholder: PropTypes.Requireable<boolean>;
|
|
64
|
+
onBeforeLoad: PropTypes.Requireable<(...args: any[]) => any>;
|
|
64
65
|
forwardedPluginRef: PropTypes.Requireable<any>;
|
|
66
|
+
onMountChange: PropTypes.Requireable<(...args: any[]) => any>;
|
|
65
67
|
};
|
|
66
68
|
contextType: React.Context<any>;
|
|
67
69
|
};
|
|
@@ -11,7 +11,7 @@ export function prepareItem(Component) {
|
|
|
11
11
|
};
|
|
12
12
|
this._currentRenderProps = {};
|
|
13
13
|
this.getRenderProps = () => {
|
|
14
|
-
const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder } = this.props;
|
|
14
|
+
const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder, onBeforeLoad, } = this.props;
|
|
15
15
|
const { itemsState, itemsParams, registerManager, settings, context, editMode } = this.context;
|
|
16
16
|
const { data, defaults, namespace } = item;
|
|
17
17
|
const rendererProps = {
|
|
@@ -20,6 +20,7 @@ export function prepareItem(Component) {
|
|
|
20
20
|
params: itemsParams[id],
|
|
21
21
|
state: itemsState[id],
|
|
22
22
|
onStateAndParamsChange: this._onStateAndParamsChange,
|
|
23
|
+
onBeforeLoad,
|
|
23
24
|
width,
|
|
24
25
|
height,
|
|
25
26
|
id,
|
|
@@ -51,10 +52,10 @@ export function prepareItem(Component) {
|
|
|
51
52
|
return true;
|
|
52
53
|
}
|
|
53
54
|
render() {
|
|
54
|
-
const { item, isPlaceholder } = this.props;
|
|
55
|
+
const { item, isPlaceholder, forwardedPluginRef, onMountChange } = this.props;
|
|
55
56
|
const { registerManager } = this.context;
|
|
56
57
|
const { type } = item;
|
|
57
|
-
return (React.createElement(Component, { forwardedPluginRef:
|
|
58
|
+
return (React.createElement(Component, { forwardedPluginRef: forwardedPluginRef, rendererProps: this.getRenderProps(), registerManager: registerManager, type: type, isPlaceholder: isPlaceholder, onMountChange: onMountChange }));
|
|
58
59
|
}
|
|
59
60
|
},
|
|
60
61
|
_a.propTypes = {
|
|
@@ -67,7 +68,9 @@ export function prepareItem(Component) {
|
|
|
67
68
|
height: PropTypes.number,
|
|
68
69
|
transform: PropTypes.string,
|
|
69
70
|
isPlaceholder: PropTypes.bool,
|
|
71
|
+
onBeforeLoad: PropTypes.func,
|
|
70
72
|
forwardedPluginRef: PropTypes.any,
|
|
73
|
+
onMountChange: PropTypes.func,
|
|
71
74
|
},
|
|
72
75
|
_a.contextType = DashKitContext,
|
|
73
76
|
_a;
|
|
@@ -317,6 +317,8 @@ function useMemoStateContext(props) {
|
|
|
317
317
|
onItemStateAndParamsChange,
|
|
318
318
|
onDrop,
|
|
319
319
|
onDropDragOver,
|
|
320
|
+
onItemMountChange: props.onItemMountChange,
|
|
321
|
+
onItemRender: props.onItemRender,
|
|
320
322
|
layoutChange: onLayoutChange,
|
|
321
323
|
getItemsMeta,
|
|
322
324
|
reloadItems,
|
|
@@ -344,6 +346,8 @@ function useMemoStateContext(props) {
|
|
|
344
346
|
onDrop,
|
|
345
347
|
onDropDragOver,
|
|
346
348
|
onLayoutChange,
|
|
349
|
+
props.onItemMountChange,
|
|
350
|
+
props.onItemRender,
|
|
347
351
|
getItemsMeta,
|
|
348
352
|
reloadItems,
|
|
349
353
|
memorizeOriginalLayout,
|
|
@@ -7,8 +7,8 @@ export declare const useCalcPropsLayout: (config: Config, registerManager: Regis
|
|
|
7
7
|
x: number;
|
|
8
8
|
y: number;
|
|
9
9
|
parent?: string | undefined;
|
|
10
|
-
minW
|
|
11
|
-
minH
|
|
10
|
+
minW?: number | undefined;
|
|
11
|
+
minH?: number | undefined;
|
|
12
12
|
maxW?: number | undefined;
|
|
13
13
|
maxH?: number | undefined;
|
|
14
14
|
}[];
|
|
@@ -77,6 +77,7 @@ export class PluginText extends React.PureComponent {
|
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
79
|
this.setState({ status: LoadStatus.Pending });
|
|
80
|
+
const onLoadComplete = this.props.onBeforeLoad();
|
|
80
81
|
try {
|
|
81
82
|
let htmlText = '';
|
|
82
83
|
if (this.state.text && this.state.text.trim()) {
|
|
@@ -97,6 +98,7 @@ export class PluginText extends React.PureComponent {
|
|
|
97
98
|
}
|
|
98
99
|
this.setState({ status: LoadStatus.Fail });
|
|
99
100
|
}
|
|
101
|
+
onLoadComplete();
|
|
100
102
|
}
|
|
101
103
|
get withMarkdown() {
|
|
102
104
|
return typeof this.props.apiHandler === 'function';
|
|
@@ -8,6 +8,7 @@ export interface PluginWidgetProps<T = StringParams> {
|
|
|
8
8
|
params: T;
|
|
9
9
|
state: ItemState;
|
|
10
10
|
onStateAndParamsChange: (stateAndParams: ItemStateAndParams, options?: ItemStateAndParamsChangeOptions) => void;
|
|
11
|
+
onBeforeLoad: () => () => void;
|
|
11
12
|
width: number;
|
|
12
13
|
height: number;
|
|
13
14
|
data: ConfigItem['data'];
|
|
@@ -186,6 +186,104 @@ beforeEach(() => {
|
|
|
186
186
|
jest.spyOn(console, 'warn').mockImplementation(jest.fn());
|
|
187
187
|
});
|
|
188
188
|
describe('UpdateManager', () => {
|
|
189
|
+
describe('addItem', () => {
|
|
190
|
+
it('add new item', () => {
|
|
191
|
+
expect(UpdateManager.addItem({
|
|
192
|
+
item: {
|
|
193
|
+
data: {},
|
|
194
|
+
type: 'widget',
|
|
195
|
+
},
|
|
196
|
+
namespace: 'default',
|
|
197
|
+
layout: { h: 4, w: 4, x: 0, y: 0 },
|
|
198
|
+
config: config,
|
|
199
|
+
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 15, items: [
|
|
200
|
+
...config.items,
|
|
201
|
+
{
|
|
202
|
+
id: 'EZ',
|
|
203
|
+
data: {},
|
|
204
|
+
type: 'widget',
|
|
205
|
+
namespace: 'default',
|
|
206
|
+
},
|
|
207
|
+
], layout: [...config.layout, { h: 4, w: 4, x: 0, y: 32, i: 'EZ' }] }));
|
|
208
|
+
});
|
|
209
|
+
it('add new item excludeIds', () => {
|
|
210
|
+
expect(UpdateManager.addItem({
|
|
211
|
+
item: {
|
|
212
|
+
data: {},
|
|
213
|
+
type: 'widget',
|
|
214
|
+
},
|
|
215
|
+
namespace: 'default',
|
|
216
|
+
layout: { h: 4, w: 4, x: 0, y: 0 },
|
|
217
|
+
config: config,
|
|
218
|
+
options: {
|
|
219
|
+
excludeIds: ['EZ'],
|
|
220
|
+
},
|
|
221
|
+
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 16, items: [
|
|
222
|
+
...config.items,
|
|
223
|
+
{
|
|
224
|
+
id: '1n',
|
|
225
|
+
data: {},
|
|
226
|
+
type: 'widget',
|
|
227
|
+
namespace: 'default',
|
|
228
|
+
},
|
|
229
|
+
], layout: [...config.layout, { h: 4, w: 4, x: 0, y: 32, i: '1n' }] }));
|
|
230
|
+
});
|
|
231
|
+
it('add new item with layout update', () => {
|
|
232
|
+
const updateLayout = [
|
|
233
|
+
{ h: 4, i: 'al', w: 4, x: 8, y: 4 },
|
|
234
|
+
{ h: 16, i: 'Q8', w: 12, x: 12, y: 4 },
|
|
235
|
+
{ h: 2, i: 'L5', w: 8, x: 0, y: 6 },
|
|
236
|
+
{ h: 2, i: 'C8', w: 8, x: 10, y: 34 },
|
|
237
|
+
{ h: 2, i: 'lko', w: 8, x: 0, y: 16 },
|
|
238
|
+
{ h: 2, i: 'qY', w: 8, x: 0, y: 28 },
|
|
239
|
+
];
|
|
240
|
+
expect(UpdateManager.addItem({
|
|
241
|
+
item: {
|
|
242
|
+
data: {},
|
|
243
|
+
type: 'widget',
|
|
244
|
+
},
|
|
245
|
+
namespace: 'default',
|
|
246
|
+
layout: { h: 4, w: 12, x: 0, y: 0 },
|
|
247
|
+
config: config,
|
|
248
|
+
options: {
|
|
249
|
+
updateLayout,
|
|
250
|
+
},
|
|
251
|
+
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 15, items: [
|
|
252
|
+
...config.items,
|
|
253
|
+
{
|
|
254
|
+
id: 'EZ',
|
|
255
|
+
data: {},
|
|
256
|
+
type: 'widget',
|
|
257
|
+
namespace: 'default',
|
|
258
|
+
},
|
|
259
|
+
], layout: [...updateLayout, { h: 4, w: 12, x: 0, y: 0, i: 'EZ' }] }));
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
describe('removeItem', () => {
|
|
263
|
+
it('remove item by id', () => {
|
|
264
|
+
const deleteId = 'lko';
|
|
265
|
+
expect(UpdateManager.removeItem({ id: deleteId, config, itemsStateAndParams: {} })).toEqual({
|
|
266
|
+
config: Object.assign(Object.assign({}, config), { items: config.items.filter(({ id }) => id !== deleteId), layout: config.layout.filter(({ i }) => i !== deleteId) }),
|
|
267
|
+
itemsStateAndParams: {
|
|
268
|
+
__meta__: { queue: [], version: 2 },
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
it('remove item when items and layout not sorted', () => {
|
|
273
|
+
const deleteId = 'lko';
|
|
274
|
+
const configCopy = Object.assign(Object.assign({}, config), { layout: config.layout.reverse() });
|
|
275
|
+
expect(UpdateManager.removeItem({
|
|
276
|
+
id: deleteId,
|
|
277
|
+
config: configCopy,
|
|
278
|
+
itemsStateAndParams: {},
|
|
279
|
+
})).toEqual({
|
|
280
|
+
config: Object.assign(Object.assign({}, config), { items: config.items.filter(({ id }) => id !== deleteId), layout: config.layout.filter(({ i }) => i !== deleteId) }),
|
|
281
|
+
itemsStateAndParams: {
|
|
282
|
+
__meta__: { queue: [], version: 2 },
|
|
283
|
+
},
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
});
|
|
189
287
|
describe('changeStateAndParams', () => {
|
|
190
288
|
it('control adds params to empty itemsStateAndParams: common control', () => {
|
|
191
289
|
expect(UpdateManager.changeStateAndParams({
|
|
@@ -5,8 +5,8 @@ interface RegisterManagerDefaultLayout {
|
|
|
5
5
|
y: number;
|
|
6
6
|
w: number;
|
|
7
7
|
h: number;
|
|
8
|
-
minW
|
|
9
|
-
minH
|
|
8
|
+
minW?: number;
|
|
9
|
+
minH?: number;
|
|
10
10
|
}
|
|
11
11
|
export type RegisterManagerPluginLayout = RegisterManagerDefaultLayout & PluginDefaultLayout;
|
|
12
12
|
export interface RegisterManagerPlugin extends Omit<Plugin, 'defaultLayout'> {
|
|
@@ -26,13 +26,13 @@ export declare class UpdateManager {
|
|
|
26
26
|
namespace: string;
|
|
27
27
|
layout: RegisterManagerPluginLayout;
|
|
28
28
|
config: Config;
|
|
29
|
-
options
|
|
29
|
+
options?: SetNewItemOptions;
|
|
30
30
|
}): Config;
|
|
31
31
|
static editItem({ item, namespace, config, options, }: {
|
|
32
32
|
item: ConfigItem;
|
|
33
33
|
namespace: string;
|
|
34
34
|
config: Config;
|
|
35
|
-
options
|
|
35
|
+
options?: SetItemOptions;
|
|
36
36
|
}): Config;
|
|
37
37
|
static removeItem({ id, config, itemsStateAndParams }: RemoveItemArg): {
|
|
38
38
|
config: Config;
|
|
@@ -222,7 +222,7 @@ function changeGroupParams({ groupItemIds, initiatorId, initiatorItem, itemsStat
|
|
|
222
222
|
return update(itemsStateAndParams, obj);
|
|
223
223
|
}
|
|
224
224
|
export class UpdateManager {
|
|
225
|
-
static addItem({ item, namespace = DEFAULT_NAMESPACE, layout, config, options, }) {
|
|
225
|
+
static addItem({ item, namespace = DEFAULT_NAMESPACE, layout, config, options = {}, }) {
|
|
226
226
|
const salt = config.salt;
|
|
227
227
|
const newItemData = getNewItemData({ item, config, salt, counter: config.counter, options });
|
|
228
228
|
let counter = newItemData.counter;
|
|
@@ -255,7 +255,7 @@ export class UpdateManager {
|
|
|
255
255
|
});
|
|
256
256
|
}
|
|
257
257
|
}
|
|
258
|
-
static editItem({ item, namespace = DEFAULT_NAMESPACE, config, options, }) {
|
|
258
|
+
static editItem({ item, namespace = DEFAULT_NAMESPACE, config, options = {}, }) {
|
|
259
259
|
const itemIndex = config.items.findIndex(({ id }) => item.id === id);
|
|
260
260
|
const { counter, data } = getNewItemData({
|
|
261
261
|
item,
|
|
@@ -274,6 +274,7 @@ export class UpdateManager {
|
|
|
274
274
|
return removeItemVersion1({ id, config, itemsStateAndParams });
|
|
275
275
|
}
|
|
276
276
|
const itemIndex = config.items.findIndex((item) => item.id === id);
|
|
277
|
+
const layoutIndex = config.layout.findIndex((item) => item.i === id);
|
|
277
278
|
const item = config.items[itemIndex];
|
|
278
279
|
let itemIds = [id];
|
|
279
280
|
if (isItemWithTabs(item)) {
|
|
@@ -289,7 +290,7 @@ export class UpdateManager {
|
|
|
289
290
|
$splice: [[itemIndex, 1]],
|
|
290
291
|
},
|
|
291
292
|
layout: {
|
|
292
|
-
$splice: [[
|
|
293
|
+
$splice: [[layoutIndex, 1]],
|
|
293
294
|
},
|
|
294
295
|
connections: {
|
|
295
296
|
$set: connections,
|