diff --git a/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.html b/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.html index 365dcea5af..177c9d3bf1 100644 --- a/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.html +++ b/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.html @@ -11,7 +11,33 @@ undo -
Save status
+
+ + check_circle + editor.record.saveStatus.notPublishedYet + + + check_circle + editor.record.saveStatus.publishedUpToDate + + + pending + editor.record.saveStatus.publishedChangesPending + +
help diff --git a/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.spec.ts b/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.spec.ts index 77c3cb5b09..6f7ad48d9f 100644 --- a/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.spec.ts +++ b/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.spec.ts @@ -2,6 +2,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing' import { TopToolbarComponent } from './top-toolbar.component' import { Component } from '@angular/core' import { PublishButtonComponent } from '../publish-button/publish-button.component' +import { BehaviorSubject } from 'rxjs' +import { EditorFacade } from '@geonetwork-ui/feature/editor' +import { TranslateModule } from '@ngx-translate/core' + +class EditorFacadeMock { + changedSinceSave$ = new BehaviorSubject(false) + alreadySavedOnce$ = new BehaviorSubject(false) +} @Component({ selector: 'md-editor-publish-button', @@ -13,10 +21,17 @@ class MockPublishButtonComponent {} describe('TopToolbarComponent', () => { let component: TopToolbarComponent let fixture: ComponentFixture + let editorFacade: EditorFacadeMock beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [TopToolbarComponent], + imports: [TopToolbarComponent, TranslateModule.forRoot()], + providers: [ + { + provide: EditorFacade, + useClass: EditorFacadeMock, + }, + ], }) .overrideComponent(TopToolbarComponent, { add: { @@ -30,10 +45,47 @@ describe('TopToolbarComponent', () => { fixture = TestBed.createComponent(TopToolbarComponent) component = fixture.componentInstance + editorFacade = TestBed.inject(EditorFacade) as any fixture.detectChanges() }) it('should create', () => { expect(component).toBeTruthy() }) + + describe('save status', () => { + let saveStatus: string + beforeEach(() => { + component['saveStatus$'].subscribe((status) => { + saveStatus = status + }) + }) + describe('saved and not published', () => { + beforeEach(() => { + editorFacade.alreadySavedOnce$.next(false) + editorFacade.changedSinceSave$.next(true) + }) + it('sets the correct status', () => { + expect(saveStatus).toBe('saved_not_published') + }) + }) + describe('saved, published and up to date', () => { + beforeEach(() => { + editorFacade.alreadySavedOnce$.next(true) + editorFacade.changedSinceSave$.next(false) + }) + it('sets the correct status', () => { + expect(saveStatus).toBe('saved_published_up_to_date') + }) + }) + describe('saved, published, pending changes', () => { + beforeEach(() => { + editorFacade.alreadySavedOnce$.next(true) + editorFacade.changedSinceSave$.next(true) + }) + it('sets the correct status', () => { + expect(saveStatus).toBe('saved_published_changes_pending') + }) + }) + }) }) diff --git a/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.ts b/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.ts index c7717d8342..685820ca1c 100644 --- a/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.ts +++ b/apps/metadata-editor/src/app/edit/components/top-toolbar/top-toolbar.component.ts @@ -3,6 +3,10 @@ import { CommonModule } from '@angular/common' import { PublishButtonComponent } from '../publish-button/publish-button.component' import { ButtonComponent } from '@geonetwork-ui/ui/inputs' import { MatIconModule } from '@angular/material/icon' +import { EditorFacade } from '@geonetwork-ui/feature/editor' +import { combineLatest, Observable } from 'rxjs' +import { map } from 'rxjs/operators' +import { TranslateModule } from '@ngx-translate/core' @Component({ selector: 'md-editor-top-toolbar', @@ -12,9 +16,37 @@ import { MatIconModule } from '@angular/material/icon' PublishButtonComponent, ButtonComponent, MatIconModule, + TranslateModule, ], templateUrl: './top-toolbar.component.html', styleUrls: ['./top-toolbar.component.css'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class TopToolbarComponent {} +export class TopToolbarComponent { + protected SaveStatus = [ + 'saved_not_published', + 'saved_published_up_to_date', + 'saved_published_changes_pending', + // these are not used since the draft is saved locally + // TODO: use these states when the draft is saved on the server + // 'saving', + // 'saving_failed', + ] as const + + protected saveStatus$: Observable = + combineLatest([ + this.editorFacade.alreadySavedOnce$, + this.editorFacade.changedSinceSave$, + ]).pipe( + map(([alreadySavedOnce, changedSinceSave]) => { + if (!alreadySavedOnce) { + return 'saved_not_published' + } + return changedSinceSave + ? 'saved_published_changes_pending' + : 'saved_published_up_to_date' + }) + ) + + constructor(private editorFacade: EditorFacade) {} +}