diff --git a/apps/builder/app/builder/features/sidebar-left/panels/pages/address-bar.tsx b/apps/builder/app/builder/features/sidebar-left/panels/pages/address-bar.tsx index 56f6be9552..9b1c0f3ca5 100644 --- a/apps/builder/app/builder/features/sidebar-left/panels/pages/address-bar.tsx +++ b/apps/builder/app/builder/features/sidebar-left/panels/pages/address-bar.tsx @@ -1,16 +1,35 @@ -import { Fragment, useId, useState } from "react"; -import { compilePathnamePattern, parsePathnamePattern } from "./url-pattern"; -import { Grid, InputField, Label } from "@webstudio-is/design-system"; +import { computed } from "nanostores"; import { useStore } from "@nanostores/react"; -import { $dataSourceVariables } from "~/shared/nano-states"; +import { Fragment, useEffect, useId, useState } from "react"; +import { + Button, + Grid, + InputField, + Label, + Tooltip, +} from "@webstudio-is/design-system"; +import { CheckMarkIcon, CopyIcon, LinkIcon } from "@webstudio-is/icons"; import type { DataSource } from "@webstudio-is/sdk"; +import { $dataSourceVariables, $domains, $project } from "~/shared/nano-states"; +import env from "~/shared/env"; +import { compilePathnamePattern, parsePathnamePattern } from "./url-pattern"; + +const $publishedOrigin = computed([$project, $domains], (project, domains) => { + const customDomain: string | undefined = domains[0]; + const projectDomain = `${project?.domain}.${ + env.PUBLISHER_HOST ?? "wstd.work" + }`; + const domain = customDomain ?? projectDomain; + const publishedUrl = new URL(`https://${domain}`); + return publishedUrl.origin; +}); type PathParams = Record; export type AddressBarApi = { pathParamNames: string[]; pathParams: PathParams; - compiledPath: string; + pageUrl: string; updatePathParam: (name: string, value: string) => void; savePathParams: () => void; }; @@ -40,7 +59,9 @@ export const useAddressBar = ({ : (dataSourceVariables.get(dataSourceId) as Record); const pathParams = storedParams ?? localParams; + const publishedOrigin = useStore($publishedOrigin); const compiledPath = compilePathnamePattern(path, pathParams); + const pageUrl = `${publishedOrigin}${compiledPath}`; const updatePathParam: AddressBarApi["updatePathParam"] = (name, value) => { // delete stale fields @@ -70,14 +91,74 @@ export const useAddressBar = ({ return { pathParamNames, pathParams, - compiledPath, + pageUrl, updatePathParam, savePathParams, }; }; +const CopyPageUrl = ({ pageUrl }: { pageUrl: string }) => { + const [copyState, setCopyState] = useState<"copy" | "copied">("copy"); + + // reset copied state after 2 seconds + useEffect(() => { + if (copyState === "copied") { + const timeoutId = setTimeout(() => { + setCopyState("copy"); + }, 2000); + return () => { + clearTimeout(timeoutId); + }; + } + }, [copyState]); + + let copyIcon = ( + <> + + + + ); + if (copyState === "copied") { + copyIcon = ; + } + + const parsed = new URL(pageUrl); + const pageDomainAndPath = `${parsed.host}${parsed.pathname}`; + + return ( + + + + ); +}; + export const AddressBar = ({ addressBar }: { addressBar: AddressBarApi }) => { - const { pathParamNames, pathParams, updatePathParam } = addressBar; + const { pathParamNames, pathParams, pageUrl, updatePathParam } = addressBar; const id = useId(); return ( @@ -93,6 +174,7 @@ export const AddressBar = ({ addressBar }: { addressBar: AddressBarApi }) => { /> ))} + ); }; diff --git a/apps/builder/app/builder/features/sidebar-left/panels/pages/custom-metadata.tsx b/apps/builder/app/builder/features/sidebar-left/panels/pages/custom-metadata.tsx index 58e5f67f47..bda9772894 100644 --- a/apps/builder/app/builder/features/sidebar-left/panels/pages/custom-metadata.tsx +++ b/apps/builder/app/builder/features/sidebar-left/panels/pages/custom-metadata.tsx @@ -60,7 +60,6 @@ const MetadataItem = (props: { = (event) => event.target.select(); -const CopyPageDomainAndPathButton = ({ - pageDomainAndPath, -}: { - pageDomainAndPath: string; -}) => { - const [pathIconState, setPathIconState] = useState< - "link" | "copy" | "checkmark" - >("link"); - - let pathIcon = ; - if (pathIconState === "checkmark") { - pathIcon = ; - } else if (pathIconState === "link") { - pathIcon = ; - } - - return ( - - - - ); -}; - const FormFields = ({ addressBar, disabled, @@ -336,27 +282,6 @@ const FormFields = ({ const faviconUrl = faviconAsset?.type === "image" ? faviconAsset.name : ""; - const project = $project.get(); - const customDomain: string | undefined = $domains.get()[0]; - const projectDomain = `${project?.domain}.${ - env.PUBLISHER_HOST ?? "wstd.work" - }`; - const domain = customDomain ?? projectDomain; - - const publishedUrl = new URL(`https://${domain}`); - - const foldersPath = getPagePath(values.parentFolderId, pages); - - const pageDomainAndPath = [ - publishedUrl.host, - foldersPath, - addressBar.compiledPath, - ] - .filter(Boolean) - .join("/") - .replace(/\/+/g, "/"); - const pageUrl = `https://${pageDomainAndPath}`; - const title = String(computeExpression(values.title, variableValues)); const description = String( computeExpression(values.description, variableValues) @@ -379,7 +304,6 @@ const FormFields = ({