@gravity-ui/dashkit 4.1.0 → 5.1.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 (52) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/build/cjs/components/DashKit/DashKit.d.ts +4 -3
  3. package/build/cjs/components/DashKit/DashKit.js +3 -2
  4. package/build/cjs/components/Item/Item.d.ts +4 -8
  5. package/build/cjs/components/OverlayControls/OverlayControls.d.ts +10 -1
  6. package/build/cjs/components/OverlayControls/OverlayControls.js +1 -2
  7. package/build/cjs/hocs/prepareItem.d.ts +4 -8
  8. package/build/cjs/plugins/Text/Text.d.ts +4 -4
  9. package/build/cjs/shared/modules/__tests__/uniq-id.test.d.ts +1 -0
  10. package/build/cjs/shared/modules/__tests__/uniq-id.test.js +77 -0
  11. package/build/cjs/shared/modules/helpers.d.ts +1 -1
  12. package/build/cjs/shared/modules/index.d.ts +1 -0
  13. package/build/cjs/shared/modules/index.js +1 -0
  14. package/build/cjs/shared/modules/state-and-params.d.ts +1 -1
  15. package/build/cjs/shared/modules/uniq-id.d.ts +12 -0
  16. package/build/cjs/shared/modules/uniq-id.js +36 -0
  17. package/build/cjs/shared/types/common.d.ts +1 -1
  18. package/build/cjs/shared/types/state-and-params.d.ts +5 -5
  19. package/build/cjs/typings/common.d.ts +1 -1
  20. package/build/cjs/typings/config.d.ts +4 -1
  21. package/build/cjs/utils/configure.d.ts +2 -2
  22. package/build/cjs/utils/get-new-id.d.ts +12 -0
  23. package/build/cjs/utils/get-new-id.js +9 -0
  24. package/build/cjs/utils/register-manager.d.ts +3 -3
  25. package/build/cjs/utils/update-manager.d.ts +5 -3
  26. package/build/cjs/utils/update-manager.js +35 -14
  27. package/build/esm/components/DashKit/DashKit.d.ts +4 -3
  28. package/build/esm/components/DashKit/DashKit.js +3 -2
  29. package/build/esm/components/Item/Item.d.ts +4 -8
  30. package/build/esm/components/OverlayControls/OverlayControls.d.ts +10 -1
  31. package/build/esm/components/OverlayControls/OverlayControls.js +1 -2
  32. package/build/esm/hocs/prepareItem.d.ts +4 -8
  33. package/build/esm/plugins/Text/Text.d.ts +4 -4
  34. package/build/esm/shared/modules/__tests__/uniq-id.test.d.ts +1 -0
  35. package/build/esm/shared/modules/__tests__/uniq-id.test.js +74 -0
  36. package/build/esm/shared/modules/helpers.d.ts +1 -1
  37. package/build/esm/shared/modules/index.d.ts +1 -0
  38. package/build/esm/shared/modules/index.js +1 -0
  39. package/build/esm/shared/modules/state-and-params.d.ts +1 -1
  40. package/build/esm/shared/modules/uniq-id.d.ts +12 -0
  41. package/build/esm/shared/modules/uniq-id.js +30 -0
  42. package/build/esm/shared/types/common.d.ts +1 -1
  43. package/build/esm/shared/types/state-and-params.d.ts +5 -5
  44. package/build/esm/typings/common.d.ts +1 -1
  45. package/build/esm/typings/config.d.ts +4 -1
  46. package/build/esm/utils/configure.d.ts +2 -2
  47. package/build/esm/utils/get-new-id.d.ts +12 -0
  48. package/build/esm/utils/get-new-id.js +5 -0
  49. package/build/esm/utils/register-manager.d.ts +3 -3
  50. package/build/esm/utils/update-manager.d.ts +5 -3
  51. package/build/esm/utils/update-manager.js +35 -14
  52. package/package.json +12 -12
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.1.0](https://github.com/gravity-ui/dashkit/compare/v5.0.0...v5.1.0) (2023-02-09)
4
+
5
+
6
+ ### Features
7
+
8
+ * generating a unique id for config ([#41](https://github.com/gravity-ui/dashkit/issues/41)) ([062c8d0](https://github.com/gravity-ui/dashkit/commit/062c8d015e334061fac193cf8c0a549a932e3a87))
9
+
10
+ ## [5.0.0](https://github.com/gravity-ui/dashkit/compare/v4.1.0...v5.0.0) (2023-02-01)
11
+
12
+
13
+ ### ⚠ BREAKING CHANGES
14
+
15
+ * up @gravity-ui/uikit to 4 version ([#39](https://github.com/gravity-ui/dashkit/issues/39))
16
+
17
+ ### Features
18
+
19
+ * up @gravity-ui/uikit to 4 version ([#39](https://github.com/gravity-ui/dashkit/issues/39)) ([8b4c123](https://github.com/gravity-ui/dashkit/commit/8b4c123a69009918518d4c296af3c315f811afd9))
20
+
3
21
  ## [4.1.0](https://github.com/gravity-ui/dashkit/compare/v4.0.0...v4.1.0) (2023-01-31)
4
22
 
5
23
 
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import GridLayout from '../GridLayout/GridLayout';
3
- import { SetConfigItem, Settings, SettingsProps, ContextProps, Plugin } from '../../typings';
3
+ import { SetConfigItem, Settings, SettingsProps, ContextProps, Plugin, SetItemOptions } from '../../typings';
4
4
  import { GlobalParams, Config, ConfigItem, ItemsStateAndParams } from '../../shared';
5
5
  import { OverlayControlItem } from '../OverlayControls/OverlayControls';
6
6
  interface DashKitGeneralProps {
@@ -24,15 +24,16 @@ interface DashKitDefaultProps {
24
24
  }
25
25
  export interface DashKitProps extends DashKitGeneralProps, Partial<DashKitDefaultProps> {
26
26
  }
27
- declare type DashKitInnerProps = DashKitGeneralProps & DashKitDefaultProps;
27
+ type DashKitInnerProps = DashKitGeneralProps & DashKitDefaultProps;
28
28
  export declare class DashKit extends React.PureComponent<DashKitInnerProps> {
29
29
  static defaultProps: DashKitDefaultProps;
30
30
  static registerPlugins(...plugins: Plugin[]): void;
31
31
  static setSettings(settings: Settings): void;
32
- static setItem({ item: setItem, namespace, config, }: {
32
+ static setItem({ item: setItem, namespace, config, options, }: {
33
33
  item: SetConfigItem;
34
34
  namespace?: string;
35
35
  config: Config;
36
+ options?: SetItemOptions;
36
37
  }): Config;
37
38
  static removeItem({ id, config, itemsStateAndParams, }: {
38
39
  id: string;
@@ -21,9 +21,9 @@ class DashKit extends react_1.default.PureComponent {
21
21
  static setSettings(settings) {
22
22
  registerManager.setSettings(settings);
23
23
  }
24
- static setItem({ item: setItem, namespace = constants_1.DEFAULT_NAMESPACE, config, }) {
24
+ static setItem({ item: setItem, namespace = constants_1.DEFAULT_NAMESPACE, config, options = {}, }) {
25
25
  if (setItem.id) {
26
- return utils_1.UpdateManager.editItem({ item: setItem, namespace, config });
26
+ return utils_1.UpdateManager.editItem({ item: setItem, namespace, config, options });
27
27
  }
28
28
  else {
29
29
  const item = setItem;
@@ -36,6 +36,7 @@ class DashKit extends react_1.default.PureComponent {
36
36
  namespace,
37
37
  config,
38
38
  layout,
39
+ options,
39
40
  });
40
41
  }
41
42
  }
@@ -3,12 +3,10 @@ declare const _default: {
3
3
  shouldComponentUpdate(nextProps: any): boolean;
4
4
  _onStateAndParamsChange: (stateAndParams: any) => void;
5
5
  render(): JSX.Element;
6
- context: any;
6
+ context: unknown;
7
7
  setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
8
8
  forceUpdate(callback?: (() => void) | undefined): void;
9
- readonly props: Readonly<any> & Readonly<{
10
- children?: React.ReactNode;
11
- }>;
9
+ readonly props: Readonly<any>;
12
10
  state: Readonly<any>;
13
11
  refs: {
14
12
  [key: string]: React.ReactInstance;
@@ -29,12 +27,10 @@ declare const _default: {
29
27
  shouldComponentUpdate(nextProps: any): boolean;
30
28
  _onStateAndParamsChange: (stateAndParams: any) => void;
31
29
  render(): JSX.Element;
32
- context: any;
30
+ context: unknown;
33
31
  setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
34
32
  forceUpdate(callback?: (() => void) | undefined): void;
35
- readonly props: Readonly<any> & Readonly<{
36
- children?: React.ReactNode;
37
- }>;
33
+ readonly props: Readonly<any>;
38
34
  state: Readonly<any>;
39
35
  refs: {
40
36
  [key: string]: React.ReactInstance;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { ButtonView, ButtonSize, IconProps, MenuItemProps } from '@gravity-ui/uikit';
3
- import { ConfigItem, PluginBase, StringParams } from '../../shared';
3
+ import { ConfigItem, PluginBase, StringParams, Config } from '../../shared';
4
+ import type { RegisterManager } from '../../utils/register-manager';
4
5
  export declare enum OverlayControlsPosition {
5
6
  TopRight = "top_right",
6
7
  TopLeft = "top_left",
@@ -35,9 +36,17 @@ interface OverlayControlsProps extends OverlayControlsDefaultProps {
35
36
  items?: OverlayControlItem[];
36
37
  overlayControls?: Record<string, OverlayControlItem[]>;
37
38
  }
39
+ type DashKitCtx = React.Context<{
40
+ registerManager: RegisterManager;
41
+ itemsParams: Record<string, StringParams>;
42
+ editItem: (item: ConfigItem) => void;
43
+ removeItem: (id: string) => void;
44
+ config: Config;
45
+ }>;
38
46
  declare class OverlayControls extends React.Component<OverlayControlsProps> {
39
47
  static contextType: React.Context<any>;
40
48
  static defaultProps: OverlayControlsDefaultProps;
49
+ context: React.ContextType<DashKitCtx>;
41
50
  render(): JSX.Element;
42
51
  private renderControlsItem;
43
52
  private getDropDownMenuItemConfig;
@@ -143,8 +143,7 @@ class OverlayControls extends react_1.default.Component {
143
143
  }
144
144
  renderDropdownMenu() {
145
145
  const { view, size } = this.props;
146
- const { registerManager } = this.context;
147
- const itemsParams = this.context.itemsParams;
146
+ const { registerManager, itemsParams } = this.context;
148
147
  const configItem = this.props.configItem;
149
148
  const itemParams = itemsParams[configItem.id];
150
149
  let menu = registerManager.settings.menu;
@@ -3,12 +3,10 @@ export function prepareItem(Component: any): {
3
3
  shouldComponentUpdate(nextProps: any): boolean;
4
4
  _onStateAndParamsChange: (stateAndParams: any) => void;
5
5
  render(): JSX.Element;
6
- context: any;
6
+ context: unknown;
7
7
  setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
8
8
  forceUpdate(callback?: (() => void) | undefined): void;
9
- readonly props: Readonly<any> & Readonly<{
10
- children?: React.ReactNode;
11
- }>;
9
+ readonly props: Readonly<any>;
12
10
  state: Readonly<any>;
13
11
  refs: {
14
12
  [key: string]: React.ReactInstance;
@@ -29,12 +27,10 @@ export function prepareItem(Component: any): {
29
27
  shouldComponentUpdate(nextProps: any): boolean;
30
28
  _onStateAndParamsChange: (stateAndParams: any) => void;
31
29
  render(): JSX.Element;
32
- context: any;
30
+ context: unknown;
33
31
  setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
34
32
  forceUpdate(callback?: (() => void) | undefined): void;
35
- readonly props: Readonly<any> & Readonly<{
36
- children?: React.ReactNode;
37
- }>;
33
+ readonly props: Readonly<any>;
38
34
  state: Readonly<any>;
39
35
  refs: {
40
36
  [key: string]: React.ReactInstance;
@@ -5,7 +5,7 @@ declare enum LoadStatus {
5
5
  Success = "success",
6
6
  Fail = "fail"
7
7
  }
8
- export declare type PluginTextApiHandler = (data: {
8
+ export type PluginTextApiHandler = (data: {
9
9
  text: string;
10
10
  }) => Promise<{
11
11
  result: string;
@@ -40,11 +40,11 @@ export declare class PluginText extends React.PureComponent<PluginTextProps, Plu
40
40
  private onRetryClick;
41
41
  get withMarkdown(): boolean;
42
42
  }
43
- declare type PluginDataProps = Omit<PluginTextProps, 'apiHandler'>;
44
- export declare type PluginTextObjectSettings = {
43
+ type PluginDataProps = Omit<PluginTextProps, 'apiHandler'>;
44
+ export type PluginTextObjectSettings = {
45
45
  apiHandler?: PluginTextApiHandler;
46
46
  };
47
- export declare type PluginTextObject = Plugin<PluginDataProps> & {
47
+ export type PluginTextObject = Plugin<PluginDataProps> & {
48
48
  setSettings: (settings: PluginTextObjectSettings) => PluginTextObject;
49
49
  _apiHandler?: PluginTextApiHandler;
50
50
  };
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const hashids_1 = tslib_1.__importDefault(require("hashids"));
5
+ const uniq_id_1 = require("../uniq-id");
6
+ const salt = 'salt';
7
+ const hashids = new hashids_1.default(salt);
8
+ const testCounter = 1;
9
+ const id1 = hashids.encode(testCounter + 1);
10
+ const id2 = hashids.encode(testCounter + 2);
11
+ const id3 = hashids.encode(testCounter + 3);
12
+ const id4 = hashids.encode(testCounter + 4);
13
+ describe('modules.uniq-id: generateUniqId', () => {
14
+ it('return correct first id and counter', () => {
15
+ const { id, counter } = (0, uniq_id_1.generateUniqId)({
16
+ counter: testCounter,
17
+ ids: [],
18
+ salt,
19
+ });
20
+ expect(hashids.encode(counter)).toEqual(id1);
21
+ expect(id).toEqual(id1);
22
+ expect(counter).toEqual(testCounter + 1);
23
+ });
24
+ it('return correct id and counter with ids=[id1]', () => {
25
+ const { id, counter } = (0, uniq_id_1.generateUniqId)({
26
+ counter: testCounter + 1,
27
+ ids: [id1],
28
+ salt,
29
+ });
30
+ expect(hashids.encode(counter)).toEqual(id2);
31
+ expect(id).toEqual(id2);
32
+ expect(counter).toEqual(testCounter + 2);
33
+ });
34
+ it('return correct id4 and counter with ids=[id1, id2, id3] and incorrect counter=1', () => {
35
+ const { id, counter } = (0, uniq_id_1.generateUniqId)({
36
+ counter: 1,
37
+ ids: [id1, id2, id3],
38
+ salt,
39
+ });
40
+ expect(hashids.encode(counter)).toEqual(id4);
41
+ expect(id).toEqual(id4);
42
+ expect(counter).toEqual(testCounter + 4);
43
+ });
44
+ });
45
+ const IDS = ['WZ', '9X', '2m', 'R2', 'Pd'];
46
+ const config = {
47
+ items: [
48
+ {
49
+ id: IDS[0],
50
+ data: {
51
+ tabs: [
52
+ {
53
+ id: IDS[1],
54
+ },
55
+ {
56
+ id: IDS[2],
57
+ },
58
+ ],
59
+ },
60
+ },
61
+ {
62
+ id: IDS[3],
63
+ },
64
+ ],
65
+ layout: [{ i: IDS[0] }, { i: IDS[3] }],
66
+ connections: [
67
+ { from: IDS[2], to: IDS[4] },
68
+ { from: IDS[1], to: IDS[3] },
69
+ ],
70
+ };
71
+ describe('modules.uniq-id: extractIdsFromConfig', () => {
72
+ it('correct extract ids from config', () => {
73
+ const ids = (0, uniq_id_1.extractIdsFromConfig)(config);
74
+ expect(Array.isArray(ids)).toBe(true);
75
+ expect(IDS.concat().sort()).toEqual(ids.sort());
76
+ });
77
+ });
@@ -6,7 +6,7 @@ export declare function prerenderItems({ items, plugins, }: {
6
6
  export declare function getItemsStateAndParamsMeta(itemsStateAndParams: ItemsStateAndParams): StateAndParamsMetaData | undefined;
7
7
  export declare function getCurrentVersion(itemsStateAndParams: ItemsStateAndParams): number;
8
8
  export declare function isItemWithTabs(item: Pick<ConfigItem, 'data'>): item is Pick<ConfigItemWithTabs, 'data'>;
9
- export declare type FormedQueueData = {
9
+ export type FormedQueueData = {
10
10
  id: string;
11
11
  namespace: string;
12
12
  params: StringParams;
@@ -1,2 +1,3 @@
1
1
  export * from './helpers';
2
2
  export * from './state-and-params';
3
+ export * from './uniq-id';
@@ -3,3 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./helpers"), exports);
5
5
  tslib_1.__exportStar(require("./state-and-params"), exports);
6
+ tslib_1.__exportStar(require("./uniq-id"), exports);
@@ -6,7 +6,7 @@ export interface GetItemsParamsArg {
6
6
  itemsStateAndParams: ItemsStateAndParams;
7
7
  plugins: PluginBase[];
8
8
  }
9
- declare type GetItemsParamsReturn = Record<string, StringParams>;
9
+ type GetItemsParamsReturn = Record<string, StringParams>;
10
10
  export declare function getItemsParams({ defaultGlobalParams, globalParams, config, itemsStateAndParams, plugins, }: GetItemsParamsArg): GetItemsParamsReturn;
11
11
  export declare function getItemsState({ config, itemsStateAndParams, }: {
12
12
  config: Config;
@@ -0,0 +1,12 @@
1
+ import type { Config } from '../types';
2
+ export declare function extractIdsFromConfig(config: Config): string[];
3
+ type GenerateUniqIdArgs = {
4
+ salt: Config['salt'];
5
+ counter: Config['counter'];
6
+ ids: string[];
7
+ };
8
+ export declare function generateUniqId({ salt, counter, ids }: GenerateUniqIdArgs): {
9
+ counter: number;
10
+ id: string;
11
+ };
12
+ export {};
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateUniqId = exports.extractIdsFromConfig = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const hashids_1 = tslib_1.__importDefault(require("hashids"));
6
+ const helpers_1 = require("./helpers");
7
+ function extractIdsFromConfig(config) {
8
+ const ids = [];
9
+ const items = config.items || [];
10
+ const connections = config.connections || [];
11
+ const layout = config.layout || [];
12
+ items.forEach((item) => {
13
+ ids.push(item.id);
14
+ if ((0, helpers_1.isItemWithTabs)(item)) {
15
+ item.data.tabs.forEach((tabItem) => ids.push(tabItem.id));
16
+ }
17
+ });
18
+ connections.forEach(({ from, to }) => ids.push(from, to));
19
+ layout.forEach(({ i }) => ids.push(i));
20
+ return Array.from(new Set(ids));
21
+ }
22
+ exports.extractIdsFromConfig = extractIdsFromConfig;
23
+ function generateUniqId({ salt, counter, ids }) {
24
+ let newCounter = counter;
25
+ let uniqId = null;
26
+ const idsSet = new Set(ids);
27
+ const hashids = new hashids_1.default(salt);
28
+ while (uniqId === null) {
29
+ const id = hashids.encode(++newCounter);
30
+ if (!idsSet.has(id)) {
31
+ uniqId = id;
32
+ }
33
+ }
34
+ return { counter: newCounter, id: uniqId };
35
+ }
36
+ exports.generateUniqId = generateUniqId;
@@ -1,4 +1,4 @@
1
- export declare type Dictionary<T = unknown> = Record<string, T>;
1
+ export type Dictionary<T = unknown> = Record<string, T>;
2
2
  export interface StringParams extends Dictionary<string | string[]> {
3
3
  }
4
4
  export interface GlobalParams extends StringParams {
@@ -7,16 +7,16 @@ export interface QueueItem {
7
7
  id: string;
8
8
  tabId?: string;
9
9
  }
10
- export declare type StateAndParamsMetaData = {
10
+ export type StateAndParamsMetaData = {
11
11
  queue: QueueItem[];
12
12
  version: number;
13
13
  };
14
- export declare type StateAndParamsMeta = {
14
+ export type StateAndParamsMeta = {
15
15
  [META_KEY]: StateAndParamsMetaData;
16
16
  };
17
- export declare type ItemStateAndParams = {
17
+ export type ItemStateAndParams = {
18
18
  params?: StringParams;
19
19
  state?: ItemState;
20
20
  };
21
- export declare type ItemsStateAndParamsBase = Record<string, ItemStateAndParams>;
22
- export declare type ItemsStateAndParams = ItemsStateAndParamsBase | StateAndParamsMeta;
21
+ export type ItemsStateAndParamsBase = Record<string, ItemStateAndParams>;
22
+ export type ItemsStateAndParams = ItemsStateAndParamsBase | StateAndParamsMeta;
@@ -11,7 +11,7 @@ export interface Settings {
11
11
  isMobile?: boolean;
12
12
  menu?: Array<MenuItem>;
13
13
  }
14
- export declare type MenuItem = typeof MenuItems[keyof typeof MenuItems] | OverlayCustomControlItem;
14
+ export type MenuItem = typeof MenuItems[keyof typeof MenuItems] | OverlayCustomControlItem;
15
15
  export interface SettingsProps {
16
16
  autoupdateInterval: number;
17
17
  silentLoading: boolean;
@@ -4,4 +4,7 @@ export interface AddConfigItem extends Omit<ConfigItem, 'id' | 'namespace'> {
4
4
  namespace?: string;
5
5
  layout?: ConfigLayout;
6
6
  }
7
- export declare type SetConfigItem = ConfigItem | AddConfigItem;
7
+ export type SetConfigItem = ConfigItem | AddConfigItem;
8
+ export type SetItemOptions = {
9
+ excludeIds?: string[];
10
+ };
@@ -1,8 +1,8 @@
1
- export declare type Lang = 'ru' | 'en';
1
+ export type Lang = 'ru' | 'en';
2
2
  interface Config {
3
3
  lang?: Lang;
4
4
  }
5
- declare type Subscriber = (config: Config) => void;
5
+ type Subscriber = (config: Config) => void;
6
6
  export declare const configure: (newConfig: Config) => void;
7
7
  export declare const subscribeConfigure: (sub: Subscriber) => () => void;
8
8
  export declare const getConfig: () => Config;
@@ -0,0 +1,12 @@
1
+ import { Config } from '../shared';
2
+ type GetNewIdArgs = {
3
+ config: Config;
4
+ salt: Config['salt'];
5
+ counter: Config['counter'];
6
+ excludeIds?: string[];
7
+ };
8
+ export declare function getNewId({ config, salt, counter, excludeIds }: GetNewIdArgs): {
9
+ counter: number;
10
+ id: string;
11
+ };
12
+ export {};
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getNewId = void 0;
4
+ const shared_1 = require("../shared");
5
+ function getNewId({ config, salt, counter, excludeIds = [] }) {
6
+ const allIds = [...(0, shared_1.extractIdsFromConfig)(config), ...excludeIds];
7
+ return (0, shared_1.generateUniqId)({ salt, counter, ids: allIds });
8
+ }
9
+ exports.getNewId = getNewId;
@@ -7,17 +7,17 @@ interface RegisterManagerDefaultLayout {
7
7
  minW: number;
8
8
  minH: number;
9
9
  }
10
- export declare type RegisterManagerPluginLayout = RegisterManagerDefaultLayout & PluginDefaultLayout;
10
+ export type RegisterManagerPluginLayout = RegisterManagerDefaultLayout & PluginDefaultLayout;
11
11
  export interface RegisterManagerPlugin extends Omit<Plugin, 'defaultLayout'> {
12
12
  defaultLayout: RegisterManagerDefaultLayout & Plugin['defaultLayout'];
13
13
  }
14
- export declare type RegisterManagerGridLayout = {
14
+ export type RegisterManagerGridLayout = {
15
15
  margin: [number, number];
16
16
  rowHeight: number;
17
17
  cols: number;
18
18
  containerPadding: [number, number];
19
19
  } & Settings['gridLayout'];
20
- export declare type RegisterManagerSettings = {
20
+ export type RegisterManagerSettings = {
21
21
  theme: string;
22
22
  } & Settings;
23
23
  export declare class RegisterManager {
@@ -1,5 +1,5 @@
1
1
  import { Config, ConfigItem, ItemsStateAndParams, ItemStateAndParams } from '../shared';
2
- import { AddConfigItem, WidgetLayout } from '../typings';
2
+ import { AddConfigItem, WidgetLayout, SetItemOptions } from '../typings';
3
3
  import { RegisterManagerPluginLayout } from './register-manager';
4
4
  interface RemoveItemArg {
5
5
  id: string;
@@ -13,16 +13,18 @@ interface ChangeStateAndParamsArg {
13
13
  stateAndParams: ItemStateAndParams;
14
14
  }
15
15
  export declare class UpdateManager {
16
- static addItem({ item, namespace, layout, config, }: {
16
+ static addItem({ item, namespace, layout, config, options, }: {
17
17
  item: AddConfigItem;
18
18
  namespace: string;
19
19
  layout: RegisterManagerPluginLayout;
20
20
  config: Config;
21
+ options: SetItemOptions;
21
22
  }): Config;
22
- static editItem({ item, namespace, config, }: {
23
+ static editItem({ item, namespace, config, options, }: {
23
24
  item: ConfigItem;
24
25
  namespace: string;
25
26
  config: Config;
27
+ options: SetItemOptions;
26
28
  }): Config;
27
29
  static removeItem({ id, config, itemsStateAndParams }: RemoveItemArg): {
28
30
  config: Config;
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UpdateManager = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const immutability_helper_1 = tslib_1.__importStar(require("immutability-helper"));
6
- const hashids_1 = tslib_1.__importDefault(require("hashids"));
7
6
  const omit_1 = tslib_1.__importDefault(require("lodash/omit"));
8
7
  const pick_1 = tslib_1.__importDefault(require("lodash/pick"));
9
8
  const shared_1 = require("../shared");
10
9
  const constants_1 = require("../constants");
10
+ const get_new_id_1 = require("./get-new-id");
11
11
  (0, immutability_helper_1.extend)('$auto', (value, object) => (object ? (0, immutability_helper_1.default)(object, value) : (0, immutability_helper_1.default)({}, value)));
12
12
  function removeItemVersion1({ id, config, itemsStateAndParams }) {
13
13
  const itemIndex = config.items.findIndex((item) => item.id === id);
@@ -134,30 +134,51 @@ function changeStateAndParamsVersion1({ id: initiatorId, config, stateAndParams,
134
134
  return itemsStateAndParams;
135
135
  }
136
136
  }
137
+ function getNewItemData({ item, config, counter: argsCounter, salt, options }) {
138
+ const excludeIds = [...(options.excludeIds || [])];
139
+ let counter = argsCounter;
140
+ let data = item.data;
141
+ if ((0, shared_1.isItemWithTabs)(item)) {
142
+ const tabs = item.data.tabs.map((tab) => {
143
+ if (tab.id) {
144
+ return tab;
145
+ }
146
+ const newIdTabData = (0, get_new_id_1.getNewId)({ config, salt, counter, excludeIds });
147
+ counter = newIdTabData.counter;
148
+ excludeIds.push(newIdTabData.id);
149
+ return Object.assign(Object.assign({}, tab), { id: newIdTabData.id });
150
+ });
151
+ data = Object.assign(Object.assign({}, item.data), { tabs });
152
+ }
153
+ return { data, counter, excludeIds };
154
+ }
137
155
  class UpdateManager {
138
- // TODO: проверять, что id нового элемента уникальный
139
- static addItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, layout, config, }) {
156
+ static addItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, layout, config, options, }) {
140
157
  const layoutY = Math.max(0, ...config.layout.map(({ h, y }) => h + y));
141
158
  const saveDefaultLayout = (0, pick_1.default)(layout, ['h', 'w', 'x', 'y']);
142
- const hashids = new hashids_1.default(config.salt);
143
- let counter = config.counter;
144
- const resultData = (0, shared_1.isItemWithTabs)(item)
145
- ? Object.assign(Object.assign({}, item.data), { tabs: item.data.tabs.map((tab) => tab.id ? tab : Object.assign(Object.assign({}, tab), { id: hashids.encode(++counter) })) }) : item.data;
146
- const newItem = Object.assign(Object.assign({}, item), { id: hashids.encode(++counter), data: resultData, namespace });
159
+ const salt = config.salt;
160
+ const newItemData = getNewItemData({ item, config, salt, counter: config.counter, options });
161
+ let counter = newItemData.counter;
162
+ const newIdData = (0, get_new_id_1.getNewId)({ config, salt, counter, excludeIds: newItemData.excludeIds });
163
+ counter = newIdData.counter;
164
+ const newItem = Object.assign(Object.assign({}, item), { id: newIdData.id, data: newItemData.data, namespace });
147
165
  return (0, immutability_helper_1.default)(config, {
148
166
  items: { $push: [newItem] },
149
167
  layout: { $push: [Object.assign(Object.assign({}, saveDefaultLayout), { y: layoutY, i: newItem.id })] },
150
168
  counter: { $set: counter },
151
169
  });
152
170
  }
153
- static editItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, config, }) {
154
- const hashids = new hashids_1.default(config.salt);
155
- let counter = config.counter;
171
+ static editItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, config, options, }) {
156
172
  const itemIndex = config.items.findIndex(({ id }) => item.id === id);
157
- const resultData = (0, shared_1.isItemWithTabs)(item)
158
- ? Object.assign(Object.assign({}, item.data), { tabs: item.data.tabs.map((tab) => tab.id ? tab : Object.assign(Object.assign({}, tab), { id: hashids.encode(++counter) })) }) : item.data;
173
+ const { counter, data } = getNewItemData({
174
+ item,
175
+ config,
176
+ salt: config.salt,
177
+ counter: config.counter,
178
+ options,
179
+ });
159
180
  return (0, immutability_helper_1.default)(config, {
160
- items: { [itemIndex]: { $set: Object.assign(Object.assign({}, item), { data: resultData, namespace }) } },
181
+ items: { [itemIndex]: { $set: Object.assign(Object.assign({}, item), { data, namespace }) } },
161
182
  counter: { $set: counter },
162
183
  });
163
184
  }
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import GridLayout from '../GridLayout/GridLayout';
3
- import { SetConfigItem, Settings, SettingsProps, ContextProps, Plugin } from '../../typings';
3
+ import { SetConfigItem, Settings, SettingsProps, ContextProps, Plugin, SetItemOptions } from '../../typings';
4
4
  import { GlobalParams, Config, ConfigItem, ItemsStateAndParams } from '../../shared';
5
5
  import { OverlayControlItem } from '../OverlayControls/OverlayControls';
6
6
  interface DashKitGeneralProps {
@@ -24,15 +24,16 @@ interface DashKitDefaultProps {
24
24
  }
25
25
  export interface DashKitProps extends DashKitGeneralProps, Partial<DashKitDefaultProps> {
26
26
  }
27
- declare type DashKitInnerProps = DashKitGeneralProps & DashKitDefaultProps;
27
+ type DashKitInnerProps = DashKitGeneralProps & DashKitDefaultProps;
28
28
  export declare class DashKit extends React.PureComponent<DashKitInnerProps> {
29
29
  static defaultProps: DashKitDefaultProps;
30
30
  static registerPlugins(...plugins: Plugin[]): void;
31
31
  static setSettings(settings: Settings): void;
32
- static setItem({ item: setItem, namespace, config, }: {
32
+ static setItem({ item: setItem, namespace, config, options, }: {
33
33
  item: SetConfigItem;
34
34
  namespace?: string;
35
35
  config: Config;
36
+ options?: SetItemOptions;
36
37
  }): Config;
37
38
  static removeItem({ id, config, itemsStateAndParams, }: {
38
39
  id: string;
@@ -17,9 +17,9 @@ export class DashKit extends React.PureComponent {
17
17
  static setSettings(settings) {
18
18
  registerManager.setSettings(settings);
19
19
  }
20
- static setItem({ item: setItem, namespace = DEFAULT_NAMESPACE, config, }) {
20
+ static setItem({ item: setItem, namespace = DEFAULT_NAMESPACE, config, options = {}, }) {
21
21
  if (setItem.id) {
22
- return UpdateManager.editItem({ item: setItem, namespace, config });
22
+ return UpdateManager.editItem({ item: setItem, namespace, config, options });
23
23
  }
24
24
  else {
25
25
  const item = setItem;
@@ -32,6 +32,7 @@ export class DashKit extends React.PureComponent {
32
32
  namespace,
33
33
  config,
34
34
  layout,
35
+ options,
35
36
  });
36
37
  }
37
38
  }
@@ -3,12 +3,10 @@ declare const _default: {
3
3
  shouldComponentUpdate(nextProps: any): boolean;
4
4
  _onStateAndParamsChange: (stateAndParams: any) => void;
5
5
  render(): JSX.Element;
6
- context: any;
6
+ context: unknown;
7
7
  setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
8
8
  forceUpdate(callback?: (() => void) | undefined): void;
9
- readonly props: Readonly<any> & Readonly<{
10
- children?: React.ReactNode;
11
- }>;
9
+ readonly props: Readonly<any>;
12
10
  state: Readonly<any>;
13
11
  refs: {
14
12
  [key: string]: React.ReactInstance;
@@ -29,12 +27,10 @@ declare const _default: {
29
27
  shouldComponentUpdate(nextProps: any): boolean;
30
28
  _onStateAndParamsChange: (stateAndParams: any) => void;
31
29
  render(): JSX.Element;
32
- context: any;
30
+ context: unknown;
33
31
  setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
34
32
  forceUpdate(callback?: (() => void) | undefined): void;
35
- readonly props: Readonly<any> & Readonly<{
36
- children?: React.ReactNode;
37
- }>;
33
+ readonly props: Readonly<any>;
38
34
  state: Readonly<any>;
39
35
  refs: {
40
36
  [key: string]: React.ReactInstance;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { ButtonView, ButtonSize, IconProps, MenuItemProps } from '@gravity-ui/uikit';
3
- import { ConfigItem, PluginBase, StringParams } from '../../shared';
3
+ import { ConfigItem, PluginBase, StringParams, Config } from '../../shared';
4
+ import type { RegisterManager } from '../../utils/register-manager';
4
5
  import './OverlayControls.css';
5
6
  export declare enum OverlayControlsPosition {
6
7
  TopRight = "top_right",
@@ -36,9 +37,17 @@ interface OverlayControlsProps extends OverlayControlsDefaultProps {
36
37
  items?: OverlayControlItem[];
37
38
  overlayControls?: Record<string, OverlayControlItem[]>;
38
39
  }
40
+ type DashKitCtx = React.Context<{
41
+ registerManager: RegisterManager;
42
+ itemsParams: Record<string, StringParams>;
43
+ editItem: (item: ConfigItem) => void;
44
+ removeItem: (id: string) => void;
45
+ config: Config;
46
+ }>;
39
47
  declare class OverlayControls extends React.Component<OverlayControlsProps> {
40
48
  static contextType: React.Context<any>;
41
49
  static defaultProps: OverlayControlsDefaultProps;
50
+ context: React.ContextType<DashKitCtx>;
42
51
  render(): JSX.Element;
43
52
  private renderControlsItem;
44
53
  private getDropDownMenuItemConfig;
@@ -140,8 +140,7 @@ class OverlayControls extends React.Component {
140
140
  }
141
141
  renderDropdownMenu() {
142
142
  const { view, size } = this.props;
143
- const { registerManager } = this.context;
144
- const itemsParams = this.context.itemsParams;
143
+ const { registerManager, itemsParams } = this.context;
145
144
  const configItem = this.props.configItem;
146
145
  const itemParams = itemsParams[configItem.id];
147
146
  let menu = registerManager.settings.menu;
@@ -3,12 +3,10 @@ export function prepareItem(Component: any): {
3
3
  shouldComponentUpdate(nextProps: any): boolean;
4
4
  _onStateAndParamsChange: (stateAndParams: any) => void;
5
5
  render(): JSX.Element;
6
- context: any;
6
+ context: unknown;
7
7
  setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
8
8
  forceUpdate(callback?: (() => void) | undefined): void;
9
- readonly props: Readonly<any> & Readonly<{
10
- children?: React.ReactNode;
11
- }>;
9
+ readonly props: Readonly<any>;
12
10
  state: Readonly<any>;
13
11
  refs: {
14
12
  [key: string]: React.ReactInstance;
@@ -29,12 +27,10 @@ export function prepareItem(Component: any): {
29
27
  shouldComponentUpdate(nextProps: any): boolean;
30
28
  _onStateAndParamsChange: (stateAndParams: any) => void;
31
29
  render(): JSX.Element;
32
- context: any;
30
+ context: unknown;
33
31
  setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
34
32
  forceUpdate(callback?: (() => void) | undefined): void;
35
- readonly props: Readonly<any> & Readonly<{
36
- children?: React.ReactNode;
37
- }>;
33
+ readonly props: Readonly<any>;
38
34
  state: Readonly<any>;
39
35
  refs: {
40
36
  [key: string]: React.ReactInstance;
@@ -6,7 +6,7 @@ declare enum LoadStatus {
6
6
  Success = "success",
7
7
  Fail = "fail"
8
8
  }
9
- export declare type PluginTextApiHandler = (data: {
9
+ export type PluginTextApiHandler = (data: {
10
10
  text: string;
11
11
  }) => Promise<{
12
12
  result: string;
@@ -41,11 +41,11 @@ export declare class PluginText extends React.PureComponent<PluginTextProps, Plu
41
41
  private onRetryClick;
42
42
  get withMarkdown(): boolean;
43
43
  }
44
- declare type PluginDataProps = Omit<PluginTextProps, 'apiHandler'>;
45
- export declare type PluginTextObjectSettings = {
44
+ type PluginDataProps = Omit<PluginTextProps, 'apiHandler'>;
45
+ export type PluginTextObjectSettings = {
46
46
  apiHandler?: PluginTextApiHandler;
47
47
  };
48
- export declare type PluginTextObject = Plugin<PluginDataProps> & {
48
+ export type PluginTextObject = Plugin<PluginDataProps> & {
49
49
  setSettings: (settings: PluginTextObjectSettings) => PluginTextObject;
50
50
  _apiHandler?: PluginTextApiHandler;
51
51
  };
@@ -0,0 +1,74 @@
1
+ import Hashids from 'hashids';
2
+ import { generateUniqId, extractIdsFromConfig } from '../uniq-id';
3
+ const salt = 'salt';
4
+ const hashids = new Hashids(salt);
5
+ const testCounter = 1;
6
+ const id1 = hashids.encode(testCounter + 1);
7
+ const id2 = hashids.encode(testCounter + 2);
8
+ const id3 = hashids.encode(testCounter + 3);
9
+ const id4 = hashids.encode(testCounter + 4);
10
+ describe('modules.uniq-id: generateUniqId', () => {
11
+ it('return correct first id and counter', () => {
12
+ const { id, counter } = generateUniqId({
13
+ counter: testCounter,
14
+ ids: [],
15
+ salt,
16
+ });
17
+ expect(hashids.encode(counter)).toEqual(id1);
18
+ expect(id).toEqual(id1);
19
+ expect(counter).toEqual(testCounter + 1);
20
+ });
21
+ it('return correct id and counter with ids=[id1]', () => {
22
+ const { id, counter } = generateUniqId({
23
+ counter: testCounter + 1,
24
+ ids: [id1],
25
+ salt,
26
+ });
27
+ expect(hashids.encode(counter)).toEqual(id2);
28
+ expect(id).toEqual(id2);
29
+ expect(counter).toEqual(testCounter + 2);
30
+ });
31
+ it('return correct id4 and counter with ids=[id1, id2, id3] and incorrect counter=1', () => {
32
+ const { id, counter } = generateUniqId({
33
+ counter: 1,
34
+ ids: [id1, id2, id3],
35
+ salt,
36
+ });
37
+ expect(hashids.encode(counter)).toEqual(id4);
38
+ expect(id).toEqual(id4);
39
+ expect(counter).toEqual(testCounter + 4);
40
+ });
41
+ });
42
+ const IDS = ['WZ', '9X', '2m', 'R2', 'Pd'];
43
+ const config = {
44
+ items: [
45
+ {
46
+ id: IDS[0],
47
+ data: {
48
+ tabs: [
49
+ {
50
+ id: IDS[1],
51
+ },
52
+ {
53
+ id: IDS[2],
54
+ },
55
+ ],
56
+ },
57
+ },
58
+ {
59
+ id: IDS[3],
60
+ },
61
+ ],
62
+ layout: [{ i: IDS[0] }, { i: IDS[3] }],
63
+ connections: [
64
+ { from: IDS[2], to: IDS[4] },
65
+ { from: IDS[1], to: IDS[3] },
66
+ ],
67
+ };
68
+ describe('modules.uniq-id: extractIdsFromConfig', () => {
69
+ it('correct extract ids from config', () => {
70
+ const ids = extractIdsFromConfig(config);
71
+ expect(Array.isArray(ids)).toBe(true);
72
+ expect(IDS.concat().sort()).toEqual(ids.sort());
73
+ });
74
+ });
@@ -6,7 +6,7 @@ export declare function prerenderItems({ items, plugins, }: {
6
6
  export declare function getItemsStateAndParamsMeta(itemsStateAndParams: ItemsStateAndParams): StateAndParamsMetaData | undefined;
7
7
  export declare function getCurrentVersion(itemsStateAndParams: ItemsStateAndParams): number;
8
8
  export declare function isItemWithTabs(item: Pick<ConfigItem, 'data'>): item is Pick<ConfigItemWithTabs, 'data'>;
9
- export declare type FormedQueueData = {
9
+ export type FormedQueueData = {
10
10
  id: string;
11
11
  namespace: string;
12
12
  params: StringParams;
@@ -1,2 +1,3 @@
1
1
  export * from './helpers';
2
2
  export * from './state-and-params';
3
+ export * from './uniq-id';
@@ -1,2 +1,3 @@
1
1
  export * from './helpers';
2
2
  export * from './state-and-params';
3
+ export * from './uniq-id';
@@ -6,7 +6,7 @@ export interface GetItemsParamsArg {
6
6
  itemsStateAndParams: ItemsStateAndParams;
7
7
  plugins: PluginBase[];
8
8
  }
9
- declare type GetItemsParamsReturn = Record<string, StringParams>;
9
+ type GetItemsParamsReturn = Record<string, StringParams>;
10
10
  export declare function getItemsParams({ defaultGlobalParams, globalParams, config, itemsStateAndParams, plugins, }: GetItemsParamsArg): GetItemsParamsReturn;
11
11
  export declare function getItemsState({ config, itemsStateAndParams, }: {
12
12
  config: Config;
@@ -0,0 +1,12 @@
1
+ import type { Config } from '../types';
2
+ export declare function extractIdsFromConfig(config: Config): string[];
3
+ type GenerateUniqIdArgs = {
4
+ salt: Config['salt'];
5
+ counter: Config['counter'];
6
+ ids: string[];
7
+ };
8
+ export declare function generateUniqId({ salt, counter, ids }: GenerateUniqIdArgs): {
9
+ counter: number;
10
+ id: string;
11
+ };
12
+ export {};
@@ -0,0 +1,30 @@
1
+ import Hashids from 'hashids';
2
+ import { isItemWithTabs } from './helpers';
3
+ export function extractIdsFromConfig(config) {
4
+ const ids = [];
5
+ const items = config.items || [];
6
+ const connections = config.connections || [];
7
+ const layout = config.layout || [];
8
+ items.forEach((item) => {
9
+ ids.push(item.id);
10
+ if (isItemWithTabs(item)) {
11
+ item.data.tabs.forEach((tabItem) => ids.push(tabItem.id));
12
+ }
13
+ });
14
+ connections.forEach(({ from, to }) => ids.push(from, to));
15
+ layout.forEach(({ i }) => ids.push(i));
16
+ return Array.from(new Set(ids));
17
+ }
18
+ export function generateUniqId({ salt, counter, ids }) {
19
+ let newCounter = counter;
20
+ let uniqId = null;
21
+ const idsSet = new Set(ids);
22
+ const hashids = new Hashids(salt);
23
+ while (uniqId === null) {
24
+ const id = hashids.encode(++newCounter);
25
+ if (!idsSet.has(id)) {
26
+ uniqId = id;
27
+ }
28
+ }
29
+ return { counter: newCounter, id: uniqId };
30
+ }
@@ -1,4 +1,4 @@
1
- export declare type Dictionary<T = unknown> = Record<string, T>;
1
+ export type Dictionary<T = unknown> = Record<string, T>;
2
2
  export interface StringParams extends Dictionary<string | string[]> {
3
3
  }
4
4
  export interface GlobalParams extends StringParams {
@@ -7,16 +7,16 @@ export interface QueueItem {
7
7
  id: string;
8
8
  tabId?: string;
9
9
  }
10
- export declare type StateAndParamsMetaData = {
10
+ export type StateAndParamsMetaData = {
11
11
  queue: QueueItem[];
12
12
  version: number;
13
13
  };
14
- export declare type StateAndParamsMeta = {
14
+ export type StateAndParamsMeta = {
15
15
  [META_KEY]: StateAndParamsMetaData;
16
16
  };
17
- export declare type ItemStateAndParams = {
17
+ export type ItemStateAndParams = {
18
18
  params?: StringParams;
19
19
  state?: ItemState;
20
20
  };
21
- export declare type ItemsStateAndParamsBase = Record<string, ItemStateAndParams>;
22
- export declare type ItemsStateAndParams = ItemsStateAndParamsBase | StateAndParamsMeta;
21
+ export type ItemsStateAndParamsBase = Record<string, ItemStateAndParams>;
22
+ export type ItemsStateAndParams = ItemsStateAndParamsBase | StateAndParamsMeta;
@@ -11,7 +11,7 @@ export interface Settings {
11
11
  isMobile?: boolean;
12
12
  menu?: Array<MenuItem>;
13
13
  }
14
- export declare type MenuItem = typeof MenuItems[keyof typeof MenuItems] | OverlayCustomControlItem;
14
+ export type MenuItem = typeof MenuItems[keyof typeof MenuItems] | OverlayCustomControlItem;
15
15
  export interface SettingsProps {
16
16
  autoupdateInterval: number;
17
17
  silentLoading: boolean;
@@ -4,4 +4,7 @@ export interface AddConfigItem extends Omit<ConfigItem, 'id' | 'namespace'> {
4
4
  namespace?: string;
5
5
  layout?: ConfigLayout;
6
6
  }
7
- export declare type SetConfigItem = ConfigItem | AddConfigItem;
7
+ export type SetConfigItem = ConfigItem | AddConfigItem;
8
+ export type SetItemOptions = {
9
+ excludeIds?: string[];
10
+ };
@@ -1,8 +1,8 @@
1
- export declare type Lang = 'ru' | 'en';
1
+ export type Lang = 'ru' | 'en';
2
2
  interface Config {
3
3
  lang?: Lang;
4
4
  }
5
- declare type Subscriber = (config: Config) => void;
5
+ type Subscriber = (config: Config) => void;
6
6
  export declare const configure: (newConfig: Config) => void;
7
7
  export declare const subscribeConfigure: (sub: Subscriber) => () => void;
8
8
  export declare const getConfig: () => Config;
@@ -0,0 +1,12 @@
1
+ import { Config } from '../shared';
2
+ type GetNewIdArgs = {
3
+ config: Config;
4
+ salt: Config['salt'];
5
+ counter: Config['counter'];
6
+ excludeIds?: string[];
7
+ };
8
+ export declare function getNewId({ config, salt, counter, excludeIds }: GetNewIdArgs): {
9
+ counter: number;
10
+ id: string;
11
+ };
12
+ export {};
@@ -0,0 +1,5 @@
1
+ import { extractIdsFromConfig, generateUniqId } from '../shared';
2
+ export function getNewId({ config, salt, counter, excludeIds = [] }) {
3
+ const allIds = [...extractIdsFromConfig(config), ...excludeIds];
4
+ return generateUniqId({ salt, counter, ids: allIds });
5
+ }
@@ -7,17 +7,17 @@ interface RegisterManagerDefaultLayout {
7
7
  minW: number;
8
8
  minH: number;
9
9
  }
10
- export declare type RegisterManagerPluginLayout = RegisterManagerDefaultLayout & PluginDefaultLayout;
10
+ export type RegisterManagerPluginLayout = RegisterManagerDefaultLayout & PluginDefaultLayout;
11
11
  export interface RegisterManagerPlugin extends Omit<Plugin, 'defaultLayout'> {
12
12
  defaultLayout: RegisterManagerDefaultLayout & Plugin['defaultLayout'];
13
13
  }
14
- export declare type RegisterManagerGridLayout = {
14
+ export type RegisterManagerGridLayout = {
15
15
  margin: [number, number];
16
16
  rowHeight: number;
17
17
  cols: number;
18
18
  containerPadding: [number, number];
19
19
  } & Settings['gridLayout'];
20
- export declare type RegisterManagerSettings = {
20
+ export type RegisterManagerSettings = {
21
21
  theme: string;
22
22
  } & Settings;
23
23
  export declare class RegisterManager {
@@ -1,5 +1,5 @@
1
1
  import { Config, ConfigItem, ItemsStateAndParams, ItemStateAndParams } from '../shared';
2
- import { AddConfigItem, WidgetLayout } from '../typings';
2
+ import { AddConfigItem, WidgetLayout, SetItemOptions } from '../typings';
3
3
  import { RegisterManagerPluginLayout } from './register-manager';
4
4
  interface RemoveItemArg {
5
5
  id: string;
@@ -13,16 +13,18 @@ interface ChangeStateAndParamsArg {
13
13
  stateAndParams: ItemStateAndParams;
14
14
  }
15
15
  export declare class UpdateManager {
16
- static addItem({ item, namespace, layout, config, }: {
16
+ static addItem({ item, namespace, layout, config, options, }: {
17
17
  item: AddConfigItem;
18
18
  namespace: string;
19
19
  layout: RegisterManagerPluginLayout;
20
20
  config: Config;
21
+ options: SetItemOptions;
21
22
  }): Config;
22
- static editItem({ item, namespace, config, }: {
23
+ static editItem({ item, namespace, config, options, }: {
23
24
  item: ConfigItem;
24
25
  namespace: string;
25
26
  config: Config;
27
+ options: SetItemOptions;
26
28
  }): Config;
27
29
  static removeItem({ id, config, itemsStateAndParams }: RemoveItemArg): {
28
30
  config: Config;
@@ -1,9 +1,9 @@
1
1
  import update, { extend } from 'immutability-helper';
2
- import Hashids from 'hashids';
3
2
  import omit from 'lodash/omit';
4
3
  import pick from 'lodash/pick';
5
4
  import { mergeParamsWithAliases, isItemWithTabs, getCurrentVersion, META_KEY, deleteFromQueue, addToQueue, getInitialItemsStateAndParamsMeta, resolveItemInnerId, getItemsStateAndParamsMeta, } from '../shared';
6
5
  import { DEFAULT_NAMESPACE } from '../constants';
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 }) {
9
9
  const itemIndex = config.items.findIndex((item) => item.id === id);
@@ -130,30 +130,51 @@ function changeStateAndParamsVersion1({ id: initiatorId, config, stateAndParams,
130
130
  return itemsStateAndParams;
131
131
  }
132
132
  }
133
+ function getNewItemData({ item, config, counter: argsCounter, salt, options }) {
134
+ const excludeIds = [...(options.excludeIds || [])];
135
+ let counter = argsCounter;
136
+ let data = item.data;
137
+ if (isItemWithTabs(item)) {
138
+ const tabs = item.data.tabs.map((tab) => {
139
+ if (tab.id) {
140
+ return tab;
141
+ }
142
+ const newIdTabData = getNewId({ config, salt, counter, excludeIds });
143
+ counter = newIdTabData.counter;
144
+ excludeIds.push(newIdTabData.id);
145
+ return Object.assign(Object.assign({}, tab), { id: newIdTabData.id });
146
+ });
147
+ data = Object.assign(Object.assign({}, item.data), { tabs });
148
+ }
149
+ return { data, counter, excludeIds };
150
+ }
133
151
  export class UpdateManager {
134
- // TODO: проверять, что id нового элемента уникальный
135
- static addItem({ item, namespace = DEFAULT_NAMESPACE, layout, config, }) {
152
+ static addItem({ item, namespace = DEFAULT_NAMESPACE, layout, config, options, }) {
136
153
  const layoutY = Math.max(0, ...config.layout.map(({ h, y }) => h + y));
137
154
  const saveDefaultLayout = pick(layout, ['h', 'w', 'x', 'y']);
138
- const hashids = new Hashids(config.salt);
139
- let counter = config.counter;
140
- const resultData = isItemWithTabs(item)
141
- ? Object.assign(Object.assign({}, item.data), { tabs: item.data.tabs.map((tab) => tab.id ? tab : Object.assign(Object.assign({}, tab), { id: hashids.encode(++counter) })) }) : item.data;
142
- const newItem = Object.assign(Object.assign({}, item), { id: hashids.encode(++counter), data: resultData, namespace });
155
+ const salt = config.salt;
156
+ const newItemData = getNewItemData({ item, config, salt, counter: config.counter, options });
157
+ let counter = newItemData.counter;
158
+ const newIdData = getNewId({ config, salt, counter, excludeIds: newItemData.excludeIds });
159
+ counter = newIdData.counter;
160
+ const newItem = Object.assign(Object.assign({}, item), { id: newIdData.id, data: newItemData.data, namespace });
143
161
  return update(config, {
144
162
  items: { $push: [newItem] },
145
163
  layout: { $push: [Object.assign(Object.assign({}, saveDefaultLayout), { y: layoutY, i: newItem.id })] },
146
164
  counter: { $set: counter },
147
165
  });
148
166
  }
149
- static editItem({ item, namespace = DEFAULT_NAMESPACE, config, }) {
150
- const hashids = new Hashids(config.salt);
151
- let counter = config.counter;
167
+ static editItem({ item, namespace = DEFAULT_NAMESPACE, config, options, }) {
152
168
  const itemIndex = config.items.findIndex(({ id }) => item.id === id);
153
- const resultData = isItemWithTabs(item)
154
- ? Object.assign(Object.assign({}, item.data), { tabs: item.data.tabs.map((tab) => tab.id ? tab : Object.assign(Object.assign({}, tab), { id: hashids.encode(++counter) })) }) : item.data;
169
+ const { counter, data } = getNewItemData({
170
+ item,
171
+ config,
172
+ salt: config.salt,
173
+ counter: config.counter,
174
+ options,
175
+ });
155
176
  return update(config, {
156
- items: { [itemIndex]: { $set: Object.assign(Object.assign({}, item), { data: resultData, namespace }) } },
177
+ items: { [itemIndex]: { $set: Object.assign(Object.assign({}, item), { data, namespace }) } },
157
178
  counter: { $set: counter },
158
179
  });
159
180
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "4.1.0",
3
+ "version": "5.1.0",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,25 +41,25 @@
41
41
  "react-grid-layout": "^1.3.4"
42
42
  },
43
43
  "peerDependencies": {
44
- "@gravity-ui/uikit": "^3.0.0",
44
+ "@gravity-ui/uikit": "^4.0.0",
45
45
  "bem-cn-lite": "^4.0.0",
46
- "react": "^16.0.0 || ^17.0.0"
46
+ "react": "^16.8.0 || ^17 || ^18"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@commitlint/cli": "^17.0.3",
50
50
  "@commitlint/config-conventional": "^17.0.3",
51
+ "@gravity-ui/eslint-config": "^1.0.2",
52
+ "@gravity-ui/prettier-config": "^1.0.1",
53
+ "@gravity-ui/stylelint-config": "^1.0.1",
54
+ "@gravity-ui/tsconfig": "^1.0.0",
55
+ "@gravity-ui/uikit": "^4.0.5",
51
56
  "@storybook/addon-essentials": "^6.5.9",
52
57
  "@storybook/preset-scss": "^1.0.3",
53
58
  "@storybook/react": "^6.5.9",
54
59
  "@types/enzyme": "^3.10.8",
55
60
  "@types/jest": "^26.0.20",
56
61
  "@types/lodash": "^4.14.170",
57
- "@types/react": "^17.0.47",
58
- "@gravity-ui/eslint-config": "^1.0.2",
59
- "@gravity-ui/prettier-config": "^1.0.1",
60
- "@gravity-ui/stylelint-config": "^1.0.1",
61
- "@gravity-ui/tsconfig": "^1.0.0",
62
- "@gravity-ui/uikit": "^3.0.0",
62
+ "@types/react": "^18.0.27",
63
63
  "babel-jest": "^26.6.3",
64
64
  "bem-cn-lite": "^4.0.0",
65
65
  "copyfiles": "^2.4.1",
@@ -78,15 +78,15 @@
78
78
  "npm-run-all": "^4.1.5",
79
79
  "postcss": "^8.4.12",
80
80
  "prettier": "^2.6.0",
81
- "react": "^17.0.2",
81
+ "react": "^18.2.0",
82
82
  "react-docgen-typescript": "^2.2.2",
83
- "react-dom": "^17.0.2",
83
+ "react-dom": "^18.2.0",
84
84
  "rimraf": "^3.0.2",
85
85
  "sass": "^1.53.0",
86
86
  "sass-loader": "^10.3.1",
87
87
  "stylelint": "^14.6.0",
88
88
  "ts-jest": "^26.5.3",
89
- "typescript": "^4.7.4"
89
+ "typescript": "^4.9.5"
90
90
  },
91
91
  "husky": {
92
92
  "hooks": {