@gravity-ui/dashkit 8.11.0 → 8.12.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/build/cjs/components/DashKit/DashKit.d.ts +6 -4
- package/build/cjs/components/DashKit/DashKit.js +32 -6
- package/build/cjs/components/GridLayout/GridLayout.d.ts +1 -1
- package/build/cjs/components/GridLayout/GridLayout.js +20 -13
- package/build/cjs/components/GridLayout/ReactGridLayout.js +12 -4
- package/build/cjs/hocs/withContext.js +1 -1
- package/build/cjs/typings/config.d.ts +15 -3
- package/build/cjs/utils/__tests__/update-manager.test.js +63 -2
- package/build/cjs/utils/grid-layout.d.ts +4 -0
- package/build/cjs/utils/grid-layout.js +17 -0
- package/build/cjs/utils/update-manager.d.ts +4 -2
- package/build/cjs/utils/update-manager.js +72 -6
- package/build/esm/components/DashKit/DashKit.d.ts +6 -4
- package/build/esm/components/DashKit/DashKit.js +34 -8
- package/build/esm/components/GridLayout/GridLayout.d.ts +1 -1
- package/build/esm/components/GridLayout/GridLayout.js +20 -13
- package/build/esm/components/GridLayout/ReactGridLayout.js +12 -4
- package/build/esm/hocs/withContext.js +1 -1
- package/build/esm/typings/config.d.ts +15 -3
- package/build/esm/utils/__tests__/update-manager.test.js +63 -2
- package/build/esm/utils/grid-layout.d.ts +4 -0
- package/build/esm/utils/grid-layout.js +11 -0
- package/build/esm/utils/update-manager.d.ts +4 -2
- package/build/esm/utils/update-manager.js +71 -6
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { Config, ConfigItem, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
|
|
3
|
-
import { ContextProps, DashKitGroup, MenuItem, Plugin, SetConfigItem,
|
|
2
|
+
import type { Config, ConfigItem, ConfigLayout, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
|
|
3
|
+
import { AddNewItemOptions, ContextProps, DashKitGroup, MenuItem, Plugin, SetConfigItem, Settings, SettingsProps } from '../../typings';
|
|
4
4
|
import GridLayout from '../GridLayout/GridLayout';
|
|
5
5
|
import { OverlayControlItem } from '../OverlayControls/OverlayControls';
|
|
6
6
|
interface DashKitGeneralProps {
|
|
@@ -39,11 +39,12 @@ export declare class DashKit extends React.PureComponent<DashKitInnerProps> {
|
|
|
39
39
|
static defaultProps: DashKitDefaultProps;
|
|
40
40
|
static registerPlugins(...plugins: Plugin[]): void;
|
|
41
41
|
static setSettings(settings: Settings): void;
|
|
42
|
-
static setItem({ item: setItem, namespace, config, options, }: {
|
|
42
|
+
static setItem({ item: setItem, namespace, config, options, groups, }: {
|
|
43
43
|
item: SetConfigItem;
|
|
44
44
|
namespace?: string;
|
|
45
45
|
config: Config;
|
|
46
|
-
options?:
|
|
46
|
+
options?: Omit<AddNewItemOptions, 'reflowLayoutOptions'>;
|
|
47
|
+
groups?: DashKitGroup[];
|
|
47
48
|
}): Config;
|
|
48
49
|
static removeItem({ id, config, itemsStateAndParams, }: {
|
|
49
50
|
id: string;
|
|
@@ -53,6 +54,7 @@ export declare class DashKit extends React.PureComponent<DashKitInnerProps> {
|
|
|
53
54
|
config: Config;
|
|
54
55
|
itemsStateAndParams: ItemsStateAndParams;
|
|
55
56
|
};
|
|
57
|
+
static reflowLayout(newLayoutItem: ConfigLayout, layout: ConfigLayout[], groups?: DashKitGroup[]): ConfigLayout[];
|
|
56
58
|
metaRef: React.RefObject<GridLayout>;
|
|
57
59
|
render(): JSX.Element;
|
|
58
60
|
getItemsMeta(): any;
|
|
@@ -4,10 +4,25 @@ exports.DashKit = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
6
|
const noop_1 = tslib_1.__importDefault(require("lodash/noop"));
|
|
7
|
+
const pick_1 = tslib_1.__importDefault(require("lodash/pick"));
|
|
7
8
|
const constants_1 = require("../../constants");
|
|
8
9
|
const utils_1 = require("../../utils");
|
|
9
10
|
const DashKitView_1 = tslib_1.__importDefault(require("../DashKitView/DashKitView"));
|
|
10
11
|
const registerManager = new utils_1.RegisterManager();
|
|
12
|
+
const getReflowProps = (props) => Object.assign({ compactType: 'vertical', cols: 36 }, (0, pick_1.default)(props, 'cols', 'maxRows', 'compactType'));
|
|
13
|
+
const getReflowGroupsConfig = (groups = []) => {
|
|
14
|
+
const defaultGridProps = getReflowProps(registerManager.gridLayout);
|
|
15
|
+
return {
|
|
16
|
+
defaultProps: defaultGridProps,
|
|
17
|
+
groups: groups.reduce((memo, g) => {
|
|
18
|
+
const groupId = g.id || constants_1.DEFAULT_GROUP;
|
|
19
|
+
memo[groupId] = g.gridProperties
|
|
20
|
+
? getReflowProps(g.gridProperties(defaultGridProps))
|
|
21
|
+
: defaultGridProps;
|
|
22
|
+
return memo;
|
|
23
|
+
}, {}),
|
|
24
|
+
};
|
|
25
|
+
};
|
|
11
26
|
class DashKit extends react_1.default.PureComponent {
|
|
12
27
|
constructor() {
|
|
13
28
|
super(...arguments);
|
|
@@ -21,28 +36,39 @@ class DashKit extends react_1.default.PureComponent {
|
|
|
21
36
|
static setSettings(settings) {
|
|
22
37
|
registerManager.setSettings(settings);
|
|
23
38
|
}
|
|
24
|
-
static setItem({ item: setItem, namespace = constants_1.DEFAULT_NAMESPACE, config, options = {}, }) {
|
|
39
|
+
static setItem({ item: setItem, namespace = constants_1.DEFAULT_NAMESPACE, config, options = {}, groups = [], }) {
|
|
25
40
|
if (setItem.id) {
|
|
26
|
-
return utils_1.UpdateManager.editItem({
|
|
41
|
+
return utils_1.UpdateManager.editItem({
|
|
42
|
+
item: setItem,
|
|
43
|
+
namespace,
|
|
44
|
+
config,
|
|
45
|
+
options,
|
|
46
|
+
});
|
|
27
47
|
}
|
|
28
48
|
else {
|
|
29
49
|
const item = setItem;
|
|
30
50
|
const layout = Object.assign({}, registerManager.getItem(item.type).defaultLayout);
|
|
31
|
-
|
|
32
|
-
|
|
51
|
+
const reflowLayoutOptions = getReflowGroupsConfig(groups);
|
|
52
|
+
const copyItem = Object.assign({}, item);
|
|
53
|
+
if (copyItem.layout) {
|
|
54
|
+
Object.assign(layout, copyItem.layout);
|
|
55
|
+
delete copyItem.layout;
|
|
33
56
|
}
|
|
34
57
|
return utils_1.UpdateManager.addItem({
|
|
35
|
-
item,
|
|
58
|
+
item: copyItem,
|
|
36
59
|
namespace,
|
|
37
60
|
config,
|
|
38
61
|
layout,
|
|
39
|
-
options,
|
|
62
|
+
options: Object.assign(Object.assign({}, options), { reflowLayoutOptions }),
|
|
40
63
|
});
|
|
41
64
|
}
|
|
42
65
|
}
|
|
43
66
|
static removeItem({ id, config, itemsStateAndParams, }) {
|
|
44
67
|
return utils_1.UpdateManager.removeItem({ id, config, itemsStateAndParams });
|
|
45
68
|
}
|
|
69
|
+
static reflowLayout(newLayoutItem, layout, groups) {
|
|
70
|
+
return (0, utils_1.reflowLayout)(newLayoutItem, layout, getReflowGroupsConfig(groups));
|
|
71
|
+
}
|
|
46
72
|
render() {
|
|
47
73
|
return react_1.default.createElement(DashKitView_1.default, Object.assign({ registerManager: registerManager, ref: this.metaRef }, this.props));
|
|
48
74
|
}
|
|
@@ -38,7 +38,7 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
|
|
|
38
38
|
getMemoForwardRefCallback: (refIndex: any) => any;
|
|
39
39
|
mergeGroupsLayout(group: any, newLayout: any, temporaryItem: any): any;
|
|
40
40
|
reloadItems(): void;
|
|
41
|
-
_onDragStart: (group: any, _newLayout: any, layoutItem: any) => void;
|
|
41
|
+
_onDragStart: (group: any, _newLayout: any, layoutItem: any, _newItem: any, _placeholder: any, e: any) => void;
|
|
42
42
|
_onResizeStart: () => void;
|
|
43
43
|
_onTargetRestore: () => void;
|
|
44
44
|
_onStop: (group: any, newLayout: any) => void;
|
|
@@ -94,7 +94,7 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
94
94
|
}
|
|
95
95
|
return this._memoForwardedPluginRef[refIndex];
|
|
96
96
|
};
|
|
97
|
-
this._onDragStart = (group, _newLayout, layoutItem) => {
|
|
97
|
+
this._onDragStart = (group, _newLayout, layoutItem, _newItem, _placeholder, e) => {
|
|
98
98
|
if (this.temporaryLayout)
|
|
99
99
|
return;
|
|
100
100
|
if (this.context.dragOverPlugin) {
|
|
@@ -103,9 +103,15 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
103
103
|
else {
|
|
104
104
|
let currentDraggingElement = this.state.currentDraggingElement;
|
|
105
105
|
if (!currentDraggingElement) {
|
|
106
|
-
const
|
|
107
|
-
const item = this.context.config.items.find(({ id }) => id ===
|
|
108
|
-
|
|
106
|
+
const layoutId = layoutItem.i;
|
|
107
|
+
const item = this.context.config.items.find(({ id }) => id === layoutId);
|
|
108
|
+
const { offsetX, offsetY } = e.nativeEvent;
|
|
109
|
+
currentDraggingElement = {
|
|
110
|
+
group,
|
|
111
|
+
layoutItem,
|
|
112
|
+
item,
|
|
113
|
+
cursorPosition: { offsetX, offsetY },
|
|
114
|
+
};
|
|
109
115
|
}
|
|
110
116
|
this.setState({
|
|
111
117
|
isDragging: true,
|
|
@@ -123,7 +129,7 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
123
129
|
const { currentDraggingElement } = this.state;
|
|
124
130
|
if (currentDraggingElement) {
|
|
125
131
|
this.setState({
|
|
126
|
-
draggedOverGroup: currentDraggingElement
|
|
132
|
+
draggedOverGroup: currentDraggingElement.group,
|
|
127
133
|
});
|
|
128
134
|
}
|
|
129
135
|
};
|
|
@@ -132,7 +138,7 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
132
138
|
const { draggedOverGroup, currentDraggingElement } = this.state;
|
|
133
139
|
if (currentDraggingElement &&
|
|
134
140
|
draggedOverGroup !== null &&
|
|
135
|
-
draggedOverGroup !== currentDraggingElement
|
|
141
|
+
draggedOverGroup !== currentDraggingElement.group) {
|
|
136
142
|
// Skipping layout update when change event called for source grid
|
|
137
143
|
// and waiting _onDrop
|
|
138
144
|
return;
|
|
@@ -156,15 +162,15 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
156
162
|
if (!currentDraggingElement) {
|
|
157
163
|
return;
|
|
158
164
|
}
|
|
159
|
-
const
|
|
165
|
+
const sourceLayoutItem = currentDraggingElement.layoutItem;
|
|
160
166
|
const groupedLayout = this.mergeGroupsLayout(targetGroup, newLayout, tempItem).map((item) => {
|
|
161
|
-
if (item.i ===
|
|
167
|
+
if (item.i === sourceLayoutItem.i) {
|
|
162
168
|
const copy = Object.assign({}, tempItem);
|
|
163
169
|
delete copy.parent;
|
|
164
170
|
if (targetGroup !== constants_1.DEFAULT_GROUP) {
|
|
165
171
|
copy.parent = targetGroup;
|
|
166
172
|
}
|
|
167
|
-
copy.i =
|
|
173
|
+
copy.i = sourceLayoutItem.i;
|
|
168
174
|
return copy;
|
|
169
175
|
}
|
|
170
176
|
return item;
|
|
@@ -205,7 +211,8 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
205
211
|
}
|
|
206
212
|
const { properties, layout } = this.getLayoutAndPropsByGroup(group);
|
|
207
213
|
if (currentDraggingElement) {
|
|
208
|
-
const
|
|
214
|
+
const { h, w, i } = currentDraggingElement.layoutItem;
|
|
215
|
+
const { type } = currentDraggingElement.item;
|
|
209
216
|
return onDropDragOver(e, properties, layout, { h, w, i, type });
|
|
210
217
|
}
|
|
211
218
|
if (dragOverPlugin) {
|
|
@@ -297,12 +304,12 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
297
304
|
compactType = 'horizontal';
|
|
298
305
|
}
|
|
299
306
|
const { callbacks, layout } = this.getMemoGroupProps(group, renderLayout, properties);
|
|
300
|
-
const hasSharedDragItem = Boolean(currentDraggingElement && currentDraggingElement
|
|
307
|
+
const hasSharedDragItem = Boolean(currentDraggingElement && currentDraggingElement.group !== group);
|
|
301
308
|
const isDragCaptured = currentDraggingElement &&
|
|
302
|
-
group === currentDraggingElement
|
|
309
|
+
group === currentDraggingElement.group &&
|
|
303
310
|
draggedOverGroup !== null &&
|
|
304
311
|
draggedOverGroup !== group;
|
|
305
|
-
return (react_1.default.createElement(ReactGridLayout_1.Layout, Object.assign({}, properties, { compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, onResizeStart: this._onResizeStart, onDragStart: callbacks.onDragStart, onDragStop: callbacks.onDragStop, onResizeStop: callbacks.onResizeStop, onDragTargetRestore: callbacks.onDragTargetRestore, onDropDragOver: callbacks.onDropDragOver, onDrop: callbacks.onDrop, hasSharedDragItem: hasSharedDragItem, isDragCaptured: isDragCaptured }, (draggableHandleClassName
|
|
312
|
+
return (react_1.default.createElement(ReactGridLayout_1.Layout, Object.assign({}, properties, { compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, onResizeStart: this._onResizeStart, onDragStart: callbacks.onDragStart, onDragStop: callbacks.onDragStop, onResizeStop: callbacks.onResizeStop, onDragTargetRestore: callbacks.onDragTargetRestore, onDropDragOver: callbacks.onDropDragOver, onDrop: callbacks.onDrop, hasSharedDragItem: hasSharedDragItem, sharedDragPosition: currentDraggingElement === null || currentDraggingElement === void 0 ? void 0 : currentDraggingElement.cursorPosition, isDragCaptured: isDragCaptured }, (draggableHandleClassName
|
|
306
313
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
307
314
|
: null), (outerDnDEnable
|
|
308
315
|
? {
|
|
@@ -170,15 +170,23 @@ class DragOverLayout extends react_grid_layout_1.default {
|
|
|
170
170
|
const { props: itemProps } = gridItem;
|
|
171
171
|
if (isDroppingItem) {
|
|
172
172
|
const { containerWidth, cols, w, h, rowHeight, margin, transformScale, droppingPosition, } = itemProps;
|
|
173
|
-
const
|
|
174
|
-
|
|
173
|
+
const { sharedDragPosition, hasSharedDragItem } = this.props;
|
|
174
|
+
let offsetX, offsetY;
|
|
175
|
+
if (sharedDragPosition) {
|
|
176
|
+
offsetX = sharedDragPosition.offsetX;
|
|
177
|
+
offsetY = sharedDragPosition.offsetY;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
offsetX = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
|
|
181
|
+
offsetY = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
|
|
182
|
+
}
|
|
175
183
|
const style = gridItem.props.style || null;
|
|
176
184
|
// React.cloneElement is just cleaner then copy-paste whole processGridItem method
|
|
177
185
|
return react_1.default.cloneElement(gridItem, {
|
|
178
186
|
// hiding previre if dragging shared item
|
|
179
|
-
style:
|
|
187
|
+
style: hasSharedDragItem ? Object.assign(Object.assign({}, style), { opacity: 0 }) : style,
|
|
180
188
|
className: constants_1.OVERLAY_CLASS_NAME,
|
|
181
|
-
droppingPosition: Object.assign(Object.assign({}, droppingPosition), { left: droppingPosition.left -
|
|
189
|
+
droppingPosition: Object.assign(Object.assign({}, droppingPosition), { left: droppingPosition.left - offsetX, top: droppingPosition.top - offsetY }),
|
|
182
190
|
});
|
|
183
191
|
}
|
|
184
192
|
return gridItem;
|
|
@@ -128,7 +128,7 @@ function useMemoStateContext(props) {
|
|
|
128
128
|
react_1.default.useMemo(() => {
|
|
129
129
|
const groups = props.groups;
|
|
130
130
|
const layout = props.layout;
|
|
131
|
-
const defaultProps = props.registerManager.
|
|
131
|
+
const defaultProps = props.registerManager.gridLayout || {};
|
|
132
132
|
const nowrapGroups = {};
|
|
133
133
|
let hasNowrapGroups = false;
|
|
134
134
|
if (defaultProps.compactType === common_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
@@ -4,14 +4,26 @@ import type { Config, ConfigItem, ConfigLayout } from '../shared';
|
|
|
4
4
|
export interface AddConfigItem extends Omit<ConfigItem, 'id' | 'namespace'> {
|
|
5
5
|
id?: null;
|
|
6
6
|
namespace?: string;
|
|
7
|
-
layout?: ConfigLayout
|
|
7
|
+
layout?: Omit<ConfigLayout, 'i'>;
|
|
8
8
|
}
|
|
9
9
|
export type SetConfigItem = ConfigItem | AddConfigItem;
|
|
10
10
|
export type SetItemOptions = {
|
|
11
11
|
excludeIds?: string[];
|
|
12
|
+
};
|
|
13
|
+
export type GridReflowOptions = {
|
|
14
|
+
cols: number;
|
|
15
|
+
maxRows?: number;
|
|
16
|
+
compactType?: CompactType;
|
|
17
|
+
};
|
|
18
|
+
export type CompactType = ReactGridLayout.ReactGridLayoutProps['compactType'] | 'horizontal-nowrap';
|
|
19
|
+
export type ReflowLayoutOptions = {
|
|
20
|
+
defaultProps: GridReflowOptions;
|
|
21
|
+
groups?: Record<string, GridReflowOptions>;
|
|
22
|
+
};
|
|
23
|
+
export type AddNewItemOptions = SetItemOptions & {
|
|
12
24
|
updateLayout?: ConfigLayout[];
|
|
25
|
+
reflowLayoutOptions?: ReflowLayoutOptions;
|
|
13
26
|
};
|
|
14
|
-
export type SetNewItemOptions = SetItemOptions;
|
|
15
27
|
export interface DashkitGroupRenderProps {
|
|
16
28
|
config: Config;
|
|
17
29
|
editMode: boolean;
|
|
@@ -19,7 +31,7 @@ export interface DashkitGroupRenderProps {
|
|
|
19
31
|
layout: ConfigLayout[];
|
|
20
32
|
}
|
|
21
33
|
export type ReactGridLayoutProps = Omit<ReactGridLayout.ReactGridLayoutProps, 'children' | 'compactType' | 'innerRef' | 'key' | 'layout' | 'isDraggable' | 'isResizable' | 'onDragStart' | 'onDragStop' | 'onResizeStart' | 'onResizeStop' | 'draggableHandle' | 'isDroppable' | 'onDropDragOver' | 'onDrop' | 'draggableCancel'> & {
|
|
22
|
-
compactType?:
|
|
34
|
+
compactType?: CompactType;
|
|
23
35
|
};
|
|
24
36
|
export interface DashKitGroup {
|
|
25
37
|
id?: string;
|
|
@@ -196,7 +196,7 @@ describe('UpdateManager', () => {
|
|
|
196
196
|
type: 'widget',
|
|
197
197
|
},
|
|
198
198
|
namespace: 'default',
|
|
199
|
-
layout: { h: 4, w: 4, x: 0, y:
|
|
199
|
+
layout: { h: 4, w: 4, x: 0, y: Infinity },
|
|
200
200
|
config: config,
|
|
201
201
|
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 15, items: [
|
|
202
202
|
...config.items,
|
|
@@ -215,7 +215,7 @@ describe('UpdateManager', () => {
|
|
|
215
215
|
type: 'widget',
|
|
216
216
|
},
|
|
217
217
|
namespace: 'default',
|
|
218
|
-
layout: { h: 4, w: 4, x: 0, y:
|
|
218
|
+
layout: { h: 4, w: 4, x: 0, y: Infinity },
|
|
219
219
|
config: config,
|
|
220
220
|
options: {
|
|
221
221
|
excludeIds: ['EZ'],
|
|
@@ -260,6 +260,67 @@ describe('UpdateManager', () => {
|
|
|
260
260
|
},
|
|
261
261
|
], layout: [...updateLayout, { h: 4, w: 12, x: 0, y: 0, i: 'EZ' }] }));
|
|
262
262
|
});
|
|
263
|
+
it('prepend new item', () => {
|
|
264
|
+
expect(update_manager_1.UpdateManager.addItem({
|
|
265
|
+
item: {
|
|
266
|
+
data: {},
|
|
267
|
+
type: 'widget',
|
|
268
|
+
},
|
|
269
|
+
namespace: 'default',
|
|
270
|
+
layout: { h: 4, w: 36, x: 0, y: 0 },
|
|
271
|
+
config: config,
|
|
272
|
+
options: {
|
|
273
|
+
reflowLayoutOptions: {
|
|
274
|
+
defaultProps: {
|
|
275
|
+
cols: 36,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 15, items: [
|
|
280
|
+
...config.items,
|
|
281
|
+
{
|
|
282
|
+
id: 'EZ',
|
|
283
|
+
data: {},
|
|
284
|
+
type: 'widget',
|
|
285
|
+
namespace: 'default',
|
|
286
|
+
},
|
|
287
|
+
], layout: [
|
|
288
|
+
{ i: 'al', h: 4, w: 4, x: 8, y: 4 },
|
|
289
|
+
{ i: 'Q8', h: 16, w: 12, x: 12, y: 4 },
|
|
290
|
+
{ i: 'L5', h: 2, w: 8, x: 0, y: 4 },
|
|
291
|
+
{ i: 'C8', h: 2, w: 8, x: 10, y: 30 },
|
|
292
|
+
{ i: 'lko', h: 2, w: 8, x: 0, y: 12 },
|
|
293
|
+
{ i: 'qY', h: 2, w: 8, x: 0, y: 24 },
|
|
294
|
+
{ i: 'EZ', h: 4, w: 36, x: 0, y: 0 },
|
|
295
|
+
] }));
|
|
296
|
+
});
|
|
297
|
+
it('add item with no compactType', () => {
|
|
298
|
+
expect(update_manager_1.UpdateManager.addItem({
|
|
299
|
+
item: {
|
|
300
|
+
data: {},
|
|
301
|
+
type: 'widget',
|
|
302
|
+
},
|
|
303
|
+
namespace: 'default',
|
|
304
|
+
layout: { h: 4, w: 36, x: 0, y: 0 },
|
|
305
|
+
config: config,
|
|
306
|
+
options: {
|
|
307
|
+
reflowLayoutOptions: {
|
|
308
|
+
defaultProps: {
|
|
309
|
+
cols: 36,
|
|
310
|
+
compactType: null,
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 15, items: [
|
|
315
|
+
...config.items,
|
|
316
|
+
{
|
|
317
|
+
id: 'EZ',
|
|
318
|
+
data: {},
|
|
319
|
+
type: 'widget',
|
|
320
|
+
namespace: 'default',
|
|
321
|
+
},
|
|
322
|
+
], layout: [...config.layout, { i: 'EZ', h: 4, w: 36, x: 0, y: 0 }] }));
|
|
323
|
+
});
|
|
263
324
|
});
|
|
264
325
|
describe('removeItem', () => {
|
|
265
326
|
it('remove item by id', () => {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bottom = exports.compact = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const react_grid_layout_1 = tslib_1.__importDefault(require("react-grid-layout"));
|
|
6
|
+
const { utils } = react_grid_layout_1.default;
|
|
7
|
+
const compact = (layout, compactType, cols) => {
|
|
8
|
+
if (compactType === 'horizontal-nowrap') {
|
|
9
|
+
compactType = 'horizontal';
|
|
10
|
+
}
|
|
11
|
+
return utils.compact(layout, compactType, cols);
|
|
12
|
+
};
|
|
13
|
+
exports.compact = compact;
|
|
14
|
+
const bottom = (layout) => {
|
|
15
|
+
return utils.bottom(layout);
|
|
16
|
+
};
|
|
17
|
+
exports.bottom = bottom;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ConfigLayout } from '../shared';
|
|
1
2
|
import type { Config, ConfigItem, ConfigItemGroup, ItemStateAndParams, ItemStateAndParamsChangeOptions, ItemsStateAndParams } from '../shared';
|
|
2
|
-
import type { AddConfigItem,
|
|
3
|
+
import type { AddConfigItem, AddNewItemOptions, ReflowLayoutOptions, SetItemOptions, WidgetLayout } from '../typings';
|
|
3
4
|
import { RegisterManagerPluginLayout } from './register-manager';
|
|
4
5
|
interface RemoveItemArg {
|
|
5
6
|
id: string;
|
|
@@ -20,13 +21,14 @@ export declare const getChangedParams: ({ initiatorItem, stateAndParams, itemsSt
|
|
|
20
21
|
}) => {
|
|
21
22
|
[x: string]: string | string[];
|
|
22
23
|
};
|
|
24
|
+
export declare function reflowLayout(newLayoutItem: ConfigLayout, layout: ConfigLayout[], reflowLayoutOptions: ReflowLayoutOptions): ConfigLayout[];
|
|
23
25
|
export declare class UpdateManager {
|
|
24
26
|
static addItem({ item, namespace, layout, config, options, }: {
|
|
25
27
|
item: AddConfigItem;
|
|
26
28
|
namespace: string;
|
|
27
29
|
layout: RegisterManagerPluginLayout;
|
|
28
30
|
config: Config;
|
|
29
|
-
options?:
|
|
31
|
+
options?: AddNewItemOptions;
|
|
30
32
|
}): Config;
|
|
31
33
|
static editItem({ item, namespace, config, options, }: {
|
|
32
34
|
item: ConfigItem;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UpdateManager = exports.getChangedParams = void 0;
|
|
3
|
+
exports.UpdateManager = exports.reflowLayout = exports.getChangedParams = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const immutability_helper_1 = tslib_1.__importStar(require("immutability-helper"));
|
|
6
6
|
const omit_1 = tslib_1.__importDefault(require("lodash/omit"));
|
|
@@ -8,6 +8,7 @@ const pick_1 = tslib_1.__importDefault(require("lodash/pick"));
|
|
|
8
8
|
const constants_1 = require("../constants");
|
|
9
9
|
const shared_1 = require("../shared");
|
|
10
10
|
const get_new_id_1 = require("./get-new-id");
|
|
11
|
+
const grid_layout_1 = require("./grid-layout");
|
|
11
12
|
(0, immutability_helper_1.extend)('$auto', (value, object) => (object ? (0, immutability_helper_1.default)(object, value) : (0, immutability_helper_1.default)({}, value)));
|
|
12
13
|
function removeItemVersion1({ id, config, itemsStateAndParams }) {
|
|
13
14
|
const itemIndex = config.items.findIndex((item) => item.id === id);
|
|
@@ -226,6 +227,49 @@ function changeGroupParams({ groupItemIds, initiatorId, initiatorItem, itemsStat
|
|
|
226
227
|
};
|
|
227
228
|
return (0, immutability_helper_1.default)(itemsStateAndParams, obj);
|
|
228
229
|
}
|
|
230
|
+
function reflowLayout(newLayoutItem, layout, reflowLayoutOptions) {
|
|
231
|
+
const byGroup = {};
|
|
232
|
+
const reducer = (memo, item, i, _items, isNewItem) => {
|
|
233
|
+
memo[item.i] = i;
|
|
234
|
+
const parent = item.parent || constants_1.DEFAULT_GROUP;
|
|
235
|
+
if (byGroup[parent]) {
|
|
236
|
+
if (isNewItem) {
|
|
237
|
+
byGroup[parent].unshift(item);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
byGroup[parent].push(item);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
byGroup[parent] = [item];
|
|
245
|
+
}
|
|
246
|
+
return memo;
|
|
247
|
+
};
|
|
248
|
+
const orderById = layout.reduce(reducer, {});
|
|
249
|
+
reducer(orderById, newLayoutItem, layout.length, layout, true);
|
|
250
|
+
const { defaultProps } = reflowLayoutOptions;
|
|
251
|
+
return Object.entries(byGroup)
|
|
252
|
+
.reduce((memo, [groupId, layoutItems]) => {
|
|
253
|
+
var _a;
|
|
254
|
+
let reflowOptions = defaultProps;
|
|
255
|
+
if ((_a = reflowLayoutOptions === null || reflowLayoutOptions === void 0 ? void 0 : reflowLayoutOptions.groups) === null || _a === void 0 ? void 0 : _a[groupId]) {
|
|
256
|
+
reflowOptions = reflowLayoutOptions === null || reflowLayoutOptions === void 0 ? void 0 : reflowLayoutOptions.groups[groupId];
|
|
257
|
+
}
|
|
258
|
+
if (reflowOptions.compactType === null) {
|
|
259
|
+
return memo.concat(layoutItems);
|
|
260
|
+
}
|
|
261
|
+
const compactedList = (0, grid_layout_1.compact)(layoutItems, reflowOptions.compactType, reflowOptions.cols).map((item) => {
|
|
262
|
+
const cleanCopy = (0, pick_1.default)(item, ['i', 'h', 'w', 'x', 'y', 'parent']);
|
|
263
|
+
if (groupId === constants_1.DEFAULT_GROUP) {
|
|
264
|
+
return cleanCopy;
|
|
265
|
+
}
|
|
266
|
+
return Object.assign(Object.assign({}, cleanCopy), { parent: groupId });
|
|
267
|
+
});
|
|
268
|
+
return memo.concat(compactedList);
|
|
269
|
+
}, [])
|
|
270
|
+
.sort((a, b) => orderById[a.i] - orderById[b.i]);
|
|
271
|
+
}
|
|
272
|
+
exports.reflowLayout = reflowLayout;
|
|
229
273
|
class UpdateManager {
|
|
230
274
|
static addItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, layout, config, options = {}, }) {
|
|
231
275
|
const salt = config.salt;
|
|
@@ -240,10 +284,32 @@ class UpdateManager {
|
|
|
240
284
|
memo[t.i] = t;
|
|
241
285
|
return memo;
|
|
242
286
|
}, {});
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
287
|
+
let newLayout;
|
|
288
|
+
const newLayoutItem = Object.assign(Object.assign({}, saveDefaultLayout), { i: newItem.id });
|
|
289
|
+
if (options.reflowLayoutOptions) {
|
|
290
|
+
newLayout = reflowLayout(newLayoutItem, config.layout.map((t) => (Object.assign(Object.assign({}, t), (byId[t.i] || {})))), options.reflowLayoutOptions);
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
newLayout = [
|
|
294
|
+
...config.layout.map((t) => (Object.assign(Object.assign({}, t), (byId[t.i] || {})))),
|
|
295
|
+
Object.assign(Object.assign({}, saveDefaultLayout), { i: newItem.id }),
|
|
296
|
+
];
|
|
297
|
+
}
|
|
298
|
+
return (0, immutability_helper_1.default)(config, {
|
|
299
|
+
items: { $push: [newItem] },
|
|
300
|
+
layout: { $set: newLayout },
|
|
301
|
+
counter: { $set: counter },
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
else if (isFinite(layout.y)) {
|
|
305
|
+
let newLayout;
|
|
306
|
+
const newLayoutItem = Object.assign(Object.assign({}, saveDefaultLayout), { i: newItem.id });
|
|
307
|
+
if (options.reflowLayoutOptions) {
|
|
308
|
+
newLayout = reflowLayout(newLayoutItem, config.layout, options.reflowLayoutOptions);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
newLayout = [...config.layout, newLayoutItem];
|
|
312
|
+
}
|
|
247
313
|
return (0, immutability_helper_1.default)(config, {
|
|
248
314
|
items: { $push: [newItem] },
|
|
249
315
|
layout: { $set: newLayout },
|
|
@@ -251,7 +317,7 @@ class UpdateManager {
|
|
|
251
317
|
});
|
|
252
318
|
}
|
|
253
319
|
else {
|
|
254
|
-
const layoutY =
|
|
320
|
+
const layoutY = (0, grid_layout_1.bottom)(config.layout);
|
|
255
321
|
const newLayoutItem = Object.assign(Object.assign({}, saveDefaultLayout), { y: layoutY, i: newItem.id });
|
|
256
322
|
return (0, immutability_helper_1.default)(config, {
|
|
257
323
|
items: { $push: [newItem] },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { Config, ConfigItem, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
|
|
3
|
-
import { ContextProps, DashKitGroup, MenuItem, Plugin, SetConfigItem,
|
|
2
|
+
import type { Config, ConfigItem, ConfigLayout, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
|
|
3
|
+
import { AddNewItemOptions, ContextProps, DashKitGroup, MenuItem, Plugin, SetConfigItem, Settings, SettingsProps } from '../../typings';
|
|
4
4
|
import GridLayout from '../GridLayout/GridLayout';
|
|
5
5
|
import { OverlayControlItem } from '../OverlayControls/OverlayControls';
|
|
6
6
|
interface DashKitGeneralProps {
|
|
@@ -39,11 +39,12 @@ export declare class DashKit extends React.PureComponent<DashKitInnerProps> {
|
|
|
39
39
|
static defaultProps: DashKitDefaultProps;
|
|
40
40
|
static registerPlugins(...plugins: Plugin[]): void;
|
|
41
41
|
static setSettings(settings: Settings): void;
|
|
42
|
-
static setItem({ item: setItem, namespace, config, options, }: {
|
|
42
|
+
static setItem({ item: setItem, namespace, config, options, groups, }: {
|
|
43
43
|
item: SetConfigItem;
|
|
44
44
|
namespace?: string;
|
|
45
45
|
config: Config;
|
|
46
|
-
options?:
|
|
46
|
+
options?: Omit<AddNewItemOptions, 'reflowLayoutOptions'>;
|
|
47
|
+
groups?: DashKitGroup[];
|
|
47
48
|
}): Config;
|
|
48
49
|
static removeItem({ id, config, itemsStateAndParams, }: {
|
|
49
50
|
id: string;
|
|
@@ -53,6 +54,7 @@ export declare class DashKit extends React.PureComponent<DashKitInnerProps> {
|
|
|
53
54
|
config: Config;
|
|
54
55
|
itemsStateAndParams: ItemsStateAndParams;
|
|
55
56
|
};
|
|
57
|
+
static reflowLayout(newLayoutItem: ConfigLayout, layout: ConfigLayout[], groups?: DashKitGroup[]): ConfigLayout[];
|
|
56
58
|
metaRef: React.RefObject<GridLayout>;
|
|
57
59
|
render(): JSX.Element;
|
|
58
60
|
getItemsMeta(): any;
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import noop from 'lodash/noop';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
3
|
+
import pick from 'lodash/pick';
|
|
4
|
+
import { DEFAULT_GROUP, DEFAULT_NAMESPACE } from '../../constants';
|
|
5
|
+
import { RegisterManager, UpdateManager, reflowLayout } from '../../utils';
|
|
5
6
|
import DashKitView from '../DashKitView/DashKitView';
|
|
6
7
|
const registerManager = new RegisterManager();
|
|
8
|
+
const getReflowProps = (props) => Object.assign({ compactType: 'vertical', cols: 36 }, pick(props, 'cols', 'maxRows', 'compactType'));
|
|
9
|
+
const getReflowGroupsConfig = (groups = []) => {
|
|
10
|
+
const defaultGridProps = getReflowProps(registerManager.gridLayout);
|
|
11
|
+
return {
|
|
12
|
+
defaultProps: defaultGridProps,
|
|
13
|
+
groups: groups.reduce((memo, g) => {
|
|
14
|
+
const groupId = g.id || DEFAULT_GROUP;
|
|
15
|
+
memo[groupId] = g.gridProperties
|
|
16
|
+
? getReflowProps(g.gridProperties(defaultGridProps))
|
|
17
|
+
: defaultGridProps;
|
|
18
|
+
return memo;
|
|
19
|
+
}, {}),
|
|
20
|
+
};
|
|
21
|
+
};
|
|
7
22
|
export class DashKit extends React.PureComponent {
|
|
8
23
|
constructor() {
|
|
9
24
|
super(...arguments);
|
|
@@ -17,28 +32,39 @@ export class DashKit extends React.PureComponent {
|
|
|
17
32
|
static setSettings(settings) {
|
|
18
33
|
registerManager.setSettings(settings);
|
|
19
34
|
}
|
|
20
|
-
static setItem({ item: setItem, namespace = DEFAULT_NAMESPACE, config, options = {}, }) {
|
|
35
|
+
static setItem({ item: setItem, namespace = DEFAULT_NAMESPACE, config, options = {}, groups = [], }) {
|
|
21
36
|
if (setItem.id) {
|
|
22
|
-
return UpdateManager.editItem({
|
|
37
|
+
return UpdateManager.editItem({
|
|
38
|
+
item: setItem,
|
|
39
|
+
namespace,
|
|
40
|
+
config,
|
|
41
|
+
options,
|
|
42
|
+
});
|
|
23
43
|
}
|
|
24
44
|
else {
|
|
25
45
|
const item = setItem;
|
|
26
46
|
const layout = Object.assign({}, registerManager.getItem(item.type).defaultLayout);
|
|
27
|
-
|
|
28
|
-
|
|
47
|
+
const reflowLayoutOptions = getReflowGroupsConfig(groups);
|
|
48
|
+
const copyItem = Object.assign({}, item);
|
|
49
|
+
if (copyItem.layout) {
|
|
50
|
+
Object.assign(layout, copyItem.layout);
|
|
51
|
+
delete copyItem.layout;
|
|
29
52
|
}
|
|
30
53
|
return UpdateManager.addItem({
|
|
31
|
-
item,
|
|
54
|
+
item: copyItem,
|
|
32
55
|
namespace,
|
|
33
56
|
config,
|
|
34
57
|
layout,
|
|
35
|
-
options,
|
|
58
|
+
options: Object.assign(Object.assign({}, options), { reflowLayoutOptions }),
|
|
36
59
|
});
|
|
37
60
|
}
|
|
38
61
|
}
|
|
39
62
|
static removeItem({ id, config, itemsStateAndParams, }) {
|
|
40
63
|
return UpdateManager.removeItem({ id, config, itemsStateAndParams });
|
|
41
64
|
}
|
|
65
|
+
static reflowLayout(newLayoutItem, layout, groups) {
|
|
66
|
+
return reflowLayout(newLayoutItem, layout, getReflowGroupsConfig(groups));
|
|
67
|
+
}
|
|
42
68
|
render() {
|
|
43
69
|
return React.createElement(DashKitView, Object.assign({ registerManager: registerManager, ref: this.metaRef }, this.props));
|
|
44
70
|
}
|
|
@@ -38,7 +38,7 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
|
|
|
38
38
|
getMemoForwardRefCallback: (refIndex: any) => any;
|
|
39
39
|
mergeGroupsLayout(group: any, newLayout: any, temporaryItem: any): any;
|
|
40
40
|
reloadItems(): void;
|
|
41
|
-
_onDragStart: (group: any, _newLayout: any, layoutItem: any) => void;
|
|
41
|
+
_onDragStart: (group: any, _newLayout: any, layoutItem: any, _newItem: any, _placeholder: any, e: any) => void;
|
|
42
42
|
_onResizeStart: () => void;
|
|
43
43
|
_onTargetRestore: () => void;
|
|
44
44
|
_onStop: (group: any, newLayout: any) => void;
|
|
@@ -91,7 +91,7 @@ class GridLayout extends React.PureComponent {
|
|
|
91
91
|
}
|
|
92
92
|
return this._memoForwardedPluginRef[refIndex];
|
|
93
93
|
};
|
|
94
|
-
this._onDragStart = (group, _newLayout, layoutItem) => {
|
|
94
|
+
this._onDragStart = (group, _newLayout, layoutItem, _newItem, _placeholder, e) => {
|
|
95
95
|
if (this.temporaryLayout)
|
|
96
96
|
return;
|
|
97
97
|
if (this.context.dragOverPlugin) {
|
|
@@ -100,9 +100,15 @@ class GridLayout extends React.PureComponent {
|
|
|
100
100
|
else {
|
|
101
101
|
let currentDraggingElement = this.state.currentDraggingElement;
|
|
102
102
|
if (!currentDraggingElement) {
|
|
103
|
-
const
|
|
104
|
-
const item = this.context.config.items.find(({ id }) => id ===
|
|
105
|
-
|
|
103
|
+
const layoutId = layoutItem.i;
|
|
104
|
+
const item = this.context.config.items.find(({ id }) => id === layoutId);
|
|
105
|
+
const { offsetX, offsetY } = e.nativeEvent;
|
|
106
|
+
currentDraggingElement = {
|
|
107
|
+
group,
|
|
108
|
+
layoutItem,
|
|
109
|
+
item,
|
|
110
|
+
cursorPosition: { offsetX, offsetY },
|
|
111
|
+
};
|
|
106
112
|
}
|
|
107
113
|
this.setState({
|
|
108
114
|
isDragging: true,
|
|
@@ -120,7 +126,7 @@ class GridLayout extends React.PureComponent {
|
|
|
120
126
|
const { currentDraggingElement } = this.state;
|
|
121
127
|
if (currentDraggingElement) {
|
|
122
128
|
this.setState({
|
|
123
|
-
draggedOverGroup: currentDraggingElement
|
|
129
|
+
draggedOverGroup: currentDraggingElement.group,
|
|
124
130
|
});
|
|
125
131
|
}
|
|
126
132
|
};
|
|
@@ -129,7 +135,7 @@ class GridLayout extends React.PureComponent {
|
|
|
129
135
|
const { draggedOverGroup, currentDraggingElement } = this.state;
|
|
130
136
|
if (currentDraggingElement &&
|
|
131
137
|
draggedOverGroup !== null &&
|
|
132
|
-
draggedOverGroup !== currentDraggingElement
|
|
138
|
+
draggedOverGroup !== currentDraggingElement.group) {
|
|
133
139
|
// Skipping layout update when change event called for source grid
|
|
134
140
|
// and waiting _onDrop
|
|
135
141
|
return;
|
|
@@ -153,15 +159,15 @@ class GridLayout extends React.PureComponent {
|
|
|
153
159
|
if (!currentDraggingElement) {
|
|
154
160
|
return;
|
|
155
161
|
}
|
|
156
|
-
const
|
|
162
|
+
const sourceLayoutItem = currentDraggingElement.layoutItem;
|
|
157
163
|
const groupedLayout = this.mergeGroupsLayout(targetGroup, newLayout, tempItem).map((item) => {
|
|
158
|
-
if (item.i ===
|
|
164
|
+
if (item.i === sourceLayoutItem.i) {
|
|
159
165
|
const copy = Object.assign({}, tempItem);
|
|
160
166
|
delete copy.parent;
|
|
161
167
|
if (targetGroup !== DEFAULT_GROUP) {
|
|
162
168
|
copy.parent = targetGroup;
|
|
163
169
|
}
|
|
164
|
-
copy.i =
|
|
170
|
+
copy.i = sourceLayoutItem.i;
|
|
165
171
|
return copy;
|
|
166
172
|
}
|
|
167
173
|
return item;
|
|
@@ -202,7 +208,8 @@ class GridLayout extends React.PureComponent {
|
|
|
202
208
|
}
|
|
203
209
|
const { properties, layout } = this.getLayoutAndPropsByGroup(group);
|
|
204
210
|
if (currentDraggingElement) {
|
|
205
|
-
const
|
|
211
|
+
const { h, w, i } = currentDraggingElement.layoutItem;
|
|
212
|
+
const { type } = currentDraggingElement.item;
|
|
206
213
|
return onDropDragOver(e, properties, layout, { h, w, i, type });
|
|
207
214
|
}
|
|
208
215
|
if (dragOverPlugin) {
|
|
@@ -294,12 +301,12 @@ class GridLayout extends React.PureComponent {
|
|
|
294
301
|
compactType = 'horizontal';
|
|
295
302
|
}
|
|
296
303
|
const { callbacks, layout } = this.getMemoGroupProps(group, renderLayout, properties);
|
|
297
|
-
const hasSharedDragItem = Boolean(currentDraggingElement && currentDraggingElement
|
|
304
|
+
const hasSharedDragItem = Boolean(currentDraggingElement && currentDraggingElement.group !== group);
|
|
298
305
|
const isDragCaptured = currentDraggingElement &&
|
|
299
|
-
group === currentDraggingElement
|
|
306
|
+
group === currentDraggingElement.group &&
|
|
300
307
|
draggedOverGroup !== null &&
|
|
301
308
|
draggedOverGroup !== group;
|
|
302
|
-
return (React.createElement(Layout, Object.assign({}, properties, { compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, onResizeStart: this._onResizeStart, onDragStart: callbacks.onDragStart, onDragStop: callbacks.onDragStop, onResizeStop: callbacks.onResizeStop, onDragTargetRestore: callbacks.onDragTargetRestore, onDropDragOver: callbacks.onDropDragOver, onDrop: callbacks.onDrop, hasSharedDragItem: hasSharedDragItem, isDragCaptured: isDragCaptured }, (draggableHandleClassName
|
|
309
|
+
return (React.createElement(Layout, Object.assign({}, properties, { compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, onResizeStart: this._onResizeStart, onDragStart: callbacks.onDragStart, onDragStop: callbacks.onDragStop, onResizeStop: callbacks.onResizeStop, onDragTargetRestore: callbacks.onDragTargetRestore, onDropDragOver: callbacks.onDropDragOver, onDrop: callbacks.onDrop, hasSharedDragItem: hasSharedDragItem, sharedDragPosition: currentDraggingElement === null || currentDraggingElement === void 0 ? void 0 : currentDraggingElement.cursorPosition, isDragCaptured: isDragCaptured }, (draggableHandleClassName
|
|
303
310
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
304
311
|
: null), (outerDnDEnable
|
|
305
312
|
? {
|
|
@@ -166,15 +166,23 @@ class DragOverLayout extends ReactGridLayout {
|
|
|
166
166
|
const { props: itemProps } = gridItem;
|
|
167
167
|
if (isDroppingItem) {
|
|
168
168
|
const { containerWidth, cols, w, h, rowHeight, margin, transformScale, droppingPosition, } = itemProps;
|
|
169
|
-
const
|
|
170
|
-
|
|
169
|
+
const { sharedDragPosition, hasSharedDragItem } = this.props;
|
|
170
|
+
let offsetX, offsetY;
|
|
171
|
+
if (sharedDragPosition) {
|
|
172
|
+
offsetX = sharedDragPosition.offsetX;
|
|
173
|
+
offsetY = sharedDragPosition.offsetY;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
offsetX = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
|
|
177
|
+
offsetY = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
|
|
178
|
+
}
|
|
171
179
|
const style = gridItem.props.style || null;
|
|
172
180
|
// React.cloneElement is just cleaner then copy-paste whole processGridItem method
|
|
173
181
|
return React.cloneElement(gridItem, {
|
|
174
182
|
// hiding previre if dragging shared item
|
|
175
|
-
style:
|
|
183
|
+
style: hasSharedDragItem ? Object.assign(Object.assign({}, style), { opacity: 0 }) : style,
|
|
176
184
|
className: OVERLAY_CLASS_NAME,
|
|
177
|
-
droppingPosition: Object.assign(Object.assign({}, droppingPosition), { left: droppingPosition.left -
|
|
185
|
+
droppingPosition: Object.assign(Object.assign({}, droppingPosition), { left: droppingPosition.left - offsetX, top: droppingPosition.top - offsetY }),
|
|
178
186
|
});
|
|
179
187
|
}
|
|
180
188
|
return gridItem;
|
|
@@ -125,7 +125,7 @@ function useMemoStateContext(props) {
|
|
|
125
125
|
React.useMemo(() => {
|
|
126
126
|
const groups = props.groups;
|
|
127
127
|
const layout = props.layout;
|
|
128
|
-
const defaultProps = props.registerManager.
|
|
128
|
+
const defaultProps = props.registerManager.gridLayout || {};
|
|
129
129
|
const nowrapGroups = {};
|
|
130
130
|
let hasNowrapGroups = false;
|
|
131
131
|
if (defaultProps.compactType === COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
@@ -4,14 +4,26 @@ import type { Config, ConfigItem, ConfigLayout } from '../shared';
|
|
|
4
4
|
export interface AddConfigItem extends Omit<ConfigItem, 'id' | 'namespace'> {
|
|
5
5
|
id?: null;
|
|
6
6
|
namespace?: string;
|
|
7
|
-
layout?: ConfigLayout
|
|
7
|
+
layout?: Omit<ConfigLayout, 'i'>;
|
|
8
8
|
}
|
|
9
9
|
export type SetConfigItem = ConfigItem | AddConfigItem;
|
|
10
10
|
export type SetItemOptions = {
|
|
11
11
|
excludeIds?: string[];
|
|
12
|
+
};
|
|
13
|
+
export type GridReflowOptions = {
|
|
14
|
+
cols: number;
|
|
15
|
+
maxRows?: number;
|
|
16
|
+
compactType?: CompactType;
|
|
17
|
+
};
|
|
18
|
+
export type CompactType = ReactGridLayout.ReactGridLayoutProps['compactType'] | 'horizontal-nowrap';
|
|
19
|
+
export type ReflowLayoutOptions = {
|
|
20
|
+
defaultProps: GridReflowOptions;
|
|
21
|
+
groups?: Record<string, GridReflowOptions>;
|
|
22
|
+
};
|
|
23
|
+
export type AddNewItemOptions = SetItemOptions & {
|
|
12
24
|
updateLayout?: ConfigLayout[];
|
|
25
|
+
reflowLayoutOptions?: ReflowLayoutOptions;
|
|
13
26
|
};
|
|
14
|
-
export type SetNewItemOptions = SetItemOptions;
|
|
15
27
|
export interface DashkitGroupRenderProps {
|
|
16
28
|
config: Config;
|
|
17
29
|
editMode: boolean;
|
|
@@ -19,7 +31,7 @@ export interface DashkitGroupRenderProps {
|
|
|
19
31
|
layout: ConfigLayout[];
|
|
20
32
|
}
|
|
21
33
|
export type ReactGridLayoutProps = Omit<ReactGridLayout.ReactGridLayoutProps, 'children' | 'compactType' | 'innerRef' | 'key' | 'layout' | 'isDraggable' | 'isResizable' | 'onDragStart' | 'onDragStop' | 'onResizeStart' | 'onResizeStop' | 'draggableHandle' | 'isDroppable' | 'onDropDragOver' | 'onDrop' | 'draggableCancel'> & {
|
|
22
|
-
compactType?:
|
|
34
|
+
compactType?: CompactType;
|
|
23
35
|
};
|
|
24
36
|
export interface DashKitGroup {
|
|
25
37
|
id?: string;
|
|
@@ -194,7 +194,7 @@ describe('UpdateManager', () => {
|
|
|
194
194
|
type: 'widget',
|
|
195
195
|
},
|
|
196
196
|
namespace: 'default',
|
|
197
|
-
layout: { h: 4, w: 4, x: 0, y:
|
|
197
|
+
layout: { h: 4, w: 4, x: 0, y: Infinity },
|
|
198
198
|
config: config,
|
|
199
199
|
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 15, items: [
|
|
200
200
|
...config.items,
|
|
@@ -213,7 +213,7 @@ describe('UpdateManager', () => {
|
|
|
213
213
|
type: 'widget',
|
|
214
214
|
},
|
|
215
215
|
namespace: 'default',
|
|
216
|
-
layout: { h: 4, w: 4, x: 0, y:
|
|
216
|
+
layout: { h: 4, w: 4, x: 0, y: Infinity },
|
|
217
217
|
config: config,
|
|
218
218
|
options: {
|
|
219
219
|
excludeIds: ['EZ'],
|
|
@@ -258,6 +258,67 @@ describe('UpdateManager', () => {
|
|
|
258
258
|
},
|
|
259
259
|
], layout: [...updateLayout, { h: 4, w: 12, x: 0, y: 0, i: 'EZ' }] }));
|
|
260
260
|
});
|
|
261
|
+
it('prepend new item', () => {
|
|
262
|
+
expect(UpdateManager.addItem({
|
|
263
|
+
item: {
|
|
264
|
+
data: {},
|
|
265
|
+
type: 'widget',
|
|
266
|
+
},
|
|
267
|
+
namespace: 'default',
|
|
268
|
+
layout: { h: 4, w: 36, x: 0, y: 0 },
|
|
269
|
+
config: config,
|
|
270
|
+
options: {
|
|
271
|
+
reflowLayoutOptions: {
|
|
272
|
+
defaultProps: {
|
|
273
|
+
cols: 36,
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 15, items: [
|
|
278
|
+
...config.items,
|
|
279
|
+
{
|
|
280
|
+
id: 'EZ',
|
|
281
|
+
data: {},
|
|
282
|
+
type: 'widget',
|
|
283
|
+
namespace: 'default',
|
|
284
|
+
},
|
|
285
|
+
], layout: [
|
|
286
|
+
{ i: 'al', h: 4, w: 4, x: 8, y: 4 },
|
|
287
|
+
{ i: 'Q8', h: 16, w: 12, x: 12, y: 4 },
|
|
288
|
+
{ i: 'L5', h: 2, w: 8, x: 0, y: 4 },
|
|
289
|
+
{ i: 'C8', h: 2, w: 8, x: 10, y: 30 },
|
|
290
|
+
{ i: 'lko', h: 2, w: 8, x: 0, y: 12 },
|
|
291
|
+
{ i: 'qY', h: 2, w: 8, x: 0, y: 24 },
|
|
292
|
+
{ i: 'EZ', h: 4, w: 36, x: 0, y: 0 },
|
|
293
|
+
] }));
|
|
294
|
+
});
|
|
295
|
+
it('add item with no compactType', () => {
|
|
296
|
+
expect(UpdateManager.addItem({
|
|
297
|
+
item: {
|
|
298
|
+
data: {},
|
|
299
|
+
type: 'widget',
|
|
300
|
+
},
|
|
301
|
+
namespace: 'default',
|
|
302
|
+
layout: { h: 4, w: 36, x: 0, y: 0 },
|
|
303
|
+
config: config,
|
|
304
|
+
options: {
|
|
305
|
+
reflowLayoutOptions: {
|
|
306
|
+
defaultProps: {
|
|
307
|
+
cols: 36,
|
|
308
|
+
compactType: null,
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
})).toEqual(Object.assign(Object.assign({}, config), { salt: '0.09852189776033704', counter: 15, items: [
|
|
313
|
+
...config.items,
|
|
314
|
+
{
|
|
315
|
+
id: 'EZ',
|
|
316
|
+
data: {},
|
|
317
|
+
type: 'widget',
|
|
318
|
+
namespace: 'default',
|
|
319
|
+
},
|
|
320
|
+
], layout: [...config.layout, { i: 'EZ', h: 4, w: 36, x: 0, y: 0 }] }));
|
|
321
|
+
});
|
|
261
322
|
});
|
|
262
323
|
describe('removeItem', () => {
|
|
263
324
|
it('remove item by id', () => {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import gridLayout from 'react-grid-layout';
|
|
2
|
+
const { utils } = gridLayout;
|
|
3
|
+
export const compact = (layout, compactType, cols) => {
|
|
4
|
+
if (compactType === 'horizontal-nowrap') {
|
|
5
|
+
compactType = 'horizontal';
|
|
6
|
+
}
|
|
7
|
+
return utils.compact(layout, compactType, cols);
|
|
8
|
+
};
|
|
9
|
+
export const bottom = (layout) => {
|
|
10
|
+
return utils.bottom(layout);
|
|
11
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ConfigLayout } from '../shared';
|
|
1
2
|
import type { Config, ConfigItem, ConfigItemGroup, ItemStateAndParams, ItemStateAndParamsChangeOptions, ItemsStateAndParams } from '../shared';
|
|
2
|
-
import type { AddConfigItem,
|
|
3
|
+
import type { AddConfigItem, AddNewItemOptions, ReflowLayoutOptions, SetItemOptions, WidgetLayout } from '../typings';
|
|
3
4
|
import { RegisterManagerPluginLayout } from './register-manager';
|
|
4
5
|
interface RemoveItemArg {
|
|
5
6
|
id: string;
|
|
@@ -20,13 +21,14 @@ export declare const getChangedParams: ({ initiatorItem, stateAndParams, itemsSt
|
|
|
20
21
|
}) => {
|
|
21
22
|
[x: string]: string | string[];
|
|
22
23
|
};
|
|
24
|
+
export declare function reflowLayout(newLayoutItem: ConfigLayout, layout: ConfigLayout[], reflowLayoutOptions: ReflowLayoutOptions): ConfigLayout[];
|
|
23
25
|
export declare class UpdateManager {
|
|
24
26
|
static addItem({ item, namespace, layout, config, options, }: {
|
|
25
27
|
item: AddConfigItem;
|
|
26
28
|
namespace: string;
|
|
27
29
|
layout: RegisterManagerPluginLayout;
|
|
28
30
|
config: Config;
|
|
29
|
-
options?:
|
|
31
|
+
options?: AddNewItemOptions;
|
|
30
32
|
}): Config;
|
|
31
33
|
static editItem({ item, namespace, config, options, }: {
|
|
32
34
|
item: ConfigItem;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import update, { extend } from 'immutability-helper';
|
|
2
2
|
import omit from 'lodash/omit';
|
|
3
3
|
import pick from 'lodash/pick';
|
|
4
|
-
import { DEFAULT_NAMESPACE } from '../constants';
|
|
4
|
+
import { DEFAULT_GROUP, DEFAULT_NAMESPACE } from '../constants';
|
|
5
5
|
import { META_KEY, addGroupToQueue, addToQueue, deleteFromQueue, getCurrentVersion, getInitialItemsStateAndParamsMeta, getItemsStateAndParamsMeta, isItemWithGroup, isItemWithTabs, mergeParamsWithAliases, pickActionParamsFromParams, resolveItemInnerId, transformParamsToActionParams, } from '../shared';
|
|
6
6
|
import { getNewId } from './get-new-id';
|
|
7
|
+
import { bottom, compact } from './grid-layout';
|
|
7
8
|
extend('$auto', (value, object) => (object ? update(object, value) : update({}, value)));
|
|
8
9
|
function removeItemVersion1({ id, config, itemsStateAndParams }) {
|
|
9
10
|
const itemIndex = config.items.findIndex((item) => item.id === id);
|
|
@@ -221,6 +222,48 @@ function changeGroupParams({ groupItemIds, initiatorId, initiatorItem, itemsStat
|
|
|
221
222
|
};
|
|
222
223
|
return update(itemsStateAndParams, obj);
|
|
223
224
|
}
|
|
225
|
+
export function reflowLayout(newLayoutItem, layout, reflowLayoutOptions) {
|
|
226
|
+
const byGroup = {};
|
|
227
|
+
const reducer = (memo, item, i, _items, isNewItem) => {
|
|
228
|
+
memo[item.i] = i;
|
|
229
|
+
const parent = item.parent || DEFAULT_GROUP;
|
|
230
|
+
if (byGroup[parent]) {
|
|
231
|
+
if (isNewItem) {
|
|
232
|
+
byGroup[parent].unshift(item);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
byGroup[parent].push(item);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
byGroup[parent] = [item];
|
|
240
|
+
}
|
|
241
|
+
return memo;
|
|
242
|
+
};
|
|
243
|
+
const orderById = layout.reduce(reducer, {});
|
|
244
|
+
reducer(orderById, newLayoutItem, layout.length, layout, true);
|
|
245
|
+
const { defaultProps } = reflowLayoutOptions;
|
|
246
|
+
return Object.entries(byGroup)
|
|
247
|
+
.reduce((memo, [groupId, layoutItems]) => {
|
|
248
|
+
var _a;
|
|
249
|
+
let reflowOptions = defaultProps;
|
|
250
|
+
if ((_a = reflowLayoutOptions === null || reflowLayoutOptions === void 0 ? void 0 : reflowLayoutOptions.groups) === null || _a === void 0 ? void 0 : _a[groupId]) {
|
|
251
|
+
reflowOptions = reflowLayoutOptions === null || reflowLayoutOptions === void 0 ? void 0 : reflowLayoutOptions.groups[groupId];
|
|
252
|
+
}
|
|
253
|
+
if (reflowOptions.compactType === null) {
|
|
254
|
+
return memo.concat(layoutItems);
|
|
255
|
+
}
|
|
256
|
+
const compactedList = compact(layoutItems, reflowOptions.compactType, reflowOptions.cols).map((item) => {
|
|
257
|
+
const cleanCopy = pick(item, ['i', 'h', 'w', 'x', 'y', 'parent']);
|
|
258
|
+
if (groupId === DEFAULT_GROUP) {
|
|
259
|
+
return cleanCopy;
|
|
260
|
+
}
|
|
261
|
+
return Object.assign(Object.assign({}, cleanCopy), { parent: groupId });
|
|
262
|
+
});
|
|
263
|
+
return memo.concat(compactedList);
|
|
264
|
+
}, [])
|
|
265
|
+
.sort((a, b) => orderById[a.i] - orderById[b.i]);
|
|
266
|
+
}
|
|
224
267
|
export class UpdateManager {
|
|
225
268
|
static addItem({ item, namespace = DEFAULT_NAMESPACE, layout, config, options = {}, }) {
|
|
226
269
|
const salt = config.salt;
|
|
@@ -235,10 +278,32 @@ export class UpdateManager {
|
|
|
235
278
|
memo[t.i] = t;
|
|
236
279
|
return memo;
|
|
237
280
|
}, {});
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
281
|
+
let newLayout;
|
|
282
|
+
const newLayoutItem = Object.assign(Object.assign({}, saveDefaultLayout), { i: newItem.id });
|
|
283
|
+
if (options.reflowLayoutOptions) {
|
|
284
|
+
newLayout = reflowLayout(newLayoutItem, config.layout.map((t) => (Object.assign(Object.assign({}, t), (byId[t.i] || {})))), options.reflowLayoutOptions);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
newLayout = [
|
|
288
|
+
...config.layout.map((t) => (Object.assign(Object.assign({}, t), (byId[t.i] || {})))),
|
|
289
|
+
Object.assign(Object.assign({}, saveDefaultLayout), { i: newItem.id }),
|
|
290
|
+
];
|
|
291
|
+
}
|
|
292
|
+
return update(config, {
|
|
293
|
+
items: { $push: [newItem] },
|
|
294
|
+
layout: { $set: newLayout },
|
|
295
|
+
counter: { $set: counter },
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
else if (isFinite(layout.y)) {
|
|
299
|
+
let newLayout;
|
|
300
|
+
const newLayoutItem = Object.assign(Object.assign({}, saveDefaultLayout), { i: newItem.id });
|
|
301
|
+
if (options.reflowLayoutOptions) {
|
|
302
|
+
newLayout = reflowLayout(newLayoutItem, config.layout, options.reflowLayoutOptions);
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
newLayout = [...config.layout, newLayoutItem];
|
|
306
|
+
}
|
|
242
307
|
return update(config, {
|
|
243
308
|
items: { $push: [newItem] },
|
|
244
309
|
layout: { $set: newLayout },
|
|
@@ -246,7 +311,7 @@ export class UpdateManager {
|
|
|
246
311
|
});
|
|
247
312
|
}
|
|
248
313
|
else {
|
|
249
|
-
const layoutY =
|
|
314
|
+
const layoutY = bottom(config.layout);
|
|
250
315
|
const newLayoutItem = Object.assign(Object.assign({}, saveDefaultLayout), { y: layoutY, i: newItem.id });
|
|
251
316
|
return update(config, {
|
|
252
317
|
items: { $push: [newItem] },
|