@gravity-ui/dashkit 8.2.0-beta.0 → 8.3.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/components/DashKit/DashKit.d.ts +3 -1
- package/build/cjs/components/DashKit/DashKit.js +1 -5
- package/build/cjs/components/GridLayout/GridLayout.d.ts +6 -3
- package/build/cjs/components/GridLayout/GridLayout.js +100 -13
- package/build/cjs/components/GridLayout/ReactGridLayout.js +17 -2
- package/build/cjs/constants/common.d.ts +1 -0
- package/build/cjs/constants/common.js +2 -1
- package/build/cjs/hocs/withContext.js +13 -9
- package/build/cjs/hooks/useCalcLayout.d.ts +1 -0
- package/build/cjs/shared/types/config.d.ts +4 -1
- package/build/cjs/typings/common.d.ts +2 -1
- package/build/cjs/typings/config.d.ts +12 -1
- package/build/cjs/typings/plugin.d.ts +1 -10
- package/build/cjs/utils/update-manager.js +3 -2
- package/build/esm/components/DashKit/DashKit.d.ts +3 -1
- package/build/esm/components/DashKit/DashKit.js +1 -5
- package/build/esm/components/GridLayout/GridLayout.d.ts +6 -3
- package/build/esm/components/GridLayout/GridLayout.js +101 -14
- package/build/esm/components/GridLayout/ReactGridLayout.js +17 -2
- package/build/esm/constants/common.d.ts +1 -0
- package/build/esm/constants/common.js +1 -0
- package/build/esm/hocs/withContext.js +13 -9
- package/build/esm/hooks/useCalcLayout.d.ts +1 -0
- package/build/esm/shared/types/config.d.ts +4 -1
- package/build/esm/typings/common.d.ts +2 -1
- package/build/esm/typings/config.d.ts +12 -1
- package/build/esm/typings/plugin.d.ts +1 -10
- package/build/esm/utils/update-manager.js +3 -2
- package/package.json +4 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Config, ConfigItem, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
|
|
3
|
-
import { ContextProps, Plugin, SetConfigItem, SetNewItemOptions, Settings, SettingsProps } from '../../typings';
|
|
3
|
+
import { ContextProps, DashKiGroup, Plugin, SetConfigItem, SetNewItemOptions, Settings, SettingsProps } from '../../typings';
|
|
4
4
|
import GridLayout from '../GridLayout/GridLayout';
|
|
5
5
|
import { OverlayControlItem } from '../OverlayControls/OverlayControls';
|
|
6
6
|
interface DashKitGeneralProps {
|
|
@@ -14,6 +14,7 @@ interface DashKitDefaultProps {
|
|
|
14
14
|
onChange: (data: {
|
|
15
15
|
config: Config;
|
|
16
16
|
itemsStateAndParams: ItemsStateAndParams;
|
|
17
|
+
groups?: DashKiGroup[];
|
|
17
18
|
}) => void;
|
|
18
19
|
onDrop: (dropProps: ItemDropProps) => void;
|
|
19
20
|
defaultGlobalParams: GlobalParams;
|
|
@@ -23,6 +24,7 @@ interface DashKitDefaultProps {
|
|
|
23
24
|
context: ContextProps;
|
|
24
25
|
noOverlay: boolean;
|
|
25
26
|
focusable?: boolean;
|
|
27
|
+
groups?: DashKiGroup[];
|
|
26
28
|
}
|
|
27
29
|
export interface DashKitProps extends DashKitGeneralProps, Partial<DashKitDefaultProps> {
|
|
28
30
|
}
|
|
@@ -44,11 +44,7 @@ class DashKit extends react_1.default.PureComponent {
|
|
|
44
44
|
return utils_1.UpdateManager.removeItem({ id, config, itemsStateAndParams });
|
|
45
45
|
}
|
|
46
46
|
render() {
|
|
47
|
-
return
|
|
48
|
-
// @ts-ignore
|
|
49
|
-
, Object.assign({
|
|
50
|
-
// @ts-ignore
|
|
51
|
-
registerManager: registerManager, ref: this.metaRef }, this.props)));
|
|
47
|
+
return react_1.default.createElement(DashKitView_1.default, Object.assign({ registerManager: registerManager, ref: this.metaRef }, this.props));
|
|
52
48
|
}
|
|
53
49
|
getItemsMeta() {
|
|
54
50
|
var _a;
|
|
@@ -18,12 +18,15 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
|
|
|
18
18
|
adjustedWidgetLayout: any;
|
|
19
19
|
}) => void;
|
|
20
20
|
getItemsMeta: () => any;
|
|
21
|
+
getActiveLayout(): any;
|
|
22
|
+
mergeGroupsLayout(group: any, newLayout: any, temporaryItem: any): any;
|
|
21
23
|
reloadItems(): void;
|
|
22
24
|
_onStart: () => void;
|
|
23
|
-
_onStop: (newLayout: any) => void;
|
|
25
|
+
_onStop: (group: any, newLayout: any) => void;
|
|
24
26
|
_onDropDragOver: (e: any) => any;
|
|
25
|
-
_onDrop: (
|
|
27
|
+
_onDrop: (group: any, newLayout: any, item: any, e: any) => false | undefined;
|
|
26
28
|
renderTemporaryPlaceholder(): JSX.Element | null;
|
|
27
|
-
|
|
29
|
+
renderGroup(group: any, renderLayout: any, renderItems: any, offset?: number): JSX.Element;
|
|
30
|
+
render(): any;
|
|
28
31
|
}
|
|
29
32
|
import React from 'react';
|
|
@@ -35,13 +35,14 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
35
35
|
return;
|
|
36
36
|
this.setState({ isDragging: true });
|
|
37
37
|
};
|
|
38
|
-
this._onStop = (newLayout) => {
|
|
38
|
+
this._onStop = (group, newLayout) => {
|
|
39
39
|
const { layoutChange, onDrop, temporaryLayout } = this.context;
|
|
40
|
+
const groupedLayout = this.mergeGroupsLayout(group, newLayout);
|
|
40
41
|
if (temporaryLayout) {
|
|
41
|
-
onDrop === null || onDrop === void 0 ? void 0 : onDrop(
|
|
42
|
+
onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, groupedLayout.find(({ i }) => i === constants_1.TEMPORARY_ITEM_ID));
|
|
42
43
|
}
|
|
43
44
|
else {
|
|
44
|
-
layoutChange(
|
|
45
|
+
layoutChange(groupedLayout);
|
|
45
46
|
}
|
|
46
47
|
this.setState({ isDragging: false });
|
|
47
48
|
};
|
|
@@ -52,7 +53,7 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
52
53
|
}
|
|
53
54
|
return onDropDragOver(e);
|
|
54
55
|
};
|
|
55
|
-
this._onDrop = (
|
|
56
|
+
this._onDrop = (group, newLayout, item, e) => {
|
|
56
57
|
if (!item) {
|
|
57
58
|
return false;
|
|
58
59
|
}
|
|
@@ -60,7 +61,11 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
60
61
|
if (!editMode) {
|
|
61
62
|
return false;
|
|
62
63
|
}
|
|
63
|
-
|
|
64
|
+
if (group !== constants_1.DEFAULT_GROUP) {
|
|
65
|
+
item.parent = group;
|
|
66
|
+
}
|
|
67
|
+
const groupedLayout = this.mergeGroupsLayout(group, newLayout, item);
|
|
68
|
+
onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, item, e);
|
|
64
69
|
};
|
|
65
70
|
this.pluginsRefs = [];
|
|
66
71
|
this.state = {
|
|
@@ -80,6 +85,29 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
80
85
|
clearTimeout(this._timeout);
|
|
81
86
|
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
82
87
|
}
|
|
88
|
+
getActiveLayout() {
|
|
89
|
+
const { layout, temporaryLayout } = this.context;
|
|
90
|
+
return (temporaryLayout === null || temporaryLayout === void 0 ? void 0 : temporaryLayout.data) || layout;
|
|
91
|
+
}
|
|
92
|
+
mergeGroupsLayout(group, newLayout, temporaryItem) {
|
|
93
|
+
const renderLayout = this.getActiveLayout();
|
|
94
|
+
const itemsByGroup = renderLayout.reduce((memo, item) => {
|
|
95
|
+
memo[item.i] = item;
|
|
96
|
+
return memo;
|
|
97
|
+
}, temporaryItem ? { [temporaryItem.i]: temporaryItem } : {});
|
|
98
|
+
const newItemsLayoutById = newLayout.reduce((memo, item) => {
|
|
99
|
+
const parent = itemsByGroup[item.i].parent;
|
|
100
|
+
memo[item.i] = Object.assign(Object.assign({}, item), { parent });
|
|
101
|
+
return memo;
|
|
102
|
+
}, {});
|
|
103
|
+
return renderLayout.map((currentItem) => {
|
|
104
|
+
const itemParent = itemsByGroup[currentItem.i].parent || constants_1.DEFAULT_GROUP;
|
|
105
|
+
if (itemParent === group) {
|
|
106
|
+
return newItemsLayoutById[currentItem.i];
|
|
107
|
+
}
|
|
108
|
+
return currentItem;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
83
111
|
reloadItems() {
|
|
84
112
|
const { editMode, settings: { autoupdateInterval, silentLoading } = {}, reloadItems, } = this.context;
|
|
85
113
|
const { isPageHidden } = this.state;
|
|
@@ -103,25 +131,84 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
103
131
|
const { type } = temporaryLayout.dragProps;
|
|
104
132
|
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), overlayControls: this.props.overlayControls }));
|
|
105
133
|
}
|
|
106
|
-
|
|
107
|
-
const {
|
|
108
|
-
this.
|
|
109
|
-
return (react_1.default.createElement(ReactGridLayout_1.Layout, Object.assign({}, registerManager.gridLayout, { layout: (temporaryLayout === null || temporaryLayout === void 0 ? void 0 : temporaryLayout.data) || layout, isDraggable: editMode, isResizable: editMode, onDragStart: this._onStart, onDragStop: this._onStop, onResizeStart: this._onStart, onResizeStop: this._onStop }, (draggableHandleClassName
|
|
134
|
+
renderGroup(group, renderLayout, renderItems, offset = 0) {
|
|
135
|
+
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
136
|
+
return (react_1.default.createElement(ReactGridLayout_1.Layout, Object.assign({}, registerManager.gridLayout, { key: `group_${group}`, layout: renderLayout, isDraggable: editMode, isResizable: editMode, onDragStart: this._onStart, onDragStop: (...args) => this._onStop(group, ...args), onResizeStart: this._onStart, onResizeStop: (...args) => this._onStop(group, ...args) }, (draggableHandleClassName
|
|
110
137
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
111
138
|
: null), (outerDnDEnable
|
|
112
139
|
? {
|
|
113
140
|
isDroppable: true,
|
|
114
141
|
onDropDragOver: this._onDropDragOver,
|
|
115
|
-
onDrop: this._onDrop,
|
|
142
|
+
onDrop: (...args) => this._onDrop(group, ...args),
|
|
116
143
|
}
|
|
117
144
|
: null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
118
|
-
|
|
145
|
+
renderItems.map((item, i) => {
|
|
119
146
|
return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: (pluginRef) => {
|
|
120
|
-
this.pluginsRefs[i] = pluginRef;
|
|
121
|
-
}, key: item.id, id: item.id, item: item, layout:
|
|
147
|
+
this.pluginsRefs[offset + i] = pluginRef;
|
|
148
|
+
}, key: item.id, id: item.id, item: item, layout: renderLayout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
|
|
122
149
|
}),
|
|
123
150
|
this.renderTemporaryPlaceholder()));
|
|
124
151
|
}
|
|
152
|
+
render() {
|
|
153
|
+
const { config, groups, editMode } = this.context;
|
|
154
|
+
this.pluginsRefs.length = config.items.length;
|
|
155
|
+
const defaultRenderLayout = [];
|
|
156
|
+
const defaultRenderItems = [];
|
|
157
|
+
const layoutMap = {};
|
|
158
|
+
const groupedLayout = this.getActiveLayout().reduce((memo, item) => {
|
|
159
|
+
if (item.parent) {
|
|
160
|
+
if (!memo[item.parent]) {
|
|
161
|
+
memo[item.parent] = [];
|
|
162
|
+
}
|
|
163
|
+
memo[item.parent].push(item);
|
|
164
|
+
layoutMap[item.i] = item.parent;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
defaultRenderLayout.push(item);
|
|
168
|
+
}
|
|
169
|
+
return memo;
|
|
170
|
+
}, []);
|
|
171
|
+
const itemsByGroup = config.items.reduce((memo, item) => {
|
|
172
|
+
const group = layoutMap[item.id];
|
|
173
|
+
if (group) {
|
|
174
|
+
if (!memo[group]) {
|
|
175
|
+
memo[group] = [];
|
|
176
|
+
}
|
|
177
|
+
memo[group].push(item);
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
defaultRenderItems.push(item);
|
|
181
|
+
}
|
|
182
|
+
return memo;
|
|
183
|
+
}, {});
|
|
184
|
+
let offset = 0;
|
|
185
|
+
if (groups) {
|
|
186
|
+
return groups.map((group) => {
|
|
187
|
+
const id = group.id || constants_1.DEFAULT_GROUP;
|
|
188
|
+
let element;
|
|
189
|
+
if (id === constants_1.DEFAULT_GROUP) {
|
|
190
|
+
element = this.renderGroup(constants_1.DEFAULT_GROUP, defaultRenderLayout, defaultRenderItems, offset);
|
|
191
|
+
offset += defaultRenderItems.length;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
element = this.renderGroup(id, groupedLayout[id], itemsByGroup[id], offset);
|
|
195
|
+
offset += itemsByGroup[id].length;
|
|
196
|
+
}
|
|
197
|
+
if (group.render) {
|
|
198
|
+
return group.render(id, element, {
|
|
199
|
+
config,
|
|
200
|
+
editMode,
|
|
201
|
+
items: itemsByGroup[id],
|
|
202
|
+
layout: groupedLayout[id],
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return element;
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
return this.renderGroup(constants_1.DEFAULT_GROUP, defaultRenderLayout, defaultRenderItems, offset);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
125
212
|
}
|
|
126
213
|
GridLayout.contextType = DashKitContext_1.DashKitContext;
|
|
127
214
|
exports.default = GridLayout;
|
|
@@ -6,14 +6,29 @@ const react_1 = tslib_1.__importDefault(require("react"));
|
|
|
6
6
|
const react_grid_layout_1 = tslib_1.__importStar(require("react-grid-layout"));
|
|
7
7
|
const constants_1 = require("../../constants");
|
|
8
8
|
class DragOverLayout extends react_grid_layout_1.default {
|
|
9
|
-
constructor() {
|
|
10
|
-
super(...
|
|
9
|
+
constructor(...args) {
|
|
10
|
+
super(...args);
|
|
11
11
|
this.dragReset = () => {
|
|
12
12
|
if (this.dragEnterCounter) {
|
|
13
13
|
this.dragEnterCounter = 0;
|
|
14
14
|
this.removeDroppingPlaceholder();
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
|
+
this.mouseLeaveHandler = (e) => {
|
|
18
|
+
var _a;
|
|
19
|
+
const rect = ((_a = this.props.innerRef) === null || _a === void 0 ? void 0 : _a.current.getBoundingClientRect()) || {};
|
|
20
|
+
if (rect.bottom <= e.clientY ||
|
|
21
|
+
rect.top >= e.clientY ||
|
|
22
|
+
rect.left >= e.clientX ||
|
|
23
|
+
rect.right <= e.clientX) {
|
|
24
|
+
this.dragReset();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const oldonDrag = this.onDrag;
|
|
28
|
+
this.onDrag = (i, x, y, sintE) => {
|
|
29
|
+
oldonDrag(i, x, y, sintE);
|
|
30
|
+
this.mouseLeaveHandler(sintE.e);
|
|
31
|
+
};
|
|
17
32
|
}
|
|
18
33
|
componentDidMount() {
|
|
19
34
|
var _a;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_WIDGET_WIDTH = exports.DEFAULT_WIDGET_HEIGHT = exports.MenuItems = exports.TEMPORARY_ITEM_ID = exports.OVERLAY_CLASS_NAME = exports.OVERLAY_CONTROLS_CLASS_NAME = exports.DEFAULT_NAMESPACE = exports.COPIED_WIDGET_STORE_KEY = void 0;
|
|
3
|
+
exports.DEFAULT_GROUP = exports.DEFAULT_WIDGET_WIDTH = exports.DEFAULT_WIDGET_HEIGHT = exports.MenuItems = exports.TEMPORARY_ITEM_ID = exports.OVERLAY_CLASS_NAME = exports.OVERLAY_CONTROLS_CLASS_NAME = exports.DEFAULT_NAMESPACE = exports.COPIED_WIDGET_STORE_KEY = void 0;
|
|
4
4
|
exports.COPIED_WIDGET_STORE_KEY = 'dashCopiedItem';
|
|
5
5
|
exports.DEFAULT_NAMESPACE = 'default';
|
|
6
6
|
exports.OVERLAY_CONTROLS_CLASS_NAME = 'dashkit-overlay-controls';
|
|
@@ -13,3 +13,4 @@ exports.MenuItems = {
|
|
|
13
13
|
};
|
|
14
14
|
exports.DEFAULT_WIDGET_HEIGHT = 3;
|
|
15
15
|
exports.DEFAULT_WIDGET_WIDTH = 3;
|
|
16
|
+
exports.DEFAULT_GROUP = '__default';
|
|
@@ -4,6 +4,7 @@ exports.withContext = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
6
|
const isEqual_1 = tslib_1.__importDefault(require("lodash/isEqual"));
|
|
7
|
+
const pick_1 = tslib_1.__importDefault(require("lodash/pick"));
|
|
7
8
|
const common_1 = require("../constants/common");
|
|
8
9
|
const DashKitContext_1 = require("../context/DashKitContext");
|
|
9
10
|
const shared_1 = require("../shared");
|
|
@@ -22,10 +23,11 @@ function useMemoStateContext(props) {
|
|
|
22
23
|
const outerDnDEnable = Boolean(dndContext);
|
|
23
24
|
// TODO: need move originalLayouts, adjustedLayouts to state
|
|
24
25
|
const [layoutUpdateCounter, forceUpdateLayout] = react_1.default.useState(0);
|
|
25
|
-
const onChange = react_1.default.useCallback(({ config = props.config, itemsStateAndParams = props.itemsStateAndParams }) => {
|
|
26
|
+
const onChange = react_1.default.useCallback(({ config = props.config, itemsStateAndParams = props.itemsStateAndParams, groups = props.groups, }) => {
|
|
26
27
|
if (!((0, isEqual_1.default)(config, props.config) &&
|
|
27
|
-
(0, isEqual_1.default)(itemsStateAndParams, props.itemsStateAndParams)
|
|
28
|
-
|
|
28
|
+
(0, isEqual_1.default)(itemsStateAndParams, props.itemsStateAndParams) &&
|
|
29
|
+
(0, isEqual_1.default)(groups, props.groups))) {
|
|
30
|
+
props.onChange({ config, itemsStateAndParams, groups });
|
|
29
31
|
}
|
|
30
32
|
}, [props.config, props.itemsStateAndParams, props.onChange]);
|
|
31
33
|
// каллбэк вызывающийся при изменение лэйаута сетки, первым аргументом приходит актуальный конфиг лэйаута,
|
|
@@ -171,6 +173,7 @@ function useMemoStateContext(props) {
|
|
|
171
173
|
}
|
|
172
174
|
return false;
|
|
173
175
|
}, [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps]);
|
|
176
|
+
const onDropProp = props.onDrop;
|
|
174
177
|
const onDrop = react_1.default.useCallback((newLayout, item) => {
|
|
175
178
|
if (!dragProps) {
|
|
176
179
|
return;
|
|
@@ -179,23 +182,23 @@ function useMemoStateContext(props) {
|
|
|
179
182
|
data: newLayout,
|
|
180
183
|
dragProps,
|
|
181
184
|
});
|
|
182
|
-
|
|
183
|
-
props.onDrop({
|
|
185
|
+
onDropProp({
|
|
184
186
|
newLayout: newLayout.reduce((memo, l) => {
|
|
185
|
-
if (l.i !== i) {
|
|
186
|
-
memo.push(
|
|
187
|
+
if (l.i !== item.i) {
|
|
188
|
+
memo.push((0, pick_1.default)(l, ['i', 'h', 'w', 'x', 'y', 'parent']));
|
|
187
189
|
}
|
|
188
190
|
return memo;
|
|
189
191
|
}, []),
|
|
190
|
-
itemLayout:
|
|
192
|
+
itemLayout: (0, pick_1.default)(item, ['i', 'h', 'w', 'x', 'y', 'parent']),
|
|
191
193
|
commit: resetTemporaryLayout,
|
|
192
194
|
dragProps,
|
|
193
195
|
});
|
|
194
|
-
}, [dragProps,
|
|
196
|
+
}, [dragProps, onDropProp, setTemporaryLayout, resetTemporaryLayout]);
|
|
195
197
|
return react_1.default.useMemo(() => ({
|
|
196
198
|
layout: resultLayout,
|
|
197
199
|
temporaryLayout,
|
|
198
200
|
config: props.config,
|
|
201
|
+
groups: props.groups,
|
|
199
202
|
context: props.context,
|
|
200
203
|
noOverlay: props.noOverlay,
|
|
201
204
|
focusable: props.focusable,
|
|
@@ -224,6 +227,7 @@ function useMemoStateContext(props) {
|
|
|
224
227
|
resultLayout,
|
|
225
228
|
temporaryLayout,
|
|
226
229
|
props.config,
|
|
230
|
+
props.groups,
|
|
227
231
|
props.context,
|
|
228
232
|
props.noOverlay,
|
|
229
233
|
props.focusable,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type ReactGridLayout from 'react-grid-layout';
|
|
2
2
|
import type { OverlayCustomControlItem } from '../components/OverlayControls/OverlayControls';
|
|
3
3
|
import { MenuItems } from '../constants';
|
|
4
|
+
import { AdditionalWidgetLayout } from '../shared';
|
|
4
5
|
export interface Settings {
|
|
5
6
|
gridLayout?: ReactGridLayout.ReactGridLayoutProps;
|
|
6
7
|
theme?: string;
|
|
@@ -15,7 +16,7 @@ export interface SettingsProps {
|
|
|
15
16
|
export interface ContextProps {
|
|
16
17
|
[key: string]: any;
|
|
17
18
|
}
|
|
18
|
-
export interface WidgetLayout {
|
|
19
|
+
export interface WidgetLayout extends AdditionalWidgetLayout {
|
|
19
20
|
i: string;
|
|
20
21
|
w: number;
|
|
21
22
|
h: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { Config, ConfigItem, ConfigLayout } from '../shared';
|
|
2
3
|
export interface AddConfigItem extends Omit<ConfigItem, 'id' | 'namespace'> {
|
|
3
4
|
id?: null;
|
|
4
5
|
namespace?: string;
|
|
@@ -11,3 +12,13 @@ export type SetItemOptions = {
|
|
|
11
12
|
export type SetNewItemOptions = SetItemOptions & {
|
|
12
13
|
updateLayout?: ConfigLayout[];
|
|
13
14
|
};
|
|
15
|
+
export interface DashkitGroupRenderProps {
|
|
16
|
+
config: Config;
|
|
17
|
+
editMode: boolean;
|
|
18
|
+
items: ConfigItem[];
|
|
19
|
+
layout: ConfigLayout[];
|
|
20
|
+
}
|
|
21
|
+
export interface DashKiGroup {
|
|
22
|
+
id?: string;
|
|
23
|
+
render?: (id: string, children: React.ReactNode, props: DashkitGroupRenderProps) => React.ReactNode;
|
|
24
|
+
}
|
|
@@ -23,16 +23,7 @@ export interface PluginWidgetProps<T = StringParams> {
|
|
|
23
23
|
adjustedWidgetLayout?: WidgetLayout;
|
|
24
24
|
}) => void;
|
|
25
25
|
}
|
|
26
|
-
export
|
|
27
|
-
w?: number;
|
|
28
|
-
h?: number;
|
|
29
|
-
x?: number;
|
|
30
|
-
y?: number;
|
|
31
|
-
minW?: number;
|
|
32
|
-
maxW?: number;
|
|
33
|
-
minH?: number;
|
|
34
|
-
maxH?: number;
|
|
35
|
-
}
|
|
26
|
+
export type PluginDefaultLayout = Partial<Omit<WidgetLayout, 'i'>>;
|
|
36
27
|
export interface Plugin<P extends PluginWidgetProps<T> = any, T = StringParams> extends PluginBase {
|
|
37
28
|
defaultLayout?: PluginDefaultLayout;
|
|
38
29
|
renderer: (props: P, forwardedRef: React.RefObject<any>) => React.ReactNode;
|
|
@@ -82,6 +82,7 @@ function getAllowableChangedParams(item, stateAndParams, itemsStateAndParams, pa
|
|
|
82
82
|
// if it's Record<string, StringParams>, then this is a group application of params
|
|
83
83
|
// and checking for comparison of allowedParams and stateParamsConf is not necessary
|
|
84
84
|
const isGroupParamsApply = typeof (stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id]) === 'object' &&
|
|
85
|
+
(stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id]) !== null &&
|
|
85
86
|
!Array.isArray(stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id]);
|
|
86
87
|
if ((0, shared_1.isItemWithTabs)(item)) {
|
|
87
88
|
let tab;
|
|
@@ -233,7 +234,7 @@ class UpdateManager {
|
|
|
233
234
|
const newIdData = (0, get_new_id_1.getNewId)({ config, salt, counter, excludeIds: newItemData.excludeIds });
|
|
234
235
|
counter = newIdData.counter;
|
|
235
236
|
const newItem = Object.assign(Object.assign({}, item), { id: newIdData.id, data: newItemData.data, namespace });
|
|
236
|
-
const saveDefaultLayout = (0, pick_1.default)(layout, ['h', 'w', 'x', 'y']);
|
|
237
|
+
const saveDefaultLayout = (0, pick_1.default)(layout, ['h', 'w', 'x', 'y', 'parent']);
|
|
237
238
|
if (options.updateLayout) {
|
|
238
239
|
const byId = options.updateLayout.reduce((memo, t) => {
|
|
239
240
|
memo[t.i] = t;
|
|
@@ -314,7 +315,7 @@ class UpdateManager {
|
|
|
314
315
|
static updateLayout({ layout, config }) {
|
|
315
316
|
return (0, immutability_helper_1.default)(config, {
|
|
316
317
|
layout: {
|
|
317
|
-
$set: layout.map((
|
|
318
|
+
$set: layout.map((item) => (0, pick_1.default)(item, ['i', 'h', 'w', 'x', 'y', 'parent'])),
|
|
318
319
|
},
|
|
319
320
|
});
|
|
320
321
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Config, ConfigItem, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
|
|
3
|
-
import { ContextProps, Plugin, SetConfigItem, SetNewItemOptions, Settings, SettingsProps } from '../../typings';
|
|
3
|
+
import { ContextProps, DashKiGroup, Plugin, SetConfigItem, SetNewItemOptions, Settings, SettingsProps } from '../../typings';
|
|
4
4
|
import GridLayout from '../GridLayout/GridLayout';
|
|
5
5
|
import { OverlayControlItem } from '../OverlayControls/OverlayControls';
|
|
6
6
|
interface DashKitGeneralProps {
|
|
@@ -14,6 +14,7 @@ interface DashKitDefaultProps {
|
|
|
14
14
|
onChange: (data: {
|
|
15
15
|
config: Config;
|
|
16
16
|
itemsStateAndParams: ItemsStateAndParams;
|
|
17
|
+
groups?: DashKiGroup[];
|
|
17
18
|
}) => void;
|
|
18
19
|
onDrop: (dropProps: ItemDropProps) => void;
|
|
19
20
|
defaultGlobalParams: GlobalParams;
|
|
@@ -23,6 +24,7 @@ interface DashKitDefaultProps {
|
|
|
23
24
|
context: ContextProps;
|
|
24
25
|
noOverlay: boolean;
|
|
25
26
|
focusable?: boolean;
|
|
27
|
+
groups?: DashKiGroup[];
|
|
26
28
|
}
|
|
27
29
|
export interface DashKitProps extends DashKitGeneralProps, Partial<DashKitDefaultProps> {
|
|
28
30
|
}
|
|
@@ -40,11 +40,7 @@ export class DashKit extends React.PureComponent {
|
|
|
40
40
|
return UpdateManager.removeItem({ id, config, itemsStateAndParams });
|
|
41
41
|
}
|
|
42
42
|
render() {
|
|
43
|
-
return
|
|
44
|
-
// @ts-ignore
|
|
45
|
-
, Object.assign({
|
|
46
|
-
// @ts-ignore
|
|
47
|
-
registerManager: registerManager, ref: this.metaRef }, this.props)));
|
|
43
|
+
return React.createElement(DashKitView, Object.assign({ registerManager: registerManager, ref: this.metaRef }, this.props));
|
|
48
44
|
}
|
|
49
45
|
getItemsMeta() {
|
|
50
46
|
var _a;
|
|
@@ -18,12 +18,15 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
|
|
|
18
18
|
adjustedWidgetLayout: any;
|
|
19
19
|
}) => void;
|
|
20
20
|
getItemsMeta: () => any;
|
|
21
|
+
getActiveLayout(): any;
|
|
22
|
+
mergeGroupsLayout(group: any, newLayout: any, temporaryItem: any): any;
|
|
21
23
|
reloadItems(): void;
|
|
22
24
|
_onStart: () => void;
|
|
23
|
-
_onStop: (newLayout: any) => void;
|
|
25
|
+
_onStop: (group: any, newLayout: any) => void;
|
|
24
26
|
_onDropDragOver: (e: any) => any;
|
|
25
|
-
_onDrop: (
|
|
27
|
+
_onDrop: (group: any, newLayout: any, item: any, e: any) => false | undefined;
|
|
26
28
|
renderTemporaryPlaceholder(): JSX.Element | null;
|
|
27
|
-
|
|
29
|
+
renderGroup(group: any, renderLayout: any, renderItems: any, offset?: number): JSX.Element;
|
|
30
|
+
render(): any;
|
|
28
31
|
}
|
|
29
32
|
import React from 'react';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { OVERLAY_CONTROLS_CLASS_NAME, TEMPORARY_ITEM_ID } from '../../constants';
|
|
2
|
+
import { DEFAULT_GROUP, OVERLAY_CONTROLS_CLASS_NAME, TEMPORARY_ITEM_ID } from '../../constants';
|
|
3
3
|
import { DashKitContext } from '../../context/DashKitContext';
|
|
4
4
|
import GridItem from '../GridItem/GridItem';
|
|
5
5
|
import { Layout } from './ReactGridLayout';
|
|
@@ -32,13 +32,14 @@ class GridLayout extends React.PureComponent {
|
|
|
32
32
|
return;
|
|
33
33
|
this.setState({ isDragging: true });
|
|
34
34
|
};
|
|
35
|
-
this._onStop = (newLayout) => {
|
|
35
|
+
this._onStop = (group, newLayout) => {
|
|
36
36
|
const { layoutChange, onDrop, temporaryLayout } = this.context;
|
|
37
|
+
const groupedLayout = this.mergeGroupsLayout(group, newLayout);
|
|
37
38
|
if (temporaryLayout) {
|
|
38
|
-
onDrop === null || onDrop === void 0 ? void 0 : onDrop(
|
|
39
|
+
onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, groupedLayout.find(({ i }) => i === TEMPORARY_ITEM_ID));
|
|
39
40
|
}
|
|
40
41
|
else {
|
|
41
|
-
layoutChange(
|
|
42
|
+
layoutChange(groupedLayout);
|
|
42
43
|
}
|
|
43
44
|
this.setState({ isDragging: false });
|
|
44
45
|
};
|
|
@@ -49,7 +50,7 @@ class GridLayout extends React.PureComponent {
|
|
|
49
50
|
}
|
|
50
51
|
return onDropDragOver(e);
|
|
51
52
|
};
|
|
52
|
-
this._onDrop = (
|
|
53
|
+
this._onDrop = (group, newLayout, item, e) => {
|
|
53
54
|
if (!item) {
|
|
54
55
|
return false;
|
|
55
56
|
}
|
|
@@ -57,7 +58,11 @@ class GridLayout extends React.PureComponent {
|
|
|
57
58
|
if (!editMode) {
|
|
58
59
|
return false;
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
+
if (group !== DEFAULT_GROUP) {
|
|
62
|
+
item.parent = group;
|
|
63
|
+
}
|
|
64
|
+
const groupedLayout = this.mergeGroupsLayout(group, newLayout, item);
|
|
65
|
+
onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, item, e);
|
|
61
66
|
};
|
|
62
67
|
this.pluginsRefs = [];
|
|
63
68
|
this.state = {
|
|
@@ -77,6 +82,29 @@ class GridLayout extends React.PureComponent {
|
|
|
77
82
|
clearTimeout(this._timeout);
|
|
78
83
|
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
79
84
|
}
|
|
85
|
+
getActiveLayout() {
|
|
86
|
+
const { layout, temporaryLayout } = this.context;
|
|
87
|
+
return (temporaryLayout === null || temporaryLayout === void 0 ? void 0 : temporaryLayout.data) || layout;
|
|
88
|
+
}
|
|
89
|
+
mergeGroupsLayout(group, newLayout, temporaryItem) {
|
|
90
|
+
const renderLayout = this.getActiveLayout();
|
|
91
|
+
const itemsByGroup = renderLayout.reduce((memo, item) => {
|
|
92
|
+
memo[item.i] = item;
|
|
93
|
+
return memo;
|
|
94
|
+
}, temporaryItem ? { [temporaryItem.i]: temporaryItem } : {});
|
|
95
|
+
const newItemsLayoutById = newLayout.reduce((memo, item) => {
|
|
96
|
+
const parent = itemsByGroup[item.i].parent;
|
|
97
|
+
memo[item.i] = Object.assign(Object.assign({}, item), { parent });
|
|
98
|
+
return memo;
|
|
99
|
+
}, {});
|
|
100
|
+
return renderLayout.map((currentItem) => {
|
|
101
|
+
const itemParent = itemsByGroup[currentItem.i].parent || DEFAULT_GROUP;
|
|
102
|
+
if (itemParent === group) {
|
|
103
|
+
return newItemsLayoutById[currentItem.i];
|
|
104
|
+
}
|
|
105
|
+
return currentItem;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
80
108
|
reloadItems() {
|
|
81
109
|
const { editMode, settings: { autoupdateInterval, silentLoading } = {}, reloadItems, } = this.context;
|
|
82
110
|
const { isPageHidden } = this.state;
|
|
@@ -100,25 +128,84 @@ class GridLayout extends React.PureComponent {
|
|
|
100
128
|
const { type } = temporaryLayout.dragProps;
|
|
101
129
|
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), overlayControls: this.props.overlayControls }));
|
|
102
130
|
}
|
|
103
|
-
|
|
104
|
-
const {
|
|
105
|
-
this.
|
|
106
|
-
return (React.createElement(Layout, Object.assign({}, registerManager.gridLayout, { layout: (temporaryLayout === null || temporaryLayout === void 0 ? void 0 : temporaryLayout.data) || layout, isDraggable: editMode, isResizable: editMode, onDragStart: this._onStart, onDragStop: this._onStop, onResizeStart: this._onStart, onResizeStop: this._onStop }, (draggableHandleClassName
|
|
131
|
+
renderGroup(group, renderLayout, renderItems, offset = 0) {
|
|
132
|
+
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
133
|
+
return (React.createElement(Layout, Object.assign({}, registerManager.gridLayout, { key: `group_${group}`, layout: renderLayout, isDraggable: editMode, isResizable: editMode, onDragStart: this._onStart, onDragStop: (...args) => this._onStop(group, ...args), onResizeStart: this._onStart, onResizeStop: (...args) => this._onStop(group, ...args) }, (draggableHandleClassName
|
|
107
134
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
108
135
|
: null), (outerDnDEnable
|
|
109
136
|
? {
|
|
110
137
|
isDroppable: true,
|
|
111
138
|
onDropDragOver: this._onDropDragOver,
|
|
112
|
-
onDrop: this._onDrop,
|
|
139
|
+
onDrop: (...args) => this._onDrop(group, ...args),
|
|
113
140
|
}
|
|
114
141
|
: null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
115
|
-
|
|
142
|
+
renderItems.map((item, i) => {
|
|
116
143
|
return (React.createElement(GridItem, { forwardedPluginRef: (pluginRef) => {
|
|
117
|
-
this.pluginsRefs[i] = pluginRef;
|
|
118
|
-
}, key: item.id, id: item.id, item: item, layout:
|
|
144
|
+
this.pluginsRefs[offset + i] = pluginRef;
|
|
145
|
+
}, key: item.id, id: item.id, item: item, layout: renderLayout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
|
|
119
146
|
}),
|
|
120
147
|
this.renderTemporaryPlaceholder()));
|
|
121
148
|
}
|
|
149
|
+
render() {
|
|
150
|
+
const { config, groups, editMode } = this.context;
|
|
151
|
+
this.pluginsRefs.length = config.items.length;
|
|
152
|
+
const defaultRenderLayout = [];
|
|
153
|
+
const defaultRenderItems = [];
|
|
154
|
+
const layoutMap = {};
|
|
155
|
+
const groupedLayout = this.getActiveLayout().reduce((memo, item) => {
|
|
156
|
+
if (item.parent) {
|
|
157
|
+
if (!memo[item.parent]) {
|
|
158
|
+
memo[item.parent] = [];
|
|
159
|
+
}
|
|
160
|
+
memo[item.parent].push(item);
|
|
161
|
+
layoutMap[item.i] = item.parent;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
defaultRenderLayout.push(item);
|
|
165
|
+
}
|
|
166
|
+
return memo;
|
|
167
|
+
}, []);
|
|
168
|
+
const itemsByGroup = config.items.reduce((memo, item) => {
|
|
169
|
+
const group = layoutMap[item.id];
|
|
170
|
+
if (group) {
|
|
171
|
+
if (!memo[group]) {
|
|
172
|
+
memo[group] = [];
|
|
173
|
+
}
|
|
174
|
+
memo[group].push(item);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
defaultRenderItems.push(item);
|
|
178
|
+
}
|
|
179
|
+
return memo;
|
|
180
|
+
}, {});
|
|
181
|
+
let offset = 0;
|
|
182
|
+
if (groups) {
|
|
183
|
+
return groups.map((group) => {
|
|
184
|
+
const id = group.id || DEFAULT_GROUP;
|
|
185
|
+
let element;
|
|
186
|
+
if (id === DEFAULT_GROUP) {
|
|
187
|
+
element = this.renderGroup(DEFAULT_GROUP, defaultRenderLayout, defaultRenderItems, offset);
|
|
188
|
+
offset += defaultRenderItems.length;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
element = this.renderGroup(id, groupedLayout[id], itemsByGroup[id], offset);
|
|
192
|
+
offset += itemsByGroup[id].length;
|
|
193
|
+
}
|
|
194
|
+
if (group.render) {
|
|
195
|
+
return group.render(id, element, {
|
|
196
|
+
config,
|
|
197
|
+
editMode,
|
|
198
|
+
items: itemsByGroup[id],
|
|
199
|
+
layout: groupedLayout[id],
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
return element;
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
return this.renderGroup(DEFAULT_GROUP, defaultRenderLayout, defaultRenderItems, offset);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
122
209
|
}
|
|
123
210
|
GridLayout.contextType = DashKitContext;
|
|
124
211
|
export default GridLayout;
|
|
@@ -2,14 +2,29 @@ import React from 'react';
|
|
|
2
2
|
import ReactGridLayout, { WidthProvider } from 'react-grid-layout';
|
|
3
3
|
import { OVERLAY_CLASS_NAME } from '../../constants';
|
|
4
4
|
class DragOverLayout extends ReactGridLayout {
|
|
5
|
-
constructor() {
|
|
6
|
-
super(...
|
|
5
|
+
constructor(...args) {
|
|
6
|
+
super(...args);
|
|
7
7
|
this.dragReset = () => {
|
|
8
8
|
if (this.dragEnterCounter) {
|
|
9
9
|
this.dragEnterCounter = 0;
|
|
10
10
|
this.removeDroppingPlaceholder();
|
|
11
11
|
}
|
|
12
12
|
};
|
|
13
|
+
this.mouseLeaveHandler = (e) => {
|
|
14
|
+
var _a;
|
|
15
|
+
const rect = ((_a = this.props.innerRef) === null || _a === void 0 ? void 0 : _a.current.getBoundingClientRect()) || {};
|
|
16
|
+
if (rect.bottom <= e.clientY ||
|
|
17
|
+
rect.top >= e.clientY ||
|
|
18
|
+
rect.left >= e.clientX ||
|
|
19
|
+
rect.right <= e.clientX) {
|
|
20
|
+
this.dragReset();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const oldonDrag = this.onDrag;
|
|
24
|
+
this.onDrag = (i, x, y, sintE) => {
|
|
25
|
+
oldonDrag(i, x, y, sintE);
|
|
26
|
+
this.mouseLeaveHandler(sintE.e);
|
|
27
|
+
};
|
|
13
28
|
}
|
|
14
29
|
componentDidMount() {
|
|
15
30
|
var _a;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import isEqual from 'lodash/isEqual';
|
|
3
|
+
import pick from 'lodash/pick';
|
|
3
4
|
import { DEFAULT_WIDGET_HEIGHT, DEFAULT_WIDGET_WIDTH, TEMPORARY_ITEM_ID } from '../constants/common';
|
|
4
5
|
import { DashKitContext, DashKitDnDContext } from '../context/DashKitContext';
|
|
5
6
|
import { getItemsParams, getItemsState } from '../shared';
|
|
@@ -18,10 +19,11 @@ function useMemoStateContext(props) {
|
|
|
18
19
|
const outerDnDEnable = Boolean(dndContext);
|
|
19
20
|
// TODO: need move originalLayouts, adjustedLayouts to state
|
|
20
21
|
const [layoutUpdateCounter, forceUpdateLayout] = React.useState(0);
|
|
21
|
-
const onChange = React.useCallback(({ config = props.config, itemsStateAndParams = props.itemsStateAndParams }) => {
|
|
22
|
+
const onChange = React.useCallback(({ config = props.config, itemsStateAndParams = props.itemsStateAndParams, groups = props.groups, }) => {
|
|
22
23
|
if (!(isEqual(config, props.config) &&
|
|
23
|
-
isEqual(itemsStateAndParams, props.itemsStateAndParams)
|
|
24
|
-
|
|
24
|
+
isEqual(itemsStateAndParams, props.itemsStateAndParams) &&
|
|
25
|
+
isEqual(groups, props.groups))) {
|
|
26
|
+
props.onChange({ config, itemsStateAndParams, groups });
|
|
25
27
|
}
|
|
26
28
|
}, [props.config, props.itemsStateAndParams, props.onChange]);
|
|
27
29
|
// каллбэк вызывающийся при изменение лэйаута сетки, первым аргументом приходит актуальный конфиг лэйаута,
|
|
@@ -167,6 +169,7 @@ function useMemoStateContext(props) {
|
|
|
167
169
|
}
|
|
168
170
|
return false;
|
|
169
171
|
}, [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps]);
|
|
172
|
+
const onDropProp = props.onDrop;
|
|
170
173
|
const onDrop = React.useCallback((newLayout, item) => {
|
|
171
174
|
if (!dragProps) {
|
|
172
175
|
return;
|
|
@@ -175,23 +178,23 @@ function useMemoStateContext(props) {
|
|
|
175
178
|
data: newLayout,
|
|
176
179
|
dragProps,
|
|
177
180
|
});
|
|
178
|
-
|
|
179
|
-
props.onDrop({
|
|
181
|
+
onDropProp({
|
|
180
182
|
newLayout: newLayout.reduce((memo, l) => {
|
|
181
|
-
if (l.i !== i) {
|
|
182
|
-
memo.push(
|
|
183
|
+
if (l.i !== item.i) {
|
|
184
|
+
memo.push(pick(l, ['i', 'h', 'w', 'x', 'y', 'parent']));
|
|
183
185
|
}
|
|
184
186
|
return memo;
|
|
185
187
|
}, []),
|
|
186
|
-
itemLayout:
|
|
188
|
+
itemLayout: pick(item, ['i', 'h', 'w', 'x', 'y', 'parent']),
|
|
187
189
|
commit: resetTemporaryLayout,
|
|
188
190
|
dragProps,
|
|
189
191
|
});
|
|
190
|
-
}, [dragProps,
|
|
192
|
+
}, [dragProps, onDropProp, setTemporaryLayout, resetTemporaryLayout]);
|
|
191
193
|
return React.useMemo(() => ({
|
|
192
194
|
layout: resultLayout,
|
|
193
195
|
temporaryLayout,
|
|
194
196
|
config: props.config,
|
|
197
|
+
groups: props.groups,
|
|
195
198
|
context: props.context,
|
|
196
199
|
noOverlay: props.noOverlay,
|
|
197
200
|
focusable: props.focusable,
|
|
@@ -220,6 +223,7 @@ function useMemoStateContext(props) {
|
|
|
220
223
|
resultLayout,
|
|
221
224
|
temporaryLayout,
|
|
222
225
|
props.config,
|
|
226
|
+
props.groups,
|
|
223
227
|
props.context,
|
|
224
228
|
props.noOverlay,
|
|
225
229
|
props.focusable,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type ReactGridLayout from 'react-grid-layout';
|
|
2
2
|
import type { OverlayCustomControlItem } from '../components/OverlayControls/OverlayControls';
|
|
3
3
|
import { MenuItems } from '../constants';
|
|
4
|
+
import { AdditionalWidgetLayout } from '../shared';
|
|
4
5
|
export interface Settings {
|
|
5
6
|
gridLayout?: ReactGridLayout.ReactGridLayoutProps;
|
|
6
7
|
theme?: string;
|
|
@@ -15,7 +16,7 @@ export interface SettingsProps {
|
|
|
15
16
|
export interface ContextProps {
|
|
16
17
|
[key: string]: any;
|
|
17
18
|
}
|
|
18
|
-
export interface WidgetLayout {
|
|
19
|
+
export interface WidgetLayout extends AdditionalWidgetLayout {
|
|
19
20
|
i: string;
|
|
20
21
|
w: number;
|
|
21
22
|
h: number;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { Config, ConfigItem, ConfigLayout } from '../shared';
|
|
2
3
|
export interface AddConfigItem extends Omit<ConfigItem, 'id' | 'namespace'> {
|
|
3
4
|
id?: null;
|
|
4
5
|
namespace?: string;
|
|
@@ -11,3 +12,13 @@ export type SetItemOptions = {
|
|
|
11
12
|
export type SetNewItemOptions = SetItemOptions & {
|
|
12
13
|
updateLayout?: ConfigLayout[];
|
|
13
14
|
};
|
|
15
|
+
export interface DashkitGroupRenderProps {
|
|
16
|
+
config: Config;
|
|
17
|
+
editMode: boolean;
|
|
18
|
+
items: ConfigItem[];
|
|
19
|
+
layout: ConfigLayout[];
|
|
20
|
+
}
|
|
21
|
+
export interface DashKiGroup {
|
|
22
|
+
id?: string;
|
|
23
|
+
render?: (id: string, children: React.ReactNode, props: DashkitGroupRenderProps) => React.ReactNode;
|
|
24
|
+
}
|
|
@@ -23,16 +23,7 @@ export interface PluginWidgetProps<T = StringParams> {
|
|
|
23
23
|
adjustedWidgetLayout?: WidgetLayout;
|
|
24
24
|
}) => void;
|
|
25
25
|
}
|
|
26
|
-
export
|
|
27
|
-
w?: number;
|
|
28
|
-
h?: number;
|
|
29
|
-
x?: number;
|
|
30
|
-
y?: number;
|
|
31
|
-
minW?: number;
|
|
32
|
-
maxW?: number;
|
|
33
|
-
minH?: number;
|
|
34
|
-
maxH?: number;
|
|
35
|
-
}
|
|
26
|
+
export type PluginDefaultLayout = Partial<Omit<WidgetLayout, 'i'>>;
|
|
36
27
|
export interface Plugin<P extends PluginWidgetProps<T> = any, T = StringParams> extends PluginBase {
|
|
37
28
|
defaultLayout?: PluginDefaultLayout;
|
|
38
29
|
renderer: (props: P, forwardedRef: React.RefObject<any>) => React.ReactNode;
|
|
@@ -78,6 +78,7 @@ function getAllowableChangedParams(item, stateAndParams, itemsStateAndParams, pa
|
|
|
78
78
|
// if it's Record<string, StringParams>, then this is a group application of params
|
|
79
79
|
// and checking for comparison of allowedParams and stateParamsConf is not necessary
|
|
80
80
|
const isGroupParamsApply = typeof (stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id]) === 'object' &&
|
|
81
|
+
(stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id]) !== null &&
|
|
81
82
|
!Array.isArray(stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id]);
|
|
82
83
|
if (isItemWithTabs(item)) {
|
|
83
84
|
let tab;
|
|
@@ -228,7 +229,7 @@ export class UpdateManager {
|
|
|
228
229
|
const newIdData = getNewId({ config, salt, counter, excludeIds: newItemData.excludeIds });
|
|
229
230
|
counter = newIdData.counter;
|
|
230
231
|
const newItem = Object.assign(Object.assign({}, item), { id: newIdData.id, data: newItemData.data, namespace });
|
|
231
|
-
const saveDefaultLayout = pick(layout, ['h', 'w', 'x', 'y']);
|
|
232
|
+
const saveDefaultLayout = pick(layout, ['h', 'w', 'x', 'y', 'parent']);
|
|
232
233
|
if (options.updateLayout) {
|
|
233
234
|
const byId = options.updateLayout.reduce((memo, t) => {
|
|
234
235
|
memo[t.i] = t;
|
|
@@ -309,7 +310,7 @@ export class UpdateManager {
|
|
|
309
310
|
static updateLayout({ layout, config }) {
|
|
310
311
|
return update(config, {
|
|
311
312
|
layout: {
|
|
312
|
-
$set: layout.map((
|
|
313
|
+
$set: layout.map((item) => pick(item, ['i', 'h', 'w', 'x', 'y', 'parent'])),
|
|
313
314
|
},
|
|
314
315
|
});
|
|
315
316
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/dashkit",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.3.0-beta.0",
|
|
4
4
|
"description": "Library for rendering dashboard grid layout",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -60,12 +60,12 @@
|
|
|
60
60
|
"prepublishOnly": "npm run lint && npm run test && npm run build"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@gravity-ui/icons": "^2.8.1",
|
|
64
63
|
"@bem-react/classname": "^1.6.0",
|
|
64
|
+
"@gravity-ui/icons": "^2.8.1",
|
|
65
65
|
"hashids": "^2.2.8",
|
|
66
66
|
"immutability-helper": "^3.1.1",
|
|
67
67
|
"prop-types": "^15.8.1",
|
|
68
|
-
"react-grid-layout": "^1.
|
|
68
|
+
"react-grid-layout": "^1.4.4",
|
|
69
69
|
"react-transition-group": "^4.4.5"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"@types/jest": "^26.0.20",
|
|
91
91
|
"@types/lodash": "^4.14.170",
|
|
92
92
|
"@types/react": "^18.0.27",
|
|
93
|
-
"@types/react-grid-layout": "^1.3.
|
|
93
|
+
"@types/react-grid-layout": "^1.3.5",
|
|
94
94
|
"babel-jest": "^26.6.3",
|
|
95
95
|
"copyfiles": "^2.4.1",
|
|
96
96
|
"enzyme": "^3.11.0",
|