@xh/hoist 75.0.0-SNAPSHOT.1753727619217 → 75.0.0-SNAPSHOT.1754329446115
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 +14 -0
- package/build/types/cmp/dataview/DataViewModel.d.ts +1 -1
- package/build/types/cmp/grid/GridModel.d.ts +1 -1
- package/build/types/cmp/zoneGrid/ZoneGridModel.d.ts +1 -1
- package/build/types/data/Store.d.ts +13 -2
- package/build/types/data/cube/Cube.d.ts +14 -1
- package/data/Store.ts +50 -13
- package/data/cube/Cube.ts +21 -1
- package/package.json +2 -2
- package/styles/XH.scss +1 -1
- package/styles/vars.scss +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -23,6 +23,11 @@
|
|
|
23
23
|
which `dimensions` are provided to the model.
|
|
24
24
|
* Added new `ClipboardButton.errorMessage` prop to customize or suppress a toast alert if the copy
|
|
25
25
|
operation fails. Set to `false` to fail silently (the behavior prior to this change).
|
|
26
|
+
* Added new `Cube.modifyRecordsAsync` for modifying individual field values in a local uncommitted
|
|
27
|
+
state. Additionally enhanced `Store.modifyRecords` to return a `StoreChangeLog` of updates.
|
|
28
|
+
|
|
29
|
+
### 🐞 Bug Fixes
|
|
30
|
+
* Fixed bug where `Store.modifyRecords` was not properly handling changes to `SummaryRecords`.
|
|
26
31
|
|
|
27
32
|
### 🐞 Bug Fixes
|
|
28
33
|
|
|
@@ -55,11 +60,20 @@
|
|
|
55
60
|
* Removed deprecated `FetchService.setDefaultTimeout`
|
|
56
61
|
* Removed deprecated `IdentityService.logoutAsync`
|
|
57
62
|
|
|
63
|
+
### ✨ Styles
|
|
64
|
+
|
|
65
|
+
* Upgraded the version of Hoist's default Inter UI font to a new major version, now v4.1. Note
|
|
66
|
+
that this brings slight differences to the font's appearance, including tweaks to internal
|
|
67
|
+
spacing and letterforms for tabular numbers. The name of the font face has also changed, from
|
|
68
|
+
`Inter Var` to `InterVariable`. The default value of the `--xh-font-family` CSS variable has been
|
|
69
|
+
updated to match, making this change transparent for most applications.
|
|
70
|
+
|
|
58
71
|
### 📚 Libraries
|
|
59
72
|
|
|
60
73
|
* @auth0/auth0-spa-js `2.1 → 2.3`
|
|
61
74
|
* @azure/msal-browser `4.12 → 4.16`
|
|
62
75
|
* filesize `6.4 → 11.0`
|
|
76
|
+
* inter-ui `3.19 → 4.1`
|
|
63
77
|
* mobx-react-lite `4.0 → 4.1`
|
|
64
78
|
* qs `6.13 → 6.14`
|
|
65
79
|
* react-markdown `9.0 → 10.1`
|
|
@@ -110,7 +110,7 @@ export declare class DataViewModel extends HoistModel {
|
|
|
110
110
|
ensureSelectionVisibleAsync(): Promise<void>;
|
|
111
111
|
doLoadAsync(loadSpec: LoadSpec): Promise<any>;
|
|
112
112
|
loadData(rawData: any[], rawSummaryData?: PlainObject): void;
|
|
113
|
-
updateData(rawData: PlainObject[] | StoreTransaction):
|
|
113
|
+
updateData(rawData: PlainObject[] | StoreTransaction): import("@xh/hoist/data").StoreChangeLog;
|
|
114
114
|
clear(): void;
|
|
115
115
|
setGroupBy(colIds: Some<string>): void;
|
|
116
116
|
setSortBy(sorters: Some<GridSorterLike>): void;
|
|
@@ -450,7 +450,7 @@ export declare class GridModel extends HoistModel {
|
|
|
450
450
|
/** Load the underlying store. */
|
|
451
451
|
loadData(rawData: any[], rawSummaryData?: Some<PlainObject>): void;
|
|
452
452
|
/** Update the underlying store. */
|
|
453
|
-
updateData(rawData: PlainObject[] | StoreTransaction):
|
|
453
|
+
updateData(rawData: PlainObject[] | StoreTransaction): import("@xh/hoist/data").StoreChangeLog;
|
|
454
454
|
/** Clear the underlying store, removing all rows. */
|
|
455
455
|
clear(): void;
|
|
456
456
|
/** @param colConfigs - {@link Column} or {@link ColumnGroup} configs. */
|
|
@@ -243,7 +243,7 @@ export declare class ZoneGridModel extends HoistModel {
|
|
|
243
243
|
ensureSelectionVisibleAsync(): Promise<void>;
|
|
244
244
|
doLoadAsync(loadSpec: LoadSpec): Promise<any>;
|
|
245
245
|
loadData(rawData: any[], rawSummaryData?: Some<PlainObject>): void;
|
|
246
|
-
updateData(rawData: PlainObject[] | StoreTransaction):
|
|
246
|
+
updateData(rawData: PlainObject[] | StoreTransaction): import("@xh/hoist/data").StoreChangeLog;
|
|
247
247
|
clear(): void;
|
|
248
248
|
setGroupBy(colIds: Some<string>): void;
|
|
249
249
|
private createGridModel;
|
|
@@ -104,6 +104,16 @@ export interface StoreTransaction {
|
|
|
104
104
|
*/
|
|
105
105
|
rawSummaryData?: Some<PlainObject>;
|
|
106
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Collection of changes made to a Store's RecordSet. Unlike `StoreTransaction` which is used to
|
|
109
|
+
* specify changes, this object is used to report the actual changes made in a single transaction.
|
|
110
|
+
*/
|
|
111
|
+
export interface StoreChangeLog {
|
|
112
|
+
update?: StoreRecord[];
|
|
113
|
+
add?: StoreRecord[];
|
|
114
|
+
remove?: StoreRecordId[];
|
|
115
|
+
summaryRecords?: StoreRecord[];
|
|
116
|
+
}
|
|
107
117
|
export interface ChildRawData {
|
|
108
118
|
/** ID of the pre-existing parent record. */
|
|
109
119
|
parentId: string;
|
|
@@ -197,7 +207,7 @@ export declare class Store extends HoistBase {
|
|
|
197
207
|
* into adds and updates, with updates determined by matching existing records by ID.
|
|
198
208
|
* @returns changes applied, or null if no record changes were made.
|
|
199
209
|
*/
|
|
200
|
-
updateData(rawData: PlainObject[] | StoreTransaction):
|
|
210
|
+
updateData(rawData: PlainObject[] | StoreTransaction): StoreChangeLog;
|
|
201
211
|
/**
|
|
202
212
|
* Re-runs the Filter on the current data. Applications only need to call this method if
|
|
203
213
|
* the state underlying the filter, other than the record data itself, has changed. Store will
|
|
@@ -242,8 +252,9 @@ export declare class Store extends HoistBase {
|
|
|
242
252
|
* Records in this Store. Each object in the list must have an `id` property identifying
|
|
243
253
|
* the StoreRecord to modify, plus any other properties with updated field values to apply,
|
|
244
254
|
* e.g. `{id: 4, quantity: 100}, {id: 5, quantity: 99, customer: 'bob'}`.
|
|
255
|
+
* @returns changes applied, or null if no record changes were made.
|
|
245
256
|
*/
|
|
246
|
-
modifyRecords(modifications: Some<PlainObject>):
|
|
257
|
+
modifyRecords(modifications: Some<PlainObject>): StoreChangeLog;
|
|
247
258
|
/**
|
|
248
259
|
* Revert all changes made to the specified Records since they were last committed.
|
|
249
260
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HoistBase, PlainObject } from '@xh/hoist/core';
|
|
1
|
+
import { HoistBase, PlainObject, Some } from '@xh/hoist/core';
|
|
2
2
|
import { CubeField, CubeFieldSpec } from './CubeField';
|
|
3
3
|
import { QueryConfig } from './Query';
|
|
4
4
|
import { View } from './View';
|
|
@@ -126,6 +126,19 @@ export declare class Cube extends HoistBase {
|
|
|
126
126
|
* @param infoUpdates - new key-value pairs to be applied to existing info on this cube.
|
|
127
127
|
*/
|
|
128
128
|
updateDataAsync(rawData: PlainObject[] | StoreTransaction, infoUpdates?: PlainObject): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Similar to `updateDataAsync`, but intended for modifying individual field values in a local
|
|
131
|
+
* uncommitted state - i.e. when updating via an inline grid editor or similar control. Like
|
|
132
|
+
* `updateDataAsync`, this method will update its views asynchronously.
|
|
133
|
+
*
|
|
134
|
+
* This method largely delegates to {@link Store.modifyRecords} - see that method for more info.
|
|
135
|
+
*
|
|
136
|
+
* @param modifications - field-level modifications to apply to existing
|
|
137
|
+
* Records in this Cube. Each object in the list must have an `id` property identifying
|
|
138
|
+
* the StoreRecord to modify, plus any other properties with updated field values to apply,
|
|
139
|
+
* e.g. `{id: 4, quantity: 100}, {id: 5, quantity: 99, customer: 'bob'}`.
|
|
140
|
+
*/
|
|
141
|
+
modifyRecordsAsync(modifications: Some<PlainObject>): Promise<void>;
|
|
129
142
|
/** Clear any/all data and info from this Cube. */
|
|
130
143
|
clearAsync(): Promise<void>;
|
|
131
144
|
/**
|
package/data/Store.ts
CHANGED
|
@@ -153,6 +153,17 @@ export interface StoreTransaction {
|
|
|
153
153
|
rawSummaryData?: Some<PlainObject>;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Collection of changes made to a Store's RecordSet. Unlike `StoreTransaction` which is used to
|
|
158
|
+
* specify changes, this object is used to report the actual changes made in a single transaction.
|
|
159
|
+
*/
|
|
160
|
+
export interface StoreChangeLog {
|
|
161
|
+
update?: StoreRecord[];
|
|
162
|
+
add?: StoreRecord[];
|
|
163
|
+
remove?: StoreRecordId[];
|
|
164
|
+
summaryRecords?: StoreRecord[];
|
|
165
|
+
}
|
|
166
|
+
|
|
156
167
|
export interface ChildRawData {
|
|
157
168
|
/** ID of the pre-existing parent record. */
|
|
158
169
|
parentId: string;
|
|
@@ -348,13 +359,13 @@ export class Store extends HoistBase {
|
|
|
348
359
|
*/
|
|
349
360
|
@action
|
|
350
361
|
@logWithDebug
|
|
351
|
-
updateData(rawData: PlainObject[] | StoreTransaction):
|
|
362
|
+
updateData(rawData: PlainObject[] | StoreTransaction): StoreChangeLog {
|
|
352
363
|
if (isEmpty(rawData)) return null;
|
|
353
364
|
|
|
354
|
-
const changeLog:
|
|
365
|
+
const changeLog: StoreChangeLog = {};
|
|
355
366
|
|
|
356
367
|
// Build a transaction object out of a flat list of adds and updates
|
|
357
|
-
let rawTransaction;
|
|
368
|
+
let rawTransaction: StoreTransaction;
|
|
358
369
|
if (isArray(rawData)) {
|
|
359
370
|
const update = [],
|
|
360
371
|
add = [];
|
|
@@ -381,7 +392,7 @@ export class Store extends HoistBase {
|
|
|
381
392
|
throwIf(!isEmpty(other), 'Unknown argument(s) passed to updateData().');
|
|
382
393
|
|
|
383
394
|
// 1) Pre-process updates and adds into Records
|
|
384
|
-
let updateRecs, addRecs
|
|
395
|
+
let updateRecs: StoreRecord[], addRecs: Map<StoreRecordId, StoreRecord>;
|
|
385
396
|
if (update) {
|
|
386
397
|
updateRecs = update.map(it => {
|
|
387
398
|
const recId = this.idSpec(it),
|
|
@@ -426,7 +437,11 @@ export class Store extends HoistBase {
|
|
|
426
437
|
}
|
|
427
438
|
|
|
428
439
|
// 3) Apply changes
|
|
429
|
-
let rsTransaction:
|
|
440
|
+
let rsTransaction: {
|
|
441
|
+
update?: StoreRecord[];
|
|
442
|
+
add?: StoreRecord[];
|
|
443
|
+
remove?: StoreRecordId[];
|
|
444
|
+
} = {};
|
|
430
445
|
if (!isEmpty(updateRecs)) rsTransaction.update = updateRecs;
|
|
431
446
|
if (!isEmpty(addRecs)) rsTransaction.add = Array.from(addRecs.values());
|
|
432
447
|
if (!isEmpty(remove)) rsTransaction.remove = remove;
|
|
@@ -545,13 +560,15 @@ export class Store extends HoistBase {
|
|
|
545
560
|
* Records in this Store. Each object in the list must have an `id` property identifying
|
|
546
561
|
* the StoreRecord to modify, plus any other properties with updated field values to apply,
|
|
547
562
|
* e.g. `{id: 4, quantity: 100}, {id: 5, quantity: 99, customer: 'bob'}`.
|
|
563
|
+
* @returns changes applied, or null if no record changes were made.
|
|
548
564
|
*/
|
|
549
565
|
@action
|
|
550
|
-
modifyRecords(modifications: Some<PlainObject>) {
|
|
566
|
+
modifyRecords(modifications: Some<PlainObject>): StoreChangeLog {
|
|
551
567
|
modifications = castArray(modifications);
|
|
552
568
|
if (isEmpty(modifications)) return;
|
|
553
569
|
|
|
554
|
-
|
|
570
|
+
// 1) Pre-process modifications into Records
|
|
571
|
+
const updateMap = new Map<StoreRecordId, StoreRecord>();
|
|
555
572
|
let hadDupes = false;
|
|
556
573
|
modifications.forEach(mod => {
|
|
557
574
|
let {id} = mod;
|
|
@@ -559,7 +576,7 @@ export class Store extends HoistBase {
|
|
|
559
576
|
// Ignore multiple updates for the same record - we are updating this Store in a
|
|
560
577
|
// transaction after processing all modifications, so this method is not currently setup
|
|
561
578
|
// to process more than one update for a given rec at a time.
|
|
562
|
-
if (
|
|
579
|
+
if (updateMap.has(id)) {
|
|
563
580
|
hadDupes = true;
|
|
564
581
|
return;
|
|
565
582
|
}
|
|
@@ -577,20 +594,40 @@ export class Store extends HoistBase {
|
|
|
577
594
|
});
|
|
578
595
|
|
|
579
596
|
if (!equal(currentRec.data, updatedRec.data)) {
|
|
580
|
-
|
|
597
|
+
updateMap.set(id, updatedRec);
|
|
581
598
|
}
|
|
582
599
|
});
|
|
583
600
|
|
|
584
|
-
if (isEmpty(
|
|
601
|
+
if (isEmpty(updateMap)) return null;
|
|
585
602
|
|
|
586
603
|
warnIf(
|
|
587
604
|
hadDupes,
|
|
588
605
|
'Store.modifyRecords() called with multiple updates for the same Records. Only the first modification for each StoreRecord was processed.'
|
|
589
606
|
);
|
|
590
607
|
|
|
591
|
-
|
|
608
|
+
const updateRecs = Array.from(updateMap.values()),
|
|
609
|
+
changeLog: StoreChangeLog = {};
|
|
592
610
|
|
|
593
|
-
|
|
611
|
+
// 2) Pre-process summary records, peeling them out of updates if needed
|
|
612
|
+
const {summaryRecords} = this;
|
|
613
|
+
let summaryUpdateRecs: StoreRecord[];
|
|
614
|
+
if (!isEmpty(summaryRecords)) {
|
|
615
|
+
summaryUpdateRecs = lodashRemove(updateRecs, ({id}) => some(summaryRecords, {id}));
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
if (!isEmpty(summaryUpdateRecs)) {
|
|
619
|
+
this.summaryRecords = summaryUpdateRecs;
|
|
620
|
+
changeLog.summaryRecords = this.summaryRecords;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// 3) Apply changes
|
|
624
|
+
if (!isEmpty(updateRecs)) {
|
|
625
|
+
this._current = this._current.withTransaction({update: updateRecs});
|
|
626
|
+
changeLog.update = updateRecs;
|
|
627
|
+
this.rebuildFiltered();
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return changeLog;
|
|
594
631
|
}
|
|
595
632
|
|
|
596
633
|
/**
|
|
@@ -705,7 +742,7 @@ export class Store extends HoistBase {
|
|
|
705
742
|
/** True if the store has changes which need to be committed. */
|
|
706
743
|
@computed
|
|
707
744
|
get isDirty(): boolean {
|
|
708
|
-
return this._current !== this._committed;
|
|
745
|
+
return this._current !== this._committed || this.summaryRecords?.some(it => it.isModified);
|
|
709
746
|
}
|
|
710
747
|
|
|
711
748
|
/** Alias for {@link Store.isDirty} */
|
package/data/cube/Cube.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Copyright © 2025 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {HoistBase, managed, PlainObject} from '@xh/hoist/core';
|
|
8
|
+
import {HoistBase, managed, PlainObject, Some} from '@xh/hoist/core';
|
|
9
9
|
import {action, makeObservable, observable} from '@xh/hoist/mobx';
|
|
10
10
|
import {forEachAsync} from '@xh/hoist/utils/async';
|
|
11
11
|
import {CubeField, CubeFieldSpec} from './CubeField';
|
|
@@ -244,6 +244,26 @@ export class Cube extends HoistBase {
|
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Similar to `updateDataAsync`, but intended for modifying individual field values in a local
|
|
249
|
+
* uncommitted state - i.e. when updating via an inline grid editor or similar control. Like
|
|
250
|
+
* `updateDataAsync`, this method will update its views asynchronously.
|
|
251
|
+
*
|
|
252
|
+
* This method largely delegates to {@link Store.modifyRecords} - see that method for more info.
|
|
253
|
+
*
|
|
254
|
+
* @param modifications - field-level modifications to apply to existing
|
|
255
|
+
* Records in this Cube. Each object in the list must have an `id` property identifying
|
|
256
|
+
* the StoreRecord to modify, plus any other properties with updated field values to apply,
|
|
257
|
+
* e.g. `{id: 4, quantity: 100}, {id: 5, quantity: 99, customer: 'bob'}`.
|
|
258
|
+
*/
|
|
259
|
+
async modifyRecordsAsync(modifications: Some<PlainObject>): Promise<void> {
|
|
260
|
+
const changeLog = this.store.modifyRecords(modifications);
|
|
261
|
+
|
|
262
|
+
if (changeLog) {
|
|
263
|
+
await forEachAsync(this._connectedViews, v => v.noteCubeUpdated(changeLog));
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
247
267
|
/** Clear any/all data and info from this Cube. */
|
|
248
268
|
async clearAsync() {
|
|
249
269
|
await this.loadDataAsync([]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xh/hoist",
|
|
3
|
-
"version": "75.0.0-SNAPSHOT.
|
|
3
|
+
"version": "75.0.0-SNAPSHOT.1754329446115",
|
|
4
4
|
"description": "Hoist add-on for building and deploying React Applications.",
|
|
5
5
|
"repository": "github:xh/hoist-react",
|
|
6
6
|
"homepage": "https://xh.io",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"filesize": "~11.0.2",
|
|
55
55
|
"golden-layout": "~1.5.9",
|
|
56
56
|
"http-status-codes": "~2.3.0",
|
|
57
|
-
"inter-ui": "~
|
|
57
|
+
"inter-ui": "~4.1.1",
|
|
58
58
|
"jwt-decode": "~4.0.0",
|
|
59
59
|
"lodash": "~4.17.21",
|
|
60
60
|
"lodash-inflection": "~1.5.0",
|
package/styles/XH.scss
CHANGED
package/styles/vars.scss
CHANGED
|
@@ -374,7 +374,7 @@ body {
|
|
|
374
374
|
//------------------------
|
|
375
375
|
// Fonts
|
|
376
376
|
//------------------------
|
|
377
|
-
--xh-font-family: var(--font-family, #{("
|
|
377
|
+
--xh-font-family: var(--font-family, #{("InterVariable", system-ui, sans-serif)});
|
|
378
378
|
--xh-font-family-headings: var(--font-family-headings, var(--xh-font-family));
|
|
379
379
|
--xh-font-family-mono: var(--font-family-mono, #{(Monaco, Consolas, monospace)});
|
|
380
380
|
|