fix(builder): un-hide and relabel static-page content editor, warn on publish/remove-language

- KNOWN-ISSUES item 11: the WYSIWYG page content editor was buried inside
  a collapsed Advanced <details>, labeled 'Raw HTML (advanced)'. Moved it
  to the top of the Content tab, unwrapped, relabeled 'Page Content' /
  'Содержимое страницы' / 'Эջի բովանդակություն' with a plain-language
  description. Advanced tab keeps genuinely technical fields (id, slug,
  route, custom template).
- Publish (save-bar) and Remove language (languages-section) had no
  confirmation despite being destructive/high-impact — added
  window.confirm guards using the existing builder.confirm* i18n pattern
  (matches resetDraft/resetSection/dirty-guard precedent), all 3 locales.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sdarbinyan
2026-07-25 20:43:43 +04:00
parent 38253f7e83
commit 72846b44b1
8 changed files with 50 additions and 27 deletions

View File

@@ -49,6 +49,25 @@
</app-form-field>
}
<div class="page-editor__content-block">
<h3 class="page-editor__content-heading">{{ 'contentManagement.pageContentLabel' | translate }}</h3>
<p class="page-editor__explain">{{ 'contentManagement.pageContentDesc' | translate }}</p>
@for (locale of locales(); track locale) {
<label class="full page-editor__html-block">
@if (locales().length > 1) {
<span>{{ ('contentManagement.pageContentLabel' | translate) + ' — ' + locale }}</span>
}
<app-marketplace-html-editor
[html]="page().translations[locale]?.html || ''"
(htmlChange)="updateTranslation.emit({ locale, field: 'html', value: $event })"
/>
@if (hasInvalidHtml()) {
<p class="page-editor__error">{{ 'staticPages.invalidHtml' | translate }}</p>
}
</label>
}
</div>
<div class="page-editor__media-grid">
<div class="media-block">
<span class="media-block__label">{{ 'staticPages.heroImageLabel' | translate }}</span>
@@ -193,22 +212,6 @@
<app-form-field [label]="'builder.seoKeywords' | translate">
<app-input [ngModel]="page().seo?.keywords || ''" (ngModelChange)="updateSeo.emit({ keywords: $event })" />
</app-form-field>
<details class="page-editor__html-disclosure">
<summary>{{ 'contentManagement.groupAdvancedHtml' | translate }}</summary>
@for (locale of locales(); track locale) {
<label class="full page-editor__html-block">
<span>{{ 'builder.htmlPreview' | translate }} {{ locale }}</span>
<app-marketplace-html-editor
[html]="page().translations[locale]?.html || ''"
(htmlChange)="updateTranslation.emit({ locale, field: 'html', value: $event })"
/>
@if (hasInvalidHtml()) {
<p class="page-editor__error">{{ 'staticPages.invalidHtml' | translate }}</p>
}
</label>
}
</details>
</div>
}
</div>

View File

@@ -109,17 +109,17 @@
gap: 8px;
}
.page-editor__html-disclosure {
border: 1px solid var(--border-subtle, #e7ece9);
border-radius: 10px;
padding: 10px 14px;
.page-editor__content-block {
display: grid;
gap: 8px;
}
summary {
cursor: pointer;
.page-editor__content-heading {
margin: 0;
font-size: var(--font-size-base, 0.875rem);
font-weight: var(--font-weight-bold, 700);
color: var(--text-primary, #1e3c38);
}
}
.page-editor__html-block {
display: grid;

View File

@@ -37,8 +37,10 @@ export class ProjectEditorSaveBarComponent {
}
publish(): void {
if (confirm(this.translate.t('builder.confirmPublish'))) {
this.facade.publish();
}
}
resetDraft(): void {
if (confirm(this.translate.t('builder.confirmResetDraft'))) {

View File

@@ -59,8 +59,10 @@ export class ProjectEditorLanguagesSectionComponent {
}
removeLocale(code: string): void {
if (confirm(this.translate.t('builder.confirmRemoveLanguage'))) {
this.facade.removeLocale(code);
}
}
setDefault(code: string): void {
this.facade.setDefaultLocale(code);

View File

@@ -574,6 +574,8 @@ export const en: Translations = {
save: 'Save',
publish: 'Publish',
confirmLeaveUnsaved: 'You have unsaved changes. Leave anyway?',
confirmPublish: 'This makes your current changes live on the storefront immediately, replacing what shoppers see now. Continue?',
confirmRemoveLanguage: 'This removes the language and any content translated into it. Shoppers using this language will see the default language instead. Continue?',
promptLinkUrl: 'URL',
promptImageUrl: 'Image URL',
promptEmbedUrl: 'Embed URL',
@@ -1040,6 +1042,8 @@ export const en: Translations = {
groupSharing: 'Sharing',
groupAdvanced: 'Advanced',
groupAdvancedHtml: 'Raw HTML (advanced)',
pageContentLabel: 'Page Content',
pageContentDesc: 'Write and format the text, images, and links shoppers will see on this page.',
seoExplainDesc: 'This is what shows up in search results — a clear title and description help customers find this page.',
seoTitleHelp: 'The headline shown in search results. Keep it short and descriptive.',
seoDescriptionHelp: 'A short summary shown under the title in search results.',

View File

@@ -574,6 +574,8 @@ export const hy: Translations = {
save: 'Պահպանել',
publish: 'Հրապարակել',
confirmLeaveUnsaved: 'Կան չպահված փոփոխություններ։ Այնուամենայնիվ դուրս գա՞լ։',
confirmPublish: 'Սա անմիջապես կկիրառի ընթացիկ փոփոխությունները կայքում՝ փոխարինելով այն, ինչ գնորդներն այժմ տեսնում են։ Շարունակե՞լ։',
confirmRemoveLanguage: 'Սա կհեռացնի լեզուն և դրանով թարգմանված ողջ բովանդակությունը։ Այս լեզվով օգտվող գնորդները կտեսնեն հիմնական լեզուն։ Շարունակե՞լ։',
promptLinkUrl: 'URL',
promptImageUrl: 'Նկարի URL',
promptEmbedUrl: 'Ներդրման URL',
@@ -1040,6 +1042,8 @@ export const hy: Translations = {
groupSharing: 'Տարածում',
groupAdvanced: 'Լրացուցիչ',
groupAdvancedHtml: 'Հում HTML (լրացուցիչ)',
pageContentLabel: 'Էջի բովանդակություն',
pageContentDesc: 'Գրեք և ձևավորեք տեքստը, նկարներն ու հղումները, որոնք գնորդները կտեսնեն այս էջում։',
seoExplainDesc: 'Սա այն է, ինչ երևում է որոնման արդյունքներում․ հստակ վերնագիրն ու նկարագրությունը օգնում են հաճախորդներին գտնել այս էջը։',
seoTitleHelp: 'Վերնագիրը, որ երևում է որոնման արդյունքներում։ Պահեք կարճ և հստակ։',
seoDescriptionHelp: 'Կարճ նկարագրություն՝ վերնագրի տակ, որոնման արդյունքներում։',

View File

@@ -574,6 +574,8 @@ export const ru: Translations = {
save: 'Сохранить',
publish: 'Опубликовать',
confirmLeaveUnsaved: 'Есть несохранённые изменения. Всё равно уйти?',
confirmPublish: 'Это сразу применит текущие изменения на витрине магазина вместо того, что покупатели видят сейчас. Продолжить?',
confirmRemoveLanguage: 'Это удалит язык и весь переведённый на него контент. Покупатели, использующие этот язык, увидят язык по умолчанию. Продолжить?',
promptLinkUrl: 'URL',
promptImageUrl: 'URL изображения',
promptEmbedUrl: 'URL для встраивания',
@@ -1040,6 +1042,8 @@ export const ru: Translations = {
groupSharing: 'Публикация в соцсетях',
groupAdvanced: 'Дополнительно',
groupAdvancedHtml: 'Исходный HTML (дополнительно)',
pageContentLabel: 'Содержимое страницы',
pageContentDesc: 'Напишите и оформите текст, изображения и ссылки, которые увидят покупатели на этой странице.',
seoExplainDesc: 'Это то, что видно в результатах поиска — понятный заголовок и описание помогают клиентам найти страницу.',
seoTitleHelp: 'Заголовок, отображаемый в результатах поиска. Делайте его коротким и понятным.',
seoDescriptionHelp: 'Краткое описание под заголовком в результатах поиска.',

View File

@@ -572,6 +572,8 @@ export interface Translations {
save: string;
publish: string;
confirmLeaveUnsaved: string;
confirmPublish: string;
confirmRemoveLanguage: string;
promptLinkUrl: string;
promptImageUrl: string;
promptEmbedUrl: string;
@@ -1039,6 +1041,8 @@ export interface Translations {
groupSharing: string;
groupAdvanced: string;
groupAdvancedHtml: string;
pageContentLabel: string;
pageContentDesc: string;
seoExplainDesc: string;
seoTitleHelp: string;
seoDescriptionHelp: string;