feat(project-editor): add sticky save/publish bar with validation summary
Mounts a new ProjectEditorSaveBarComponent in the editor page that shows draft/published status, unsaved-changes indicator, and validation issues, wiring the Task 8 facade save()/publish()/dirty/status/validationIssues signals to an actual UI for the first time.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
<div class="project-editor-save-bar">
|
||||
<div class="project-editor-save-bar-status">
|
||||
<span>{{ (status() === 'published' ? 'builder.statusPublished' : 'builder.statusDraft') | translate }}</span>
|
||||
@if (dirty()) {
|
||||
<span class="project-editor-save-bar-dirty">{{ 'builder.unsavedChanges' | translate }}</span>
|
||||
}
|
||||
@if (issues().length > 0) {
|
||||
<ul class="project-editor-save-bar-issues">
|
||||
@for (issue of issues(); track issue.code) {
|
||||
<li>{{ issue.message | translate }}</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</div>
|
||||
<div class="project-editor-save-bar-actions">
|
||||
<button type="button" (click)="save()">{{ 'builder.save' | translate }}</button>
|
||||
<button type="button" [disabled]="issues().length > 0" (click)="publish()">{{ 'builder.publish' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user