@@ -16,6 +16,7 @@ import {
16
16
lensPath ,
17
17
mergeLeft ,
18
18
mergeDeepRight ,
19
+ path ,
19
20
pluck ,
20
21
propEq ,
21
22
reject ,
@@ -31,6 +32,7 @@ import {getAction} from './constants';
31
32
import cookie from 'cookie' ;
32
33
import { uid , urlBase , isMultiOutputProp , parseMultipleOutputs } from '../utils' ;
33
34
import { STATUS } from '../constants/constants' ;
35
+ import { applyPersistence , prunePersistence } from '../persistence' ;
34
36
35
37
export const updateProps = createAction ( getAction ( 'ON_PROP_CHANGE' ) ) ;
36
38
export const setRequestQueue = createAction ( getAction ( 'SET_REQUEST_QUEUE' ) ) ;
@@ -530,6 +532,32 @@ function updateOutput(
530
532
} ) ;
531
533
}
532
534
535
+ function doUpdateProps ( id , updatedProps ) {
536
+ const { layout, paths} = getState ( ) ;
537
+ const itempath = paths [ id ] ;
538
+ if ( ! itempath ) {
539
+ return false ;
540
+ }
541
+
542
+ // This is a callback-generated update.
543
+ // Check if this invalidates existing persisted prop values,
544
+ prunePersistence ( path ( itempath , layout ) , updatedProps ) ;
545
+
546
+ // In case the update contains whole components, see if any of
547
+ // those components have props to update to persist user edits.
548
+ const finalProps = applyPersistence ( updatedProps ) ;
549
+
550
+ dispatch (
551
+ updateProps ( {
552
+ itempath,
553
+ props : finalProps ,
554
+ source : 'response' ,
555
+ } )
556
+ ) ;
557
+
558
+ return finalProps ;
559
+ }
560
+
533
561
// Clientside hook
534
562
if ( clientside_function ) {
535
563
let returnValue ;
@@ -587,24 +615,20 @@ function updateOutput(
587
615
updateRequestQueue ( false , STATUS . OK ) ;
588
616
589
617
// Update the layout with the new result
590
- dispatch (
591
- updateProps ( {
592
- itempath : getState ( ) . paths [ outputId ] ,
593
- props : updatedProps ,
594
- source : 'response' ,
595
- } )
596
- ) ;
618
+ const appliedProps = doUpdateProps ( outputId , updatedProps ) ;
597
619
598
620
/*
599
621
* This output could itself be a serverside or clientside input
600
622
* to another function
601
623
*/
602
- dispatch (
603
- notifyObservers ( {
604
- id : outputId ,
605
- props : updatedProps ,
606
- } )
607
- ) ;
624
+ if ( appliedProps ) {
625
+ dispatch (
626
+ notifyObservers ( {
627
+ id : outputId ,
628
+ props : appliedProps ,
629
+ } )
630
+ ) ;
631
+ }
608
632
}
609
633
610
634
if ( isMultiOutputProp ( payload . output ) ) {
@@ -717,20 +741,16 @@ function updateOutput(
717
741
const handleResponse = ( [ outputIdAndProp , props ] ) => {
718
742
// Backward compatibility
719
743
const pathKey = multi ? outputIdAndProp : outputComponentId ;
720
- const observerUpdatePayload = {
721
- itempath : getState ( ) . paths [ pathKey ] ,
722
- props,
723
- source : 'response' ,
724
- } ;
725
- if ( ! observerUpdatePayload . itempath ) {
744
+
745
+ const appliedProps = doUpdateProps ( pathKey , props ) ;
746
+ if ( ! appliedProps ) {
726
747
return ;
727
748
}
728
- dispatch ( updateProps ( observerUpdatePayload ) ) ;
729
749
730
750
dispatch (
731
751
notifyObservers ( {
732
752
id : pathKey ,
733
- props : props ,
753
+ props : appliedProps ,
734
754
} )
735
755
) ;
736
756
@@ -739,10 +759,11 @@ function updateOutput(
739
759
* paths store.
740
760
* TODO - Do we need to wait for updateProps to finish?
741
761
*/
742
- if ( has ( 'children' , observerUpdatePayload . props ) ) {
762
+ if ( has ( 'children' , appliedProps ) ) {
763
+ const newChildren = appliedProps . children ;
743
764
dispatch (
744
765
computePaths ( {
745
- subTree : observerUpdatePayload . props . children ,
766
+ subTree : newChildren ,
746
767
startingPath : concat (
747
768
getState ( ) . paths [ pathKey ] ,
748
769
[ 'props' , 'children' ]
@@ -756,11 +777,8 @@ function updateOutput(
756
777
* new children components
757
778
*/
758
779
if (
759
- contains (
760
- type ( observerUpdatePayload . props . children ) ,
761
- [ 'Array' , 'Object' ]
762
- ) &&
763
- ! isEmpty ( observerUpdatePayload . props . children )
780
+ contains ( type ( newChildren ) , [ 'Array' , 'Object' ] ) &&
781
+ ! isEmpty ( newChildren )
764
782
) {
765
783
/*
766
784
* TODO: We're just naively crawling
@@ -770,32 +788,27 @@ function updateOutput(
770
788
* to compute the subtree
771
789
*/
772
790
const newProps = { } ;
773
- crawlLayout (
774
- observerUpdatePayload . props . children ,
775
- function appendIds ( child ) {
776
- if ( hasId ( child ) ) {
777
- keys ( child . props ) . forEach ( childProp => {
778
- const componentIdAndProp = `${ child . props . id } .${ childProp } ` ;
779
- if (
780
- has (
781
- componentIdAndProp ,
782
- InputGraph . nodes
783
- )
784
- ) {
785
- newProps [ componentIdAndProp ] = {
786
- id : child . props . id ,
787
- props : {
788
- [ childProp ] :
789
- child . props [
790
- childProp
791
- ] ,
792
- } ,
793
- } ;
794
- }
795
- } ) ;
796
- }
791
+ crawlLayout ( newChildren , function appendIds ( child ) {
792
+ if ( hasId ( child ) ) {
793
+ keys ( child . props ) . forEach ( childProp => {
794
+ const componentIdAndProp = `${ child . props . id } .${ childProp } ` ;
795
+ if (
796
+ has (
797
+ componentIdAndProp ,
798
+ InputGraph . nodes
799
+ )
800
+ ) {
801
+ newProps [ componentIdAndProp ] = {
802
+ id : child . props . id ,
803
+ props : {
804
+ [ childProp ] :
805
+ child . props [ childProp ] ,
806
+ } ,
807
+ } ;
808
+ }
809
+ } ) ;
797
810
}
798
- ) ;
811
+ } ) ;
799
812
800
813
/*
801
814
* Organize props by shared outputs so that we
0 commit comments