@gravity-ui/dashkit 7.0.0 → 7.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,12 @@ export interface ConfigLayout {
6
6
  x: number;
7
7
  y: number;
8
8
  }
9
+ export type ConfigItemGroup = {
10
+ id: string;
11
+ defaults?: StringParams;
12
+ namespace: string;
13
+ [key: string]: unknown;
14
+ };
9
15
  export interface ConfigItemData {
10
16
  _editActive?: boolean;
11
17
  tabs?: {
@@ -14,11 +20,15 @@ export interface ConfigItemData {
14
20
  params?: StringParams;
15
21
  [key: string]: unknown;
16
22
  }[];
23
+ group?: ConfigItemGroup[];
17
24
  [key: string]: unknown;
18
25
  }
19
26
  export interface ConfigItemDataWithTabs extends Omit<ConfigItemData, 'tabs'> {
20
27
  tabs: NonNullable<ConfigItemData['tabs']>;
21
28
  }
29
+ export interface ConfigItemDataWithGroup extends Omit<ConfigItemData, 'group'> {
30
+ group: NonNullable<ConfigItemData['group']>;
31
+ }
22
32
  export interface ConfigItem {
23
33
  id: string;
24
34
  data: ConfigItemData;
@@ -31,6 +41,9 @@ export interface ConfigItem {
31
41
  export interface ConfigItemWithTabs extends Omit<ConfigItem, 'data'> {
32
42
  data: ConfigItemDataWithTabs;
33
43
  }
44
+ export interface ConfigItemWithGroup extends Omit<ConfigItem, 'data'> {
45
+ data: ConfigItemDataWithGroup;
46
+ }
34
47
  export interface ConfigAliases {
35
48
  [namespace: string]: string[][];
36
49
  }
@@ -6,6 +6,7 @@ export interface ItemState {
6
6
  export interface QueueItem {
7
7
  id: string;
8
8
  tabId?: string;
9
+ groupItemId?: string;
9
10
  }
10
11
  export type StateAndParamsMetaData = {
11
12
  queue: QueueItem[];
@@ -15,11 +16,12 @@ export type StateAndParamsMeta = {
15
16
  [META_KEY]: StateAndParamsMetaData;
16
17
  };
17
18
  export type ItemStateAndParams = {
18
- params?: StringParams;
19
+ params?: StringParams | Record<string, StringParams>;
19
20
  state?: ItemState;
20
21
  };
21
22
  export type ItemStateAndParamsChangeOptions = {
22
- action: 'setParams' | 'removeItem';
23
+ action?: 'setParams' | 'removeItem';
24
+ groupItemIds?: string[];
23
25
  };
24
26
  export type ItemsStateAndParamsBase = Record<string, ItemStateAndParams>;
25
27
  export type ItemsStateAndParams = ItemsStateAndParamsBase | StateAndParamsMeta;
@@ -1,8 +1,8 @@
1
- import type { ReactGridLayoutProps } from 'react-grid-layout';
1
+ import type ReactGridLayout from 'react-grid-layout';
2
2
  import { OverlayCustomControlItem } from '../components/OverlayControls/OverlayControls';
3
3
  import { MenuItems } from '../constants';
4
4
  export interface Settings {
5
- gridLayout?: ReactGridLayoutProps;
5
+ gridLayout?: ReactGridLayout.ReactGridLayoutProps;
6
6
  theme?: string;
7
7
  isMobile?: boolean;
8
8
  menu?: Array<MenuItem>;
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
- import type { ReactGridLayoutProps } from 'react-grid-layout';
2
+ import ReactGridLayout from 'react-grid-layout';
3
3
  import { ConfigItem, ItemState, ItemStateAndParams, ItemStateAndParamsChangeOptions, PluginBase, StringParams } from '../shared';
4
4
  import { ContextProps, SettingsProps, WidgetLayout } from './common';
5
- export interface PluginWidgetProps {
5
+ export interface PluginWidgetProps<T = StringParams> {
6
6
  id: string;
7
7
  editMode: boolean;
8
- params: StringParams;
8
+ params: T;
9
9
  state: ItemState;
10
10
  onStateAndParamsChange: (stateAndParams: ItemStateAndParams, options?: ItemStateAndParamsChangeOptions) => void;
11
11
  width: number;
@@ -16,7 +16,7 @@ export interface PluginWidgetProps {
16
16
  settings: SettingsProps;
17
17
  context: ContextProps;
18
18
  layout: WidgetLayout[];
19
- gridLayout: ReactGridLayoutProps;
19
+ gridLayout: ReactGridLayout.ReactGridLayoutProps;
20
20
  adjustWidgetLayout: (data: {
21
21
  widgetId: string;
22
22
  needSetDefault?: boolean;
@@ -33,7 +33,7 @@ export interface PluginDefaultLayout {
33
33
  minH?: number;
34
34
  maxH?: number;
35
35
  }
36
- export interface Plugin<P extends PluginWidgetProps = any> extends PluginBase {
36
+ export interface Plugin<P extends PluginWidgetProps<T> = any, T = StringParams> extends PluginBase {
37
37
  defaultLayout?: PluginDefaultLayout;
38
38
  renderer: (props: P, forwardedRef: React.RefObject<any>) => React.ReactNode;
39
39
  }
@@ -115,6 +115,61 @@ const config = {
115
115
  },
116
116
  namespace: 'default',
117
117
  },
118
+ {
119
+ id: 'qY',
120
+ data: {
121
+ group: [
122
+ {
123
+ id: '9YN',
124
+ title: 'Category',
125
+ width: '',
126
+ source: {
127
+ datasetId: 'rfvnhj345gugf',
128
+ fieldType: 'string',
129
+ elementType: 'select',
130
+ datasetFieldId: 'ab089',
131
+ datasetFieldType: 'DIMENSION',
132
+ },
133
+ defaults: {
134
+ ab089: '',
135
+ },
136
+ sourceType: 'dataset',
137
+ placementMode: 'auto',
138
+ namespace: 'default',
139
+ },
140
+ {
141
+ id: 'qav',
142
+ title: 'Селектор 1',
143
+ width: '',
144
+ source: {
145
+ fieldName: 'sds',
146
+ elementType: 'select',
147
+ acceptableValues: [
148
+ {
149
+ title: '2',
150
+ value: '2',
151
+ },
152
+ {
153
+ title: '34',
154
+ value: '34',
155
+ },
156
+ ],
157
+ },
158
+ defaults: {
159
+ sds: '',
160
+ },
161
+ sourceType: 'manual',
162
+ placementMode: 'auto',
163
+ namespace: 'default',
164
+ },
165
+ ],
166
+ autoHeight: true,
167
+ buttonApply: false,
168
+ buttonReset: false,
169
+ },
170
+ type: 'group_control',
171
+ namespace: 'default',
172
+ },
118
173
  ],
119
174
  layout: [
120
175
  { h: 4, i: 'al', w: 4, x: 8, y: 0 },
@@ -122,6 +177,7 @@ const config = {
122
177
  { h: 2, i: 'L5', w: 8, x: 0, y: 2 },
123
178
  { h: 2, i: 'C8', w: 8, x: 10, y: 30 },
124
179
  { h: 2, i: 'lko', w: 8, x: 0, y: 12 },
180
+ { h: 2, i: 'qY', w: 8, x: 0, y: 24 },
125
181
  ],
126
182
  aliases: {},
127
183
  connections: [],
@@ -131,7 +187,7 @@ beforeEach(() => {
131
187
  });
132
188
  describe('UpdateManager', () => {
133
189
  describe('changeStateAndParams', () => {
134
- it('control adds params to empty itemsStateAndParams', () => {
190
+ it('control adds params to empty itemsStateAndParams: common control', () => {
135
191
  expect(UpdateManager.changeStateAndParams({
136
192
  id: 'L5',
137
193
  config,
@@ -150,6 +206,30 @@ describe('UpdateManager', () => {
150
206
  __meta__: { queue: [{ id: 'L5' }], version: 2 },
151
207
  });
152
208
  });
209
+ it('control adds params to empty itemsStateAndParams: group control', () => {
210
+ expect(UpdateManager.changeStateAndParams({
211
+ id: 'qY',
212
+ config,
213
+ itemsStateAndParams: {},
214
+ stateAndParams: {
215
+ params: {
216
+ ab089: ['red'],
217
+ },
218
+ },
219
+ options: {
220
+ groupItemIds: ['9YN'],
221
+ },
222
+ })).toEqual({
223
+ qY: {
224
+ params: {
225
+ '9YN': {
226
+ ab089: ['red'],
227
+ },
228
+ },
229
+ },
230
+ __meta__: { queue: [{ id: 'qY', groupItemId: '9YN' }], version: 2 },
231
+ });
232
+ });
153
233
  it('state changes only do not push into the queue', () => {
154
234
  expect(UpdateManager.changeStateAndParams({
155
235
  id: 'al',
@@ -160,7 +240,17 @@ describe('UpdateManager', () => {
160
240
  d079: ['Russia'],
161
241
  },
162
242
  },
163
- __meta__: { queue: [{ id: 'L5' }, { id: 'Unk' }], version: 2 },
243
+ qY: {
244
+ params: {
245
+ '9YN': {
246
+ ab089: ['red'],
247
+ },
248
+ },
249
+ },
250
+ __meta__: {
251
+ queue: [{ id: 'L5' }, { id: 'qY', groupItemId: '9YN' }, { id: 'Unk' }],
252
+ version: 2,
253
+ },
164
254
  },
165
255
  stateAndParams: {
166
256
  state: { tabId: 'Pf' },
@@ -171,12 +261,19 @@ describe('UpdateManager', () => {
171
261
  d079: ['Russia'],
172
262
  },
173
263
  },
264
+ qY: {
265
+ params: {
266
+ '9YN': {
267
+ ab089: ['red'],
268
+ },
269
+ },
270
+ },
174
271
  al: {
175
272
  state: {
176
273
  tabId: 'Pf',
177
274
  },
178
275
  },
179
- __meta__: { queue: [{ id: 'L5' }], version: 2 },
276
+ __meta__: { queue: [{ id: 'L5' }, { id: 'qY', groupItemId: '9YN' }], version: 2 },
180
277
  });
181
278
  });
182
279
  it('tab changes clear previous tab params', () => {
@@ -206,7 +303,7 @@ describe('UpdateManager', () => {
206
303
  __meta__: { queue: [], version: 2 },
207
304
  });
208
305
  });
209
- it('control changes rearrange position in the queue', () => {
306
+ it('control changes rearrange position in the queue: common control', () => {
210
307
  expect(UpdateManager.changeStateAndParams({
211
308
  id: 'L5',
212
309
  config,
@@ -264,6 +361,74 @@ describe('UpdateManager', () => {
264
361
  },
265
362
  });
266
363
  });
364
+ it('control changes rearrange position in the queue: group control', () => {
365
+ expect(UpdateManager.changeStateAndParams({
366
+ id: 'qY',
367
+ config,
368
+ itemsStateAndParams: {
369
+ al: {
370
+ params: {
371
+ Country: 'USA',
372
+ },
373
+ },
374
+ qY: {
375
+ params: {
376
+ qav: {
377
+ sds: ['yellow'],
378
+ },
379
+ '9YN': {
380
+ ab089: ['red'],
381
+ },
382
+ },
383
+ },
384
+ __meta__: {
385
+ queue: [
386
+ { id: 'qY', groupItemId: 'qav' },
387
+ { id: 'qY', groupItemId: '9YN' },
388
+ { id: 'al' },
389
+ ],
390
+ version: 2,
391
+ },
392
+ },
393
+ stateAndParams: {
394
+ params: {
395
+ qav: {
396
+ sds: ['violet'],
397
+ },
398
+ '9YN': {
399
+ ab089: ['purple'],
400
+ },
401
+ },
402
+ },
403
+ options: {
404
+ groupItemIds: ['qav'],
405
+ },
406
+ })).toEqual({
407
+ al: {
408
+ params: {
409
+ Country: 'USA',
410
+ },
411
+ },
412
+ qY: {
413
+ params: {
414
+ qav: {
415
+ sds: ['violet'],
416
+ },
417
+ '9YN': {
418
+ ab089: ['red'],
419
+ },
420
+ },
421
+ },
422
+ __meta__: {
423
+ queue: [
424
+ { id: 'qY', groupItemId: '9YN' },
425
+ { id: 'al' },
426
+ { id: 'qY', groupItemId: 'qav' },
427
+ ],
428
+ version: 2,
429
+ },
430
+ });
431
+ });
267
432
  it('control params should merge', () => {
268
433
  expect(UpdateManager.changeStateAndParams({
269
434
  id: 'lko',
@@ -307,7 +472,7 @@ describe('UpdateManager', () => {
307
472
  __meta__: { queue: [{ id: 'L5' }, { id: 'lko' }], version: 2 },
308
473
  });
309
474
  });
310
- it('control cannot set params not from defaults', () => {
475
+ it('control cannot set params not from defaults: common control', () => {
311
476
  expect(UpdateManager.changeStateAndParams({
312
477
  id: 'lko',
313
478
  config,
@@ -327,6 +492,29 @@ describe('UpdateManager', () => {
327
492
  __meta__: { queue: [{ id: 'lko' }], version: 2 },
328
493
  });
329
494
  });
495
+ it('control cannot set params not from defaults: group control', () => {
496
+ expect(UpdateManager.changeStateAndParams({
497
+ id: 'qY',
498
+ config,
499
+ itemsStateAndParams: {},
500
+ stateAndParams: {
501
+ params: {
502
+ sds: ['value'],
503
+ UnknownParam: ['Value'],
504
+ },
505
+ },
506
+ options: { groupItemIds: ['qav'] },
507
+ })).toEqual({
508
+ qY: {
509
+ params: {
510
+ qav: {
511
+ sds: ['value'],
512
+ },
513
+ },
514
+ },
515
+ __meta__: { queue: [{ id: 'qY', groupItemId: 'qav' }], version: 2 },
516
+ });
517
+ });
330
518
  it('filtering_charts_table can set action params not from defaults', () => {
331
519
  expect(UpdateManager.changeStateAndParams({
332
520
  id: 'Q8',
@@ -1,4 +1,4 @@
1
- import type { ReactGridLayoutProps } from 'react-grid-layout';
1
+ import ReactGridLayout from 'react-grid-layout';
2
2
  import { Plugin, PluginDefaultLayout, Settings } from '../typings';
3
3
  interface RegisterManagerDefaultLayout {
4
4
  x: number;
@@ -23,7 +23,7 @@ export declare class RegisterManager {
23
23
  registerPlugin(plugin: Plugin): void;
24
24
  setSettings(settings?: Settings): void;
25
25
  get settings(): RegisterManagerSettings;
26
- get gridLayout(): ReactGridLayoutProps;
26
+ get gridLayout(): ReactGridLayout.ReactGridLayoutProps;
27
27
  getPlugins(): RegisterManagerPlugin[];
28
28
  getItem(type: string): RegisterManagerPlugin;
29
29
  check(type: string): boolean;
@@ -2,7 +2,7 @@ import update, { extend } from 'immutability-helper';
2
2
  import omit from 'lodash/omit';
3
3
  import pick from 'lodash/pick';
4
4
  import { DEFAULT_NAMESPACE } from '../constants';
5
- import { META_KEY, addToQueue, deleteFromQueue, getCurrentVersion, getInitialItemsStateAndParamsMeta, getItemsStateAndParamsMeta, isItemWithTabs, mergeParamsWithAliases, pickActionParamsFromParams, resolveItemInnerId, transformParamsToActionParams, } from '../shared';
5
+ import { META_KEY, addGroupToQueue, addToQueue, deleteFromQueue, getCurrentVersion, getInitialItemsStateAndParamsMeta, getItemsStateAndParamsMeta, isItemWithGroup, isItemWithTabs, mergeParamsWithAliases, pickActionParamsFromParams, resolveItemInnerId, transformParamsToActionParams, } from '../shared';
6
6
  import { getNewId } from './get-new-id';
7
7
  extend('$auto', (value, object) => (object ? update(object, value) : update({}, value)));
8
8
  function removeItemVersion1({ id, config, itemsStateAndParams }) {
@@ -86,7 +86,12 @@ function getAllowableChangedParams(item, stateAndParams, itemsStateAndParams, pa
86
86
  allowedParams = pick(stateParamsConf, Object.keys((tab === null || tab === void 0 ? void 0 : tab.params) || {}));
87
87
  }
88
88
  else {
89
- allowedParams = pick(stateParamsConf, Object.keys(item.defaults || {}));
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;
94
+ allowedParams = pick(paramsConf, Object.keys(item.defaults || {}));
90
95
  }
91
96
  if (Object.keys(allowedParams || {}).length !== Object.keys(stateParamsConf || {}).length) {
92
97
  console.warn('Параметры, которых нет в defaults, будут проигнорированы!');
@@ -157,8 +162,54 @@ function getNewItemData({ item, config, counter: argsCounter, salt, options }) {
157
162
  });
158
163
  data = Object.assign(Object.assign({}, item.data), { tabs });
159
164
  }
165
+ if (isItemWithGroup(item)) {
166
+ const group = item.data.group.map((groupItem) => {
167
+ if (groupItem.id) {
168
+ return groupItem;
169
+ }
170
+ const newIdGroupData = getNewId({ config, salt, counter, excludeIds });
171
+ counter = newIdGroupData.counter;
172
+ excludeIds.push(newIdGroupData.id);
173
+ return Object.assign(Object.assign({}, groupItem), { id: newIdGroupData.id, namespace: groupItem.namespace || DEFAULT_NAMESPACE });
174
+ });
175
+ data = Object.assign(Object.assign({}, item.data), { group });
176
+ }
160
177
  return { data, counter, excludeIds };
161
178
  }
179
+ function changeGroupParams({ groupItemIds, initiatorId, initiatorItem, itemsStateAndParams, stateAndParams, config, unusedIds, }) {
180
+ var _a;
181
+ const meta = addGroupToQueue({
182
+ id: initiatorId,
183
+ groupItemIds,
184
+ config,
185
+ itemsStateAndParams,
186
+ });
187
+ const updatedItems = {};
188
+ const currentItemParams = (_a = itemsStateAndParams[initiatorId]) === null || _a === void 0 ? void 0 : _a.params;
189
+ for (const groupItem of initiatorItem.data.group) {
190
+ 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);
194
+ continue;
195
+ }
196
+ if (currentItemParams && currentItemParams[groupItem.id]) {
197
+ updatedItems[groupItem.id] = currentItemParams[groupItem.id];
198
+ }
199
+ }
200
+ const obj = {
201
+ $unset: unusedIds,
202
+ [initiatorId]: {
203
+ $auto: {
204
+ params: {
205
+ $set: updatedItems,
206
+ },
207
+ },
208
+ },
209
+ [META_KEY]: { $set: meta },
210
+ };
211
+ return update(itemsStateAndParams, obj);
212
+ }
162
213
  export class UpdateManager {
163
214
  static addItem({ item, namespace = DEFAULT_NAMESPACE, layout, config, options, }) {
164
215
  const layoutY = Math.max(0, ...config.layout.map(({ h, y }) => h + y));
@@ -195,9 +246,13 @@ export class UpdateManager {
195
246
  }
196
247
  const itemIndex = config.items.findIndex((item) => item.id === id);
197
248
  const item = config.items[itemIndex];
198
- const itemIds = isItemWithTabs(item)
199
- ? [id].concat(item.data.tabs.map((tab) => tab.id))
200
- : [id];
249
+ let itemIds = [id];
250
+ if (isItemWithTabs(item)) {
251
+ itemIds = [id].concat(item.data.tabs.map((tab) => tab.id));
252
+ }
253
+ if (isItemWithGroup(item)) {
254
+ itemIds = [id].concat(item.data.group.map((groupItem) => groupItem.id));
255
+ }
201
256
  const connections = config.connections.filter(({ from, to }) => !itemIds.includes(from) && !itemIds.includes(to));
202
257
  return {
203
258
  config: update(config, {
@@ -250,6 +305,7 @@ export class UpdateManager {
250
305
  const newTabId = (_a = stateAndParams.state) === null || _a === void 0 ? void 0 : _a.tabId;
251
306
  const isTabSwitched = isItemWithTabs(initiatorItem) && Boolean(newTabId);
252
307
  const currentMeta = getItemsStateAndParamsMeta(itemsStateAndParams);
308
+ const groupItemIds = options === null || options === void 0 ? void 0 : options.groupItemIds;
253
309
  if (action === 'removeItem') {
254
310
  return update(itemsStateAndParams, {
255
311
  $unset: [...unusedIds, initiatorId],
@@ -264,6 +320,17 @@ export class UpdateManager {
264
320
  },
265
321
  });
266
322
  }
323
+ if (isItemWithGroup(initiatorItem) && groupItemIds) {
324
+ return changeGroupParams({
325
+ initiatorId,
326
+ initiatorItem,
327
+ groupItemIds,
328
+ itemsStateAndParams,
329
+ stateAndParams,
330
+ config,
331
+ unusedIds,
332
+ });
333
+ }
267
334
  if ('params' in stateAndParams) {
268
335
  const allowableParams = getAllowableChangedParams(initiatorItem, stateAndParams, itemsStateAndParams);
269
336
  const allowableActionParams = getAllowableChangedParams(initiatorItem, stateAndParams, itemsStateAndParams, { type: 'actionParams', returnPrefix: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "7.0.0",
3
+ "version": "7.1.1",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {