diff --git a/packages/visual-editor/src/components/Locator.tsx b/packages/visual-editor/src/components/Locator.tsx index 35fd8b885..9651b7623 100644 --- a/packages/visual-editor/src/components/Locator.tsx +++ b/packages/visual-editor/src/components/Locator.tsx @@ -52,7 +52,7 @@ import { } from "../editor/DynamicOptionsSelector.tsx"; import { YextField } from "../editor/YextField.tsx"; import { useDocument } from "../hooks/useDocument.tsx"; -import { Button } from "../internal/puck/ui/button.tsx"; +import { Button } from "./atoms/button.tsx"; import { TranslatableString } from "../types/types.ts"; import { getPreferredDistanceUnit, @@ -1363,7 +1363,6 @@ const LocatorInternal = ({ diff --git a/packages/visual-editor/src/components/directory/DirectoryWrapper.tsx b/packages/visual-editor/src/components/directory/DirectoryWrapper.tsx index 20503295f..3bfd464a6 100644 --- a/packages/visual-editor/src/components/directory/DirectoryWrapper.tsx +++ b/packages/visual-editor/src/components/directory/DirectoryWrapper.tsx @@ -42,7 +42,7 @@ export const DirectoryList = ({ {sortedDirectoryChildren.map((child, idx) => { const childSlug = resolveDirectoryListChildren(streamDocument, child); let label; - switch (streamDocument?.dm_directoryChildren?.meta?.entityType?.id) { + switch (child?.meta?.entityType?.id) { case "dm_country": label = child.c_addressCountryDisplayName ?? child.name; break; diff --git a/packages/visual-editor/src/utils/urls/legacyResolveUrlTemplate.test.ts b/packages/visual-editor/src/utils/urls/legacyResolveUrlTemplate.test.ts index 35ba535dc..11d567d09 100644 --- a/packages/visual-editor/src/utils/urls/legacyResolveUrlTemplate.test.ts +++ b/packages/visual-editor/src/utils/urls/legacyResolveUrlTemplate.test.ts @@ -73,6 +73,29 @@ const mockLocatorMergedDocument: StreamDocument = { }), }; +const mockNewLocatorMergedDocument: StreamDocument = { + name: "Yext", + id: "123", + locale: "en", + address: { + line1: "61 9th Ave", + city: "New York", + region: "NY", + country: "USA", + }, + __: { + codeTemplate: "locator", + entityPageSetUrlTemplates: JSON.stringify({ + primary: "[[address.region]]/location/[[id]]", + includeLocalePrefixForPrimaryLocale: false, + primaryLocale: "en", + }), + }, + _pageset: JSON.stringify({ + type: "LOCATOR", + }), +}; + describe("legacyResolveUrlTemplate with isChild flag", () => { it("handles primary url template on directory pages", () => { expect( @@ -114,6 +137,22 @@ describe("legacyResolveUrlTemplate with isChild flag", () => { ).toBe("es/ny/location/123"); }); + it("handles primary locale on new locator pages", () => { + expect( + legacyResolveUrlTemplate(mockNewLocatorMergedDocument, "", true) + ).toBe("ny/location/123"); + }); + + it("handles non-primary locale on new locator pages", () => { + expect( + legacyResolveUrlTemplate( + { ...mockNewLocatorMergedDocument, locale: "es" }, + "", + true + ) + ).toBe("es/ny/location/123"); + }); + it("uses base entity template (entityPageSetUrlTemplates) for directory pages", () => { const directoryDocWithBothTemplates = { ...mockDirectoryMergedDocument, diff --git a/packages/visual-editor/src/utils/urls/legacyResolveUrlTemplate.ts b/packages/visual-editor/src/utils/urls/legacyResolveUrlTemplate.ts index 7d0ffd66f..61b0df73d 100644 --- a/packages/visual-editor/src/utils/urls/legacyResolveUrlTemplate.ts +++ b/packages/visual-editor/src/utils/urls/legacyResolveUrlTemplate.ts @@ -48,7 +48,12 @@ export const legacyResolveUrlTemplate = ( const legacyResolveUrlTemplateWithTemplates = ( streamDocument: StreamDocument, relativePrefixToRoot: string, - urlTemplates: { primary?: string; alternate?: string } + urlTemplates: { + primary?: string; + alternate?: string; + includeLocalePrefixForPrimaryLocale?: boolean; + primaryLocale?: string; + } ): string | undefined => { const locale = streamDocument.locale || streamDocument?.meta?.locale || ""; if (!locale) { @@ -64,12 +69,25 @@ const legacyResolveUrlTemplateWithTemplates = ( ); } - return buildUrlFromTemplate( - urlTemplate, - streamDocument, - locale, - relativePrefixToRoot + const resolvedUrl = normalizeSlug( + resolveEmbeddedFieldsInString(urlTemplate, streamDocument, locale) ); + if (!resolvedUrl) { + return; + } + + // On sites that have an updated entity pageset that sets pathInfo + // but the locator pageset does not yet set pathInfo, locator links + // will use the legacy URL template resolution but include the new primary locale handling + if ( + urlTemplates.primaryLocale && + (urlTemplates.primaryLocale !== locale || + urlTemplates.includeLocalePrefixForPrimaryLocale) + ) { + return `${relativePrefixToRoot}${normalizeSlug(locale)}/${resolvedUrl}`; + } + + return `${relativePrefixToRoot}${resolvedUrl}`; }; /** @@ -89,23 +107,3 @@ const selectUrlTemplate = ( return urlTemplates.primary || urlTemplates.alternate; } }; - -/** - * Builds a URL from a template string by resolving embedded fields and normalizing the slug. - */ -export const buildUrlFromTemplate = ( - urlTemplate: string, - streamDocument: StreamDocument, - locale: string, - relativePrefixToRoot: string -): string | undefined => { - const normalizedSlug = normalizeSlug( - resolveEmbeddedFieldsInString(urlTemplate, streamDocument, locale) - ); - - if (!normalizedSlug) { - return; - } - - return relativePrefixToRoot + normalizedSlug; -}; diff --git a/packages/visual-editor/src/utils/urls/resolveUrlTemplate.test.ts b/packages/visual-editor/src/utils/urls/resolveUrlTemplate.test.ts index 86795c4ea..2c49966aa 100644 --- a/packages/visual-editor/src/utils/urls/resolveUrlTemplate.test.ts +++ b/packages/visual-editor/src/utils/urls/resolveUrlTemplate.test.ts @@ -44,6 +44,23 @@ const mockDMCityDocument: StreamDocument = { }), }; +const mockLocatorDocument: StreamDocument = { + name: "Locator", + id: "locator", + locale: "en", + __: { + codeTemplate: "locator", + entityPageSetUrlTemplates: JSON.stringify({ + primary: "location/[[address.city]]/[[id]]", + includeLocalePrefixForPrimaryLocale: false, + primaryLocale: "en", + }), + }, + _pageset: JSON.stringify({ + type: "LOCATOR", + }), +}; + const mockChildProfile = { id: "child-profile-1", locale: "en", @@ -191,4 +208,39 @@ describe("resolveUrlTemplateOfChild", () => { resolveUrlTemplateOfChild(mockChildProfile, mockDMCityDocument, "") ).toBe("va/fairfax/2000-university-dr"); }); + + it("resolves locator profile links for primary locale", () => { + expect( + resolveUrlTemplateOfChild(mockChildProfile, mockLocatorDocument, "") + ).toBe("location/fairfax/child-profile-1"); + }); + + it("resolves locator profile links for non-primary locale", () => { + expect( + resolveUrlTemplateOfChild( + { ...mockChildProfile, locale: "es" }, + mockLocatorDocument, + "" + ) + ).toBe("es/location/fairfax/child-profile-1"); + }); + + it("resolves locator profile links for primary locale with includeLocalePrefixForPrimaryLocale", () => { + expect( + resolveUrlTemplateOfChild( + { ...mockChildProfile, locale: "en" }, + { + ...mockLocatorDocument, + __: { + codeTemplate: "locator", + entityPageSetUrlTemplates: JSON.stringify({ + primary: "location/[[address.city]]/[[id]]", + includeLocalePrefixForPrimaryLocale: true, + primaryLocale: "en", + }), + }, + } + ) + ).toBe("en/location/fairfax/child-profile-1"); + }); });