Skip to content

Commit 4cd51fa

Browse files
authored
feat: select the page when opening the page settings (#4375)
Closes #4372 Editing another page settings is confusing to users and complicates the logic. Win-win
1 parent bac416c commit 4cd51fa

File tree

5 files changed

+66
-133
lines changed

5 files changed

+66
-133
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { describe, expect, test } from "@jest/globals";
2+
import { setEnv } from "@webstudio-is/feature-flags";
23
import { createDefaultPages } from "@webstudio-is/project-build";
34
import {
45
isRootFolder,
@@ -20,13 +21,13 @@ import {
2021
import {
2122
$dataSourceVariables,
2223
$dataSources,
23-
$editingPageId,
2424
$pages,
2525
$resourceValues,
2626
$selectedPageId,
2727
} from "~/shared/nano-states";
2828
import { registerContainers } from "~/shared/sync";
2929

30+
setEnv("*");
3031
registerContainers();
3132

3233
const createPages = () => {
@@ -396,7 +397,7 @@ describe("deleteFolderWithChildrenMutable", () => {
396397
});
397398
});
398399

399-
test("page root scope should rely on editing page", () => {
400+
test("page root scope should rely on selected page", () => {
400401
const pages = createDefaultPages({
401402
rootInstanceId: "homeRootId",
402403
homePageId: "homePageId",
@@ -412,8 +413,7 @@ test("page root scope should rely on editing page", () => {
412413
systemDataSourceId: "system",
413414
});
414415
$pages.set(pages);
415-
$selectedPageId.set("homePageId");
416-
$editingPageId.set("pageId");
416+
$selectedPageId.set("pageId");
417417
$dataSources.set(
418418
toMap([
419419
{
@@ -447,7 +447,7 @@ test("page root scope should use variable and resource values", () => {
447447
systemDataSourceId: "system",
448448
})
449449
);
450-
$editingPageId.set("homePageId");
450+
$selectedPageId.set("homePageId");
451451
$dataSources.set(
452452
toMap([
453453
{
@@ -494,7 +494,7 @@ test("page root scope should prefill default system variable value", () => {
494494
systemDataSourceId: "systemId",
495495
})
496496
);
497-
$editingPageId.set("homePageId");
497+
$selectedPageId.set("homePageId");
498498
$dataSources.set(
499499
toMap([
500500
{

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

Lines changed: 11 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
type Page,
55
type Folder,
66
type WebstudioData,
7-
type System,
87
Pages,
98
findPageByIdOrPath,
109
getPagePath,
@@ -19,16 +18,12 @@ import {
1918
updateWebstudioData,
2019
} from "~/shared/instance-utils";
2120
import {
22-
$dataSourceVariables,
2321
$dataSources,
24-
$editingPageId,
2522
$pages,
26-
$publishedOrigin,
27-
$resourceValues,
2823
$selectedInstanceSelector,
24+
$selectedPage,
2925
$selectedPageId,
30-
getPageDefaultSystem,
31-
mergeSystem,
26+
$variableValuesByInstanceSelector,
3227
} from "~/shared/nano-states";
3328
import { insertPageCopyMutable } from "~/shared/page-utils";
3429

@@ -244,75 +239,20 @@ export const deleteFolderWithChildrenMutable = (
244239
};
245240
};
246241

247-
const $editingPage = computed(
248-
[$editingPageId, $pages],
249-
(editingPageId, pages) => {
250-
if (editingPageId === undefined || pages === undefined) {
251-
return;
252-
}
253-
return findPageByIdOrPath(editingPageId, pages);
254-
}
255-
);
256-
257-
const $editingPagePath = computed($editingPage, (page) => page?.path);
258-
259-
const $editingPageHistory = computed($editingPage, (page) => page?.history);
260-
261-
const $editingPageDefaultSystem = computed(
262-
[$publishedOrigin, $editingPagePath, $editingPageHistory],
263-
(origin, path, history) => getPageDefaultSystem({ origin, path, history })
264-
);
265-
266-
const $pageRootVariableValues = computed(
267-
[
268-
$editingPage,
269-
$dataSources,
270-
$dataSourceVariables,
271-
$resourceValues,
272-
$editingPageDefaultSystem,
273-
],
274-
(page, dataSources, dataSourceVariables, resourceValues, defaultSystem) => {
275-
const variableValues = new Map<string, unknown>();
276-
if (page === undefined) {
277-
return variableValues;
278-
}
279-
for (const variable of dataSources.values()) {
280-
if (variable.scopeInstanceId !== page.rootInstanceId) {
281-
continue;
282-
}
283-
if (variable.type === "variable") {
284-
const value = dataSourceVariables.get(variable.id);
285-
variableValues.set(variable.id, value ?? variable.value.value);
286-
}
287-
if (variable.type === "parameter") {
288-
const value = dataSourceVariables.get(variable.id);
289-
variableValues.set(variable.id, value);
290-
if (variable.id === page.systemDataSourceId) {
291-
variableValues.set(
292-
variable.id,
293-
mergeSystem(defaultSystem, value as undefined | System)
294-
);
295-
}
296-
}
297-
if (variable.type === "resource") {
298-
const value = resourceValues.get(variable.resourceId);
299-
variableValues.set(variable.id, value);
300-
}
301-
}
302-
return variableValues;
303-
}
304-
);
305-
306242
export const $pageRootScope = computed(
307-
[$editingPage, $pageRootVariableValues, $dataSources],
308-
(editingPage, pageRootVariableValues, dataSources) => {
243+
[$selectedPage, $variableValuesByInstanceSelector, $dataSources],
244+
(page, variableValuesByInstanceSelector, dataSources) => {
309245
const scope: Record<string, unknown> = {};
310246
const aliases = new Map<string, string>();
311247
const defaultValues = new Map<string, unknown>();
312-
if (editingPage === undefined) {
248+
if (page === undefined) {
313249
return { variableValues: defaultValues, scope, aliases };
314250
}
315-
for (const [dataSourceId, value] of pageRootVariableValues) {
251+
const values =
252+
variableValuesByInstanceSelector.get(
253+
JSON.stringify([page.rootInstanceId])
254+
) ?? new Map<string, unknown>();
255+
for (const [dataSourceId, value] of values) {
316256
const dataSource = dataSources.get(dataSourceId);
317257
if (dataSource === undefined) {
318258
continue;
@@ -321,7 +261,7 @@ export const $pageRootScope = computed(
321261
scope[name] = value;
322262
aliases.set(name, dataSource.name);
323263
}
324-
return { variableValues: pageRootVariableValues, scope, aliases };
264+
return { variableValues: values, scope, aliases };
325265
}
326266
);
327267

apps/builder/app/builder/features/pages/pages.tsx

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -434,19 +434,19 @@ const newPageId = "new-page";
434434

435435
const PageEditor = ({
436436
editingPageId,
437-
setEditingPageId,
437+
onClose,
438438
}: {
439439
editingPageId: string;
440-
setEditingPageId: (pageId?: string) => void;
440+
onClose: () => void;
441441
}) => {
442442
const currentPageId = useStore($selectedPageId);
443443

444444
if (editingPageId === newPageId) {
445445
return (
446446
<NewPageSettings
447-
onClose={() => setEditingPageId(undefined)}
447+
onClose={onClose}
448448
onSuccess={(pageId) => {
449-
setEditingPageId(undefined);
449+
onClose();
450450
switchPage(pageId);
451451
}}
452452
/>
@@ -455,9 +455,9 @@ const PageEditor = ({
455455

456456
return (
457457
<PageSettings
458-
onClose={() => setEditingPageId(undefined)}
458+
onClose={onClose}
459459
onDelete={() => {
460-
setEditingPageId(undefined);
460+
onClose();
461461
// switch to home page when deleted currently selected page
462462
if (editingPageId === currentPageId) {
463463
const pages = $pages.get();
@@ -467,7 +467,7 @@ const PageEditor = ({
467467
}
468468
}}
469469
onDuplicate={(newPageId) => {
470-
setEditingPageId(undefined);
470+
onClose();
471471
switchPage(newPageId);
472472
}}
473473
pageId={editingPageId}
@@ -478,29 +478,25 @@ const PageEditor = ({
478478

479479
const FolderEditor = ({
480480
editingFolderId,
481-
setEditingFolderId,
481+
onClose,
482482
}: {
483483
editingFolderId: string;
484-
setEditingFolderId: (pageId?: string) => void;
484+
onClose: () => void;
485485
}) => {
486486
if (editingFolderId === newFolderId) {
487487
return (
488488
<NewFolderSettings
489-
onClose={() => setEditingFolderId(undefined)}
490-
onSuccess={() => {
491-
setEditingFolderId(undefined);
492-
}}
493489
key={newFolderId}
490+
onClose={onClose}
491+
onSuccess={onClose}
494492
/>
495493
);
496494
}
497495

498496
return (
499497
<FolderSettings
500-
onClose={() => setEditingFolderId(undefined)}
501-
onDelete={() => {
502-
setEditingFolderId(undefined);
503-
}}
498+
onClose={onClose}
499+
onDelete={onClose}
504500
folderId={editingFolderId}
505501
key={editingFolderId}
506502
/>
@@ -567,7 +563,13 @@ export const PagesPanel = ({ onClose }: { onClose: () => void }) => {
567563
onClose();
568564
}}
569565
editingItemId={editingItemId}
570-
onEdit={$editingPageId.set}
566+
onEdit={(itemId) => {
567+
// always select page when edit its settings
568+
if (itemId && isFolder(itemId, pages.folders) === false) {
569+
$selectedPageId.set(itemId);
570+
}
571+
$editingPageId.set(itemId);
572+
}}
571573
/>
572574

573575
<ExtendedPanel isOpen={editingItemId !== undefined}>
@@ -576,12 +578,12 @@ export const PagesPanel = ({ onClose }: { onClose: () => void }) => {
576578
{isFolder(editingItemId, pages.folders) ? (
577579
<FolderEditor
578580
editingFolderId={editingItemId}
579-
setEditingFolderId={$editingPageId.set}
581+
onClose={() => $editingPageId.set(undefined)}
580582
/>
581583
) : (
582584
<PageEditor
583585
editingPageId={editingItemId}
584-
setEditingPageId={$editingPageId.set}
586+
onClose={() => $editingPageId.set(undefined)}
585587
/>
586588
)}
587589
</>

apps/builder/app/shared/nano-states/props.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -497,9 +497,6 @@ export const $variableValuesByInstanceSelector = computed(
497497
) => {
498498
const [instanceId] = instanceSelector;
499499
const instance = instances.get(instanceId);
500-
if (instance === undefined) {
501-
return;
502-
}
503500

504501
let variableValues = new Map<string, unknown>(parentVariableValues);
505502
variableValuesByInstanceSelector.set(
@@ -563,6 +560,10 @@ export const $variableValuesByInstanceSelector = computed(
563560
}
564561
}
565562

563+
if (instance === undefined) {
564+
return;
565+
}
566+
566567
if (instance.component === collectionComponent) {
567568
const data = propValues.get("data");
568569
const itemVariableId = parameters.get("item");

apps/builder/app/shared/nano-states/variables.ts

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,35 @@ export const $dataSourceVariables = atom<Map<DataSource["id"], unknown>>(
1313

1414
export const $resourceValues = atom(new Map<Resource["id"], unknown>());
1515

16-
export const getPageDefaultSystem = ({
17-
origin,
18-
path,
19-
history,
20-
}: {
21-
origin: string;
22-
path?: string;
23-
history?: string[];
24-
}) => {
25-
const defaultSystem: System = {
26-
params: {},
27-
search: {},
28-
origin,
29-
};
30-
if (path) {
31-
const tokens = tokenizePathnamePattern(path);
32-
// try to match the first item in history to let user
33-
// see the page without manually entering params
34-
// or selecting them in address bar
35-
const matchedParams = history
36-
? matchPathnamePattern(path, history[0])
37-
: undefined;
38-
for (const token of tokens) {
39-
if (token.type === "param") {
40-
defaultSystem.params[token.name] =
41-
matchedParams?.[token.name] ?? undefined;
42-
}
43-
}
44-
}
45-
return defaultSystem;
46-
};
47-
4816
const $selectedPagePath = computed($selectedPage, (page) => page?.path);
4917

5018
const $selectedPageHistory = computed($selectedPage, (page) => page?.history);
5119

5220
export const $selectedPageDefaultSystem = computed(
5321
[$publishedOrigin, $selectedPagePath, $selectedPageHistory],
54-
(origin, path, history) => getPageDefaultSystem({ origin, path, history })
22+
(origin, path, history) => {
23+
const defaultSystem: System = {
24+
params: {},
25+
search: {},
26+
origin,
27+
};
28+
if (path) {
29+
const tokens = tokenizePathnamePattern(path);
30+
// try to match the first item in history to let user
31+
// see the page without manually entering params
32+
// or selecting them in address bar
33+
const matchedParams = history
34+
? matchPathnamePattern(path, history[0])
35+
: undefined;
36+
for (const token of tokens) {
37+
if (token.type === "param") {
38+
defaultSystem.params[token.name] =
39+
matchedParams?.[token.name] ?? undefined;
40+
}
41+
}
42+
}
43+
return defaultSystem;
44+
}
5545
);
5646

5747
export const mergeSystem = (left: System, right?: System): System => {

0 commit comments

Comments
 (0)