diff --git a/apps/builder/app/builder/features/address-bar.tsx b/apps/builder/app/builder/features/address-bar.tsx index f905baab1b68..3ea4318a36c2 100644 --- a/apps/builder/app/builder/features/address-bar.tsx +++ b/apps/builder/app/builder/features/address-bar.tsx @@ -32,7 +32,6 @@ import { ROOT_FOLDER_ID, getPagePath, type System, - findPageByIdOrPath, } from "@webstudio-is/sdk"; import { $dataSourceVariables, @@ -47,7 +46,7 @@ import { matchPathnamePattern, tokenizePathnamePattern, } from "~/builder/shared/url-pattern"; -import { serverSyncStore } from "~/shared/sync"; +import { savePathInHistory } from "~/shared/pages"; const $selectedPagePath = computed([$selectedPage, $pages], (page, pages) => { if (pages === undefined || page === undefined) { @@ -80,25 +79,6 @@ const $selectedPageHistory = computed( (page) => page?.history ?? [] ); -/** - * put new path into the beginning of history - * and drop paths in the end when exceeded 20 - */ -const savePathInHistory = (path: string, pageId: string) => { - serverSyncStore.createTransaction([$pages], (pages) => { - if (pages === undefined) { - return; - } - const page = findPageByIdOrPath(pageId, pages); - if (page === undefined) { - return; - } - const history = Array.from(page.history ?? []); - history.unshift(path); - page.history = Array.from(new Set(history)).slice(0, 20); - }); -}; - const useCopyUrl = (pageUrl: string) => { const [copyState, setCopyState] = useState<"copy" | "copied">("copy"); // reset copied state after 2 seconds @@ -342,7 +322,7 @@ const AddressBar = forwardRef< } updateSystem(page, { params: newParams }); const compiledPath = compilePathnamePattern(tokens, newParams); - savePathInHistory(compiledPath, page.id); + savePathInHistory(page.id, compiledPath); if (errors.size === 0) { onSubmit(); } diff --git a/apps/builder/app/canvas/interceptor.ts b/apps/builder/app/canvas/interceptor.ts index 21c5c36ce73e..e46ffe3567c5 100644 --- a/apps/builder/app/canvas/interceptor.ts +++ b/apps/builder/app/canvas/interceptor.ts @@ -11,7 +11,7 @@ import { $selectedPage, updateSystem, } from "~/shared/nano-states"; -import { switchPage } from "~/shared/pages"; +import { savePathInHistory, switchPage } from "~/shared/pages"; const isAbsoluteUrl = (href: string) => { try { @@ -59,6 +59,7 @@ const switchPageAndUpdateSystem = (href: string, formData?: FormData) => { const search = Object.fromEntries(pageHref.searchParams); switchPage(page.id, pageHref.hash); updateSystem(page, { params, search }); + savePathInHistory(page.id, pageHref.pathname); break; } } diff --git a/apps/builder/app/shared/pages/index.ts b/apps/builder/app/shared/pages/index.ts index d270d13b9cf2..2ccb47c60474 100644 --- a/apps/builder/app/shared/pages/index.ts +++ b/apps/builder/app/shared/pages/index.ts @@ -1 +1,2 @@ export * from "./use-switch-page"; +export * from "./pages"; diff --git a/apps/builder/app/shared/pages/pages.test.ts b/apps/builder/app/shared/pages/pages.test.ts new file mode 100644 index 000000000000..5e363c3e7876 --- /dev/null +++ b/apps/builder/app/shared/pages/pages.test.ts @@ -0,0 +1,65 @@ +import { describe, expect, test } from "@jest/globals"; +import type { Page, Pages } from "@webstudio-is/sdk"; +import { $pages } from "~/shared/nano-states"; +import { registerContainers } from "~/shared/sync"; +import { savePathInHistory } from "./pages"; + +registerContainers(); + +const getInitialPages = (page: Page): Pages => ({ + folders: [ + { + id: "rootId", + name: "", + slug: "", + children: ["homeId", "dynamicId"], + }, + ], + homePage: { + id: "homeId", + path: "", + name: "", + title: "", + meta: {}, + rootInstanceId: "", + systemDataSourceId: "", + }, + pages: [page], +}); + +describe("history", () => { + test("add new path at the start", () => { + $pages.set( + getInitialPages({ + id: "dynamicId", + path: "/blog/:date/post/:slug", + name: "", + title: "", + meta: {}, + rootInstanceId: "", + systemDataSourceId: "", + }) + ); + savePathInHistory("dynamicId", "/path1"); + expect($pages.get()?.pages[0].history).toEqual(["/path1"]); + savePathInHistory("dynamicId", "/path2"); + expect($pages.get()?.pages[0].history).toEqual(["/path2", "/path1"]); + }); + + test("move existing path to the start", () => { + $pages.set( + getInitialPages({ + id: "dynamicId", + path: "/blog/:date/post/:slug", + name: "", + title: "", + meta: {}, + rootInstanceId: "", + systemDataSourceId: "", + history: ["/path2", "/path1"], + }) + ); + savePathInHistory("dynamicId", "/path1"); + expect($pages.get()?.pages[0].history).toEqual(["/path1", "/path2"]); + }); +}); diff --git a/apps/builder/app/shared/pages/pages.ts b/apps/builder/app/shared/pages/pages.ts new file mode 100644 index 000000000000..4c7c6bef5a37 --- /dev/null +++ b/apps/builder/app/shared/pages/pages.ts @@ -0,0 +1,22 @@ +import { findPageByIdOrPath } from "@webstudio-is/sdk"; +import { $pages } from "../nano-states"; +import { serverSyncStore } from "../sync"; + +/** + * put new path into the beginning of history + * and drop paths in the end when exceeded 20 + */ +export const savePathInHistory = (pageId: string, path: string) => { + serverSyncStore.createTransaction([$pages], (pages) => { + if (pages === undefined) { + return; + } + const page = findPageByIdOrPath(pageId, pages); + if (page === undefined) { + return; + } + const history = Array.from(page.history ?? []); + history.unshift(path); + page.history = Array.from(new Set(history)).slice(0, 20); + }); +};