@gravity-ui/dashkit 8.6.0 → 8.7.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/README.md +10 -4
- package/build/cjs/components/DashKit/DashKit.d.ts +3 -2
- package/build/cjs/components/DashKitView/DashKitView.js +2 -2
- package/build/cjs/components/GridItem/GridItem.js +2 -4
- package/build/cjs/components/GridLayout/GridLayout.js +2 -2
- package/build/cjs/components/OverlayControls/OverlayControls.d.ts +8 -6
- package/build/cjs/components/OverlayControls/OverlayControls.js +58 -42
- package/build/cjs/context/DashKitContext.d.ts +1 -0
- package/build/cjs/context/DashKitContext.js +3 -1
- package/build/cjs/hocs/withContext.js +35 -16
- package/build/esm/components/DashKit/DashKit.d.ts +3 -2
- package/build/esm/components/DashKitView/DashKitView.js +2 -2
- package/build/esm/components/GridItem/GridItem.js +2 -4
- package/build/esm/components/GridLayout/GridLayout.js +2 -2
- package/build/esm/components/OverlayControls/OverlayControls.d.ts +8 -6
- package/build/esm/components/OverlayControls/OverlayControls.js +59 -43
- package/build/esm/context/DashKitContext.d.ts +1 -0
- package/build/esm/context/DashKitContext.js +2 -1
- package/build/esm/hocs/withContext.js +36 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,8 @@ interface DashKitProps {
|
|
|
35
35
|
itemsStateAndParams: ItemsStateAndParams;
|
|
36
36
|
settings: SettingsProps;
|
|
37
37
|
context: ContextProps;
|
|
38
|
-
overlayControls?: Record<string, OverlayControlItem[]
|
|
38
|
+
overlayControls?: Record<string, OverlayControlItem[]> | null;
|
|
39
|
+
overlayMenuItems?: MenuItems[] | null;
|
|
39
40
|
noOverlay?: boolean;
|
|
40
41
|
focusable?: boolean;
|
|
41
42
|
draggableHandleClassName?: string;
|
|
@@ -51,7 +52,8 @@ interface DashKitProps {
|
|
|
51
52
|
- **itemsStateAndParams**: [itemsStateAndParams](#temsStateAndParams).
|
|
52
53
|
- **settings**: DashKit settings.
|
|
53
54
|
- **context**: Object that will be propped up on all widgets.
|
|
54
|
-
- **overlayControls**: Object that overrides widget controls at the time of editing. If not transmitted, basic controls will be displayed.
|
|
55
|
+
- **overlayControls**: Object that overrides widget controls at the time of editing. If not transmitted, basic controls will be displayed. If `null` passed only close button or custom menu will be displayed.
|
|
56
|
+
- **overlayMenuItems**: Custom dropdown menu items
|
|
55
57
|
- **noOverlay**: If `true`, overlay and controls are not displayed while editing.
|
|
56
58
|
- **focusable**: If `true`, grid items will be focusable.
|
|
57
59
|
- **draggableHandleClassName** : СSS class name of the element that makes the widget draggable.
|
|
@@ -343,6 +345,10 @@ type MenuItem = {
|
|
|
343
345
|
};
|
|
344
346
|
|
|
345
347
|
// use array of menu items in settings
|
|
348
|
+
<Dashkit overlayMenuItems={[] as Array<MenuItem> | null} />
|
|
349
|
+
|
|
350
|
+
[deprecated]
|
|
351
|
+
// overlayMenuItems property has greater priority over setSettings menu
|
|
346
352
|
DashKit.setSettings({menu: [] as Array<MenuItem>});
|
|
347
353
|
```
|
|
348
354
|
|
|
@@ -386,7 +392,7 @@ type ItemDropProps = {
|
|
|
386
392
|
#### Example:
|
|
387
393
|
|
|
388
394
|
```jsx
|
|
389
|
-
const
|
|
395
|
+
const overlayMenuItems = [
|
|
390
396
|
{
|
|
391
397
|
id: 'chart',
|
|
392
398
|
icon: <Icon data={ChartColumn} />,
|
|
@@ -405,7 +411,7 @@ const onDrop = (dropProps: ItemDropProps) => {
|
|
|
405
411
|
|
|
406
412
|
<DashKitDnDWrapper>
|
|
407
413
|
<DashKit editMode={true} config={config} onChange={onChange} onDrop={onDrop} />
|
|
408
|
-
<ActionPanel items={
|
|
414
|
+
<ActionPanel items={overlayMenuItems} />
|
|
409
415
|
</DashKitDnDWrapper>
|
|
410
416
|
```
|
|
411
417
|
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Config, ConfigItem, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
|
|
3
|
-
import { ContextProps, DashKitGroup, Plugin, SetConfigItem, SetNewItemOptions, Settings, SettingsProps } from '../../typings';
|
|
3
|
+
import { ContextProps, DashKitGroup, MenuItem, 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 {
|
|
7
7
|
config: Config;
|
|
8
8
|
editMode: boolean;
|
|
9
9
|
draggableHandleClassName?: string;
|
|
10
|
-
overlayControls?: Record<string, OverlayControlItem[]
|
|
10
|
+
overlayControls?: Record<string, OverlayControlItem[]> | null;
|
|
11
|
+
overlayMenuItems?: MenuItem[] | null;
|
|
11
12
|
}
|
|
12
13
|
interface DashKitDefaultProps {
|
|
13
14
|
onItemEdit: (item: ConfigItem) => void;
|
|
@@ -9,10 +9,10 @@ const cn_1 = require("../../utils/cn");
|
|
|
9
9
|
const GridLayout_1 = tslib_1.__importDefault(require("../GridLayout/GridLayout"));
|
|
10
10
|
const MobileLayout_1 = tslib_1.__importDefault(require("../MobileLayout/MobileLayout"));
|
|
11
11
|
const b = (0, cn_1.cn)('dashkit');
|
|
12
|
-
function DashKitView(
|
|
12
|
+
function DashKitView() {
|
|
13
13
|
const context = react_1.default.useContext(DashKitContext_1.DashKitContext);
|
|
14
14
|
const { registerManager, forwardedMetaRef } = context;
|
|
15
|
-
return (react_1.default.createElement("div", { className: b({ theme: registerManager.settings.theme }) }, registerManager.settings.isMobile ? (react_1.default.createElement(MobileLayout_1.default, null)) : (react_1.default.createElement(GridLayout_1.default, { ref: forwardedMetaRef
|
|
15
|
+
return (react_1.default.createElement("div", { className: b({ theme: registerManager.settings.theme }) }, registerManager.settings.isMobile ? (react_1.default.createElement(MobileLayout_1.default, null)) : (react_1.default.createElement(GridLayout_1.default, { ref: forwardedMetaRef }))));
|
|
16
16
|
}
|
|
17
17
|
const DashKitViewWithContext = (0, withContext_1.withContext)(DashKitView);
|
|
18
18
|
const DashKitViewForwardedMeta = react_1.default.forwardRef((props, ref) => {
|
|
@@ -58,16 +58,15 @@ class GridItem extends react_1.default.PureComponent {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
renderOverlay() {
|
|
61
|
-
const {
|
|
61
|
+
const { isPlaceholder } = this.props;
|
|
62
62
|
const { editMode } = this.context;
|
|
63
63
|
if (!editMode || this.props.item.data._editActive || isPlaceholder) {
|
|
64
64
|
return null;
|
|
65
65
|
}
|
|
66
66
|
const { item } = this.props;
|
|
67
|
-
const controls = overlayControls && overlayControls[item.type];
|
|
68
67
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
69
68
|
react_1.default.createElement("div", { className: b('overlay') }),
|
|
70
|
-
react_1.default.createElement(OverlayControls_1.default, { configItem: item
|
|
69
|
+
react_1.default.createElement(OverlayControls_1.default, { configItem: item })));
|
|
71
70
|
}
|
|
72
71
|
render() {
|
|
73
72
|
// из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
|
|
@@ -108,7 +107,6 @@ GridItem.propTypes = {
|
|
|
108
107
|
item: prop_types_1.default.object,
|
|
109
108
|
isDragging: prop_types_1.default.bool,
|
|
110
109
|
layout: prop_types_1.default.array,
|
|
111
|
-
overlayControls: prop_types_1.default.object,
|
|
112
110
|
forwardedRef: prop_types_1.default.any,
|
|
113
111
|
forwardedPluginRef: prop_types_1.default.any,
|
|
114
112
|
isPlaceholder: prop_types_1.default.bool,
|
|
@@ -197,7 +197,7 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
197
197
|
}
|
|
198
198
|
const id = constants_1.TEMPORARY_ITEM_ID;
|
|
199
199
|
const { type } = temporaryLayout.dragProps;
|
|
200
|
-
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)
|
|
200
|
+
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) }));
|
|
201
201
|
}
|
|
202
202
|
renderGroup(group, renderLayout, renderItems, offset = 0, groupGridProperties) {
|
|
203
203
|
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
@@ -219,7 +219,7 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
219
219
|
}
|
|
220
220
|
: null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
221
221
|
renderItems.map((item, i) => {
|
|
222
|
-
return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName)
|
|
222
|
+
return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName) }));
|
|
223
223
|
}),
|
|
224
224
|
this.renderTemporaryPlaceholder()));
|
|
225
225
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ButtonSize, ButtonView, IconProps, MenuItemProps } from '@gravity-ui/uikit';
|
|
3
|
-
import type {
|
|
4
|
-
import
|
|
3
|
+
import type { ConfigItem, ConfigLayout, ItemState, PluginBase, StringParams } from '../../shared';
|
|
4
|
+
import { MenuItem } from '../../typings';
|
|
5
5
|
export declare enum OverlayControlsPosition {
|
|
6
6
|
TopRight = "top_right",
|
|
7
7
|
TopLeft = "top_left",
|
|
@@ -13,6 +13,7 @@ export interface OverlayControlItem {
|
|
|
13
13
|
icon?: IconProps['data'];
|
|
14
14
|
iconSize?: number | string;
|
|
15
15
|
handler?: (item: ConfigItem) => void;
|
|
16
|
+
visible?: (item: ConfigItem) => boolean;
|
|
16
17
|
allWidgetsControls?: boolean;
|
|
17
18
|
excludeWidgetsTypes?: Array<PluginBase['type']>;
|
|
18
19
|
id?: string;
|
|
@@ -35,8 +36,6 @@ interface OverlayControlsDefaultProps {
|
|
|
35
36
|
}
|
|
36
37
|
interface OverlayControlsProps extends OverlayControlsDefaultProps {
|
|
37
38
|
configItem: ConfigItem;
|
|
38
|
-
items?: OverlayControlItem[];
|
|
39
|
-
overlayControls?: Record<string, OverlayControlItem[]>;
|
|
40
39
|
}
|
|
41
40
|
type PreparedCopyItemOptionsArg = Pick<ConfigItem, 'data' | 'type' | 'defaults' | 'namespace'> & {
|
|
42
41
|
timestamp: number;
|
|
@@ -49,21 +48,24 @@ export type PreparedCopyItemOptions<C extends object = {}> = PreparedCopyItemOpt
|
|
|
49
48
|
copyContext?: C;
|
|
50
49
|
};
|
|
51
50
|
type DashKitCtx = React.Context<{
|
|
51
|
+
overlayControls?: Record<string, OverlayControlItem[]>;
|
|
52
52
|
context: Record<string, any>;
|
|
53
|
-
|
|
53
|
+
menu: MenuItem[];
|
|
54
54
|
itemsParams: Record<string, StringParams>;
|
|
55
55
|
itemsState: Record<string, ItemState>;
|
|
56
56
|
editItem: (item: ConfigItem) => void;
|
|
57
57
|
removeItem: (id: string) => void;
|
|
58
|
-
|
|
58
|
+
getLayoutItem: (id: string) => ConfigLayout | void;
|
|
59
59
|
}>;
|
|
60
60
|
declare class OverlayControls extends React.Component<OverlayControlsProps> {
|
|
61
61
|
static contextType: React.Context<any>;
|
|
62
62
|
static defaultProps: OverlayControlsDefaultProps;
|
|
63
63
|
context: React.ContextType<DashKitCtx>;
|
|
64
64
|
render(): JSX.Element;
|
|
65
|
+
private getItems;
|
|
65
66
|
private renderControlsItem;
|
|
66
67
|
private getDropDownMenuItemConfig;
|
|
68
|
+
private getDefaultControls;
|
|
67
69
|
private renderControls;
|
|
68
70
|
private renderMenu;
|
|
69
71
|
private isDefaultMenu;
|
|
@@ -24,6 +24,11 @@ const DEFAULT_DROPDOWN_MENU = [constants_1.MenuItems.Copy, constants_1.MenuItems
|
|
|
24
24
|
class OverlayControls extends react_1.default.Component {
|
|
25
25
|
constructor() {
|
|
26
26
|
super(...arguments);
|
|
27
|
+
this.getItems = () => {
|
|
28
|
+
const { overlayControls } = this.context;
|
|
29
|
+
const { configItem } = this.props;
|
|
30
|
+
return (overlayControls && overlayControls[configItem.type]) || [];
|
|
31
|
+
};
|
|
27
32
|
this.renderControlsItem = (item, index, length) => {
|
|
28
33
|
const { view, size } = this.props;
|
|
29
34
|
const { title, handler, icon, iconSize, qa } = item;
|
|
@@ -31,18 +36,28 @@ class OverlayControls extends react_1.default.Component {
|
|
|
31
36
|
return (react_1.default.createElement(uikit_1.Button, { key: index, view: view, size: size, title: title, pin: this.getControlItemPinStyle(index, length), onClick: () => onItemClickHandler(this.props.configItem), qa: qa },
|
|
32
37
|
react_1.default.createElement(uikit_1.Icon, { data: icon || CogIcon_1.CogIcon, size: icon ? iconSize : 24 })));
|
|
33
38
|
};
|
|
39
|
+
this.getDefaultControls = () => {
|
|
40
|
+
const { view, size } = this.props;
|
|
41
|
+
if (this.context.overlayControls === null) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return (react_1.default.createElement(uikit_1.Button, { view: view, size: size, title: (0, i18n_1.i18n)('label_settings'), pin: "round-brick", onClick: this.onEditItem, qa: "dashkit-overlay-control-settings" },
|
|
45
|
+
react_1.default.createElement(uikit_1.Icon, { data: CogIcon_1.CogIcon, size: "24" })));
|
|
46
|
+
};
|
|
34
47
|
this.getCustomLeftOverlayControls = () => {
|
|
35
48
|
// выбираем только items-ы у которых проставлено поле `allWidgetsControls:true`
|
|
36
49
|
// те контролы, которые будут показываться слева от меню
|
|
37
50
|
let controls = [];
|
|
38
|
-
for (const controlItem of Object.values(this.
|
|
51
|
+
for (const controlItem of Object.values(this.context.overlayControls || {})) {
|
|
39
52
|
controls = controls.concat((controlItem.filter((item) => {
|
|
40
53
|
var _a;
|
|
41
54
|
// если тип виджета-плагина в списке исключаемых, то не показываем такой контрол
|
|
42
55
|
if ((_a = item.excludeWidgetsTypes) === null || _a === void 0 ? void 0 : _a.includes(this.props.configItem.type)) {
|
|
43
56
|
return false;
|
|
44
57
|
}
|
|
45
|
-
return item.
|
|
58
|
+
return item.visible
|
|
59
|
+
? item.visible(this.props.configItem)
|
|
60
|
+
: item.allWidgetsControls;
|
|
46
61
|
}) || []).map((item) => {
|
|
47
62
|
var _a;
|
|
48
63
|
if (!(item === null || item === void 0 ? void 0 : item.id)) {
|
|
@@ -57,15 +72,14 @@ class OverlayControls extends react_1.default.Component {
|
|
|
57
72
|
};
|
|
58
73
|
this.onCopyItem = () => {
|
|
59
74
|
var _a;
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
});
|
|
75
|
+
const { configItem } = this.props;
|
|
76
|
+
const correspondedItemLayout = this.context.getLayoutItem(configItem.id);
|
|
63
77
|
let options = {
|
|
64
78
|
timestamp: Date.now(),
|
|
65
|
-
data:
|
|
66
|
-
type:
|
|
67
|
-
defaults:
|
|
68
|
-
namespace:
|
|
79
|
+
data: configItem.data,
|
|
80
|
+
type: configItem.type,
|
|
81
|
+
defaults: configItem.defaults,
|
|
82
|
+
namespace: configItem.namespace,
|
|
69
83
|
layout: {
|
|
70
84
|
w: correspondedItemLayout.w,
|
|
71
85
|
h: correspondedItemLayout.h,
|
|
@@ -87,7 +101,8 @@ class OverlayControls extends react_1.default.Component {
|
|
|
87
101
|
};
|
|
88
102
|
}
|
|
89
103
|
render() {
|
|
90
|
-
const {
|
|
104
|
+
const { position } = this.props;
|
|
105
|
+
const items = this.getItems();
|
|
91
106
|
const hasCustomControlsWithWidgets = items.length > 0;
|
|
92
107
|
const controls = hasCustomControlsWithWidgets
|
|
93
108
|
? this.getCustomControlsWithWidgets()
|
|
@@ -122,11 +137,9 @@ class OverlayControls extends react_1.default.Component {
|
|
|
122
137
|
return null;
|
|
123
138
|
}
|
|
124
139
|
renderControls() {
|
|
125
|
-
const { view, size } = this.props;
|
|
126
140
|
const customLeftControls = this.getCustomLeftOverlayControls();
|
|
127
141
|
const hasCustomOverlayLeftControls = Boolean(customLeftControls.length);
|
|
128
|
-
const defaultControl =
|
|
129
|
-
react_1.default.createElement(uikit_1.Icon, { data: CogIcon_1.CogIcon, size: "24" })));
|
|
142
|
+
const defaultControl = this.getDefaultControls();
|
|
130
143
|
const controls = hasCustomOverlayLeftControls
|
|
131
144
|
? customLeftControls.map((item, index, items) => this.renderControlsItem(item, index, items.length + 1))
|
|
132
145
|
: defaultControl;
|
|
@@ -139,50 +152,58 @@ class OverlayControls extends react_1.default.Component {
|
|
|
139
152
|
}
|
|
140
153
|
renderMenu() {
|
|
141
154
|
const { view, size } = this.props;
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
155
|
+
const dropdown = this.renderDropdownMenu();
|
|
156
|
+
if (dropdown) {
|
|
157
|
+
return dropdown;
|
|
158
|
+
}
|
|
159
|
+
return (react_1.default.createElement(uikit_1.Button, { key: 'delete-control', view: view, size: size, title: (0, i18n_1.i18n)('label_delete'), pin: "brick-round", onClick: this.onRemoveItem, qa: "dashkit-overlay-control-menu" },
|
|
160
|
+
react_1.default.createElement(uikit_1.Icon, { data: CloseIcon_1.CloseIcon, size: "12" })));
|
|
146
161
|
}
|
|
147
162
|
isDefaultMenu(menu) {
|
|
148
163
|
return menu === null || menu === void 0 ? void 0 : menu.every((item) => Object.values(constants_1.MenuItems).includes(String(item)));
|
|
149
164
|
}
|
|
150
165
|
renderDropdownMenu() {
|
|
151
166
|
const { view, size } = this.props;
|
|
152
|
-
const {
|
|
167
|
+
const { menu: contextMenu, itemsParams, itemsState } = this.context;
|
|
153
168
|
const configItem = this.props.configItem;
|
|
154
169
|
const itemParams = itemsParams[configItem.id];
|
|
155
170
|
const itemState = itemsState[configItem.id];
|
|
156
|
-
|
|
157
|
-
if (!menu.length) {
|
|
158
|
-
menu = DEFAULT_DROPDOWN_MENU;
|
|
159
|
-
}
|
|
171
|
+
const menu = (contextMenu === null || contextMenu === void 0 ? void 0 : contextMenu.length) > 0 ? contextMenu : DEFAULT_DROPDOWN_MENU;
|
|
160
172
|
const isDefaultMenu = this.isDefaultMenu(menu);
|
|
161
|
-
|
|
162
|
-
? (menu || []).
|
|
163
|
-
|
|
173
|
+
const items = isDefaultMenu
|
|
174
|
+
? (menu || []).reduce((memo, name) => {
|
|
175
|
+
const item = this.getDropDownMenuItemConfig(name, true);
|
|
176
|
+
if (item) {
|
|
177
|
+
memo.push(item);
|
|
178
|
+
}
|
|
179
|
+
return memo;
|
|
180
|
+
}, [])
|
|
181
|
+
: menu.reduce((memo, item) => {
|
|
164
182
|
var _a;
|
|
165
183
|
if (typeof item === 'string') {
|
|
166
|
-
return
|
|
184
|
+
return memo;
|
|
167
185
|
}
|
|
168
186
|
// custom menu dropdown item filter
|
|
169
187
|
if (item.visible && !item.visible(configItem)) {
|
|
170
|
-
return
|
|
188
|
+
return memo;
|
|
171
189
|
}
|
|
172
190
|
const itemHandler = item.handler;
|
|
173
191
|
const itemAction = typeof itemHandler === 'function'
|
|
174
192
|
? () => itemHandler(configItem, itemParams, itemState)
|
|
175
193
|
: ((_a = this.getDropDownMenuItemConfig(item.id)) === null || _a === void 0 ? void 0 : _a.action) || (() => { });
|
|
176
|
-
|
|
194
|
+
memo.push({
|
|
177
195
|
// @ts-expect-error
|
|
178
196
|
text: item.title || (0, i18n_1.i18n)(item.id),
|
|
179
197
|
icon: item.icon,
|
|
180
198
|
action: itemAction,
|
|
181
199
|
className: item.className,
|
|
182
200
|
qa: item.qa,
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
|
|
201
|
+
});
|
|
202
|
+
return memo;
|
|
203
|
+
}, []);
|
|
204
|
+
if (items.length === 0) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
186
207
|
return (react_1.default.createElement(uikit_1.DropdownMenu, { items: items, renderSwitcher: (props) => (react_1.default.createElement(uikit_1.Button, Object.assign({}, props, { view: view, size: size, pin: "brick-round", qa: "dashkit-overlay-control-menu" }),
|
|
187
208
|
react_1.default.createElement(uikit_1.Icon, { data: DotsIcon_1.DotsIcon, size: "16" }))) }));
|
|
188
209
|
}
|
|
@@ -202,19 +223,14 @@ class OverlayControls extends react_1.default.Component {
|
|
|
202
223
|
return 'brick-brick';
|
|
203
224
|
}
|
|
204
225
|
getCustomControlsWithWidgets() {
|
|
205
|
-
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
handler: this.onRemoveItem,
|
|
211
|
-
};
|
|
212
|
-
const { items = [] } = this.props;
|
|
213
|
-
const customOverlayControls = [...items, deleteControl];
|
|
214
|
-
return customOverlayControls.map((item, index, controlItems) => this.renderControlsItem(item, index, controlItems.length));
|
|
226
|
+
const items = this.getItems();
|
|
227
|
+
const result = items.map((item, index, controlItems) => this.renderControlsItem(item, index, controlItems.length));
|
|
228
|
+
// Добавляем контрол удаления или меню виджета по умолчанию
|
|
229
|
+
result.push(this.renderMenu());
|
|
230
|
+
return result;
|
|
215
231
|
}
|
|
216
232
|
}
|
|
217
|
-
OverlayControls.contextType = DashKitContext_1.
|
|
233
|
+
OverlayControls.contextType = DashKitContext_1.DashkitOvelayControlsContext;
|
|
218
234
|
OverlayControls.defaultProps = {
|
|
219
235
|
position: OverlayControlsPosition.TopRight,
|
|
220
236
|
view: 'flat',
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DashKitDnDContext = exports.DashKitContext = void 0;
|
|
3
|
+
exports.DashKitDnDContext = exports.DashkitOvelayControlsContext = exports.DashKitContext = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
6
|
const DashKitContext = react_1.default.createContext();
|
|
7
7
|
exports.DashKitContext = DashKitContext;
|
|
8
|
+
const DashkitOvelayControlsContext = react_1.default.createContext();
|
|
9
|
+
exports.DashkitOvelayControlsContext = DashkitOvelayControlsContext;
|
|
8
10
|
const DashKitDnDContext = react_1.default.createContext();
|
|
9
11
|
exports.DashKitDnDContext = DashKitDnDContext;
|
|
@@ -54,12 +54,13 @@ function useMemoStateContext(props) {
|
|
|
54
54
|
onChange({ config: newConfig });
|
|
55
55
|
}
|
|
56
56
|
}, [props.config, onChange]);
|
|
57
|
+
const getLayoutItem = react_1.default.useCallback((id) => {
|
|
58
|
+
return props.config.layout.find(({ i }) => i === id);
|
|
59
|
+
}, [props.config.layout]);
|
|
57
60
|
const onItemRemove = react_1.default.useCallback((id) => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
delete originalLayouts.current[id];
|
|
62
|
-
}
|
|
61
|
+
delete nowrapAdjustedLayouts.current[id];
|
|
62
|
+
delete adjustedLayouts.current[id];
|
|
63
|
+
delete originalLayouts.current[id];
|
|
63
64
|
if (id === common_1.TEMPORARY_ITEM_ID) {
|
|
64
65
|
resetTemporaryLayout();
|
|
65
66
|
}
|
|
@@ -195,7 +196,7 @@ function useMemoStateContext(props) {
|
|
|
195
196
|
const nowrapAdjust = nowrapAdjustedLayouts.current;
|
|
196
197
|
return props.layout.map((item) => {
|
|
197
198
|
const widgetId = item.i;
|
|
198
|
-
if (
|
|
199
|
+
if (widgetId in adjusted || widgetId in nowrapAdjust) {
|
|
199
200
|
original[widgetId] = item;
|
|
200
201
|
// eslint-disable-next-line no-unused-vars
|
|
201
202
|
const _a = adjusted[widgetId] || item, { parent } = _a, adjustedItem = tslib_1.__rest(_a, ["parent"]);
|
|
@@ -205,13 +206,13 @@ function useMemoStateContext(props) {
|
|
|
205
206
|
if (item.parent) {
|
|
206
207
|
adjustedItem.parent = item.parent;
|
|
207
208
|
}
|
|
208
|
-
if (nowrapAdjust
|
|
209
|
+
if (widgetId in nowrapAdjust) {
|
|
209
210
|
adjustedItem.maxW = nowrapAdjust[widgetId];
|
|
210
211
|
}
|
|
211
212
|
return adjustedItem;
|
|
212
213
|
}
|
|
213
214
|
else {
|
|
214
|
-
if (original
|
|
215
|
+
if (widgetId in original) {
|
|
215
216
|
delete original[widgetId];
|
|
216
217
|
}
|
|
217
218
|
return item;
|
|
@@ -283,7 +284,7 @@ function useMemoStateContext(props) {
|
|
|
283
284
|
dragProps,
|
|
284
285
|
});
|
|
285
286
|
}, [dragProps, onDropProp, setTemporaryLayout, resetTemporaryLayout]);
|
|
286
|
-
|
|
287
|
+
const dashkitContextValue = react_1.default.useMemo(() => ({
|
|
287
288
|
layout: resultLayout,
|
|
288
289
|
temporaryLayout,
|
|
289
290
|
config: props.config,
|
|
@@ -299,10 +300,8 @@ function useMemoStateContext(props) {
|
|
|
299
300
|
itemsParams,
|
|
300
301
|
registerManager: props.registerManager,
|
|
301
302
|
onItemStateAndParamsChange,
|
|
302
|
-
removeItem: onItemRemove,
|
|
303
303
|
onDrop,
|
|
304
304
|
onDropDragOver,
|
|
305
|
-
editItem: props.onItemEdit,
|
|
306
305
|
layoutChange: onLayoutChange,
|
|
307
306
|
getItemsMeta,
|
|
308
307
|
reloadItems,
|
|
@@ -327,10 +326,8 @@ function useMemoStateContext(props) {
|
|
|
327
326
|
itemsParams,
|
|
328
327
|
props.registerManager,
|
|
329
328
|
onItemStateAndParamsChange,
|
|
330
|
-
onItemRemove,
|
|
331
329
|
onDrop,
|
|
332
330
|
onDropDragOver,
|
|
333
|
-
props.onItemEdit,
|
|
334
331
|
onLayoutChange,
|
|
335
332
|
getItemsMeta,
|
|
336
333
|
reloadItems,
|
|
@@ -341,12 +338,34 @@ function useMemoStateContext(props) {
|
|
|
341
338
|
outerDnDEnable,
|
|
342
339
|
dragOverPlugin,
|
|
343
340
|
]);
|
|
341
|
+
const overlayMenuItems = props.overlayMenuItems || props.registerManager.settings.menu;
|
|
342
|
+
const controlsContextValue = react_1.default.useMemo(() => ({
|
|
343
|
+
overlayControls: props.overlayControls,
|
|
344
|
+
context: props.context,
|
|
345
|
+
menu: overlayMenuItems,
|
|
346
|
+
itemsParams: itemsParams,
|
|
347
|
+
itemsState: itemsState,
|
|
348
|
+
editItem: props.onItemEdit,
|
|
349
|
+
removeItem: onItemRemove,
|
|
350
|
+
getLayoutItem: getLayoutItem,
|
|
351
|
+
}), [
|
|
352
|
+
itemsParams,
|
|
353
|
+
itemsState,
|
|
354
|
+
props.context,
|
|
355
|
+
props.onItemEdit,
|
|
356
|
+
onItemRemove,
|
|
357
|
+
props.overlayControls,
|
|
358
|
+
overlayMenuItems,
|
|
359
|
+
getLayoutItem,
|
|
360
|
+
]);
|
|
361
|
+
return { controlsContextValue, dashkitContextValue };
|
|
344
362
|
}
|
|
345
363
|
function withContext(Component) {
|
|
346
364
|
const WithContext = (props) => {
|
|
347
|
-
const
|
|
348
|
-
return (react_1.default.createElement(DashKitContext_1.DashKitContext.Provider, { value:
|
|
349
|
-
react_1.default.createElement(
|
|
365
|
+
const { dashkitContextValue, controlsContextValue } = useMemoStateContext(props);
|
|
366
|
+
return (react_1.default.createElement(DashKitContext_1.DashKitContext.Provider, { value: dashkitContextValue },
|
|
367
|
+
react_1.default.createElement(DashKitContext_1.DashkitOvelayControlsContext.Provider, { value: controlsContextValue },
|
|
368
|
+
react_1.default.createElement(Component, null))));
|
|
350
369
|
};
|
|
351
370
|
WithContext.displayName = `withContext(${Component.displayName || Component.name || 'Component'}`;
|
|
352
371
|
return WithContext;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Config, ConfigItem, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
|
|
3
|
-
import { ContextProps, DashKitGroup, Plugin, SetConfigItem, SetNewItemOptions, Settings, SettingsProps } from '../../typings';
|
|
3
|
+
import { ContextProps, DashKitGroup, MenuItem, 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 {
|
|
7
7
|
config: Config;
|
|
8
8
|
editMode: boolean;
|
|
9
9
|
draggableHandleClassName?: string;
|
|
10
|
-
overlayControls?: Record<string, OverlayControlItem[]
|
|
10
|
+
overlayControls?: Record<string, OverlayControlItem[]> | null;
|
|
11
|
+
overlayMenuItems?: MenuItem[] | null;
|
|
11
12
|
}
|
|
12
13
|
interface DashKitDefaultProps {
|
|
13
14
|
onItemEdit: (item: ConfigItem) => void;
|
|
@@ -7,10 +7,10 @@ import GridLayout from '../GridLayout/GridLayout';
|
|
|
7
7
|
import MobileLayout from '../MobileLayout/MobileLayout';
|
|
8
8
|
import './DashKitView.css';
|
|
9
9
|
const b = cn('dashkit');
|
|
10
|
-
function DashKitView(
|
|
10
|
+
function DashKitView() {
|
|
11
11
|
const context = React.useContext(DashKitContext);
|
|
12
12
|
const { registerManager, forwardedMetaRef } = context;
|
|
13
|
-
return (React.createElement("div", { className: b({ theme: registerManager.settings.theme }) }, registerManager.settings.isMobile ? (React.createElement(MobileLayout, null)) : (React.createElement(GridLayout, { ref: forwardedMetaRef
|
|
13
|
+
return (React.createElement("div", { className: b({ theme: registerManager.settings.theme }) }, registerManager.settings.isMobile ? (React.createElement(MobileLayout, null)) : (React.createElement(GridLayout, { ref: forwardedMetaRef }))));
|
|
14
14
|
}
|
|
15
15
|
const DashKitViewWithContext = withContext(DashKitView);
|
|
16
16
|
const DashKitViewForwardedMeta = React.forwardRef((props, ref) => {
|
|
@@ -56,16 +56,15 @@ class GridItem extends React.PureComponent {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
renderOverlay() {
|
|
59
|
-
const {
|
|
59
|
+
const { isPlaceholder } = this.props;
|
|
60
60
|
const { editMode } = this.context;
|
|
61
61
|
if (!editMode || this.props.item.data._editActive || isPlaceholder) {
|
|
62
62
|
return null;
|
|
63
63
|
}
|
|
64
64
|
const { item } = this.props;
|
|
65
|
-
const controls = overlayControls && overlayControls[item.type];
|
|
66
65
|
return (React.createElement(React.Fragment, null,
|
|
67
66
|
React.createElement("div", { className: b('overlay') }),
|
|
68
|
-
React.createElement(OverlayControls, { configItem: item
|
|
67
|
+
React.createElement(OverlayControls, { configItem: item })));
|
|
69
68
|
}
|
|
70
69
|
render() {
|
|
71
70
|
// из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
|
|
@@ -106,7 +105,6 @@ GridItem.propTypes = {
|
|
|
106
105
|
item: PropTypes.object,
|
|
107
106
|
isDragging: PropTypes.bool,
|
|
108
107
|
layout: PropTypes.array,
|
|
109
|
-
overlayControls: PropTypes.object,
|
|
110
108
|
forwardedRef: PropTypes.any,
|
|
111
109
|
forwardedPluginRef: PropTypes.any,
|
|
112
110
|
isPlaceholder: PropTypes.bool,
|
|
@@ -194,7 +194,7 @@ class GridLayout extends React.PureComponent {
|
|
|
194
194
|
}
|
|
195
195
|
const id = TEMPORARY_ITEM_ID;
|
|
196
196
|
const { type } = temporaryLayout.dragProps;
|
|
197
|
-
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)
|
|
197
|
+
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) }));
|
|
198
198
|
}
|
|
199
199
|
renderGroup(group, renderLayout, renderItems, offset = 0, groupGridProperties) {
|
|
200
200
|
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
@@ -216,7 +216,7 @@ class GridLayout extends React.PureComponent {
|
|
|
216
216
|
}
|
|
217
217
|
: null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
218
218
|
renderItems.map((item, i) => {
|
|
219
|
-
return (React.createElement(GridItem, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName)
|
|
219
|
+
return (React.createElement(GridItem, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName) }));
|
|
220
220
|
}),
|
|
221
221
|
this.renderTemporaryPlaceholder()));
|
|
222
222
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ButtonSize, ButtonView, IconProps, MenuItemProps } from '@gravity-ui/uikit';
|
|
3
|
-
import type {
|
|
4
|
-
import
|
|
3
|
+
import type { ConfigItem, ConfigLayout, ItemState, PluginBase, StringParams } from '../../shared';
|
|
4
|
+
import { MenuItem } from '../../typings';
|
|
5
5
|
import './OverlayControls.css';
|
|
6
6
|
export declare enum OverlayControlsPosition {
|
|
7
7
|
TopRight = "top_right",
|
|
@@ -14,6 +14,7 @@ export interface OverlayControlItem {
|
|
|
14
14
|
icon?: IconProps['data'];
|
|
15
15
|
iconSize?: number | string;
|
|
16
16
|
handler?: (item: ConfigItem) => void;
|
|
17
|
+
visible?: (item: ConfigItem) => boolean;
|
|
17
18
|
allWidgetsControls?: boolean;
|
|
18
19
|
excludeWidgetsTypes?: Array<PluginBase['type']>;
|
|
19
20
|
id?: string;
|
|
@@ -36,8 +37,6 @@ interface OverlayControlsDefaultProps {
|
|
|
36
37
|
}
|
|
37
38
|
interface OverlayControlsProps extends OverlayControlsDefaultProps {
|
|
38
39
|
configItem: ConfigItem;
|
|
39
|
-
items?: OverlayControlItem[];
|
|
40
|
-
overlayControls?: Record<string, OverlayControlItem[]>;
|
|
41
40
|
}
|
|
42
41
|
type PreparedCopyItemOptionsArg = Pick<ConfigItem, 'data' | 'type' | 'defaults' | 'namespace'> & {
|
|
43
42
|
timestamp: number;
|
|
@@ -50,21 +49,24 @@ export type PreparedCopyItemOptions<C extends object = {}> = PreparedCopyItemOpt
|
|
|
50
49
|
copyContext?: C;
|
|
51
50
|
};
|
|
52
51
|
type DashKitCtx = React.Context<{
|
|
52
|
+
overlayControls?: Record<string, OverlayControlItem[]>;
|
|
53
53
|
context: Record<string, any>;
|
|
54
|
-
|
|
54
|
+
menu: MenuItem[];
|
|
55
55
|
itemsParams: Record<string, StringParams>;
|
|
56
56
|
itemsState: Record<string, ItemState>;
|
|
57
57
|
editItem: (item: ConfigItem) => void;
|
|
58
58
|
removeItem: (id: string) => void;
|
|
59
|
-
|
|
59
|
+
getLayoutItem: (id: string) => ConfigLayout | void;
|
|
60
60
|
}>;
|
|
61
61
|
declare class OverlayControls extends React.Component<OverlayControlsProps> {
|
|
62
62
|
static contextType: React.Context<any>;
|
|
63
63
|
static defaultProps: OverlayControlsDefaultProps;
|
|
64
64
|
context: React.ContextType<DashKitCtx>;
|
|
65
65
|
render(): JSX.Element;
|
|
66
|
+
private getItems;
|
|
66
67
|
private renderControlsItem;
|
|
67
68
|
private getDropDownMenuItemConfig;
|
|
69
|
+
private getDefaultControls;
|
|
68
70
|
private renderControls;
|
|
69
71
|
private renderMenu;
|
|
70
72
|
private isDefaultMenu;
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { Button, DropdownMenu, Icon, } from '@gravity-ui/uikit';
|
|
3
3
|
import noop from 'lodash/noop';
|
|
4
4
|
import { COPIED_WIDGET_STORE_KEY, MenuItems, OVERLAY_CONTROLS_CLASS_NAME } from '../../constants';
|
|
5
|
-
import {
|
|
5
|
+
import { DashkitOvelayControlsContext } from '../../context/DashKitContext';
|
|
6
6
|
import { i18n } from '../../i18n';
|
|
7
7
|
import { CloseIcon } from '../../icons/CloseIcon';
|
|
8
8
|
import { CogIcon } from '../../icons/CogIcon';
|
|
@@ -21,6 +21,11 @@ const DEFAULT_DROPDOWN_MENU = [MenuItems.Copy, MenuItems.Delete];
|
|
|
21
21
|
class OverlayControls extends React.Component {
|
|
22
22
|
constructor() {
|
|
23
23
|
super(...arguments);
|
|
24
|
+
this.getItems = () => {
|
|
25
|
+
const { overlayControls } = this.context;
|
|
26
|
+
const { configItem } = this.props;
|
|
27
|
+
return (overlayControls && overlayControls[configItem.type]) || [];
|
|
28
|
+
};
|
|
24
29
|
this.renderControlsItem = (item, index, length) => {
|
|
25
30
|
const { view, size } = this.props;
|
|
26
31
|
const { title, handler, icon, iconSize, qa } = item;
|
|
@@ -28,18 +33,28 @@ class OverlayControls extends React.Component {
|
|
|
28
33
|
return (React.createElement(Button, { key: index, view: view, size: size, title: title, pin: this.getControlItemPinStyle(index, length), onClick: () => onItemClickHandler(this.props.configItem), qa: qa },
|
|
29
34
|
React.createElement(Icon, { data: icon || CogIcon, size: icon ? iconSize : 24 })));
|
|
30
35
|
};
|
|
36
|
+
this.getDefaultControls = () => {
|
|
37
|
+
const { view, size } = this.props;
|
|
38
|
+
if (this.context.overlayControls === null) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return (React.createElement(Button, { view: view, size: size, title: i18n('label_settings'), pin: "round-brick", onClick: this.onEditItem, qa: "dashkit-overlay-control-settings" },
|
|
42
|
+
React.createElement(Icon, { data: CogIcon, size: "24" })));
|
|
43
|
+
};
|
|
31
44
|
this.getCustomLeftOverlayControls = () => {
|
|
32
45
|
// выбираем только items-ы у которых проставлено поле `allWidgetsControls:true`
|
|
33
46
|
// те контролы, которые будут показываться слева от меню
|
|
34
47
|
let controls = [];
|
|
35
|
-
for (const controlItem of Object.values(this.
|
|
48
|
+
for (const controlItem of Object.values(this.context.overlayControls || {})) {
|
|
36
49
|
controls = controls.concat((controlItem.filter((item) => {
|
|
37
50
|
var _a;
|
|
38
51
|
// если тип виджета-плагина в списке исключаемых, то не показываем такой контрол
|
|
39
52
|
if ((_a = item.excludeWidgetsTypes) === null || _a === void 0 ? void 0 : _a.includes(this.props.configItem.type)) {
|
|
40
53
|
return false;
|
|
41
54
|
}
|
|
42
|
-
return item.
|
|
55
|
+
return item.visible
|
|
56
|
+
? item.visible(this.props.configItem)
|
|
57
|
+
: item.allWidgetsControls;
|
|
43
58
|
}) || []).map((item) => {
|
|
44
59
|
var _a;
|
|
45
60
|
if (!(item === null || item === void 0 ? void 0 : item.id)) {
|
|
@@ -54,15 +69,14 @@ class OverlayControls extends React.Component {
|
|
|
54
69
|
};
|
|
55
70
|
this.onCopyItem = () => {
|
|
56
71
|
var _a;
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
});
|
|
72
|
+
const { configItem } = this.props;
|
|
73
|
+
const correspondedItemLayout = this.context.getLayoutItem(configItem.id);
|
|
60
74
|
let options = {
|
|
61
75
|
timestamp: Date.now(),
|
|
62
|
-
data:
|
|
63
|
-
type:
|
|
64
|
-
defaults:
|
|
65
|
-
namespace:
|
|
76
|
+
data: configItem.data,
|
|
77
|
+
type: configItem.type,
|
|
78
|
+
defaults: configItem.defaults,
|
|
79
|
+
namespace: configItem.namespace,
|
|
66
80
|
layout: {
|
|
67
81
|
w: correspondedItemLayout.w,
|
|
68
82
|
h: correspondedItemLayout.h,
|
|
@@ -84,7 +98,8 @@ class OverlayControls extends React.Component {
|
|
|
84
98
|
};
|
|
85
99
|
}
|
|
86
100
|
render() {
|
|
87
|
-
const {
|
|
101
|
+
const { position } = this.props;
|
|
102
|
+
const items = this.getItems();
|
|
88
103
|
const hasCustomControlsWithWidgets = items.length > 0;
|
|
89
104
|
const controls = hasCustomControlsWithWidgets
|
|
90
105
|
? this.getCustomControlsWithWidgets()
|
|
@@ -119,11 +134,9 @@ class OverlayControls extends React.Component {
|
|
|
119
134
|
return null;
|
|
120
135
|
}
|
|
121
136
|
renderControls() {
|
|
122
|
-
const { view, size } = this.props;
|
|
123
137
|
const customLeftControls = this.getCustomLeftOverlayControls();
|
|
124
138
|
const hasCustomOverlayLeftControls = Boolean(customLeftControls.length);
|
|
125
|
-
const defaultControl =
|
|
126
|
-
React.createElement(Icon, { data: CogIcon, size: "24" })));
|
|
139
|
+
const defaultControl = this.getDefaultControls();
|
|
127
140
|
const controls = hasCustomOverlayLeftControls
|
|
128
141
|
? customLeftControls.map((item, index, items) => this.renderControlsItem(item, index, items.length + 1))
|
|
129
142
|
: defaultControl;
|
|
@@ -136,50 +149,58 @@ class OverlayControls extends React.Component {
|
|
|
136
149
|
}
|
|
137
150
|
renderMenu() {
|
|
138
151
|
const { view, size } = this.props;
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
152
|
+
const dropdown = this.renderDropdownMenu();
|
|
153
|
+
if (dropdown) {
|
|
154
|
+
return dropdown;
|
|
155
|
+
}
|
|
156
|
+
return (React.createElement(Button, { key: 'delete-control', view: view, size: size, title: i18n('label_delete'), pin: "brick-round", onClick: this.onRemoveItem, qa: "dashkit-overlay-control-menu" },
|
|
157
|
+
React.createElement(Icon, { data: CloseIcon, size: "12" })));
|
|
143
158
|
}
|
|
144
159
|
isDefaultMenu(menu) {
|
|
145
160
|
return menu === null || menu === void 0 ? void 0 : menu.every((item) => Object.values(MenuItems).includes(String(item)));
|
|
146
161
|
}
|
|
147
162
|
renderDropdownMenu() {
|
|
148
163
|
const { view, size } = this.props;
|
|
149
|
-
const {
|
|
164
|
+
const { menu: contextMenu, itemsParams, itemsState } = this.context;
|
|
150
165
|
const configItem = this.props.configItem;
|
|
151
166
|
const itemParams = itemsParams[configItem.id];
|
|
152
167
|
const itemState = itemsState[configItem.id];
|
|
153
|
-
|
|
154
|
-
if (!menu.length) {
|
|
155
|
-
menu = DEFAULT_DROPDOWN_MENU;
|
|
156
|
-
}
|
|
168
|
+
const menu = (contextMenu === null || contextMenu === void 0 ? void 0 : contextMenu.length) > 0 ? contextMenu : DEFAULT_DROPDOWN_MENU;
|
|
157
169
|
const isDefaultMenu = this.isDefaultMenu(menu);
|
|
158
|
-
|
|
159
|
-
? (menu || []).
|
|
160
|
-
|
|
170
|
+
const items = isDefaultMenu
|
|
171
|
+
? (menu || []).reduce((memo, name) => {
|
|
172
|
+
const item = this.getDropDownMenuItemConfig(name, true);
|
|
173
|
+
if (item) {
|
|
174
|
+
memo.push(item);
|
|
175
|
+
}
|
|
176
|
+
return memo;
|
|
177
|
+
}, [])
|
|
178
|
+
: menu.reduce((memo, item) => {
|
|
161
179
|
var _a;
|
|
162
180
|
if (typeof item === 'string') {
|
|
163
|
-
return
|
|
181
|
+
return memo;
|
|
164
182
|
}
|
|
165
183
|
// custom menu dropdown item filter
|
|
166
184
|
if (item.visible && !item.visible(configItem)) {
|
|
167
|
-
return
|
|
185
|
+
return memo;
|
|
168
186
|
}
|
|
169
187
|
const itemHandler = item.handler;
|
|
170
188
|
const itemAction = typeof itemHandler === 'function'
|
|
171
189
|
? () => itemHandler(configItem, itemParams, itemState)
|
|
172
190
|
: ((_a = this.getDropDownMenuItemConfig(item.id)) === null || _a === void 0 ? void 0 : _a.action) || (() => { });
|
|
173
|
-
|
|
191
|
+
memo.push({
|
|
174
192
|
// @ts-expect-error
|
|
175
193
|
text: item.title || i18n(item.id),
|
|
176
194
|
icon: item.icon,
|
|
177
195
|
action: itemAction,
|
|
178
196
|
className: item.className,
|
|
179
197
|
qa: item.qa,
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
|
|
198
|
+
});
|
|
199
|
+
return memo;
|
|
200
|
+
}, []);
|
|
201
|
+
if (items.length === 0) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
183
204
|
return (React.createElement(DropdownMenu, { items: items, renderSwitcher: (props) => (React.createElement(Button, Object.assign({}, props, { view: view, size: size, pin: "brick-round", qa: "dashkit-overlay-control-menu" }),
|
|
184
205
|
React.createElement(Icon, { data: DotsIcon, size: "16" }))) }));
|
|
185
206
|
}
|
|
@@ -199,19 +220,14 @@ class OverlayControls extends React.Component {
|
|
|
199
220
|
return 'brick-brick';
|
|
200
221
|
}
|
|
201
222
|
getCustomControlsWithWidgets() {
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
handler: this.onRemoveItem,
|
|
208
|
-
};
|
|
209
|
-
const { items = [] } = this.props;
|
|
210
|
-
const customOverlayControls = [...items, deleteControl];
|
|
211
|
-
return customOverlayControls.map((item, index, controlItems) => this.renderControlsItem(item, index, controlItems.length));
|
|
223
|
+
const items = this.getItems();
|
|
224
|
+
const result = items.map((item, index, controlItems) => this.renderControlsItem(item, index, controlItems.length));
|
|
225
|
+
// Добавляем контрол удаления или меню виджета по умолчанию
|
|
226
|
+
result.push(this.renderMenu());
|
|
227
|
+
return result;
|
|
212
228
|
}
|
|
213
229
|
}
|
|
214
|
-
OverlayControls.contextType =
|
|
230
|
+
OverlayControls.contextType = DashkitOvelayControlsContext;
|
|
215
231
|
OverlayControls.defaultProps = {
|
|
216
232
|
position: OverlayControlsPosition.TopRight,
|
|
217
233
|
view: 'flat',
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
const DashKitContext = React.createContext();
|
|
3
|
+
const DashkitOvelayControlsContext = React.createContext();
|
|
3
4
|
const DashKitDnDContext = React.createContext();
|
|
4
|
-
export { DashKitContext, DashKitDnDContext };
|
|
5
|
+
export { DashKitContext, DashkitOvelayControlsContext, DashKitDnDContext };
|
|
@@ -3,7 +3,7 @@ import React from 'react';
|
|
|
3
3
|
import isEqual from 'lodash/isEqual';
|
|
4
4
|
import pick from 'lodash/pick';
|
|
5
5
|
import { COMPACT_TYPE_HORIZONTAL_NOWRAP, DEFAULT_GROUP, DEFAULT_WIDGET_HEIGHT, DEFAULT_WIDGET_WIDTH, TEMPORARY_ITEM_ID, } from '../constants/common';
|
|
6
|
-
import { DashKitContext, DashKitDnDContext } from '../context/DashKitContext';
|
|
6
|
+
import { DashKitContext, DashKitDnDContext, DashkitOvelayControlsContext, } from '../context/DashKitContext';
|
|
7
7
|
import { useDeepEqualMemo } from '../hooks/useDeepEqualMemo';
|
|
8
8
|
import { getItemsParams, getItemsState } from '../shared';
|
|
9
9
|
import { UpdateManager } from '../utils';
|
|
@@ -51,12 +51,13 @@ function useMemoStateContext(props) {
|
|
|
51
51
|
onChange({ config: newConfig });
|
|
52
52
|
}
|
|
53
53
|
}, [props.config, onChange]);
|
|
54
|
+
const getLayoutItem = React.useCallback((id) => {
|
|
55
|
+
return props.config.layout.find(({ i }) => i === id);
|
|
56
|
+
}, [props.config.layout]);
|
|
54
57
|
const onItemRemove = React.useCallback((id) => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
delete originalLayouts.current[id];
|
|
59
|
-
}
|
|
58
|
+
delete nowrapAdjustedLayouts.current[id];
|
|
59
|
+
delete adjustedLayouts.current[id];
|
|
60
|
+
delete originalLayouts.current[id];
|
|
60
61
|
if (id === TEMPORARY_ITEM_ID) {
|
|
61
62
|
resetTemporaryLayout();
|
|
62
63
|
}
|
|
@@ -192,7 +193,7 @@ function useMemoStateContext(props) {
|
|
|
192
193
|
const nowrapAdjust = nowrapAdjustedLayouts.current;
|
|
193
194
|
return props.layout.map((item) => {
|
|
194
195
|
const widgetId = item.i;
|
|
195
|
-
if (
|
|
196
|
+
if (widgetId in adjusted || widgetId in nowrapAdjust) {
|
|
196
197
|
original[widgetId] = item;
|
|
197
198
|
// eslint-disable-next-line no-unused-vars
|
|
198
199
|
const _a = adjusted[widgetId] || item, { parent } = _a, adjustedItem = __rest(_a, ["parent"]);
|
|
@@ -202,13 +203,13 @@ function useMemoStateContext(props) {
|
|
|
202
203
|
if (item.parent) {
|
|
203
204
|
adjustedItem.parent = item.parent;
|
|
204
205
|
}
|
|
205
|
-
if (nowrapAdjust
|
|
206
|
+
if (widgetId in nowrapAdjust) {
|
|
206
207
|
adjustedItem.maxW = nowrapAdjust[widgetId];
|
|
207
208
|
}
|
|
208
209
|
return adjustedItem;
|
|
209
210
|
}
|
|
210
211
|
else {
|
|
211
|
-
if (original
|
|
212
|
+
if (widgetId in original) {
|
|
212
213
|
delete original[widgetId];
|
|
213
214
|
}
|
|
214
215
|
return item;
|
|
@@ -280,7 +281,7 @@ function useMemoStateContext(props) {
|
|
|
280
281
|
dragProps,
|
|
281
282
|
});
|
|
282
283
|
}, [dragProps, onDropProp, setTemporaryLayout, resetTemporaryLayout]);
|
|
283
|
-
|
|
284
|
+
const dashkitContextValue = React.useMemo(() => ({
|
|
284
285
|
layout: resultLayout,
|
|
285
286
|
temporaryLayout,
|
|
286
287
|
config: props.config,
|
|
@@ -296,10 +297,8 @@ function useMemoStateContext(props) {
|
|
|
296
297
|
itemsParams,
|
|
297
298
|
registerManager: props.registerManager,
|
|
298
299
|
onItemStateAndParamsChange,
|
|
299
|
-
removeItem: onItemRemove,
|
|
300
300
|
onDrop,
|
|
301
301
|
onDropDragOver,
|
|
302
|
-
editItem: props.onItemEdit,
|
|
303
302
|
layoutChange: onLayoutChange,
|
|
304
303
|
getItemsMeta,
|
|
305
304
|
reloadItems,
|
|
@@ -324,10 +323,8 @@ function useMemoStateContext(props) {
|
|
|
324
323
|
itemsParams,
|
|
325
324
|
props.registerManager,
|
|
326
325
|
onItemStateAndParamsChange,
|
|
327
|
-
onItemRemove,
|
|
328
326
|
onDrop,
|
|
329
327
|
onDropDragOver,
|
|
330
|
-
props.onItemEdit,
|
|
331
328
|
onLayoutChange,
|
|
332
329
|
getItemsMeta,
|
|
333
330
|
reloadItems,
|
|
@@ -338,12 +335,34 @@ function useMemoStateContext(props) {
|
|
|
338
335
|
outerDnDEnable,
|
|
339
336
|
dragOverPlugin,
|
|
340
337
|
]);
|
|
338
|
+
const overlayMenuItems = props.overlayMenuItems || props.registerManager.settings.menu;
|
|
339
|
+
const controlsContextValue = React.useMemo(() => ({
|
|
340
|
+
overlayControls: props.overlayControls,
|
|
341
|
+
context: props.context,
|
|
342
|
+
menu: overlayMenuItems,
|
|
343
|
+
itemsParams: itemsParams,
|
|
344
|
+
itemsState: itemsState,
|
|
345
|
+
editItem: props.onItemEdit,
|
|
346
|
+
removeItem: onItemRemove,
|
|
347
|
+
getLayoutItem: getLayoutItem,
|
|
348
|
+
}), [
|
|
349
|
+
itemsParams,
|
|
350
|
+
itemsState,
|
|
351
|
+
props.context,
|
|
352
|
+
props.onItemEdit,
|
|
353
|
+
onItemRemove,
|
|
354
|
+
props.overlayControls,
|
|
355
|
+
overlayMenuItems,
|
|
356
|
+
getLayoutItem,
|
|
357
|
+
]);
|
|
358
|
+
return { controlsContextValue, dashkitContextValue };
|
|
341
359
|
}
|
|
342
360
|
export function withContext(Component) {
|
|
343
361
|
const WithContext = (props) => {
|
|
344
|
-
const
|
|
345
|
-
return (React.createElement(DashKitContext.Provider, { value:
|
|
346
|
-
React.createElement(
|
|
362
|
+
const { dashkitContextValue, controlsContextValue } = useMemoStateContext(props);
|
|
363
|
+
return (React.createElement(DashKitContext.Provider, { value: dashkitContextValue },
|
|
364
|
+
React.createElement(DashkitOvelayControlsContext.Provider, { value: controlsContextValue },
|
|
365
|
+
React.createElement(Component, null))));
|
|
347
366
|
};
|
|
348
367
|
WithContext.displayName = `withContext(${Component.displayName || Component.name || 'Component'}`;
|
|
349
368
|
return WithContext;
|