Skip to content

Commit 5cd30fe

Browse files
authored
feat: unset global variables when delete (#4904)
Global variables will be replaced with "name" or unset when deleted from data variables section. There are few cases to test 1. variable is unset on a few pages when delete 2. variable is unset on inside of slots when delete
1 parent f5b7efe commit 5cd30fe

File tree

2 files changed

+82
-2
lines changed

2 files changed

+82
-2
lines changed

apps/builder/app/shared/data-variables.test.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
ROOT_INSTANCE_ID,
1414
SYSTEM_VARIABLE_ID,
1515
} from "@webstudio-is/sdk";
16+
import { createDefaultPages } from "@webstudio-is/project-build";
1617
import {
1718
computeExpression,
1819
decodeDataVariableName,
@@ -594,3 +595,64 @@ test("prevent rebinding with variables outside of slot content scope", () => {
594595
{ type: "expression", value: "myVariable" },
595596
]);
596597
});
598+
599+
test("unset global variables on all pages when delete", () => {
600+
const globalVariable = new Variable("globalVariable", "");
601+
const pages = createDefaultPages({ rootInstanceId: "homeBodyId" });
602+
pages.pages.push({
603+
id: "",
604+
name: "",
605+
path: "",
606+
title: "",
607+
meta: {},
608+
rootInstanceId: "aboutBodyId",
609+
});
610+
const data = {
611+
pages,
612+
...renderData(
613+
<ws.root ws:id={ROOT_INSTANCE_ID} vars={expression`${globalVariable}`}>
614+
<$.Body ws:id="homeBodyId">
615+
<$.Text ws:id="homeTextId">{expression`${globalVariable}`}</$.Text>
616+
</$.Body>
617+
<$.Body ws:id="aboutBodyId">
618+
<$.Text ws:id="aboutTextId">{expression`${globalVariable}`}</$.Text>
619+
</$.Body>
620+
</ws.root>
621+
),
622+
};
623+
data.instances.delete(ROOT_INSTANCE_ID);
624+
expect(data.dataSources.size).toEqual(1);
625+
const [globalVariableId] = data.dataSources.keys();
626+
deleteVariableMutable(data, globalVariableId);
627+
expect(data.instances.get("homeTextId")?.children).toEqual([
628+
{ type: "expression", value: "globalVariable" },
629+
]);
630+
expect(data.instances.get("aboutTextId")?.children).toEqual([
631+
{ type: "expression", value: "globalVariable" },
632+
]);
633+
});
634+
635+
test("unset global variables in slots when delete", () => {
636+
const globalVariable = new Variable("globalVariable", "");
637+
const data = {
638+
pages: createDefaultPages({ rootInstanceId: "bodyId" }),
639+
...renderData(
640+
<ws.root ws:id={ROOT_INSTANCE_ID} vars={expression`${globalVariable}`}>
641+
<$.Body ws:id="bodyId">
642+
<$.Slot ws:id="slotId">
643+
<$.Fragment ws:id="fragmentId">
644+
<$.Text ws:id="textId">{expression`${globalVariable}`}</$.Text>
645+
</$.Fragment>
646+
</$.Slot>
647+
</$.Body>
648+
</ws.root>
649+
),
650+
};
651+
data.instances.delete(ROOT_INSTANCE_ID);
652+
expect(data.dataSources.size).toEqual(1);
653+
const [globalVariableId] = data.dataSources.keys();
654+
deleteVariableMutable(data, globalVariableId);
655+
expect(data.instances.get("textId")?.children).toEqual([
656+
{ type: "expression", value: "globalVariable" },
657+
]);
658+
});

apps/builder/app/shared/data-variables.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ import {
77
type Resource,
88
type Resources,
99
type WebstudioData,
10+
Pages,
1011
ROOT_INSTANCE_ID,
1112
SYSTEM_VARIABLE_ID,
1213
decodeDataVariableId,
1314
encodeDataVariableId,
15+
findTreeInstanceIds,
1416
findTreeInstanceIdsExcludingSlotDescendants,
1517
systemParameter,
1618
transpileExpression,
@@ -19,6 +21,7 @@ import {
1921
createJsonStringifyProxy,
2022
isPlainObject,
2123
} from "@webstudio-is/sdk/runtime";
24+
import { setUnion } from "./shim";
2225

2326
const allowedJsChars = /[A-Za-z_]/;
2427

@@ -258,23 +261,35 @@ export const findAvailableVariables = ({
258261

259262
const traverseExpressions = ({
260263
startingInstanceId,
264+
pages,
261265
instances,
262266
props,
263267
dataSources,
264268
resources,
265269
update,
266270
}: {
267271
startingInstanceId: Instance["id"];
272+
pages: undefined | Pages;
268273
instances: Instances;
269274
props: Props;
270275
dataSources: DataSources;
271276
resources: Resources;
272277
update: (expression: string, args?: string[]) => void | string;
273278
}) => {
274-
const instanceIds = findTreeInstanceIdsExcludingSlotDescendants(
279+
const pagesList = pages ? [pages.homePage, ...pages.pages] : [];
280+
let instanceIds = findTreeInstanceIdsExcludingSlotDescendants(
275281
instances,
276282
startingInstanceId
277283
);
284+
// global variables can be accessed on all pages and inside of slots
285+
if (startingInstanceId === ROOT_INSTANCE_ID) {
286+
for (const page of pagesList) {
287+
instanceIds = setUnion(
288+
instanceIds,
289+
findTreeInstanceIds(instances, page.rootInstanceId)
290+
);
291+
}
292+
}
278293
const resourceIds = new Set<Resource["id"]>();
279294

280295
for (const instance of instances.values()) {
@@ -365,6 +380,7 @@ export const findUnsetVariableNames = ({
365380
const unsetVariables = new Set<DataSource["name"]>();
366381
traverseExpressions({
367382
startingInstanceId: startingInstanceId,
383+
pages: undefined,
368384
instances,
369385
props,
370386
dataSources,
@@ -408,6 +424,7 @@ export const rebindTreeVariablesMutable = ({
408424
}
409425
traverseExpressions({
410426
startingInstanceId,
427+
pages: undefined,
411428
instances,
412429
props,
413430
dataSources,
@@ -434,7 +451,7 @@ export const rebindTreeVariablesMutable = ({
434451
};
435452

436453
export const deleteVariableMutable = (
437-
data: Omit<WebstudioData, "pages">,
454+
data: Omit<WebstudioData, "pages"> & { pages?: Pages },
438455
variableId: DataSource["id"]
439456
) => {
440457
const dataSource = data.dataSources.get(variableId);
@@ -456,6 +473,7 @@ export const deleteVariableMutable = (
456473
// unset deleted variable in expressions
457474
traverseExpressions({
458475
...data,
476+
pages: data.pages,
459477
startingInstanceId,
460478
update: (expression) => {
461479
expression = unsetExpressionVariables({

0 commit comments

Comments
 (0)