diff --git a/src/app/features/project-editor/components/save-bar/project-editor-save-bar.component.html b/src/app/features/project-editor/components/save-bar/project-editor-save-bar.component.html new file mode 100644 index 0000000..175bf9d --- /dev/null +++ b/src/app/features/project-editor/components/save-bar/project-editor-save-bar.component.html @@ -0,0 +1,19 @@ +
+
+ {{ (status() === 'published' ? 'builder.statusPublished' : 'builder.statusDraft') | translate }} + @if (dirty()) { + {{ 'builder.unsavedChanges' | translate }} + } + @if (issues().length > 0) { + + } +
+
+ + +
+
diff --git a/src/app/features/project-editor/components/save-bar/project-editor-save-bar.component.scss b/src/app/features/project-editor/components/save-bar/project-editor-save-bar.component.scss new file mode 100644 index 0000000..4a213a4 --- /dev/null +++ b/src/app/features/project-editor/components/save-bar/project-editor-save-bar.component.scss @@ -0,0 +1,27 @@ +.project-editor-save-bar { + position: sticky; + bottom: 0; + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 1rem; + padding: 0.75rem 1rem; + background: var(--surface, #fff); + border-top: 1px solid var(--border, #ddd); + z-index: 5; +} + +.project-editor-save-bar-dirty { + color: var(--warning, #b45309); + margin-left: 0.5rem; +} + +.project-editor-save-bar-issues { + margin: 0.25rem 0 0; + padding-left: 1.25rem; + color: var(--danger, #b91c1c); +} + +.project-editor-save-bar-actions button + button { + margin-left: 0.5rem; +} diff --git a/src/app/features/project-editor/components/save-bar/project-editor-save-bar.component.ts b/src/app/features/project-editor/components/save-bar/project-editor-save-bar.component.ts new file mode 100644 index 0000000..3b858ed --- /dev/null +++ b/src/app/features/project-editor/components/save-bar/project-editor-save-bar.component.ts @@ -0,0 +1,26 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { TranslatePipe } from '../../../../i18n/translate.pipe'; +import { ProjectEditorFacade } from '../../facade/project-editor.facade'; + +@Component({ + selector: 'app-project-editor-save-bar', + standalone: true, + imports: [TranslatePipe], + templateUrl: './project-editor-save-bar.component.html', + styleUrls: ['./project-editor-save-bar.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ProjectEditorSaveBarComponent { + private readonly facade = inject(ProjectEditorFacade); + readonly dirty = this.facade.dirty; + readonly status = this.facade.status; + readonly issues = this.facade.validationIssues; + + save(): void { + this.facade.save(); + } + + publish(): void { + this.facade.publish(); + } +} diff --git a/src/app/features/project-editor/pages/project-editor-page.component.html b/src/app/features/project-editor/pages/project-editor-page.component.html index 821be84..fa0d546 100644 --- a/src/app/features/project-editor/pages/project-editor-page.component.html +++ b/src/app/features/project-editor/pages/project-editor-page.component.html @@ -28,5 +28,6 @@ @case ('preview') { } } + } diff --git a/src/app/features/project-editor/pages/project-editor-page.component.ts b/src/app/features/project-editor/pages/project-editor-page.component.ts index bde7495..3dbb9a7 100644 --- a/src/app/features/project-editor/pages/project-editor-page.component.ts +++ b/src/app/features/project-editor/pages/project-editor-page.component.ts @@ -17,6 +17,7 @@ import { ProjectEditorNavigationSectionComponent } from '../sections/navigation- import { ProjectEditorPreviewSectionComponent } from '../sections/preview-section.component'; import { TranslatePipe } from '../../../i18n/translate.pipe'; import { StaticPagesEditorComponent } from '../../content-management/components/static-pages-editor.component'; +import { ProjectEditorSaveBarComponent } from '../components/save-bar/project-editor-save-bar.component'; import { ProjectEditorSectionId } from '../models/project-editor.model'; const KNOWN_SECTIONS: ProjectEditorSectionId[] = [ @@ -41,6 +42,7 @@ const KNOWN_SECTIONS: ProjectEditorSectionId[] = [ ProjectEditorLanguagesSectionComponent, ProjectEditorNavigationSectionComponent, ProjectEditorPreviewSectionComponent, + ProjectEditorSaveBarComponent, ], templateUrl: './project-editor-page.component.html', styleUrls: ['./project-editor-page.component.scss'], diff --git a/src/app/i18n/en.ts b/src/app/i18n/en.ts index 008c031..5d09372 100644 --- a/src/app/i18n/en.ts +++ b/src/app/i18n/en.ts @@ -512,6 +512,11 @@ export const en: Translations = { validationMissingWidget: 'A homepage section has a widget with no type.', validationDuplicateNavLinks: 'Two or more header navigation links are duplicates.', validationInvalidColors: 'One or more theme colors are not valid hex colors.', + statusDraft: 'Draft', + statusPublished: 'Published', + unsavedChanges: 'Unsaved changes', + save: 'Save', + publish: 'Publish', }, staticPages: { notFound: 'Page not found', diff --git a/src/app/i18n/hy.ts b/src/app/i18n/hy.ts index 483e80e..532131f 100644 --- a/src/app/i18n/hy.ts +++ b/src/app/i18n/hy.ts @@ -512,6 +512,11 @@ export const hy: Translations = { validationMissingWidget: 'Գլխավոր էջի սեկցիաներից մեկն ունի վիջեթ առանց տիպի։', validationDuplicateNavLinks: 'Վերնագրի նավիգացիայում կան կրկնվող հղումներ։', validationInvalidColors: 'Թեմայի գույներից մեկը կամ մի քանիսը վավեր hex գույն չեն։', + statusDraft: 'Սևագիր', + statusPublished: 'Հրապարակված', + unsavedChanges: 'Չպահված փոփոխություններ', + save: 'Պահպանել', + publish: 'Հրապարակել', }, staticPages: { notFound: 'Էջը չի գտնվել', diff --git a/src/app/i18n/ru.ts b/src/app/i18n/ru.ts index 7d46a2b..4658433 100644 --- a/src/app/i18n/ru.ts +++ b/src/app/i18n/ru.ts @@ -512,6 +512,11 @@ export const ru: Translations = { validationMissingWidget: 'В секции главной страницы есть виджет без типа.', validationDuplicateNavLinks: 'Две или более ссылки в навигации шапки дублируются.', validationInvalidColors: 'Один или несколько цветов темы указаны некорректно.', + statusDraft: 'Черновик', + statusPublished: 'Опубликовано', + unsavedChanges: 'Есть несохранённые изменения', + save: 'Сохранить', + publish: 'Опубликовать', }, staticPages: { notFound: 'Страница не найдена', diff --git a/src/app/i18n/translations.ts b/src/app/i18n/translations.ts index d1b15f8..f42d861 100644 --- a/src/app/i18n/translations.ts +++ b/src/app/i18n/translations.ts @@ -510,6 +510,11 @@ export interface Translations { validationMissingWidget: string; validationDuplicateNavLinks: string; validationInvalidColors: string; + statusDraft: string; + statusPublished: string; + unsavedChanges: string; + save: string; + publish: string; }; staticPages: { notFound: string;