diff --git a/src/app/features/project-editor/facade/project-editor.facade.ts b/src/app/features/project-editor/facade/project-editor.facade.ts index 32ec9ed..72d27dc 100644 --- a/src/app/features/project-editor/facade/project-editor.facade.ts +++ b/src/app/features/project-editor/facade/project-editor.facade.ts @@ -552,7 +552,37 @@ export class ProjectEditorFacade { const leftOrder = Math.min(...left.sections.map(section => section.order)); const rightOrder = Math.min(...right.sections.map(section => section.order)); return leftOrder - rightOrder; - }) + }), + staticPages: this.normalizeStaticPagesShape(config.staticPages), }; } + + /** + * Backfills `enabled`/`status` on record-format static pages at the + * bootstrap-normalization layer, mirroring (not importing - would create a + * project-editor <-> content-management circular dependency, since + * ContentManagementFacade already depends on this facade) the same default + * ContentPageService.normalizePage applies for display: a page with no + * enabled/status predates this field and was always live, so it defaults + * to enabled+published rather than silently disappearing. Without this, + * exportBootstrap() on a page nobody has touched this session would omit + * both fields (present in the editor's display via normalize-on-read, but + * literally absent from the stored/exported JSON) - the storefront + * resolver was never at risk (it normalizes on every read), but export + * fidelity should match what the editor shows. + */ + private normalizeStaticPagesShape(staticPages: BootstrapConfig['staticPages']): BootstrapConfig['staticPages'] { + if (!staticPages || Array.isArray(staticPages)) { + return staticPages; + } + const result: typeof staticPages = {}; + for (const [key, page] of Object.entries(staticPages)) { + result[key] = { + ...page, + enabled: page.enabled ?? true, + status: page.status ?? 'published', + }; + } + return result; + } } diff --git a/src/app/i18n/en.ts b/src/app/i18n/en.ts index 0035b93..0983504 100644 --- a/src/app/i18n/en.ts +++ b/src/app/i18n/en.ts @@ -921,6 +921,9 @@ export const en: Translations = { emptyTitle: 'No files yet', emptyDescription: 'Upload an image or document to get started.', }, + adminCategories: { + chooseImage: 'Choose image', + }, adminProducts: { emptyTitle: 'No products found', emptyDescription: 'Try adjusting your filters, or create a new product.', diff --git a/src/app/i18n/hy.ts b/src/app/i18n/hy.ts index 465b8af..2af2787 100644 --- a/src/app/i18n/hy.ts +++ b/src/app/i18n/hy.ts @@ -916,6 +916,9 @@ export const hy: Translations = { emptyTitle: 'Ֆայլեր դեռ չկան', emptyDescription: 'Վերբեռնեք պատկեր կամ փաստաթուղթ սկսելու համար։', }, + adminCategories: { + chooseImage: 'Ընտրել պատկեր', + }, adminProducts: { emptyTitle: 'Ապրանքներ չեն գտնվել', emptyDescription: 'Փոխեք ֆիլտրերը կամ ստեղծեք նոր ապրանք։', diff --git a/src/app/i18n/ru.ts b/src/app/i18n/ru.ts index ffb8c7c..44d36af 100644 --- a/src/app/i18n/ru.ts +++ b/src/app/i18n/ru.ts @@ -916,6 +916,9 @@ export const ru: Translations = { emptyTitle: 'Пока нет файлов', emptyDescription: 'Загрузите изображение или документ, чтобы начать.', }, + adminCategories: { + chooseImage: 'Выбрать изображение', + }, adminProducts: { emptyTitle: 'Товары не найдены', emptyDescription: 'Измените фильтры или создайте новый товар.', diff --git a/src/app/i18n/translations.ts b/src/app/i18n/translations.ts index 1f017b8..675276b 100644 --- a/src/app/i18n/translations.ts +++ b/src/app/i18n/translations.ts @@ -923,6 +923,14 @@ export interface Translations { // state consistency fix introduces - NOT the full adminProducts/ // adminUsers/adminMonitoring/adminAnalytics translation surface, which is // still missing entirely (see docs/KNOWN-ISSUES.md, deferred to Sprint 29). + // Shared across branding/footer/static-pages/admin-product/admin-category media + // pickers - despite the namespace name, this is a generic "choose image" label, + // not category-specific. Renaming is a separate cleanup outside this sprint's + // scope; the key was previously referenced by 5 templates but never defined + // anywhere, so it rendered as the literal string "adminCategories.chooseImage". + adminCategories: { + chooseImage: string; + }; adminProducts: { emptyTitle: string; emptyDescription: string;