@gravity-ui/dashkit 5.0.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.
- package/CHANGELOG.md +7 -0
- package/build/cjs/components/DashKit/DashKit.d.ts +3 -2
- package/build/cjs/components/DashKit/DashKit.js +3 -2
- package/build/cjs/shared/modules/__tests__/uniq-id.test.d.ts +1 -0
- package/build/cjs/shared/modules/__tests__/uniq-id.test.js +77 -0
- package/build/cjs/shared/modules/index.d.ts +1 -0
- package/build/cjs/shared/modules/index.js +1 -0
- package/build/cjs/shared/modules/uniq-id.d.ts +12 -0
- package/build/cjs/shared/modules/uniq-id.js +36 -0
- package/build/cjs/typings/config.d.ts +3 -0
- package/build/cjs/utils/get-new-id.d.ts +12 -0
- package/build/cjs/utils/get-new-id.js +9 -0
- package/build/cjs/utils/update-manager.d.ts +5 -3
- package/build/cjs/utils/update-manager.js +35 -14
- package/build/esm/components/DashKit/DashKit.d.ts +3 -2
- package/build/esm/components/DashKit/DashKit.js +3 -2
- package/build/esm/shared/modules/__tests__/uniq-id.test.d.ts +1 -0
- package/build/esm/shared/modules/__tests__/uniq-id.test.js +74 -0
- package/build/esm/shared/modules/index.d.ts +1 -0
- package/build/esm/shared/modules/index.js +1 -0
- package/build/esm/shared/modules/uniq-id.d.ts +12 -0
- package/build/esm/shared/modules/uniq-id.js +30 -0
- package/build/esm/typings/config.d.ts +3 -0
- package/build/esm/utils/get-new-id.d.ts +12 -0
- package/build/esm/utils/get-new-id.js +5 -0
- package/build/esm/utils/update-manager.d.ts +5 -3
- package/build/esm/utils/update-manager.js +35 -14
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
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
|
+
|
|
3
10
|
## [5.0.0](https://github.com/gravity-ui/dashkit/compare/v4.1.0...v5.0.0) (2023-02-01)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -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 {
|
|
@@ -29,10 +29,11 @@ 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
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -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
|
+
});
|
|
@@ -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;
|
|
@@ -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;
|
|
@@ -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
|
-
|
|
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
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
|
158
|
-
|
|
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
|
|
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 {
|
|
@@ -29,10 +29,11 @@ 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
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -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
|
+
});
|
|
@@ -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
|
+
}
|
|
@@ -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 {};
|
|
@@ -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
|
-
|
|
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
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
|
154
|
-
|
|
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
|
|
177
|
+
items: { [itemIndex]: { $set: Object.assign(Object.assign({}, item), { data, namespace }) } },
|
|
157
178
|
counter: { $set: counter },
|
|
158
179
|
});
|
|
159
180
|
}
|