Skip to content

Commit 9ce3fd2

Browse files
committed
feat: load data before saving resource variable
Ref #3691 - new resource loader with queue to avoid bloating network with huge responses - data can be loaded for new variable before saving, easier to preview result
1 parent 91588c9 commit 9ce3fd2

23 files changed

+907
-724
lines changed

apps/builder/app/builder/features/pages/page-utils.test.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
ROOT_FOLDER_ID,
88
type Page,
99
SYSTEM_VARIABLE_ID,
10+
Resource,
1011
} from "@webstudio-is/sdk";
1112
import {
1213
cleanupChildRefsMutable,
@@ -23,11 +24,12 @@ import {
2324
$dataSourceVariables,
2425
$dataSources,
2526
$pages,
26-
$resourceValues,
27+
$resources,
2728
} from "~/shared/nano-states";
2829
import { registerContainers } from "~/shared/sync";
2930
import { $awareness } from "~/shared/awareness";
3031
import { updateCurrentSystem } from "~/shared/system";
32+
import { $resourcesCache, getResourceKey } from "~/shared/resources";
3133

3234
setEnv("*");
3335
registerContainers();
@@ -521,7 +523,25 @@ test("page root scope should use variable and resource values", () => {
521523
$dataSourceVariables.set(
522524
new Map([["valueVariableId", "value variable value"]])
523525
);
524-
$resourceValues.set(new Map([["resourceId", "resource variable value"]]));
526+
const resourceKey = getResourceKey({
527+
name: "my-resource",
528+
url: "",
529+
searchParams: [],
530+
method: "get",
531+
headers: [],
532+
});
533+
$resources.set(
534+
toMap<Resource>([
535+
{
536+
id: "resourceId",
537+
name: "my-resource",
538+
url: `""`,
539+
method: "get",
540+
headers: [],
541+
},
542+
])
543+
);
544+
$resourcesCache.set(new Map([[resourceKey, "resource variable value"]]));
525545
expect($pageRootScope.get()).toEqual({
526546
aliases: new Map([
527547
["$ws$system", "system"],

apps/builder/app/builder/features/settings-panel/resource-panel.tsx

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export const parseResource = ({
7575
formData,
7676
}: {
7777
id: string;
78-
name: string;
78+
name?: string;
7979
formData: FormData;
8080
}) => {
8181
const searchParamNames = formData.getAll("search-param-name") as string[];
@@ -84,7 +84,7 @@ export const parseResource = ({
8484
const headerValues = formData.getAll("header-value") as string[];
8585
return Resource.parse({
8686
id,
87-
name,
87+
name: name ?? formData.get("name"),
8888
url: formData.get("url"),
8989
searchParams: searchParamNames
9090
.map((name, index) => ({ name, value: searchParamValues[index] }))
@@ -175,17 +175,19 @@ export const UrlField = ({
175175
}
176176
try {
177177
const url = new URL(value);
178-
const searchParams: Resource["searchParams"] = [];
179-
for (const [name, value] of url.searchParams) {
180-
searchParams.push({ name, value: JSON.stringify(value) });
178+
if (url.searchParams.size > 0) {
179+
const searchParams: Resource["searchParams"] = [];
180+
for (const [name, value] of url.searchParams) {
181+
searchParams.push({ name, value: JSON.stringify(value) });
182+
}
183+
// remove all search params from url
184+
url.search = "";
185+
// update text value as string literal
186+
onChange(JSON.stringify(url.href), searchParams);
187+
return;
181188
}
182-
// remove all search params from url
183-
url.search = "";
184-
// update text value as string literal
185-
onChange(JSON.stringify(url.href), searchParams);
186-
} catch {
187-
onChange(JSON.stringify(value));
188-
}
189+
} catch {}
190+
onChange(JSON.stringify(value));
189191
}}
190192
onBlur={(event) => event.currentTarget.checkValidity()}
191193
onInvalid={(event) =>
@@ -515,9 +517,9 @@ export const getResourceScopeForInstance = ({
515517
}
516518
if (dataSource) {
517519
const name = encodeDataVariableId(dataSourceId);
518-
variableValues.set(dataSourceId, value);
519520
scope[name] = value;
520521
aliases.set(name, dataSource.name);
522+
variableValues.set(dataSource.name, value);
521523
}
522524
}
523525
}
@@ -544,7 +546,7 @@ const getVariableInstanceKey = ({
544546
return getInstanceKey(instancePath[0].instanceSelector);
545547
};
546548

547-
const useScope = ({ variable }: { variable?: DataSource }) => {
549+
export const useResourceScope = ({ variable }: { variable?: DataSource }) => {
548550
return useStore(
549551
useMemo(
550552
() =>
@@ -561,22 +563,32 @@ const useScope = ({ variable }: { variable?: DataSource }) => {
561563
variableValuesByInstanceSelector,
562564
dataSources
563565
) => {
564-
const { scope, aliases } = getResourceScopeForInstance({
565-
page,
566-
instanceKey: getVariableInstanceKey({
567-
variable,
568-
instancePath,
569-
}),
570-
dataSources,
571-
variableValuesByInstanceSelector,
572-
});
566+
const { scope, aliases, variableValues } =
567+
getResourceScopeForInstance({
568+
page,
569+
instanceKey: getVariableInstanceKey({
570+
variable,
571+
instancePath,
572+
}),
573+
dataSources,
574+
variableValuesByInstanceSelector,
575+
});
573576
// prevent showing currently edited variable in suggestions
574577
// to avoid cirular dependeny
575578
const newScope = { ...scope };
579+
const newAliases = new Map(aliases);
580+
const newVariableValues = new Map(variableValues);
576581
if (variable) {
577-
delete newScope[encodeDataVariableId(variable.id)];
582+
const key = encodeDataVariableId(variable.id);
583+
delete newScope[key];
584+
newAliases.delete(key);
585+
newVariableValues.delete(variable.name);
578586
}
579-
return { scope: newScope, aliases };
587+
return {
588+
scope: newScope,
589+
aliases: newAliases,
590+
variableValues: newVariableValues,
591+
};
580592
}
581593
),
582594
[variable]
@@ -706,7 +718,7 @@ export const ResourceForm = forwardRef<
706718
undefined | PanelApi,
707719
{ variable?: DataSource }
708720
>(({ variable }, ref) => {
709-
const { scope, aliases } = useScope({ variable });
721+
const { scope, aliases } = useResourceScope({ variable });
710722

711723
const resources = useStore($resources);
712724
const resource =
@@ -739,16 +751,14 @@ export const ResourceForm = forwardRef<
739751
if (scopeInstanceId === undefined) {
740752
return;
741753
}
742-
const name = z.string().parse(formData.get("name"));
743754
const newResource = parseResource({
744755
id: resource?.id ?? nanoid(),
745-
name,
746756
formData,
747757
});
748758
const newVariable: DataSource = {
749759
id: variable?.id ?? nanoid(),
750760
scopeInstanceId,
751-
name,
761+
name: newResource.name,
752762
type: "resource",
753763
resourceId: newResource.id,
754764
};
@@ -942,7 +952,7 @@ export const GraphqlResourceForm = forwardRef<
942952
undefined | PanelApi,
943953
{ variable?: DataSource }
944954
>(({ variable }, ref) => {
945-
const { scope, aliases } = useScope({ variable });
955+
const { scope, aliases } = useResourceScope({ variable });
946956

947957
const resources = useStore($resources);
948958
const resource =

0 commit comments

Comments
 (0)