fix(static-pages): stop createPage/duplicatePage from generating colliding slugs/routes
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
createPage() derived its slug from array length (custom-page-${length+1}):
create, delete, create again reliably reproduces a duplicate slug against a
surviving page. duplicatePage() had the same issue with a fixed '-copy'
suffix - duplicating the same page twice collides with the first duplicate.
Both trip the duplicate-slug/route validator on a page the user never
directly touched.
Added uniqueValue() (append -2, -3, ... until free) and used it for both.
Verified live via window.ng.getComponent(): reproduced the exact collision
scenario pre-fix, confirmed no duplicates post-fix (custom-page-6-2,
about-us-copy/about-us-copy-2).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -156,8 +156,28 @@ export class StaticPagesEditorComponent {
|
||||
this.mediaPickerOpen = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends `-2`, `-3`, ... to `candidate` until it's not in `existing`.
|
||||
* createPage()/duplicatePage() both used to derive slugs/routes from array
|
||||
* length or a fixed "-copy" suffix, which reproducibly collides with an
|
||||
* existing page (create, delete, create again; or duplicate the same page
|
||||
* twice) - the duplicate then trips the duplicate-slug/route validator
|
||||
* on a page the user never touched.
|
||||
*/
|
||||
private uniqueValue(candidate: string, existing: Set<string>): string {
|
||||
if (!existing.has(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
let suffix = 2;
|
||||
while (existing.has(`${candidate}-${suffix}`)) {
|
||||
suffix++;
|
||||
}
|
||||
return `${candidate}-${suffix}`;
|
||||
}
|
||||
|
||||
createPage(): void {
|
||||
const slug = `custom-page-${this.allPages().length + 1}`;
|
||||
const existingSlugs = new Set(this.allPages().map(page => page.slug));
|
||||
const slug = this.uniqueValue(`custom-page-${this.allPages().length + 1}`, existingSlugs);
|
||||
const page: ContentPage = {
|
||||
id: `page-${Date.now()}`,
|
||||
slug,
|
||||
@@ -189,11 +209,13 @@ export class StaticPagesEditorComponent {
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
const existingSlugs = new Set(this.allPages().map(page => page.slug));
|
||||
const existingRoutes = new Set(this.allPages().map(page => page.route));
|
||||
const clone: ContentPage = {
|
||||
...source,
|
||||
id: `page-${Date.now()}`,
|
||||
slug: `${source.slug}-copy`,
|
||||
route: `${source.route}-copy`,
|
||||
slug: this.uniqueValue(`${source.slug}-copy`, existingSlugs),
|
||||
route: this.uniqueValue(`${source.route}-copy`, existingRoutes),
|
||||
order: this.allPages().length + 1,
|
||||
status: 'draft',
|
||||
translations: Object.fromEntries(Object.entries(source.translations).map(([locale, t]) => [locale, { ...t }])),
|
||||
|
||||
Reference in New Issue
Block a user