@gravity-ui/dashkit 6.8.0 → 6.10.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 (29) hide show
  1. package/README.md +1 -1
  2. package/build/cjs/components/OverlayControls/OverlayControls.d.ts +5 -3
  3. package/build/cjs/shared/modules/__tests__/helpers.test.js +212 -2
  4. package/build/cjs/shared/modules/helpers.d.ts +14 -5
  5. package/build/cjs/shared/modules/helpers.js +89 -19
  6. package/build/cjs/shared/modules/state-and-params.d.ts +2 -2
  7. package/build/cjs/shared/modules/state-and-params.js +73 -42
  8. package/build/cjs/shared/modules/uniq-id.js +3 -0
  9. package/build/cjs/shared/types/config.d.ts +13 -0
  10. package/build/cjs/shared/types/state-and-params.d.ts +4 -2
  11. package/build/cjs/typings/plugin.d.ts +4 -4
  12. package/build/cjs/utils/__tests__/update-manager.test.js +193 -5
  13. package/build/cjs/utils/update-manager.d.ts +2 -2
  14. package/build/cjs/utils/update-manager.js +71 -4
  15. package/build/esm/components/OverlayControls/OverlayControls.d.ts +5 -3
  16. package/build/esm/components/OverlayControls/OverlayControls.js +2 -2
  17. package/build/esm/shared/modules/__tests__/helpers.test.js +213 -3
  18. package/build/esm/shared/modules/helpers.d.ts +14 -5
  19. package/build/esm/shared/modules/helpers.js +87 -19
  20. package/build/esm/shared/modules/state-and-params.d.ts +2 -2
  21. package/build/esm/shared/modules/state-and-params.js +74 -43
  22. package/build/esm/shared/modules/uniq-id.js +4 -1
  23. package/build/esm/shared/types/config.d.ts +13 -0
  24. package/build/esm/shared/types/state-and-params.d.ts +4 -2
  25. package/build/esm/typings/plugin.d.ts +4 -4
  26. package/build/esm/utils/__tests__/update-manager.test.js +193 -5
  27. package/build/esm/utils/update-manager.d.ts +2 -2
  28. package/build/esm/utils/update-manager.js +72 -5
  29. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import Hashids from 'hashids';
2
- import { isItemWithTabs } from './helpers';
2
+ import { isItemWithGroup, isItemWithTabs } from './helpers';
3
3
  export function extractIdsFromConfig(config) {
4
4
  const ids = [];
5
5
  const items = config.items || [];
@@ -10,6 +10,9 @@ export function extractIdsFromConfig(config) {
10
10
  if (isItemWithTabs(item)) {
11
11
  item.data.tabs.forEach((tabItem) => ids.push(tabItem.id));
12
12
  }
13
+ if (isItemWithGroup(item)) {
14
+ item.data.group.forEach((groupItem) => ids.push(groupItem.id));
15
+ }
13
16
  });
14
17
  connections.forEach(({ from, to }) => ids.push(from, to));
15
18
  layout.forEach(({ i }) => ids.push(i));
@@ -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,11 +1,11 @@
1
1
  import React from 'react';
2
2
  import { ContextProps, SettingsProps, WidgetLayout } from './common';
3
- import { StringParams, ConfigItem, ItemState, ItemStateAndParams, PluginBase, ItemStateAndParamsChangeOptions } from '../shared';
3
+ import { ConfigItem, ItemState, ItemStateAndParams, ItemStateAndParamsChangeOptions, PluginBase, StringParams } from '../shared';
4
4
  import type { ReactGridLayoutProps } from 'react-grid-layout';
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;
@@ -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,5 +1,5 @@
1
- import { Config, ConfigItem, ItemsStateAndParams, ItemStateAndParams, ItemStateAndParamsChangeOptions } from '../shared';
2
- import { AddConfigItem, WidgetLayout, SetItemOptions } from '../typings';
1
+ import { Config, ConfigItem, ItemStateAndParams, ItemStateAndParamsChangeOptions, ItemsStateAndParams } from '../shared';
2
+ import { AddConfigItem, SetItemOptions, WidgetLayout } from '../typings';
3
3
  import { RegisterManagerPluginLayout } from './register-manager';
4
4
  interface RemoveItemArg {
5
5
  id: string;
@@ -1,7 +1,7 @@
1
1
  import update, { extend } from 'immutability-helper';
2
2
  import omit from 'lodash/omit';
3
3
  import pick from 'lodash/pick';
4
- import { mergeParamsWithAliases, isItemWithTabs, getCurrentVersion, META_KEY, deleteFromQueue, addToQueue, getInitialItemsStateAndParamsMeta, resolveItemInnerId, getItemsStateAndParamsMeta, pickActionParamsFromParams, transformParamsToActionParams, } from '../shared';
4
+ import { META_KEY, addGroupToQueue, addToQueue, deleteFromQueue, getCurrentVersion, getInitialItemsStateAndParamsMeta, getItemsStateAndParamsMeta, isItemWithGroup, isItemWithTabs, mergeParamsWithAliases, pickActionParamsFromParams, resolveItemInnerId, transformParamsToActionParams, } from '../shared';
5
5
  import { DEFAULT_NAMESPACE } from '../constants';
6
6
  import { getNewId } from './get-new-id';
7
7
  extend('$auto', (value, object) => (object ? update(object, value) : update({}, value)));
@@ -84,7 +84,12 @@ function getAllowableChangedParams(item, stateAndParams, itemsStateAndParams, pa
84
84
  allowedParams = pick(stateParamsConf, Object.keys((tab === null || tab === void 0 ? void 0 : tab.params) || {}));
85
85
  }
86
86
  else {
87
- allowedParams = pick(stateParamsConf, Object.keys(item.defaults || {}));
87
+ // check if structure is StringParams or Record<string, StringParams>
88
+ const paramsConf = typeof (stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id]) === 'object' &&
89
+ !Array.isArray(stateParamsConf === null || stateParamsConf === void 0 ? void 0 : stateParamsConf[item.id])
90
+ ? stateParamsConf[item.id]
91
+ : stateParamsConf;
92
+ allowedParams = pick(paramsConf, Object.keys(item.defaults || {}));
88
93
  }
89
94
  if (Object.keys(allowedParams || {}).length !== Object.keys(stateParamsConf || {}).length) {
90
95
  console.warn('Параметры, которых нет в defaults, будут проигнорированы!');
@@ -155,8 +160,54 @@ function getNewItemData({ item, config, counter: argsCounter, salt, options }) {
155
160
  });
156
161
  data = Object.assign(Object.assign({}, item.data), { tabs });
157
162
  }
163
+ if (isItemWithGroup(item)) {
164
+ const group = item.data.group.map((groupItem) => {
165
+ if (groupItem.id) {
166
+ return groupItem;
167
+ }
168
+ const newIdGroupData = getNewId({ config, salt, counter, excludeIds });
169
+ counter = newIdGroupData.counter;
170
+ excludeIds.push(newIdGroupData.id);
171
+ return Object.assign(Object.assign({}, groupItem), { id: newIdGroupData.id, namespace: groupItem.namespace || DEFAULT_NAMESPACE });
172
+ });
173
+ data = Object.assign(Object.assign({}, item.data), { group });
174
+ }
158
175
  return { data, counter, excludeIds };
159
176
  }
177
+ function changeGroupParams({ groupItemIds, initiatorId, initiatorItem, itemsStateAndParams, stateAndParams, config, unusedIds, }) {
178
+ var _a;
179
+ const meta = addGroupToQueue({
180
+ id: initiatorId,
181
+ groupItemIds,
182
+ config,
183
+ itemsStateAndParams,
184
+ });
185
+ const updatedItems = {};
186
+ const currentItemParams = (_a = itemsStateAndParams[initiatorId]) === null || _a === void 0 ? void 0 : _a.params;
187
+ for (const groupItem of initiatorItem.data.group) {
188
+ if (groupItemIds.includes(groupItem.id)) {
189
+ const allowableParams = getAllowableChangedParams(groupItem, stateAndParams, itemsStateAndParams);
190
+ const allowableActionParams = getAllowableChangedParams(groupItem, stateAndParams, itemsStateAndParams, { type: 'actionParams', returnPrefix: true });
191
+ updatedItems[groupItem.id] = Object.assign(Object.assign({}, allowableParams), allowableActionParams);
192
+ continue;
193
+ }
194
+ if (currentItemParams && currentItemParams[groupItem.id]) {
195
+ updatedItems[groupItem.id] = currentItemParams[groupItem.id];
196
+ }
197
+ }
198
+ const obj = {
199
+ $unset: unusedIds,
200
+ [initiatorId]: {
201
+ $auto: {
202
+ params: {
203
+ $set: updatedItems,
204
+ },
205
+ },
206
+ },
207
+ [META_KEY]: { $set: meta },
208
+ };
209
+ return update(itemsStateAndParams, obj);
210
+ }
160
211
  export class UpdateManager {
161
212
  static addItem({ item, namespace = DEFAULT_NAMESPACE, layout, config, options, }) {
162
213
  const layoutY = Math.max(0, ...config.layout.map(({ h, y }) => h + y));
@@ -193,9 +244,13 @@ export class UpdateManager {
193
244
  }
194
245
  const itemIndex = config.items.findIndex((item) => item.id === id);
195
246
  const item = config.items[itemIndex];
196
- const itemIds = isItemWithTabs(item)
197
- ? [id].concat(item.data.tabs.map((tab) => tab.id))
198
- : [id];
247
+ let itemIds = [id];
248
+ if (isItemWithTabs(item)) {
249
+ itemIds = [id].concat(item.data.tabs.map((tab) => tab.id));
250
+ }
251
+ if (isItemWithGroup(item)) {
252
+ itemIds = [id].concat(item.data.group.map((groupItem) => groupItem.id));
253
+ }
199
254
  const connections = config.connections.filter(({ from, to }) => !itemIds.includes(from) && !itemIds.includes(to));
200
255
  return {
201
256
  config: update(config, {
@@ -248,6 +303,7 @@ export class UpdateManager {
248
303
  const newTabId = (_a = stateAndParams.state) === null || _a === void 0 ? void 0 : _a.tabId;
249
304
  const isTabSwitched = isItemWithTabs(initiatorItem) && Boolean(newTabId);
250
305
  const currentMeta = getItemsStateAndParamsMeta(itemsStateAndParams);
306
+ const groupItemIds = options === null || options === void 0 ? void 0 : options.groupItemIds;
251
307
  if (action === 'removeItem') {
252
308
  return update(itemsStateAndParams, {
253
309
  $unset: [...unusedIds, initiatorId],
@@ -262,6 +318,17 @@ export class UpdateManager {
262
318
  },
263
319
  });
264
320
  }
321
+ if (isItemWithGroup(initiatorItem) && groupItemIds) {
322
+ return changeGroupParams({
323
+ initiatorId,
324
+ initiatorItem,
325
+ groupItemIds,
326
+ itemsStateAndParams,
327
+ stateAndParams,
328
+ config,
329
+ unusedIds,
330
+ });
331
+ }
265
332
  if ('params' in stateAndParams) {
266
333
  const allowableParams = getAllowableChangedParams(initiatorItem, stateAndParams, itemsStateAndParams);
267
334
  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": "6.8.0",
3
+ "version": "6.10.0",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {