@gravity-ui/dashkit 8.2.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.
Files changed (35) hide show
  1. package/build/cjs/components/DashKit/DashKit.d.ts +3 -1
  2. package/build/cjs/components/DashKit/DashKit.js +1 -5
  3. package/build/cjs/components/GridLayout/GridLayout.d.ts +6 -3
  4. package/build/cjs/components/GridLayout/GridLayout.js +100 -13
  5. package/build/cjs/components/GridLayout/ReactGridLayout.js +17 -2
  6. package/build/cjs/constants/common.d.ts +1 -0
  7. package/build/cjs/constants/common.js +2 -1
  8. package/build/cjs/hocs/withContext.js +13 -9
  9. package/build/cjs/hooks/useCalcLayout.d.ts +1 -0
  10. package/build/cjs/shared/modules/state-and-params.d.ts +2 -1
  11. package/build/cjs/shared/modules/state-and-params.js +18 -4
  12. package/build/cjs/shared/types/config.d.ts +4 -1
  13. package/build/cjs/typings/common.d.ts +2 -1
  14. package/build/cjs/typings/config.d.ts +12 -1
  15. package/build/cjs/typings/plugin.d.ts +1 -10
  16. package/build/cjs/utils/update-manager.d.ts +8 -1
  17. package/build/cjs/utils/update-manager.js +30 -15
  18. package/build/esm/components/DashKit/DashKit.d.ts +3 -1
  19. package/build/esm/components/DashKit/DashKit.js +1 -5
  20. package/build/esm/components/GridLayout/GridLayout.d.ts +6 -3
  21. package/build/esm/components/GridLayout/GridLayout.js +101 -14
  22. package/build/esm/components/GridLayout/ReactGridLayout.js +17 -2
  23. package/build/esm/constants/common.d.ts +1 -0
  24. package/build/esm/constants/common.js +1 -0
  25. package/build/esm/hocs/withContext.js +13 -9
  26. package/build/esm/hooks/useCalcLayout.d.ts +1 -0
  27. package/build/esm/shared/modules/state-and-params.d.ts +2 -1
  28. package/build/esm/shared/modules/state-and-params.js +18 -4
  29. package/build/esm/shared/types/config.d.ts +4 -1
  30. package/build/esm/typings/common.d.ts +2 -1
  31. package/build/esm/typings/config.d.ts +12 -1
  32. package/build/esm/typings/plugin.d.ts +1 -10
  33. package/build/esm/utils/update-manager.d.ts +8 -1
  34. package/build/esm/utils/update-manager.js +28 -14
  35. package/package.json +4 -4
@@ -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 (React.createElement(DashKitView
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: (layout: any, item: any, e: any) => false | undefined;
27
+ _onDrop: (group: any, newLayout: any, item: any, e: any) => false | undefined;
26
28
  renderTemporaryPlaceholder(): JSX.Element | null;
27
- render(): JSX.Element;
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(newLayout, newLayout.find(({ i }) => i === TEMPORARY_ITEM_ID));
39
+ onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, groupedLayout.find(({ i }) => i === TEMPORARY_ITEM_ID));
39
40
  }
40
41
  else {
41
- layoutChange(newLayout);
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 = (layout, item, e) => {
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
- onDrop === null || onDrop === void 0 ? void 0 : onDrop(layout, item, e);
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
- render() {
104
- const { layout, temporaryLayout, config, registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
105
- this.pluginsRefs.length = config.items.length;
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
- config.items.map((item, i) => {
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: (temporaryLayout === null || temporaryLayout === void 0 ? void 0 : temporaryLayout.data) || layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
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(...arguments);
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;
@@ -10,3 +10,4 @@ export declare const MenuItems: {
10
10
  };
11
11
  export declare const DEFAULT_WIDGET_HEIGHT = 3;
12
12
  export declare const DEFAULT_WIDGET_WIDTH = 3;
13
+ export declare const DEFAULT_GROUP = "__default";
@@ -10,3 +10,4 @@ export const MenuItems = {
10
10
  };
11
11
  export const DEFAULT_WIDGET_HEIGHT = 3;
12
12
  export const DEFAULT_WIDGET_WIDTH = 3;
13
+ export const DEFAULT_GROUP = '__default';
@@ -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
- props.onChange({ config, itemsStateAndParams });
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
- const { i, w, h, x, y } = item;
179
- props.onDrop({
181
+ onDropProp({
180
182
  newLayout: newLayout.reduce((memo, l) => {
181
- if (l.i !== i) {
182
- memo.push({ i: l.i, w: l.w, h: l.h, x: l.x, y: l.y });
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: { w, h, x, y },
188
+ itemLayout: pick(item, ['i', 'h', 'w', 'x', 'y', 'parent']),
187
189
  commit: resetTemporaryLayout,
188
190
  dragProps,
189
191
  });
190
- }, [dragProps, props.onDrop, setTemporaryLayout, resetTemporaryLayout]);
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,
@@ -6,6 +6,7 @@ export declare const useCalcPropsLayout: (config: Config, registerManager: Regis
6
6
  w: number;
7
7
  x: number;
8
8
  y: number;
9
+ parent?: string | undefined;
9
10
  minW: number;
10
11
  minH: number;
11
12
  maxW?: number | undefined;
@@ -5,9 +5,10 @@ export interface GetItemsParamsArg {
5
5
  config: Config;
6
6
  itemsStateAndParams: ItemsStateAndParams;
7
7
  plugins: PluginBase[];
8
+ useStateAsInitial?: boolean;
8
9
  }
9
10
  type GetItemsParamsReturn = Record<string, StringParams | Record<string, StringParams>>;
10
- export declare function getItemsParams({ defaultGlobalParams, globalParams, config, itemsStateAndParams, plugins, }: GetItemsParamsArg): GetItemsParamsReturn;
11
+ export declare function getItemsParams({ defaultGlobalParams, globalParams, config, itemsStateAndParams, plugins, useStateAsInitial, }: GetItemsParamsArg): GetItemsParamsReturn;
11
12
  export declare function getItemsState({ config, itemsStateAndParams, }: {
12
13
  config: Config;
13
14
  itemsStateAndParams: ItemsStateAndParams;
@@ -1,7 +1,18 @@
1
1
  import groupBy from 'lodash/groupBy';
2
2
  import { META_KEY } from '../constants';
3
3
  import { formQueueData, getCurrentVersion, getMapItemsIgnores, hasActionParam, isItemWithGroup, isItemWithTabs, mergeParamsWithAliases, pickActionParamsFromParams, pickExceptActionParamsFromParams, prerenderItems, resolveItemInnerId, } from './helpers';
4
- function getItemParams({ item, itemsStateAndParams, mapItemsIgnores, itemsWithDefaultsByNamespace, getMergedParams, defaultGlobalParams, globalParams, isFirstVersion, queueData, }) {
4
+ const getParamsFromStateAndParams = ({ itemsStateAndParams, parentItemId, item, }) => {
5
+ const widgetId = parentItemId || item.id;
6
+ if (!(widgetId in itemsStateAndParams)) {
7
+ return {};
8
+ }
9
+ const stateAndParams = itemsStateAndParams;
10
+ const itemParams = parentItemId
11
+ ? Object.assign({}, stateAndParams[widgetId].params[item.id])
12
+ : Object.assign({}, stateAndParams[widgetId].params);
13
+ return itemParams;
14
+ };
15
+ function getItemParams({ item, itemsStateAndParams, mapItemsIgnores, itemsWithDefaultsByNamespace, getMergedParams, defaultGlobalParams, globalParams, isFirstVersion, queueData, parentItemId, useStateAsInitial, }) {
5
16
  var _a, _b;
6
17
  const { id, namespace } = item;
7
18
  let defaultWidgetParams = {};
@@ -20,7 +31,9 @@ function getItemParams({ item, itemsStateAndParams, mapItemsIgnores, itemsWithDe
20
31
  // default parameters to begin with
21
32
  affectingItemsWithDefaults.reduceRight((defaultParams, itemWithDefaults) => {
22
33
  return Object.assign(Object.assign({}, defaultParams), getMergedParams(itemWithDefaults.defaults || {}));
23
- }, {}), getMergedParams(globalParams));
34
+ }, {}), getMergedParams(globalParams), useStateAsInitial
35
+ ? getParamsFromStateAndParams({ parentItemId, item, itemsStateAndParams })
36
+ : {});
24
37
  if (isFirstVersion) {
25
38
  itemParams = Object.assign(itemParams, ((_b = itemsStateAndParams === null || itemsStateAndParams === void 0 ? void 0 : itemsStateAndParams[id]) === null || _b === void 0 ? void 0 : _b.params) || {});
26
39
  }
@@ -45,7 +58,7 @@ function getItemParams({ item, itemsStateAndParams, mapItemsIgnores, itemsWithDe
45
58
  }
46
59
  return Object.assign(Object.assign({}, defaultWidgetParams), itemParams);
47
60
  }
48
- export function getItemsParams({ defaultGlobalParams = {}, globalParams = {}, config, itemsStateAndParams, plugins, }) {
61
+ export function getItemsParams({ defaultGlobalParams = {}, globalParams = {}, config, itemsStateAndParams, plugins, useStateAsInitial, }) {
49
62
  const { aliases, connections } = config;
50
63
  const items = prerenderItems({ items: config.items, plugins });
51
64
  const isFirstVersion = getCurrentVersion(itemsStateAndParams) === 1;
@@ -88,10 +101,11 @@ export function getItemsParams({ defaultGlobalParams = {}, globalParams = {}, co
88
101
  globalParams,
89
102
  isFirstVersion,
90
103
  queueData,
104
+ useStateAsInitial,
91
105
  };
92
106
  if (isItemWithGroup(item)) {
93
107
  const groupParams = item.data.group.reduce((groupItemParams, groupItem) => {
94
- groupItemParams[groupItem.id] = getItemParams(Object.assign({ item: groupItem }, paramsOptions));
108
+ groupItemParams[groupItem.id] = getItemParams(Object.assign({ item: groupItem, parentItemId: item.id }, paramsOptions));
95
109
  return groupItemParams;
96
110
  }, {});
97
111
  return Object.assign(Object.assign({}, itemsParams), { [id]: groupParams });
@@ -1,5 +1,8 @@
1
1
  import { StringParams } from './common';
2
- export interface ConfigLayout {
2
+ export interface AdditionalWidgetLayout {
3
+ parent?: string;
4
+ }
5
+ export interface ConfigLayout extends AdditionalWidgetLayout {
3
6
  i: string;
4
7
  h: number;
5
8
  w: number;
@@ -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
- import type { ConfigItem, ConfigLayout } from '../shared';
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 interface PluginDefaultLayout {
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;
@@ -1,4 +1,4 @@
1
- import type { Config, ConfigItem, ItemStateAndParams, ItemStateAndParamsChangeOptions, ItemsStateAndParams } from '../shared';
1
+ import type { Config, ConfigItem, ConfigItemGroup, ItemStateAndParams, ItemStateAndParamsChangeOptions, ItemsStateAndParams } from '../shared';
2
2
  import type { AddConfigItem, SetItemOptions, SetNewItemOptions, WidgetLayout } from '../typings';
3
3
  import { RegisterManagerPluginLayout } from './register-manager';
4
4
  interface RemoveItemArg {
@@ -13,6 +13,13 @@ interface ChangeStateAndParamsArg {
13
13
  stateAndParams: ItemStateAndParams;
14
14
  options?: ItemStateAndParamsChangeOptions;
15
15
  }
16
+ export declare const getChangedParams: ({ initiatorItem, stateAndParams, itemsStateAndParams, }: {
17
+ initiatorItem: ConfigItem | ConfigItemGroup;
18
+ stateAndParams: ItemStateAndParams;
19
+ itemsStateAndParams: ItemsStateAndParams;
20
+ }) => {
21
+ [x: string]: string | string[];
22
+ };
16
23
  export declare class UpdateManager {
17
24
  static addItem({ item, namespace, layout, config, options, }: {
18
25
  item: AddConfigItem;
@@ -74,6 +74,12 @@ function getAllowableChangedParams(item, stateAndParams, itemsStateAndParams, pa
74
74
  : allowedParams;
75
75
  }
76
76
  const stateParamsConf = stateAndParams.params;
77
+ // check if structure is StringParams or Record<string, StringParams>
78
+ // if it's Record<string, StringParams>, then this is a group application of params
79
+ // and checking for comparison of allowedParams and stateParamsConf is not necessary
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 &&
82
+ !Array.isArray(stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id]);
77
83
  if (isItemWithTabs(item)) {
78
84
  let tab;
79
85
  if ('state' in stateAndParams && ((_a = stateAndParams.state) === null || _a === void 0 ? void 0 : _a.tabId)) {
@@ -86,14 +92,11 @@ function getAllowableChangedParams(item, stateAndParams, itemsStateAndParams, pa
86
92
  allowedParams = pick(stateParamsConf, Object.keys((tab === null || tab === void 0 ? void 0 : tab.params) || {}));
87
93
  }
88
94
  else {
89
- // check if structure is StringParams or Record<string, StringParams>
90
- const paramsConf = typeof (stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id]) === 'object' &&
91
- !Array.isArray(stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id])
92
- ? stateParamsConf[item.id]
93
- : stateParamsConf;
95
+ const paramsConf = isGroupParamsApply ? stateParamsConf[item.id] : stateParamsConf;
94
96
  allowedParams = pick(paramsConf, Object.keys(item.defaults || {}));
95
97
  }
96
- if (Object.keys(allowedParams || {}).length !== Object.keys(stateParamsConf || {}).length) {
98
+ if (!isGroupParamsApply &&
99
+ Object.keys(allowedParams || {}).length !== Object.keys(stateParamsConf || {}).length) {
97
100
  console.warn('Параметры, которых нет в defaults, будут проигнорированы!');
98
101
  }
99
102
  return allowedParams;
@@ -176,6 +179,11 @@ function getNewItemData({ item, config, counter: argsCounter, salt, options }) {
176
179
  }
177
180
  return { data, counter, excludeIds };
178
181
  }
182
+ export const getChangedParams = ({ initiatorItem, stateAndParams, itemsStateAndParams, }) => {
183
+ const allowableParams = getAllowableChangedParams(initiatorItem, stateAndParams, itemsStateAndParams);
184
+ const allowableActionParams = getAllowableChangedParams(initiatorItem, stateAndParams, itemsStateAndParams, { type: 'actionParams', returnPrefix: true });
185
+ return Object.assign(Object.assign({}, allowableParams), allowableActionParams);
186
+ };
179
187
  function changeGroupParams({ groupItemIds, initiatorId, initiatorItem, itemsStateAndParams, stateAndParams, config, unusedIds, }) {
180
188
  var _a;
181
189
  const meta = addGroupToQueue({
@@ -188,9 +196,12 @@ function changeGroupParams({ groupItemIds, initiatorId, initiatorItem, itemsStat
188
196
  const currentItemParams = (_a = itemsStateAndParams[initiatorId]) === null || _a === void 0 ? void 0 : _a.params;
189
197
  for (const groupItem of initiatorItem.data.group) {
190
198
  if (groupItemIds.includes(groupItem.id)) {
191
- const allowableParams = getAllowableChangedParams(groupItem, stateAndParams, itemsStateAndParams);
192
- const allowableActionParams = getAllowableChangedParams(groupItem, stateAndParams, itemsStateAndParams, { type: 'actionParams', returnPrefix: true });
193
- updatedItems[groupItem.id] = Object.assign(Object.assign({}, allowableParams), allowableActionParams);
199
+ const changedParams = getChangedParams({
200
+ initiatorItem: groupItem,
201
+ stateAndParams,
202
+ itemsStateAndParams,
203
+ });
204
+ updatedItems[groupItem.id] = changedParams;
194
205
  continue;
195
206
  }
196
207
  if (currentItemParams && currentItemParams[groupItem.id]) {
@@ -218,7 +229,7 @@ export class UpdateManager {
218
229
  const newIdData = getNewId({ config, salt, counter, excludeIds: newItemData.excludeIds });
219
230
  counter = newIdData.counter;
220
231
  const newItem = Object.assign(Object.assign({}, item), { id: newIdData.id, data: newItemData.data, namespace });
221
- const saveDefaultLayout = pick(layout, ['h', 'w', 'x', 'y']);
232
+ const saveDefaultLayout = pick(layout, ['h', 'w', 'x', 'y', 'parent']);
222
233
  if (options.updateLayout) {
223
234
  const byId = options.updateLayout.reduce((memo, t) => {
224
235
  memo[t.i] = t;
@@ -299,7 +310,7 @@ export class UpdateManager {
299
310
  static updateLayout({ layout, config }) {
300
311
  return update(config, {
301
312
  layout: {
302
- $set: layout.map(({ x, y, w, h, i }) => ({ x, y, w, h, i })),
313
+ $set: layout.map((item) => pick(item, ['i', 'h', 'w', 'x', 'y', 'parent'])),
303
314
  },
304
315
  });
305
316
  }
@@ -350,8 +361,11 @@ export class UpdateManager {
350
361
  });
351
362
  }
352
363
  if ('params' in stateAndParams) {
353
- const allowableParams = getAllowableChangedParams(initiatorItem, stateAndParams, itemsStateAndParams);
354
- const allowableActionParams = getAllowableChangedParams(initiatorItem, stateAndParams, itemsStateAndParams, { type: 'actionParams', returnPrefix: true });
364
+ const changedParams = getChangedParams({
365
+ initiatorItem,
366
+ stateAndParams,
367
+ itemsStateAndParams,
368
+ });
355
369
  const tabId = isItemWithTabs(initiatorItem)
356
370
  ? newTabId || resolveItemInnerId({ item: initiatorItem, itemsStateAndParams })
357
371
  : undefined;
@@ -366,7 +380,7 @@ export class UpdateManager {
366
380
  $unset: unusedIds,
367
381
  [initiatorId]: {
368
382
  $auto: Object.assign({ params: {
369
- [commandUpdateParams]: Object.assign(Object.assign({}, allowableParams), allowableActionParams),
383
+ [commandUpdateParams]: changedParams,
370
384
  } }, (hasState ? { state: { $set: stateAndParams.state } } : {})),
371
385
  },
372
386
  [META_KEY]: { $set: meta },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "8.2.0",
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.3.4",
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.2",
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",