@xh/hoist 55.3.0 → 55.3.2
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 +12 -0
- package/admin/differ/DifferModel.ts +4 -4
- package/cmp/ag-grid/AgGridModel.ts +2 -1
- package/cmp/chart/Chart.ts +1 -1
- package/cmp/chart/ChartModel.ts +2 -2
- package/cmp/filter/FilterChooserModel.ts +2 -1
- package/cmp/grid/GridModel.ts +2 -1
- package/cmp/grid/filter/GridFilterFieldSpec.ts +5 -2
- package/cmp/grouping/GroupingChooserModel.ts +2 -2
- package/core/HoistBase.ts +2 -1
- package/core/HoistBaseDecorators.ts +2 -1
- package/core/persist/PersistenceProvider.ts +3 -2
- package/desktop/cmp/dash/container/DashContainerModel.ts +2 -1
- package/desktop/cmp/grid/impl/filter/values/ValuesTabModel.ts +5 -2
- package/desktop/cmp/leftrightchooser/LeftRightChooser.ts +3 -2
- package/desktop/cmp/treemap/TreeMapModel.ts +2 -2
- package/package.json +1 -1
- package/svc/PrefService.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v55.3.2 - 2023-03-22
|
|
4
|
+
|
|
5
|
+
### 🐞 Bug Fixes
|
|
6
|
+
* Fix grid bug whereby LocalDate filter entered via FilterChooser was causing column filtering
|
|
7
|
+
to fail.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## v55.3.1 - 2023-03-14
|
|
11
|
+
|
|
12
|
+
### 🐞 Bug Fixes
|
|
13
|
+
* Revert `structuredClone` to lodash `deepClone` throughout toolkit.
|
|
14
|
+
|
|
3
15
|
## v55.3.0 - 2023-03-03
|
|
4
16
|
|
|
5
17
|
### 🐞 Bug Fixes
|
|
@@ -13,7 +13,7 @@ import {Icon} from '@xh/hoist/icon';
|
|
|
13
13
|
import {bindable, makeObservable, observable, action} from '@xh/hoist/mobx';
|
|
14
14
|
import {pluralize} from '@xh/hoist/utils/js';
|
|
15
15
|
import {hbox} from '@xh/hoist/cmp/layout';
|
|
16
|
-
import {isEqual, isString, isNil, omit, remove, trimEnd} from 'lodash';
|
|
16
|
+
import {cloneDeep, isEqual, isString, isNil, omit, remove, trimEnd} from 'lodash';
|
|
17
17
|
import {hspacer} from '../../cmp/layout';
|
|
18
18
|
|
|
19
19
|
import {DifferDetailModel} from './DifferDetailModel';
|
|
@@ -151,7 +151,7 @@ export class DifferModel extends HoistModel {
|
|
|
151
151
|
const resp = await Promise.all([
|
|
152
152
|
XH.fetchJson({url: `${url}/${entityName}s`, loadSpec}),
|
|
153
153
|
this.clipboardContent ?
|
|
154
|
-
Promise.resolve(
|
|
154
|
+
Promise.resolve(cloneDeep(this.clipboardContent)) :
|
|
155
155
|
XH.fetchJson({url: `${remoteBaseUrl}${url}/${entityName}s`, loadSpec})
|
|
156
156
|
]);
|
|
157
157
|
this.processResponse(resp);
|
|
@@ -250,8 +250,8 @@ export class DifferModel extends HoistModel {
|
|
|
250
250
|
|
|
251
251
|
rawRecordsAreEqual(local, remote) {
|
|
252
252
|
// cloning to avoid disturbing the source data.
|
|
253
|
-
local =
|
|
254
|
-
remote =
|
|
253
|
+
local = cloneDeep(local);
|
|
254
|
+
remote = cloneDeep(remote);
|
|
255
255
|
|
|
256
256
|
// For JSON records, parse JSON to do an accurate value compare,
|
|
257
257
|
if (local?.valueType === 'json' && remote?.valueType === 'json') {
|
|
@@ -9,6 +9,7 @@ import {action, bindable, computed, makeObservable, observable} from '@xh/hoist/
|
|
|
9
9
|
import {throwIf} from '@xh/hoist/utils/js';
|
|
10
10
|
import {
|
|
11
11
|
castArray,
|
|
12
|
+
cloneDeep,
|
|
12
13
|
concat,
|
|
13
14
|
find,
|
|
14
15
|
has,
|
|
@@ -305,7 +306,7 @@ export class AgGridModel extends HoistModel {
|
|
|
305
306
|
setSortState(sortState: AgGridColumnSortState[]) {
|
|
306
307
|
this.throwIfNotReady();
|
|
307
308
|
|
|
308
|
-
const sortedColumnState =
|
|
309
|
+
const sortedColumnState = cloneDeep(sortState),
|
|
309
310
|
[primaryColumnState, secondaryColumnState] = partition(sortedColumnState, it => !isArray(it.colId)),
|
|
310
311
|
{agColumnApi: colApi, agApi} = this,
|
|
311
312
|
isPivot = colApi.isPivotMode(),
|
package/cmp/chart/Chart.ts
CHANGED
|
@@ -355,7 +355,7 @@ class ChartLocalModel extends HoistModel {
|
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
getThemeConfig() {
|
|
358
|
-
return XH.darkTheme ?
|
|
358
|
+
return XH.darkTheme ? cloneDeep(DarkTheme) : cloneDeep(LightTheme);
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
getModelConfig() {
|
package/cmp/chart/ChartModel.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import {HoistModel, PlainObject, Some} from '@xh/hoist/core';
|
|
8
8
|
import {action, makeObservable, observable} from '@xh/hoist/mobx';
|
|
9
|
-
import {castArray, merge} from 'lodash';
|
|
9
|
+
import {castArray, cloneDeep, merge} from 'lodash';
|
|
10
10
|
|
|
11
11
|
interface ChartConfig {
|
|
12
12
|
|
|
@@ -84,7 +84,7 @@ export class ChartModel extends HoistModel {
|
|
|
84
84
|
*/
|
|
85
85
|
@action
|
|
86
86
|
updateHighchartsConfig(update: any) {
|
|
87
|
-
this.highchartsConfig = merge(
|
|
87
|
+
this.highchartsConfig = merge(cloneDeep(this.highchartsConfig), update);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/** @param series - one or more data series to be charted. */
|
|
@@ -29,6 +29,7 @@ import {throwIf, withDefault} from '@xh/hoist/utils/js';
|
|
|
29
29
|
import {createObservableRef} from '@xh/hoist/utils/react';
|
|
30
30
|
import {ReactNode} from 'react';
|
|
31
31
|
import {
|
|
32
|
+
cloneDeep,
|
|
32
33
|
compact,
|
|
33
34
|
flatMap,
|
|
34
35
|
flatten,
|
|
@@ -373,7 +374,7 @@ export class FilterChooserModel extends HoistModel {
|
|
|
373
374
|
// it's internal `value`. Force synchronise its `value` to our bound `selectValue`
|
|
374
375
|
// to get it back inline. Note we're intentionally not using `setSelectValue()`,
|
|
375
376
|
// which returns early if the actual filter value hasn't changed.
|
|
376
|
-
this.selectValue =
|
|
377
|
+
this.selectValue = cloneDeep(this.selectValue);
|
|
377
378
|
});
|
|
378
379
|
}
|
|
379
380
|
|
package/cmp/grid/GridModel.ts
CHANGED
|
@@ -60,6 +60,7 @@ import equal from 'fast-deep-equal';
|
|
|
60
60
|
import {
|
|
61
61
|
castArray,
|
|
62
62
|
clone,
|
|
63
|
+
cloneDeep,
|
|
63
64
|
compact,
|
|
64
65
|
defaults,
|
|
65
66
|
defaultsDeep,
|
|
@@ -1060,7 +1061,7 @@ export class GridModel extends HoistModel {
|
|
|
1060
1061
|
applyColumnStateChanges(colStateChanges: Partial<ColumnState>[]) {
|
|
1061
1062
|
if (isEmpty(colStateChanges)) return;
|
|
1062
1063
|
|
|
1063
|
-
let columnState =
|
|
1064
|
+
let columnState = cloneDeep(this.columnState);
|
|
1064
1065
|
|
|
1065
1066
|
throwIf(colStateChanges.some(({colId}) => !find(columnState, {colId})),
|
|
1066
1067
|
'Invalid columns detected in column changes!');
|
|
@@ -66,7 +66,7 @@ export class GridFilterFieldSpec extends BaseFilterFieldSpec {
|
|
|
66
66
|
// Implementation
|
|
67
67
|
//------------------------
|
|
68
68
|
loadValuesFromSource() {
|
|
69
|
-
const {filterModel, field, source} = this,
|
|
69
|
+
const {filterModel, field, source, sourceField} = this,
|
|
70
70
|
columnFilters = filterModel.getColumnFilters(field),
|
|
71
71
|
sourceStore = source instanceof View ? source.cube.store : source,
|
|
72
72
|
allRecords = sourceStore.allRecords;
|
|
@@ -83,7 +83,10 @@ export class GridFilterFieldSpec extends BaseFilterFieldSpec {
|
|
|
83
83
|
// Get values from current column filter
|
|
84
84
|
const filterValues = [];
|
|
85
85
|
columnFilters.forEach(filter => {
|
|
86
|
-
const newValues = castArray(filter.value).map(value =>
|
|
86
|
+
const newValues = castArray(filter.value).map(value => {
|
|
87
|
+
value = sourceField.parseVal(value);
|
|
88
|
+
return filterModel.toDisplayValue(value);
|
|
89
|
+
});
|
|
87
90
|
filterValues.push(...newValues);
|
|
88
91
|
});
|
|
89
92
|
|
|
@@ -10,7 +10,7 @@ import {action, computed, observable, makeObservable} from '@xh/hoist/mobx';
|
|
|
10
10
|
import {genDisplayName} from '@xh/hoist/data';
|
|
11
11
|
import {throwIf} from '@xh/hoist/utils/js';
|
|
12
12
|
import {createObservableRef} from '@xh/hoist/utils/react';
|
|
13
|
-
import {difference, isFunction, isArray, isEmpty, isEqual, isString, keys, sortBy} from 'lodash';
|
|
13
|
+
import {cloneDeep, difference, isFunction, isArray, isEmpty, isEqual, isString, keys, sortBy} from 'lodash';
|
|
14
14
|
|
|
15
15
|
export interface GroupingChooserConfig {
|
|
16
16
|
/**
|
|
@@ -128,7 +128,7 @@ export class GroupingChooserModel extends HoistModel {
|
|
|
128
128
|
this.persistValue = persistWith.persistValue ?? true;
|
|
129
129
|
this.persistFavorites = persistWith.persistFavorites ?? true;
|
|
130
130
|
|
|
131
|
-
const state =
|
|
131
|
+
const state = cloneDeep(this.provider.read());
|
|
132
132
|
if (this.persistValue && state?.value && this.validateValue(state?.value)) {
|
|
133
133
|
value = state.value;
|
|
134
134
|
}
|
package/core/HoistBase.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import {XH, PersistenceProvider, PersistOptions, DebounceSpec} from './';
|
|
8
8
|
import {throwIf, getOrCreate} from '@xh/hoist/utils/js';
|
|
9
9
|
import {
|
|
10
|
+
cloneDeep,
|
|
10
11
|
debounce as lodashDebounce,
|
|
11
12
|
isFunction,
|
|
12
13
|
isNil,
|
|
@@ -219,7 +220,7 @@ export abstract class HoistBase {
|
|
|
219
220
|
provider = this.markManaged(PersistenceProvider.create(persistWith)),
|
|
220
221
|
providerState = provider.read();
|
|
221
222
|
if (!isUndefined(providerState)) {
|
|
222
|
-
runInAction(() => this[property] =
|
|
223
|
+
runInAction(() => this[property] = cloneDeep(providerState));
|
|
223
224
|
}
|
|
224
225
|
this.addReaction({
|
|
225
226
|
track: () => this[property],
|
|
@@ -9,6 +9,7 @@ import {PersistenceProvider, PersistOptions, HoistBaseClass} from './';
|
|
|
9
9
|
import {isUndefined} from 'lodash';
|
|
10
10
|
import {wait} from '../promise';
|
|
11
11
|
import {throwIf} from '../utils/js';
|
|
12
|
+
import {cloneDeep} from 'lodash';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Decorator to make a property "managed". Managed properties are designed to hold objects that
|
|
@@ -75,7 +76,7 @@ function createPersistDescriptor(target: HoistBaseClass, property: string, descr
|
|
|
75
76
|
try {
|
|
76
77
|
const persistWith = {path: property, ...this.persistWith, ...options},
|
|
77
78
|
provider = this.markManaged(PersistenceProvider.create(persistWith));
|
|
78
|
-
providerState =
|
|
79
|
+
providerState = cloneDeep(provider.read());
|
|
79
80
|
wait().then(() => {
|
|
80
81
|
this.addReaction({
|
|
81
82
|
track: () => this[property],
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import {DebounceSpec, XH} from '../';
|
|
9
9
|
import {LocalStorageProvider, PrefProvider, DashViewProvider, CustomProvider, PersistOptions} from './';
|
|
10
10
|
import {
|
|
11
|
+
cloneDeep,
|
|
11
12
|
isUndefined,
|
|
12
13
|
get,
|
|
13
14
|
set,
|
|
@@ -95,7 +96,7 @@ export class PersistenceProvider {
|
|
|
95
96
|
* Clear any state saved by this object at a path
|
|
96
97
|
*/
|
|
97
98
|
clear(path: string = this.path) {
|
|
98
|
-
const obj =
|
|
99
|
+
const obj = cloneDeep(this.readRaw());
|
|
99
100
|
unset(obj, this.path);
|
|
100
101
|
this.writeRaw(obj);
|
|
101
102
|
}
|
|
@@ -111,7 +112,7 @@ export class PersistenceProvider {
|
|
|
111
112
|
// Implementation
|
|
112
113
|
//----------------
|
|
113
114
|
protected writeInternal(data: object) {
|
|
114
|
-
const obj =
|
|
115
|
+
const obj = cloneDeep(this.readRaw());
|
|
115
116
|
set(obj, this.path, data);
|
|
116
117
|
this.writeRaw(obj);
|
|
117
118
|
}
|
|
@@ -22,6 +22,7 @@ import {debounced, ensureUniqueBy, throwIf} from '@xh/hoist/utils/js';
|
|
|
22
22
|
import {createObservableRef} from '@xh/hoist/utils/react';
|
|
23
23
|
import {isOmitted} from '@xh/hoist/utils/impl';
|
|
24
24
|
import {
|
|
25
|
+
cloneDeep,
|
|
25
26
|
defaultsDeep,
|
|
26
27
|
find,
|
|
27
28
|
isFinite,
|
|
@@ -539,7 +540,7 @@ export class DashContainerModel extends DashModel<DashContainerViewSpec, DashVie
|
|
|
539
540
|
private createGoldenLayout(containerEl: HTMLElement, state: any): GoldenLayout {
|
|
540
541
|
const {viewSpecs} = this,
|
|
541
542
|
ret = new GoldenLayout({
|
|
542
|
-
content: convertStateToGL(
|
|
543
|
+
content: convertStateToGL(cloneDeep(state), this),
|
|
543
544
|
settings: {
|
|
544
545
|
// Remove icons by default
|
|
545
546
|
showPopoutIcon: false,
|
|
@@ -142,7 +142,7 @@ export class ValuesTabModel extends HoistModel {
|
|
|
142
142
|
|
|
143
143
|
@action
|
|
144
144
|
private doSyncWithFilter() {
|
|
145
|
-
const {values, columnFilters, gridFilterModel} = this,
|
|
145
|
+
const {values, columnFilters, gridFilterModel, fieldSpec} = this,
|
|
146
146
|
{fieldType} = this.headerFilterModel;
|
|
147
147
|
|
|
148
148
|
if (isEmpty(columnFilters)) {
|
|
@@ -157,7 +157,10 @@ export class ValuesTabModel extends HoistModel {
|
|
|
157
157
|
filterValues = [];
|
|
158
158
|
|
|
159
159
|
arr.forEach(filter => {
|
|
160
|
-
const newValues = castArray(filter.value).map(value =>
|
|
160
|
+
const newValues = castArray(filter.value).map(value => {
|
|
161
|
+
value = fieldSpec.sourceField.parseVal(value);
|
|
162
|
+
return gridFilterModel.toDisplayValue(value);
|
|
163
|
+
});
|
|
161
164
|
filterValues.push(...newValues); // Todo: Is this safe?
|
|
162
165
|
});
|
|
163
166
|
|
|
@@ -12,6 +12,7 @@ import {chooserToolbar} from './impl/ChooserToolbar';
|
|
|
12
12
|
import {description} from './impl/Description';
|
|
13
13
|
import './LeftRightChooser.scss';
|
|
14
14
|
import {LeftRightChooserModel} from './LeftRightChooserModel';
|
|
15
|
+
import {cloneDeep} from 'lodash';
|
|
15
16
|
|
|
16
17
|
export interface LeftRightChooserProps extends HoistProps<LeftRightChooserModel>, BoxProps {}
|
|
17
18
|
|
|
@@ -36,8 +37,8 @@ export const [LeftRightChooser, leftRightChooser] = hoistCmp.withFactory<LeftRig
|
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
},
|
|
39
|
-
leftGridOptions =
|
|
40
|
-
rightGridOptions =
|
|
40
|
+
leftGridOptions = cloneDeep(gridOptions),
|
|
41
|
+
rightGridOptions = cloneDeep(gridOptions);
|
|
41
42
|
|
|
42
43
|
if (!leftGroupingExpanded) leftGridOptions.agOptions.groupDefaultExpanded = 0;
|
|
43
44
|
if (!rightGroupingExpanded) rightGridOptions.agOptions.groupDefaultExpanded = 0;
|
|
@@ -13,7 +13,7 @@ import {numberRenderer} from '@xh/hoist/format';
|
|
|
13
13
|
import {action, bindable, computed, makeObservable, observable} from '@xh/hoist/mobx';
|
|
14
14
|
import {throwIf, withDefault} from '@xh/hoist/utils/js';
|
|
15
15
|
import {ReactNode} from 'react';
|
|
16
|
-
import {get, isEmpty, isFinite, max, set, sortBy, sumBy, unset} from 'lodash';
|
|
16
|
+
import {cloneDeep, get, isEmpty, isFinite, max, set, sortBy, sumBy, unset} from 'lodash';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Core Model for a TreeMap.
|
|
@@ -442,7 +442,7 @@ export class TreeMapModel extends HoistModel {
|
|
|
442
442
|
|
|
443
443
|
toggleNodeExpanded(treePath) {
|
|
444
444
|
const {gridModel} = this,
|
|
445
|
-
expandState =
|
|
445
|
+
expandState = cloneDeep(gridModel.expandState);
|
|
446
446
|
|
|
447
447
|
if (get(expandState, treePath)) {
|
|
448
448
|
unset(expandState, treePath);
|
package/package.json
CHANGED
package/svc/PrefService.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import {HoistService, XH} from '@xh/hoist/core';
|
|
8
8
|
import {SECONDS} from '@xh/hoist/utils/datetime';
|
|
9
9
|
import {deepFreeze, throwIf} from '@xh/hoist/utils/js';
|
|
10
|
-
import {debounce, forEach, isEmpty, isEqual, isNil, pickBy} from 'lodash';
|
|
10
|
+
import {cloneDeep, debounce, forEach, isEmpty, isEqual, isNil, pickBy} from 'lodash';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Service to read and set user-specific preference values.
|
|
@@ -92,7 +92,7 @@ export class PrefService extends HoistService {
|
|
|
92
92
|
if (isEqual(oldValue, value)) return;
|
|
93
93
|
|
|
94
94
|
// Change local value to sanitized copy and fire.
|
|
95
|
-
value = deepFreeze(
|
|
95
|
+
value = deepFreeze(cloneDeep(value));
|
|
96
96
|
this._data[key].value = value;
|
|
97
97
|
|
|
98
98
|
// Schedule serialization to storage
|
|
@@ -198,7 +198,7 @@ export class PrefService extends HoistService {
|
|
|
198
198
|
for (let key in data) {
|
|
199
199
|
if (data[key].local) {
|
|
200
200
|
data[key].value = !isNil(localPrefs[key]) ?
|
|
201
|
-
deepFreeze(
|
|
201
|
+
deepFreeze(cloneDeep(localPrefs[key])) :
|
|
202
202
|
data[key].defaultValue;
|
|
203
203
|
}
|
|
204
204
|
}
|