fix(builder): release-candidate walkthrough fixes
- Legacy no-lang-prefix URLs with a query string (e.g. the dev ?devBypassAdmin=true bypass itself, or any bookmarked/shared deep link into the Builder) got their query string percent-encoded into the path instead of preserved (language.guard.ts) - router.createUrlTree([...]) treats a single array element as a literal path segment, so `/edit/branding?devBypassAdmin=true` became `/ru/edit/branding%3FdevBypassAdmin%3Dtrue`, a 0-result route. Switched to router.parseUrl() on the full redirect string so path, query params, and fragment are parsed and preserved correctly. This guard runs on every top-level route in the app (not just Builder), so this was silently breaking any legacy URL with a query string app-wide. - "Reset draft" (Sbrosit' chernovik) left the save-bar showing "unsaved changes" immediately after the reset, even though the reset already discarded everything and cleared the persisted localStorage draft (project-editor.facade.ts resetDraft()) - it updated the in-memory bootstrap and cleared the draft but never resynced lastSavedBootstrap, which the dirty computed diffs against. Now resetDraft() also resets lastSavedBootstrap to match, so the status bar correctly reads as clean right after a full discard. Verified live via browser walkthrough of every Builder section (General, Branding, Theme, Header, Footer, Homepage, Widgets, Static Pages, Languages, Features, Navigation, Preview) plus save/publish/undo/redo/ reset-section/reset-draft/draft-restore flows, the media picker dialog, and the Homepage block / Footer column keyboard-fallback reorder buttons (WCAG 2.1.1 fallback added in the prior a11y pass) - all functioned correctly end-to-end, no console errors, no untranslated i18n keys, no unexpected 4xx/5xx, no layout overflow at desktop or mobile widths. Investigated and flagged, not fixed (needs a design decision, not a bug fix): the static page's actual body content editor (app-marketplace-html-editor, per-locale) is not on the page editor's "Content" tab at all - it only has title/hero-image/thumbnail fields. The real WYSIWYG/HTML editor is nested inside a collapsed <details> disclosure under the "Advanced" tab, labeled "Source HTML (advanced)" as if it were a raw-HTML power-user fallback, when it is in fact the only way to edit a static page's body content. Functions correctly once found/expanded; the placement/labeling just doesn't match the "Content" tab a merchant would expect it under, and moving it is a navigation change beyond this pass's fix-what's-broken scope. npx tsc --noEmit and npm run build both green. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -461,7 +461,17 @@ export class ProjectEditorFacade {
|
||||
}
|
||||
const reset = this.normalize(JSON.parse(JSON.stringify(original)) as BootstrapConfig);
|
||||
this.draftStorage.clear();
|
||||
this.state.update(state => ({ ...state, bootstrap: reset, lastSavedAt: null, draftRestored: false }));
|
||||
this.state.update(state => ({
|
||||
...state,
|
||||
bootstrap: reset,
|
||||
// Reset also clears the persisted draft, so there is nothing pending
|
||||
// to save at this point - keep `lastSavedBootstrap` in sync too,
|
||||
// otherwise `dirty` (computed against it) immediately flags
|
||||
// "unsaved changes" right after a full discard.
|
||||
lastSavedBootstrap: JSON.parse(JSON.stringify(reset)),
|
||||
lastSavedAt: null,
|
||||
draftRestored: false
|
||||
}));
|
||||
this.clearHistory();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,12 @@ export const languageGuard: CanActivateFn = async (route, state) => {
|
||||
if (langObj && !langObj.enabled) {
|
||||
// Known but disabled language — redirect to default lang, keep the rest of the path
|
||||
const pathAfterLang = state.url.slice(1 + lang.length);
|
||||
return router.createUrlTree([`/${defaultLang}${pathAfterLang}`]);
|
||||
return router.parseUrl(`/${defaultLang}${pathAfterLang}`);
|
||||
}
|
||||
|
||||
// Not a recognized language code — treat as a legacy URL without lang prefix
|
||||
return router.createUrlTree([`/${defaultLang}${state.url}`]);
|
||||
// Not a recognized language code — treat as a legacy URL without lang prefix.
|
||||
// Use parseUrl (not createUrlTree with a single path-segment array entry) so
|
||||
// the query string/fragment on state.url are preserved as real query params
|
||||
// instead of being percent-encoded into the path segment.
|
||||
return router.parseUrl(`/${defaultLang}${state.url}`);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user