@gravity-ui/dashkit 6.6.0-beta.0 → 6.6.1-beta-v.shangin.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/README.md +0 -15
- package/build/cjs/components/GridLayout/GridLayout.d.ts +0 -4
- package/build/cjs/components/GridLayout/GridLayout.js +12 -35
- package/build/cjs/components/OverlayControls/OverlayControls.d.ts +9 -0
- package/build/cjs/components/OverlayControls/OverlayControls.js +5 -1
- package/build/cjs/components/index.d.ts +1 -1
- package/build/cjs/hocs/withContext.js +1 -2
- package/build/cjs/shared/modules/helpers.d.ts +0 -9
- package/build/cjs/shared/modules/helpers.js +1 -22
- package/build/cjs/shared/modules/state-and-params.js +3 -21
- package/build/cjs/shared/units/__tests__/state-and-params.test.js +71 -0
- package/build/cjs/typings/common.d.ts +1 -3
- package/build/esm/components/GridLayout/GridLayout.d.ts +0 -4
- package/build/esm/components/GridLayout/GridLayout.js +12 -35
- package/build/esm/components/OverlayControls/OverlayControls.d.ts +9 -0
- package/build/esm/components/OverlayControls/OverlayControls.js +5 -1
- package/build/esm/components/index.d.ts +1 -1
- package/build/esm/hocs/withContext.js +1 -2
- package/build/esm/shared/modules/helpers.d.ts +0 -9
- package/build/esm/shared/modules/helpers.js +0 -20
- package/build/esm/shared/modules/state-and-params.js +4 -22
- package/build/esm/shared/units/__tests__/state-and-params.test.js +71 -0
- package/build/esm/typings/common.d.ts +1 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -120,21 +120,6 @@ Before using `DashKit` as a react component, it must be configured.
|
|
|
120
120
|
});
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
## Settings
|
|
124
|
-
|
|
125
|
-
### Autoupdate
|
|
126
|
-
|
|
127
|
-
This functionality allows you to automatically update the items of the Dash. All items that should participate in the auto-update cycle must have the `reload` method.
|
|
128
|
-
There are two auto-update scenarios available, the first - the classic interval to enable which is enough to pass the `autoupdateInterval` parameter and the second - the so-called `realtimeMode`.
|
|
129
|
-
`realtimeMode` is useful in cases where dash items are updated at different rates and you cannot guarantee data consistency at a given time. `realtimeMode` is based on `Promise.allSettled`.
|
|
130
|
-
|
|
131
|
-
| Name | Description | Type | Default |
|
|
132
|
-
|:--------------------|:---------------------------------------------------------------------------------------|:---------:|:-------:|
|
|
133
|
-
| autoupdateInterval | The time, in **seconds**, the dash should delay in between executions auto-update | `number` | |
|
|
134
|
-
| realtimeMode | Enable realtime mode | `boolean` | |
|
|
135
|
-
| realtimeModeDelayMs | The time, in **milliseconds**, the dash should delay after all items have been updated | `number` | 5000 |
|
|
136
|
-
| silentLoading | Items update status indicator. It will be passed into the Item `reload` method | `boolean` | false |
|
|
137
|
-
|
|
138
123
|
### Config
|
|
139
124
|
|
|
140
125
|
```ts
|
|
@@ -18,10 +18,6 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
|
|
|
18
18
|
adjustedWidgetLayout: any;
|
|
19
19
|
}) => void;
|
|
20
20
|
getItemsMeta: () => any;
|
|
21
|
-
getAutoupdateIntervalMs(): number;
|
|
22
|
-
startReloadItems(): any;
|
|
23
|
-
startReloadItemsTimeout(timeoutMs: any): void;
|
|
24
|
-
forceReloadItems(): void;
|
|
25
21
|
reloadItems(): void;
|
|
26
22
|
_onStart: () => void;
|
|
27
23
|
_onStop: (newLayout: any) => void;
|
|
@@ -50,48 +50,25 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
50
50
|
document.addEventListener('visibilitychange', this.onVisibilityChange);
|
|
51
51
|
}
|
|
52
52
|
componentDidUpdate() {
|
|
53
|
-
this.
|
|
53
|
+
clearTimeout(this._timeout);
|
|
54
|
+
this.reloadItems();
|
|
54
55
|
}
|
|
55
56
|
componentWillUnmount() {
|
|
56
57
|
clearTimeout(this._timeout);
|
|
57
58
|
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
58
59
|
}
|
|
59
|
-
getAutoupdateIntervalMs() {
|
|
60
|
-
const { settings: { autoupdateInterval } = {} } = this.context;
|
|
61
|
-
const autoupdateIntervalMs = Number(autoupdateInterval) * 1000;
|
|
62
|
-
return autoupdateIntervalMs;
|
|
63
|
-
}
|
|
64
|
-
startReloadItems() {
|
|
65
|
-
const { editMode, settings: { silentLoading } = {}, reloadItems } = this.context;
|
|
66
|
-
const { isPageHidden } = this.state;
|
|
67
|
-
if (!isPageHidden && !editMode) {
|
|
68
|
-
this._lastReloadAt = new Date().getTime();
|
|
69
|
-
return reloadItems(this.pluginsRefs, { silentLoading, noVeil: true });
|
|
70
|
-
}
|
|
71
|
-
return Promise.resolve();
|
|
72
|
-
}
|
|
73
|
-
startReloadItemsTimeout(timeoutMs) {
|
|
74
|
-
this._timeout = setTimeout(() => this.forceReloadItems(), timeoutMs);
|
|
75
|
-
}
|
|
76
|
-
forceReloadItems() {
|
|
77
|
-
clearTimeout(this._timeout);
|
|
78
|
-
this._timeout = undefined;
|
|
79
|
-
this.reloadItems();
|
|
80
|
-
}
|
|
81
60
|
reloadItems() {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
if (realtimeMode) {
|
|
86
|
-
this.startReloadItems().then(() => {
|
|
87
|
-
this.startReloadItemsTimeout(realtimeModeDelayMs);
|
|
88
|
-
});
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
const autoupdateIntervalMs = this.getAutoupdateIntervalMs();
|
|
61
|
+
const { editMode, settings: { autoupdateInterval, silentLoading } = {}, reloadItems, } = this.context;
|
|
62
|
+
const { isPageHidden } = this.state;
|
|
63
|
+
const autoupdateIntervalMs = Number(autoupdateInterval) * 1000;
|
|
92
64
|
if (autoupdateIntervalMs) {
|
|
93
|
-
|
|
94
|
-
|
|
65
|
+
const timeSinceLastReload = new Date().getTime() - (this._lastReloadAt || 0);
|
|
66
|
+
const reloadIntervalRemains = autoupdateIntervalMs - timeSinceLastReload;
|
|
67
|
+
if (!isPageHidden && !editMode && reloadIntervalRemains <= 0) {
|
|
68
|
+
this._lastReloadAt = new Date().getTime();
|
|
69
|
+
reloadItems(this.pluginsRefs, { silentLoading, noVeil: true });
|
|
70
|
+
}
|
|
71
|
+
this._timeout = setTimeout(() => this.reloadItems(), reloadIntervalRemains <= 0 ? autoupdateIntervalMs : reloadIntervalRemains);
|
|
95
72
|
}
|
|
96
73
|
}
|
|
97
74
|
render() {
|
|
@@ -38,7 +38,16 @@ interface OverlayControlsProps extends OverlayControlsDefaultProps {
|
|
|
38
38
|
items?: OverlayControlItem[];
|
|
39
39
|
overlayControls?: Record<string, OverlayControlItem[]>;
|
|
40
40
|
}
|
|
41
|
+
type PreparedCopyItemOptionsArg = Pick<ConfigItem, 'data' | 'type' | 'defaults' | 'namespace'> & {
|
|
42
|
+
timestamp: number;
|
|
43
|
+
layout: {
|
|
44
|
+
w: number;
|
|
45
|
+
h: number;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export type PreparedCopyItemOptions = PreparedCopyItemOptionsArg;
|
|
41
49
|
type DashKitCtx = React.Context<{
|
|
50
|
+
context: Record<string, any>;
|
|
42
51
|
registerManager: RegisterManager;
|
|
43
52
|
itemsParams: Record<string, StringParams>;
|
|
44
53
|
itemsState: Record<string, ItemState>;
|
|
@@ -56,10 +56,11 @@ class OverlayControls extends react_1.default.Component {
|
|
|
56
56
|
return controls;
|
|
57
57
|
};
|
|
58
58
|
this.onCopyItem = () => {
|
|
59
|
+
var _a;
|
|
59
60
|
const correspondedItemLayout = this.context.config.layout.find((item) => {
|
|
60
61
|
return item.i === this.props.configItem.id;
|
|
61
62
|
});
|
|
62
|
-
|
|
63
|
+
let options = {
|
|
63
64
|
timestamp: Date.now(),
|
|
64
65
|
data: this.props.configItem.data,
|
|
65
66
|
type: this.props.configItem.type,
|
|
@@ -70,6 +71,9 @@ class OverlayControls extends react_1.default.Component {
|
|
|
70
71
|
h: correspondedItemLayout.h,
|
|
71
72
|
},
|
|
72
73
|
};
|
|
74
|
+
if (typeof ((_a = this.context.context) === null || _a === void 0 ? void 0 : _a.getPreparedCopyItemOptions) === 'function') {
|
|
75
|
+
options = this.context.context.getPreparedCopyItemOptions(options);
|
|
76
|
+
}
|
|
73
77
|
localStorage.setItem(constants_1.COPIED_WIDGET_STORE_KEY, JSON.stringify(options));
|
|
74
78
|
// https://stackoverflow.com/questions/35865481/storage-event-not-firing
|
|
75
79
|
window.dispatchEvent(new Event('storage'));
|
|
@@ -121,8 +121,7 @@ function useMemoStateContext(props) {
|
|
|
121
121
|
});
|
|
122
122
|
}, [props.layout, layoutUpdateCounter]);
|
|
123
123
|
const reloadItems = react_1.default.useCallback((pluginsRefs, data) => {
|
|
124
|
-
|
|
125
|
-
return Promise.allSettled(promises);
|
|
124
|
+
pluginsRefs.forEach((ref) => ref && ref.reload && ref.reload(data));
|
|
126
125
|
}, []);
|
|
127
126
|
return react_1.default.useMemo(() => ({
|
|
128
127
|
layout: resultLayout,
|
|
@@ -69,13 +69,4 @@ export declare function hasActionParam(conf?: StringParams): boolean;
|
|
|
69
69
|
* @param stateAndParams
|
|
70
70
|
*/
|
|
71
71
|
export declare function hasActionParams(stateAndParams: ItemStateAndParams): boolean;
|
|
72
|
-
/**
|
|
73
|
-
* Collect array of actionParams keys with prefix (_ap_) that must be cleared from widget defaults
|
|
74
|
-
* @param defaultWidgetParams
|
|
75
|
-
* @param queueWidgetParams
|
|
76
|
-
*/
|
|
77
|
-
export declare function getDefaultsActionParamsToClear({ defaultWidgetParams, queueWidgetParams, }: {
|
|
78
|
-
defaultWidgetParams: StringParams;
|
|
79
|
-
queueWidgetParams: StringParams;
|
|
80
|
-
}): string[];
|
|
81
72
|
export {};
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.hasActionParams = exports.hasActionParam = exports.transformParamsToActionParams = exports.pickExceptActionParamsFromParams = exports.pickActionParamsFromParams = exports.deleteFromQueue = exports.addToQueue = exports.getInitialItemsStateAndParamsMeta = exports.mergeParamsWithAliases = exports.getMapItemsIgnores = exports.resolveItemInnerId = exports.formQueueData = exports.isItemWithTabs = exports.getCurrentVersion = exports.getItemsStateAndParamsMeta = exports.prerenderItems = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const keyBy_1 = tslib_1.__importDefault(require("lodash/keyBy"));
|
|
6
6
|
const get_1 = tslib_1.__importDefault(require("lodash/get"));
|
|
7
7
|
const invert_1 = tslib_1.__importDefault(require("lodash/invert"));
|
|
8
8
|
const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
|
|
9
9
|
const pick_1 = tslib_1.__importDefault(require("lodash/pick"));
|
|
10
|
-
const intersection_1 = tslib_1.__importDefault(require("lodash/intersection"));
|
|
11
10
|
const constants_1 = require("../constants");
|
|
12
11
|
function getNormalizedPlugins(plugins) {
|
|
13
12
|
return (0, keyBy_1.default)(plugins, 'type');
|
|
@@ -260,23 +259,3 @@ function hasActionParams(stateAndParams) {
|
|
|
260
259
|
return hasActionParam(stateAndParams.params);
|
|
261
260
|
}
|
|
262
261
|
exports.hasActionParams = hasActionParams;
|
|
263
|
-
/**
|
|
264
|
-
* Collect array of actionParams keys with prefix (_ap_) that must be cleared from widget defaults
|
|
265
|
-
* @param defaultWidgetParams
|
|
266
|
-
* @param queueWidgetParams
|
|
267
|
-
*/
|
|
268
|
-
function getDefaultsActionParamsToClear({ defaultWidgetParams, queueWidgetParams, }) {
|
|
269
|
-
const widgetDefaultsWithActionParams = hasActionParam(defaultWidgetParams)
|
|
270
|
-
? pickActionParamsFromParams(defaultWidgetParams)
|
|
271
|
-
: null;
|
|
272
|
-
if (!widgetDefaultsWithActionParams) {
|
|
273
|
-
return [];
|
|
274
|
-
}
|
|
275
|
-
// clear default actionParams if some param with the same name without prefix affected on current widget
|
|
276
|
-
// ex.: queueWidgetParams contain {Year: 1970} and default actionParams contain {_ap_Year: 2000}
|
|
277
|
-
const actionParamKeyToClear = (0, intersection_1.default)(Object.keys(queueWidgetParams), Object.keys(widgetDefaultsWithActionParams));
|
|
278
|
-
return actionParamKeyToClear.length
|
|
279
|
-
? actionParamKeyToClear.map((key) => `${constants_1.ACTION_PARAM_PREFIX}${key}`)
|
|
280
|
-
: [];
|
|
281
|
-
}
|
|
282
|
-
exports.getDefaultsActionParamsToClear = getDefaultsActionParamsToClear;
|
|
@@ -3,8 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getItemsStateAndParams = exports.getItemsState = exports.getItemsParams = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const groupBy_1 = tslib_1.__importDefault(require("lodash/groupBy"));
|
|
6
|
-
const intersection_1 = tslib_1.__importDefault(require("lodash/intersection"));
|
|
7
|
-
const omit_1 = tslib_1.__importDefault(require("lodash/omit"));
|
|
8
6
|
const constants_1 = require("../constants");
|
|
9
7
|
const helpers_1 = require("./helpers");
|
|
10
8
|
function getItemsParams({ defaultGlobalParams = {}, globalParams = {}, config, itemsStateAndParams, plugins, }) {
|
|
@@ -54,8 +52,7 @@ function getItemsParams({ defaultGlobalParams = {}, globalParams = {}, config, i
|
|
|
54
52
|
}
|
|
55
53
|
else {
|
|
56
54
|
// params according to queue of its applying
|
|
57
|
-
let
|
|
58
|
-
let queueDataItems = {};
|
|
55
|
+
let queueDataItemsParams = {};
|
|
59
56
|
for (const data of Object.values(queueData)) {
|
|
60
57
|
if (data.namespace !== namespace || itemIgnores.includes(data.id)) {
|
|
61
58
|
continue;
|
|
@@ -68,24 +65,9 @@ function getItemsParams({ defaultGlobalParams = {}, globalParams = {}, config, i
|
|
|
68
65
|
params = (0, helpers_1.pickExceptActionParamsFromParams)(data.params);
|
|
69
66
|
}
|
|
70
67
|
const mergedParams = getMergedParams(params, actionParams);
|
|
71
|
-
|
|
72
|
-
let queueDataRes = Object.assign({}, queueDataItems);
|
|
73
|
-
if (actionParamKeyToClear.length) {
|
|
74
|
-
queueDataRes = (0, omit_1.default)(queueDataItems, actionParamKeyToClear);
|
|
75
|
-
}
|
|
76
|
-
queueDataItems = Object.assign(Object.assign({}, queueDataRes), mergedParams);
|
|
77
|
-
prevQueueDataWithActionParams = (0, helpers_1.hasActionParam)(queueDataItems)
|
|
78
|
-
? (0, helpers_1.pickActionParamsFromParams)(data.params, true)
|
|
79
|
-
: {};
|
|
80
|
-
}
|
|
81
|
-
const clearActionParams = (0, helpers_1.getDefaultsActionParamsToClear)({
|
|
82
|
-
defaultWidgetParams,
|
|
83
|
-
queueWidgetParams: queueDataItems,
|
|
84
|
-
});
|
|
85
|
-
if (clearActionParams.length) {
|
|
86
|
-
defaultWidgetParams = (0, omit_1.default)(defaultWidgetParams, clearActionParams);
|
|
68
|
+
queueDataItemsParams = Object.assign(Object.assign({}, queueDataItemsParams), mergedParams);
|
|
87
69
|
}
|
|
88
|
-
itemParams = Object.assign(itemParams,
|
|
70
|
+
itemParams = Object.assign(itemParams, queueDataItemsParams);
|
|
89
71
|
}
|
|
90
72
|
return Object.assign(Object.assign({}, itemsParams), { [id]: Object.assign(Object.assign({}, defaultWidgetParams), itemParams) });
|
|
91
73
|
}, {});
|
|
@@ -306,6 +306,7 @@ const stateAndParamsForAP2 = {
|
|
|
306
306
|
Country: 'Belgium',
|
|
307
307
|
Year: '',
|
|
308
308
|
'd079937f-6bc4-4133-9171-40092bb20d6f': 'Belgium',
|
|
309
|
+
_ap_Country: 'Italy',
|
|
309
310
|
},
|
|
310
311
|
state: {},
|
|
311
312
|
},
|
|
@@ -334,6 +335,7 @@ const stateAndParamsForAP3 = {
|
|
|
334
335
|
Country: '',
|
|
335
336
|
Year: '',
|
|
336
337
|
'd079937f-6bc4-4133-9171-40092bb20d6f': '',
|
|
338
|
+
_ap_Country: 'Italy',
|
|
337
339
|
},
|
|
338
340
|
state: {},
|
|
339
341
|
},
|
|
@@ -410,6 +412,64 @@ const stateAndParamsForAP5 = {
|
|
|
410
412
|
},
|
|
411
413
|
},
|
|
412
414
|
};
|
|
415
|
+
const stateAndParamsForAP6 = {
|
|
416
|
+
in: {
|
|
417
|
+
Q8: {
|
|
418
|
+
params: {
|
|
419
|
+
_ap_Year: '2021',
|
|
420
|
+
_ap_Country: 'Russia',
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
L5: {
|
|
424
|
+
params: {
|
|
425
|
+
_ap_Country: 'Russia',
|
|
426
|
+
_ap_Name: 'Alex',
|
|
427
|
+
_ap_Price: '1000',
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
__meta__: {
|
|
431
|
+
queue: [
|
|
432
|
+
{ id: 'Q8', tabId: 'K0' },
|
|
433
|
+
{ id: 'L5', tabId: 'K1' },
|
|
434
|
+
],
|
|
435
|
+
version: 2,
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
out: {
|
|
439
|
+
L5: {
|
|
440
|
+
params: {
|
|
441
|
+
Name: '',
|
|
442
|
+
Price: '',
|
|
443
|
+
Year: '2021',
|
|
444
|
+
Country: 'Russia',
|
|
445
|
+
_ap_Country: 'Russia',
|
|
446
|
+
_ap_Name: 'Alex',
|
|
447
|
+
_ap_Price: '1000',
|
|
448
|
+
},
|
|
449
|
+
state: {},
|
|
450
|
+
},
|
|
451
|
+
Q8: {
|
|
452
|
+
params: {
|
|
453
|
+
Year: '',
|
|
454
|
+
Country: 'Russia',
|
|
455
|
+
Name: 'Alex',
|
|
456
|
+
Price: '1000',
|
|
457
|
+
_ap_Year: '2021',
|
|
458
|
+
_ap_Country: 'Russia',
|
|
459
|
+
},
|
|
460
|
+
state: {},
|
|
461
|
+
},
|
|
462
|
+
al: {
|
|
463
|
+
params: {
|
|
464
|
+
Country: 'Russia',
|
|
465
|
+
Name: 'Alex',
|
|
466
|
+
Price: '1000',
|
|
467
|
+
Year: '2021',
|
|
468
|
+
},
|
|
469
|
+
state: {},
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
};
|
|
413
473
|
const configs = configs_json_1.default.configs;
|
|
414
474
|
describe('getItemsStateAndParamsDL', () => {
|
|
415
475
|
describe('old version fallback', () => {
|
|
@@ -502,4 +562,15 @@ describe('getItemsStateAndParams actionParams variants check', () => {
|
|
|
502
562
|
expect(resultItemsStateAndParams).toEqual((0, omit_1.default)(stateAndParamsForAP5.out, constants_1.META_KEY));
|
|
503
563
|
});
|
|
504
564
|
});
|
|
565
|
+
describe('action and params state 6', () => {
|
|
566
|
+
const resultItemsStateAndParams = (0, datalens_1.getItemsStateAndParamsDL)({
|
|
567
|
+
defaultGlobalParams: {},
|
|
568
|
+
globalParams: {},
|
|
569
|
+
config: configs[4],
|
|
570
|
+
itemsStateAndParams: stateAndParamsForAP6.in,
|
|
571
|
+
});
|
|
572
|
+
it('return stateAndParamsForAP6.out', () => {
|
|
573
|
+
expect(resultItemsStateAndParams).toEqual((0, omit_1.default)(stateAndParamsForAP6.out, constants_1.META_KEY));
|
|
574
|
+
});
|
|
575
|
+
});
|
|
505
576
|
});
|
|
@@ -9,10 +9,8 @@ export interface Settings {
|
|
|
9
9
|
}
|
|
10
10
|
export type MenuItem = (typeof MenuItems)[keyof typeof MenuItems] | OverlayCustomControlItem;
|
|
11
11
|
export interface SettingsProps {
|
|
12
|
-
autoupdateInterval
|
|
12
|
+
autoupdateInterval: number;
|
|
13
13
|
silentLoading: boolean;
|
|
14
|
-
realtimeMode?: boolean;
|
|
15
|
-
realtimeModeDelayMs?: number;
|
|
16
14
|
}
|
|
17
15
|
export interface ContextProps {
|
|
18
16
|
[key: string]: any;
|
|
@@ -18,10 +18,6 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
|
|
|
18
18
|
adjustedWidgetLayout: any;
|
|
19
19
|
}) => void;
|
|
20
20
|
getItemsMeta: () => any;
|
|
21
|
-
getAutoupdateIntervalMs(): number;
|
|
22
|
-
startReloadItems(): any;
|
|
23
|
-
startReloadItemsTimeout(timeoutMs: any): void;
|
|
24
|
-
forceReloadItems(): void;
|
|
25
21
|
reloadItems(): void;
|
|
26
22
|
_onStart: () => void;
|
|
27
23
|
_onStop: (newLayout: any) => void;
|
|
@@ -47,48 +47,25 @@ export default class GridLayout extends React.PureComponent {
|
|
|
47
47
|
document.addEventListener('visibilitychange', this.onVisibilityChange);
|
|
48
48
|
}
|
|
49
49
|
componentDidUpdate() {
|
|
50
|
-
this.
|
|
50
|
+
clearTimeout(this._timeout);
|
|
51
|
+
this.reloadItems();
|
|
51
52
|
}
|
|
52
53
|
componentWillUnmount() {
|
|
53
54
|
clearTimeout(this._timeout);
|
|
54
55
|
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
55
56
|
}
|
|
56
|
-
getAutoupdateIntervalMs() {
|
|
57
|
-
const { settings: { autoupdateInterval } = {} } = this.context;
|
|
58
|
-
const autoupdateIntervalMs = Number(autoupdateInterval) * 1000;
|
|
59
|
-
return autoupdateIntervalMs;
|
|
60
|
-
}
|
|
61
|
-
startReloadItems() {
|
|
62
|
-
const { editMode, settings: { silentLoading } = {}, reloadItems } = this.context;
|
|
63
|
-
const { isPageHidden } = this.state;
|
|
64
|
-
if (!isPageHidden && !editMode) {
|
|
65
|
-
this._lastReloadAt = new Date().getTime();
|
|
66
|
-
return reloadItems(this.pluginsRefs, { silentLoading, noVeil: true });
|
|
67
|
-
}
|
|
68
|
-
return Promise.resolve();
|
|
69
|
-
}
|
|
70
|
-
startReloadItemsTimeout(timeoutMs) {
|
|
71
|
-
this._timeout = setTimeout(() => this.forceReloadItems(), timeoutMs);
|
|
72
|
-
}
|
|
73
|
-
forceReloadItems() {
|
|
74
|
-
clearTimeout(this._timeout);
|
|
75
|
-
this._timeout = undefined;
|
|
76
|
-
this.reloadItems();
|
|
77
|
-
}
|
|
78
57
|
reloadItems() {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
if (realtimeMode) {
|
|
83
|
-
this.startReloadItems().then(() => {
|
|
84
|
-
this.startReloadItemsTimeout(realtimeModeDelayMs);
|
|
85
|
-
});
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
const autoupdateIntervalMs = this.getAutoupdateIntervalMs();
|
|
58
|
+
const { editMode, settings: { autoupdateInterval, silentLoading } = {}, reloadItems, } = this.context;
|
|
59
|
+
const { isPageHidden } = this.state;
|
|
60
|
+
const autoupdateIntervalMs = Number(autoupdateInterval) * 1000;
|
|
89
61
|
if (autoupdateIntervalMs) {
|
|
90
|
-
|
|
91
|
-
|
|
62
|
+
const timeSinceLastReload = new Date().getTime() - (this._lastReloadAt || 0);
|
|
63
|
+
const reloadIntervalRemains = autoupdateIntervalMs - timeSinceLastReload;
|
|
64
|
+
if (!isPageHidden && !editMode && reloadIntervalRemains <= 0) {
|
|
65
|
+
this._lastReloadAt = new Date().getTime();
|
|
66
|
+
reloadItems(this.pluginsRefs, { silentLoading, noVeil: true });
|
|
67
|
+
}
|
|
68
|
+
this._timeout = setTimeout(() => this.reloadItems(), reloadIntervalRemains <= 0 ? autoupdateIntervalMs : reloadIntervalRemains);
|
|
92
69
|
}
|
|
93
70
|
}
|
|
94
71
|
render() {
|
|
@@ -39,7 +39,16 @@ interface OverlayControlsProps extends OverlayControlsDefaultProps {
|
|
|
39
39
|
items?: OverlayControlItem[];
|
|
40
40
|
overlayControls?: Record<string, OverlayControlItem[]>;
|
|
41
41
|
}
|
|
42
|
+
type PreparedCopyItemOptionsArg = Pick<ConfigItem, 'data' | 'type' | 'defaults' | 'namespace'> & {
|
|
43
|
+
timestamp: number;
|
|
44
|
+
layout: {
|
|
45
|
+
w: number;
|
|
46
|
+
h: number;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
export type PreparedCopyItemOptions = PreparedCopyItemOptionsArg;
|
|
42
50
|
type DashKitCtx = React.Context<{
|
|
51
|
+
context: Record<string, any>;
|
|
43
52
|
registerManager: RegisterManager;
|
|
44
53
|
itemsParams: Record<string, StringParams>;
|
|
45
54
|
itemsState: Record<string, ItemState>;
|
|
@@ -53,10 +53,11 @@ class OverlayControls extends React.Component {
|
|
|
53
53
|
return controls;
|
|
54
54
|
};
|
|
55
55
|
this.onCopyItem = () => {
|
|
56
|
+
var _a;
|
|
56
57
|
const correspondedItemLayout = this.context.config.layout.find((item) => {
|
|
57
58
|
return item.i === this.props.configItem.id;
|
|
58
59
|
});
|
|
59
|
-
|
|
60
|
+
let options = {
|
|
60
61
|
timestamp: Date.now(),
|
|
61
62
|
data: this.props.configItem.data,
|
|
62
63
|
type: this.props.configItem.type,
|
|
@@ -67,6 +68,9 @@ class OverlayControls extends React.Component {
|
|
|
67
68
|
h: correspondedItemLayout.h,
|
|
68
69
|
},
|
|
69
70
|
};
|
|
71
|
+
if (typeof ((_a = this.context.context) === null || _a === void 0 ? void 0 : _a.getPreparedCopyItemOptions) === 'function') {
|
|
72
|
+
options = this.context.context.getPreparedCopyItemOptions(options);
|
|
73
|
+
}
|
|
70
74
|
localStorage.setItem(COPIED_WIDGET_STORE_KEY, JSON.stringify(options));
|
|
71
75
|
// https://stackoverflow.com/questions/35865481/storage-event-not-firing
|
|
72
76
|
window.dispatchEvent(new Event('storage'));
|
|
@@ -117,8 +117,7 @@ function useMemoStateContext(props) {
|
|
|
117
117
|
});
|
|
118
118
|
}, [props.layout, layoutUpdateCounter]);
|
|
119
119
|
const reloadItems = React.useCallback((pluginsRefs, data) => {
|
|
120
|
-
|
|
121
|
-
return Promise.allSettled(promises);
|
|
120
|
+
pluginsRefs.forEach((ref) => ref && ref.reload && ref.reload(data));
|
|
122
121
|
}, []);
|
|
123
122
|
return React.useMemo(() => ({
|
|
124
123
|
layout: resultLayout,
|
|
@@ -69,13 +69,4 @@ export declare function hasActionParam(conf?: StringParams): boolean;
|
|
|
69
69
|
* @param stateAndParams
|
|
70
70
|
*/
|
|
71
71
|
export declare function hasActionParams(stateAndParams: ItemStateAndParams): boolean;
|
|
72
|
-
/**
|
|
73
|
-
* Collect array of actionParams keys with prefix (_ap_) that must be cleared from widget defaults
|
|
74
|
-
* @param defaultWidgetParams
|
|
75
|
-
* @param queueWidgetParams
|
|
76
|
-
*/
|
|
77
|
-
export declare function getDefaultsActionParamsToClear({ defaultWidgetParams, queueWidgetParams, }: {
|
|
78
|
-
defaultWidgetParams: StringParams;
|
|
79
|
-
queueWidgetParams: StringParams;
|
|
80
|
-
}): string[];
|
|
81
72
|
export {};
|
|
@@ -3,7 +3,6 @@ import get from 'lodash/get';
|
|
|
3
3
|
import invert from 'lodash/invert';
|
|
4
4
|
import isEmpty from 'lodash/isEmpty';
|
|
5
5
|
import pick from 'lodash/pick';
|
|
6
|
-
import intersection from 'lodash/intersection';
|
|
7
6
|
import { META_KEY, CURRENT_VERSION, ACTION_PARAM_PREFIX } from '../constants';
|
|
8
7
|
function getNormalizedPlugins(plugins) {
|
|
9
8
|
return keyBy(plugins, 'type');
|
|
@@ -240,22 +239,3 @@ export function hasActionParams(stateAndParams) {
|
|
|
240
239
|
}
|
|
241
240
|
return hasActionParam(stateAndParams.params);
|
|
242
241
|
}
|
|
243
|
-
/**
|
|
244
|
-
* Collect array of actionParams keys with prefix (_ap_) that must be cleared from widget defaults
|
|
245
|
-
* @param defaultWidgetParams
|
|
246
|
-
* @param queueWidgetParams
|
|
247
|
-
*/
|
|
248
|
-
export function getDefaultsActionParamsToClear({ defaultWidgetParams, queueWidgetParams, }) {
|
|
249
|
-
const widgetDefaultsWithActionParams = hasActionParam(defaultWidgetParams)
|
|
250
|
-
? pickActionParamsFromParams(defaultWidgetParams)
|
|
251
|
-
: null;
|
|
252
|
-
if (!widgetDefaultsWithActionParams) {
|
|
253
|
-
return [];
|
|
254
|
-
}
|
|
255
|
-
// clear default actionParams if some param with the same name without prefix affected on current widget
|
|
256
|
-
// ex.: queueWidgetParams contain {Year: 1970} and default actionParams contain {_ap_Year: 2000}
|
|
257
|
-
const actionParamKeyToClear = intersection(Object.keys(queueWidgetParams), Object.keys(widgetDefaultsWithActionParams));
|
|
258
|
-
return actionParamKeyToClear.length
|
|
259
|
-
? actionParamKeyToClear.map((key) => `${ACTION_PARAM_PREFIX}${key}`)
|
|
260
|
-
: [];
|
|
261
|
-
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import groupBy from 'lodash/groupBy';
|
|
2
|
-
import intersection from 'lodash/intersection';
|
|
3
|
-
import omit from 'lodash/omit';
|
|
4
2
|
import { META_KEY } from '../constants';
|
|
5
|
-
import { prerenderItems, formQueueData, getMapItemsIgnores, mergeParamsWithAliases, getCurrentVersion, pickActionParamsFromParams, hasActionParam, pickExceptActionParamsFromParams,
|
|
3
|
+
import { prerenderItems, formQueueData, getMapItemsIgnores, mergeParamsWithAliases, getCurrentVersion, pickActionParamsFromParams, hasActionParam, pickExceptActionParamsFromParams, isItemWithTabs, resolveItemInnerId, } from './helpers';
|
|
6
4
|
export function getItemsParams({ defaultGlobalParams = {}, globalParams = {}, config, itemsStateAndParams, plugins, }) {
|
|
7
5
|
const { aliases, connections } = config;
|
|
8
6
|
const items = prerenderItems({ items: config.items, plugins });
|
|
@@ -50,8 +48,7 @@ export function getItemsParams({ defaultGlobalParams = {}, globalParams = {}, co
|
|
|
50
48
|
}
|
|
51
49
|
else {
|
|
52
50
|
// params according to queue of its applying
|
|
53
|
-
let
|
|
54
|
-
let queueDataItems = {};
|
|
51
|
+
let queueDataItemsParams = {};
|
|
55
52
|
for (const data of Object.values(queueData)) {
|
|
56
53
|
if (data.namespace !== namespace || itemIgnores.includes(data.id)) {
|
|
57
54
|
continue;
|
|
@@ -64,24 +61,9 @@ export function getItemsParams({ defaultGlobalParams = {}, globalParams = {}, co
|
|
|
64
61
|
params = pickExceptActionParamsFromParams(data.params);
|
|
65
62
|
}
|
|
66
63
|
const mergedParams = getMergedParams(params, actionParams);
|
|
67
|
-
|
|
68
|
-
let queueDataRes = Object.assign({}, queueDataItems);
|
|
69
|
-
if (actionParamKeyToClear.length) {
|
|
70
|
-
queueDataRes = omit(queueDataItems, actionParamKeyToClear);
|
|
71
|
-
}
|
|
72
|
-
queueDataItems = Object.assign(Object.assign({}, queueDataRes), mergedParams);
|
|
73
|
-
prevQueueDataWithActionParams = hasActionParam(queueDataItems)
|
|
74
|
-
? pickActionParamsFromParams(data.params, true)
|
|
75
|
-
: {};
|
|
76
|
-
}
|
|
77
|
-
const clearActionParams = getDefaultsActionParamsToClear({
|
|
78
|
-
defaultWidgetParams,
|
|
79
|
-
queueWidgetParams: queueDataItems,
|
|
80
|
-
});
|
|
81
|
-
if (clearActionParams.length) {
|
|
82
|
-
defaultWidgetParams = omit(defaultWidgetParams, clearActionParams);
|
|
64
|
+
queueDataItemsParams = Object.assign(Object.assign({}, queueDataItemsParams), mergedParams);
|
|
83
65
|
}
|
|
84
|
-
itemParams = Object.assign(itemParams,
|
|
66
|
+
itemParams = Object.assign(itemParams, queueDataItemsParams);
|
|
85
67
|
}
|
|
86
68
|
return Object.assign(Object.assign({}, itemsParams), { [id]: Object.assign(Object.assign({}, defaultWidgetParams), itemParams) });
|
|
87
69
|
}, {});
|
|
@@ -302,6 +302,7 @@ const stateAndParamsForAP2 = {
|
|
|
302
302
|
Country: 'Belgium',
|
|
303
303
|
Year: '',
|
|
304
304
|
'd079937f-6bc4-4133-9171-40092bb20d6f': 'Belgium',
|
|
305
|
+
_ap_Country: 'Italy',
|
|
305
306
|
},
|
|
306
307
|
state: {},
|
|
307
308
|
},
|
|
@@ -330,6 +331,7 @@ const stateAndParamsForAP3 = {
|
|
|
330
331
|
Country: '',
|
|
331
332
|
Year: '',
|
|
332
333
|
'd079937f-6bc4-4133-9171-40092bb20d6f': '',
|
|
334
|
+
_ap_Country: 'Italy',
|
|
333
335
|
},
|
|
334
336
|
state: {},
|
|
335
337
|
},
|
|
@@ -406,6 +408,64 @@ const stateAndParamsForAP5 = {
|
|
|
406
408
|
},
|
|
407
409
|
},
|
|
408
410
|
};
|
|
411
|
+
const stateAndParamsForAP6 = {
|
|
412
|
+
in: {
|
|
413
|
+
Q8: {
|
|
414
|
+
params: {
|
|
415
|
+
_ap_Year: '2021',
|
|
416
|
+
_ap_Country: 'Russia',
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
L5: {
|
|
420
|
+
params: {
|
|
421
|
+
_ap_Country: 'Russia',
|
|
422
|
+
_ap_Name: 'Alex',
|
|
423
|
+
_ap_Price: '1000',
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
__meta__: {
|
|
427
|
+
queue: [
|
|
428
|
+
{ id: 'Q8', tabId: 'K0' },
|
|
429
|
+
{ id: 'L5', tabId: 'K1' },
|
|
430
|
+
],
|
|
431
|
+
version: 2,
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
out: {
|
|
435
|
+
L5: {
|
|
436
|
+
params: {
|
|
437
|
+
Name: '',
|
|
438
|
+
Price: '',
|
|
439
|
+
Year: '2021',
|
|
440
|
+
Country: 'Russia',
|
|
441
|
+
_ap_Country: 'Russia',
|
|
442
|
+
_ap_Name: 'Alex',
|
|
443
|
+
_ap_Price: '1000',
|
|
444
|
+
},
|
|
445
|
+
state: {},
|
|
446
|
+
},
|
|
447
|
+
Q8: {
|
|
448
|
+
params: {
|
|
449
|
+
Year: '',
|
|
450
|
+
Country: 'Russia',
|
|
451
|
+
Name: 'Alex',
|
|
452
|
+
Price: '1000',
|
|
453
|
+
_ap_Year: '2021',
|
|
454
|
+
_ap_Country: 'Russia',
|
|
455
|
+
},
|
|
456
|
+
state: {},
|
|
457
|
+
},
|
|
458
|
+
al: {
|
|
459
|
+
params: {
|
|
460
|
+
Country: 'Russia',
|
|
461
|
+
Name: 'Alex',
|
|
462
|
+
Price: '1000',
|
|
463
|
+
Year: '2021',
|
|
464
|
+
},
|
|
465
|
+
state: {},
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
};
|
|
409
469
|
const configs = mockConfigs.configs;
|
|
410
470
|
describe('getItemsStateAndParamsDL', () => {
|
|
411
471
|
describe('old version fallback', () => {
|
|
@@ -498,4 +558,15 @@ describe('getItemsStateAndParams actionParams variants check', () => {
|
|
|
498
558
|
expect(resultItemsStateAndParams).toEqual(omit(stateAndParamsForAP5.out, META_KEY));
|
|
499
559
|
});
|
|
500
560
|
});
|
|
561
|
+
describe('action and params state 6', () => {
|
|
562
|
+
const resultItemsStateAndParams = getItemsStateAndParamsDL({
|
|
563
|
+
defaultGlobalParams: {},
|
|
564
|
+
globalParams: {},
|
|
565
|
+
config: configs[4],
|
|
566
|
+
itemsStateAndParams: stateAndParamsForAP6.in,
|
|
567
|
+
});
|
|
568
|
+
it('return stateAndParamsForAP6.out', () => {
|
|
569
|
+
expect(resultItemsStateAndParams).toEqual(omit(stateAndParamsForAP6.out, META_KEY));
|
|
570
|
+
});
|
|
571
|
+
});
|
|
501
572
|
});
|
|
@@ -9,10 +9,8 @@ export interface Settings {
|
|
|
9
9
|
}
|
|
10
10
|
export type MenuItem = (typeof MenuItems)[keyof typeof MenuItems] | OverlayCustomControlItem;
|
|
11
11
|
export interface SettingsProps {
|
|
12
|
-
autoupdateInterval
|
|
12
|
+
autoupdateInterval: number;
|
|
13
13
|
silentLoading: boolean;
|
|
14
|
-
realtimeMode?: boolean;
|
|
15
|
-
realtimeModeDelayMs?: number;
|
|
16
14
|
}
|
|
17
15
|
export interface ContextProps {
|
|
18
16
|
[key: string]: any;
|