@@ -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 ) : PlainObject {
362
+ updateData ( rawData : PlainObject [ ] | StoreTransaction ) : StoreChangeLog {
352
363
if ( isEmpty ( rawData ) ) return null ;
353
364
354
- const changeLog : PlainObject = { } ;
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 : any = { } ;
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,21 +560,23 @@ 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
- const updateRecs = new Map ( ) ;
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 ;
558
575
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 ( updateRecs . has ( id ) ) {
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
- updateRecs . set ( id , updatedRec ) ;
597
+ updateMap . set ( id , updatedRec ) ;
581
598
}
582
599
} ) ;
583
600
584
- if ( isEmpty ( updateRecs ) ) return ;
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
- this . _current = this . _current . withTransaction ( { update : Array . from ( updateRecs . values ( ) ) } ) ;
608
+ const updateRecs = Array . from ( updateMap . values ( ) ) ,
609
+ changeLog : StoreChangeLog = { } ;
592
610
593
- this . rebuildFiltered ( ) ;
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} */
0 commit comments