@@ -11,7 +11,12 @@ import {
11
11
useState ,
12
12
} from "react" ;
13
13
import { useStore } from "@nanostores/react" ;
14
- import { Resource , type DataSource } from "@webstudio-is/sdk" ;
14
+ import {
15
+ DataSources ,
16
+ Resource ,
17
+ type DataSource ,
18
+ type Page ,
19
+ } from "@webstudio-is/sdk" ;
15
20
import {
16
21
encodeDataVariableId ,
17
22
generateObjectExpression ,
@@ -53,14 +58,16 @@ import {
53
58
EditorDialogButton ,
54
59
EditorDialogControl ,
55
60
} from "~/builder/shared/code-editor-base" ;
56
- import { parseCurl , type CurlRequest } from "./curl" ;
57
61
import {
58
62
$selectedInstance ,
59
- $selectedInstanceKeyWithRoot ,
63
+ $selectedInstancePathWithRoot ,
60
64
$selectedPage ,
65
+ getInstanceKey ,
66
+ type InstancePath ,
61
67
} from "~/shared/awareness" ;
62
68
import { updateWebstudioData } from "~/shared/instance-utils" ;
63
69
import { rebindTreeVariablesMutable } from "~/shared/data-variables" ;
70
+ import { parseCurl , type CurlRequest } from "./curl" ;
64
71
65
72
export const parseResource = ( {
66
73
id,
@@ -408,85 +415,114 @@ export const Headers = ({
408
415
) ;
409
416
} ;
410
417
411
- const $hiddenDataSourceIds = computed (
412
- [ $dataSources , $selectedPage ] ,
413
- ( dataSources , page ) => {
414
- const dataSourceIds = new Set < DataSource [ "id" ] > ( ) ;
415
- for ( const dataSource of dataSources . values ( ) ) {
416
- // hide collection item and component parameters from resources
417
- // to prevent waterfall and loop requests ans not complicate compiler
418
- if ( dataSource . type === "parameter" ) {
419
- dataSourceIds . add ( dataSource . id ) ;
420
- }
421
- // prevent resources using data of other resources
422
- if ( dataSource . type === "resource" ) {
423
- dataSourceIds . add ( dataSource . id ) ;
424
- }
418
+ export const getResourceScopeForInstance = ( {
419
+ page,
420
+ instanceKey,
421
+ dataSources,
422
+ variableValuesByInstanceSelector,
423
+ } : {
424
+ page : undefined | Page ;
425
+ instanceKey : undefined | string ;
426
+ dataSources : DataSources ;
427
+ variableValuesByInstanceSelector : Map < string , Map < string , unknown > > ;
428
+ } ) => {
429
+ const scope : Record < string , unknown > = { } ;
430
+ const aliases = new Map < string , string > ( ) ;
431
+ const variableValues = new Map < DataSource [ "id" ] , unknown > ( ) ;
432
+ const hiddenDataSourceIds = new Set < DataSource [ "id" ] > ( ) ;
433
+ for ( const dataSource of dataSources . values ( ) ) {
434
+ // hide collection item and component parameters from resources
435
+ // to prevent waterfall and loop requests ans not complicate compiler
436
+ if ( dataSource . type === "parameter" ) {
437
+ hiddenDataSourceIds . add ( dataSource . id ) ;
425
438
}
426
- if ( page ?. systemDataSourceId ) {
427
- dataSourceIds . delete ( page . systemDataSourceId ) ;
439
+ // prevent resources using data of other resources
440
+ if ( dataSource . type === "resource" ) {
441
+ hiddenDataSourceIds . add ( dataSource . id ) ;
428
442
}
429
- return dataSourceIds ;
430
443
}
431
- ) ;
432
-
433
- export const $selectedInstanceResourceScope = computed (
434
- [
435
- $selectedInstanceKeyWithRoot ,
436
- $variableValuesByInstanceSelector ,
437
- $dataSources ,
438
- $hiddenDataSourceIds ,
439
- ] ,
440
- (
441
- instanceKey ,
442
- variableValuesByInstanceSelector ,
443
- dataSources ,
444
- hiddenDataSourceIds
445
- ) => {
446
- const scope : Record < string , unknown > = { } ;
447
- const aliases = new Map < string , string > ( ) ;
448
- const variableValues = new Map < DataSource [ "id" ] , unknown > ( ) ;
449
- if ( instanceKey === undefined ) {
450
- return { variableValues, scope, aliases } ;
451
- }
452
- const values = variableValuesByInstanceSelector . get ( instanceKey ) ;
453
- if ( values ) {
454
- for ( const [ dataSourceId , value ] of values ) {
455
- if ( hiddenDataSourceIds . has ( dataSourceId ) ) {
456
- continue ;
457
- }
458
- let dataSource = dataSources . get ( dataSourceId ) ;
459
- if ( dataSourceId === SYSTEM_VARIABLE_ID ) {
460
- dataSource = systemParameter ;
461
- }
462
- if ( dataSource ) {
463
- const name = encodeDataVariableId ( dataSourceId ) ;
464
- variableValues . set ( dataSourceId , value ) ;
465
- scope [ name ] = value ;
466
- aliases . set ( name , dataSource . name ) ;
467
- }
444
+ if ( page ?. systemDataSourceId ) {
445
+ hiddenDataSourceIds . delete ( page . systemDataSourceId ) ;
446
+ }
447
+ const values = variableValuesByInstanceSelector . get ( instanceKey ?? "" ) ;
448
+ if ( values ) {
449
+ for ( const [ dataSourceId , value ] of values ) {
450
+ if ( hiddenDataSourceIds . has ( dataSourceId ) ) {
451
+ continue ;
452
+ }
453
+ let dataSource = dataSources . get ( dataSourceId ) ;
454
+ if ( dataSourceId === SYSTEM_VARIABLE_ID ) {
455
+ dataSource = systemParameter ;
456
+ }
457
+ if ( dataSource ) {
458
+ const name = encodeDataVariableId ( dataSourceId ) ;
459
+ variableValues . set ( dataSourceId , value ) ;
460
+ scope [ name ] = value ;
461
+ aliases . set ( name , dataSource . name ) ;
468
462
}
469
463
}
470
- return { variableValues, scope, aliases } ;
471
464
}
472
- ) ;
465
+ return { variableValues, scope, aliases } ;
466
+ } ;
467
+
468
+ const getVariableInstanceKey = ( {
469
+ variable,
470
+ instancePath,
471
+ } : {
472
+ variable : undefined | DataSource ;
473
+ instancePath : undefined | InstancePath ;
474
+ } ) => {
475
+ if ( instancePath === undefined ) {
476
+ return ;
477
+ }
478
+ // find instance key for variable instance
479
+ for ( const { instance, instanceSelector } of instancePath ) {
480
+ if ( instance . id === variable ?. scopeInstanceId ) {
481
+ return getInstanceKey ( instanceSelector ) ;
482
+ }
483
+ }
484
+ // and fallback to currently selected instance
485
+ return getInstanceKey ( instancePath [ 0 ] . instanceSelector ) ;
486
+ } ;
473
487
474
488
const useScope = ( { variable } : { variable ?: DataSource } ) => {
475
- const { scope : scopeWithCurrentVariable , aliases } = useStore (
476
- $selectedInstanceResourceScope
489
+ return useStore (
490
+ useMemo (
491
+ ( ) =>
492
+ computed (
493
+ [
494
+ $selectedPage ,
495
+ $selectedInstancePathWithRoot ,
496
+ $variableValuesByInstanceSelector ,
497
+ $dataSources ,
498
+ ] ,
499
+ (
500
+ page ,
501
+ instancePath ,
502
+ variableValuesByInstanceSelector ,
503
+ dataSources
504
+ ) => {
505
+ const { scope, aliases } = getResourceScopeForInstance ( {
506
+ page,
507
+ instanceKey : getVariableInstanceKey ( {
508
+ variable,
509
+ instancePath,
510
+ } ) ,
511
+ dataSources,
512
+ variableValuesByInstanceSelector,
513
+ } ) ;
514
+ // prevent showing currently edited variable in suggestions
515
+ // to avoid cirular dependeny
516
+ const newScope = { ...scope } ;
517
+ if ( variable ) {
518
+ delete newScope [ encodeDataVariableId ( variable . id ) ] ;
519
+ }
520
+ return { scope : newScope , aliases } ;
521
+ }
522
+ ) ,
523
+ [ variable ]
524
+ )
477
525
) ;
478
- const currentVariableId = variable ?. id ;
479
- // prevent showing currently edited variable in suggestions
480
- // to avoid cirular dependeny
481
- const scope = useMemo ( ( ) => {
482
- if ( currentVariableId === undefined ) {
483
- return scopeWithCurrentVariable ;
484
- }
485
- const newScope : Record < string , unknown > = { ...scopeWithCurrentVariable } ;
486
- delete newScope [ encodeDataVariableId ( currentVariableId ) ] ;
487
- return newScope ;
488
- } , [ scopeWithCurrentVariable , currentVariableId ] ) ;
489
- return { scope, aliases } ;
490
526
} ;
491
527
492
528
type PanelApi = {
@@ -635,8 +671,10 @@ export const ResourceForm = forwardRef<
635
671
636
672
useImperativeHandle ( ref , ( ) => ( {
637
673
save : ( formData ) => {
638
- const selectedInstance = $selectedInstance . get ( ) ;
639
- if ( selectedInstance === undefined ) {
674
+ // preserve existing instance scope when edit
675
+ const scopeInstanceId =
676
+ variable ?. scopeInstanceId ?? $selectedInstance . get ( ) ?. id ;
677
+ if ( scopeInstanceId === undefined ) {
640
678
return ;
641
679
}
642
680
const name = z . string ( ) . parse ( formData . get ( "name" ) ) ;
@@ -647,17 +685,18 @@ export const ResourceForm = forwardRef<
647
685
} ) ;
648
686
const newVariable : DataSource = {
649
687
id : variable ?. id ?? nanoid ( ) ,
650
- // preserve existing instance scope when edit
651
- scopeInstanceId : variable ?. scopeInstanceId ?? selectedInstance . id ,
688
+ scopeInstanceId,
652
689
name,
653
690
type : "resource" ,
654
691
resourceId : newResource . id ,
655
692
} ;
656
693
updateWebstudioData ( ( data ) => {
657
694
data . dataSources . set ( newVariable . id , newVariable ) ;
658
695
data . resources . set ( newResource . id , newResource ) ;
659
- const startingInstanceId = selectedInstance . id ;
660
- rebindTreeVariablesMutable ( { startingInstanceId, ...data } ) ;
696
+ rebindTreeVariablesMutable ( {
697
+ startingInstanceId : scopeInstanceId ,
698
+ ...data ,
699
+ } ) ;
661
700
} ) ;
662
701
} ,
663
702
} ) ) ;
@@ -756,8 +795,10 @@ export const SystemResourceForm = forwardRef<
756
795
757
796
useImperativeHandle ( ref , ( ) => ( {
758
797
save : ( formData ) => {
759
- const selectedInstance = $selectedInstance . get ( ) ;
760
- if ( selectedInstance === undefined ) {
798
+ // preserve existing instance scope when edit
799
+ const scopeInstanceId =
800
+ variable ?. scopeInstanceId ?? $selectedInstance . get ( ) ?. id ;
801
+ if ( scopeInstanceId === undefined ) {
761
802
return ;
762
803
}
763
804
const name = z . string ( ) . parse ( formData . get ( "name" ) ) ;
@@ -771,17 +812,18 @@ export const SystemResourceForm = forwardRef<
771
812
} ;
772
813
const newVariable : DataSource = {
773
814
id : variable ?. id ?? nanoid ( ) ,
774
- // preserve existing instance scope when edit
775
- scopeInstanceId : variable ?. scopeInstanceId ?? selectedInstance . id ,
815
+ scopeInstanceId,
776
816
name,
777
817
type : "resource" ,
778
818
resourceId : newResource . id ,
779
819
} ;
780
820
updateWebstudioData ( ( data ) => {
781
821
data . dataSources . set ( newVariable . id , newVariable ) ;
782
822
data . resources . set ( newResource . id , newResource ) ;
783
- const startingInstanceId = selectedInstance . id ;
784
- rebindTreeVariablesMutable ( { startingInstanceId, ...data } ) ;
823
+ rebindTreeVariablesMutable ( {
824
+ startingInstanceId : scopeInstanceId ,
825
+ ...data ,
826
+ } ) ;
785
827
} ) ;
786
828
} ,
787
829
} ) ) ;
@@ -865,8 +907,10 @@ export const GraphqlResourceForm = forwardRef<
865
907
866
908
useImperativeHandle ( ref , ( ) => ( {
867
909
save : ( formData ) => {
868
- const selectedInstance = $selectedInstance . get ( ) ;
869
- if ( selectedInstance === undefined ) {
910
+ // preserve existing instance scope when edit
911
+ const scopeInstanceId =
912
+ variable ?. scopeInstanceId ?? $selectedInstance . get ( ) ?. id ;
913
+ if ( scopeInstanceId === undefined ) {
870
914
return ;
871
915
}
872
916
const name = z . string ( ) . parse ( formData . get ( "name" ) ) ;
@@ -887,17 +931,18 @@ export const GraphqlResourceForm = forwardRef<
887
931
} ;
888
932
const newVariable : DataSource = {
889
933
id : variable ?. id ?? nanoid ( ) ,
890
- // preserve existing instance scope when edit
891
- scopeInstanceId : variable ?. scopeInstanceId ?? selectedInstance . id ,
934
+ scopeInstanceId,
892
935
name,
893
936
type : "resource" ,
894
937
resourceId : newResource . id ,
895
938
} ;
896
939
updateWebstudioData ( ( data ) => {
897
940
data . dataSources . set ( newVariable . id , newVariable ) ;
898
941
data . resources . set ( newResource . id , newResource ) ;
899
- const startingInstanceId = selectedInstance . id ;
900
- rebindTreeVariablesMutable ( { startingInstanceId, ...data } ) ;
942
+ rebindTreeVariablesMutable ( {
943
+ startingInstanceId : scopeInstanceId ,
944
+ ...data ,
945
+ } ) ;
901
946
} ) ;
902
947
} ,
903
948
} ) ) ;
0 commit comments