From 97bd4b2b9572f84e5ea373dd09fc7a7a7746df22 Mon Sep 17 00:00:00 2001 From: sdarbinyan Date: Wed, 15 Jul 2026 04:11:18 +0400 Subject: [PATCH] feat(content-management): expose SEO fields in Static Pages editor ContentPage.seo (title/description/keywords/canonical/ogTitle/ogDescription/ ogImage) was already modeled and serialized to bootstrap JSON but had no editable UI. Added updateSeo() to the component and a translated SEO fieldset using app-form-field/app-input. Added seoSection/seoTitle/seoDescription/ seoKeywords/seoCanonical/seoOgTitle/seoOgDescription/seoOgImage translation keys to en/ru/hy and the Translations type. Verified in browser at /edit/static-pages: SEO section renders with translated labels for all three mock pages. --- .../static-pages-editor.component.html | 25 +++++++++++++++++++ .../static-pages-editor.component.scss | 9 +++++++ .../static-pages-editor.component.ts | 12 ++++++++- src/app/i18n/en.ts | 8 ++++++ src/app/i18n/hy.ts | 8 ++++++ src/app/i18n/ru.ts | 8 ++++++ src/app/i18n/translations.ts | 8 ++++++ 7 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/app/features/content-management/components/static-pages-editor.component.html b/src/app/features/content-management/components/static-pages-editor.component.html index a167f93..e516477 100644 --- a/src/app/features/content-management/components/static-pages-editor.component.html +++ b/src/app/features/content-management/components/static-pages-editor.component.html @@ -71,6 +71,31 @@ } + +

{{ 'builder.seoSection' | translate }}

+
+ + + + + + + + + + + + + + + + + + + + + +
} diff --git a/src/app/features/content-management/components/static-pages-editor.component.scss b/src/app/features/content-management/components/static-pages-editor.component.scss index 2fafaba..fce1121 100644 --- a/src/app/features/content-management/components/static-pages-editor.component.scss +++ b/src/app/features/content-management/components/static-pages-editor.component.scss @@ -18,6 +18,15 @@ color: var(--text-primary, #1e3c38); } +.page-card__subheading { + margin: 4px 0 0; + font-size: 0.875rem; + font-weight: 700; + color: var(--text-secondary, #5f6e6a); + text-transform: uppercase; + letter-spacing: 0.04em; +} + .toggle-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); diff --git a/src/app/features/content-management/components/static-pages-editor.component.ts b/src/app/features/content-management/components/static-pages-editor.component.ts index b09462e..1721fbb 100644 --- a/src/app/features/content-management/components/static-pages-editor.component.ts +++ b/src/app/features/content-management/components/static-pages-editor.component.ts @@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/c import { FormsModule } from '@angular/forms'; import { ProjectEditorFacade } from '../../project-editor/facade/project-editor.facade'; import { ContentManagementFacade } from '../facade/content-management.facade'; -import { ContentPage } from '../models/content-page.model'; +import { ContentPage, ContentPageSeoConfig } from '../models/content-page.model'; import { TranslatePipe } from '../../../i18n/translate.pipe'; import { MarketplaceHtmlEditorComponent } from '../../project-editor/components/html-editor/marketplace-html-editor.component'; import { ButtonComponent } from '../../../shared/ui/button/button.component'; @@ -81,6 +81,16 @@ export class StaticPagesEditorComponent { }))); } + updateSeo(id: string, patch: Partial): void { + this.persist(this.pages().map(page => page.id !== id ? page : ({ + ...page, + seo: { + ...(page.seo ?? {}), + ...patch, + } + }))); + } + move(id: string, direction: -1 | 1): void { const pages = [...this.pages()].sort((a, b) => a.order - b.order); const index = pages.findIndex(page => page.id === id); diff --git a/src/app/i18n/en.ts b/src/app/i18n/en.ts index 3b214f6..0d8e3fe 100644 --- a/src/app/i18n/en.ts +++ b/src/app/i18n/en.ts @@ -465,6 +465,14 @@ export const en: Translations = { orderLabel: 'Order', translationTitle: 'Translation Title', htmlPreview: 'HTML', + seoSection: 'SEO', + seoTitle: 'SEO Title', + seoDescription: 'SEO Description', + seoKeywords: 'Keywords', + seoCanonical: 'Canonical URL', + seoOgTitle: 'OG Title', + seoOgDescription: 'OG Description', + seoOgImage: 'OG Image', visible: 'Visible', layoutLabel: 'Layout', columns: 'Columns', diff --git a/src/app/i18n/hy.ts b/src/app/i18n/hy.ts index 6f99a8e..124acc4 100644 --- a/src/app/i18n/hy.ts +++ b/src/app/i18n/hy.ts @@ -465,6 +465,14 @@ export const hy: Translations = { orderLabel: 'Հերթականություն', translationTitle: 'Թարգմանության վերնագիր', htmlPreview: 'HTML', + seoSection: 'SEO', + seoTitle: 'SEO վերնագիր', + seoDescription: 'SEO նկարագրություն', + seoKeywords: 'Հիմնաբառեր', + seoCanonical: 'Canonical URL', + seoOgTitle: 'OG վերնագիր', + seoOgDescription: 'OG նկարագրություն', + seoOgImage: 'OG պատկեր', visible: 'Տեսանելի', layoutLabel: 'Layout', columns: 'Սյուներ', diff --git a/src/app/i18n/ru.ts b/src/app/i18n/ru.ts index 2eda4ca..d9e4c11 100644 --- a/src/app/i18n/ru.ts +++ b/src/app/i18n/ru.ts @@ -465,6 +465,14 @@ export const ru: Translations = { orderLabel: 'Порядок', translationTitle: 'Заголовок перевода', htmlPreview: 'HTML', + seoSection: 'SEO', + seoTitle: 'SEO заголовок', + seoDescription: 'SEO описание', + seoKeywords: 'Ключевые слова', + seoCanonical: 'Canonical URL', + seoOgTitle: 'OG заголовок', + seoOgDescription: 'OG описание', + seoOgImage: 'OG изображение', visible: 'Видимость', layoutLabel: 'Layout', columns: 'Колонки', diff --git a/src/app/i18n/translations.ts b/src/app/i18n/translations.ts index 91ec3f8..95d72f0 100644 --- a/src/app/i18n/translations.ts +++ b/src/app/i18n/translations.ts @@ -463,6 +463,14 @@ export interface Translations { orderLabel: string; translationTitle: string; htmlPreview: string; + seoSection: string; + seoTitle: string; + seoDescription: string; + seoKeywords: string; + seoCanonical: string; + seoOgTitle: string; + seoOgDescription: string; + seoOgImage: string; visible: string; layoutLabel: string; columns: string;