diff --git a/libs/api/repository/src/lib/gn4/gn4-repository.ts b/libs/api/repository/src/lib/gn4/gn4-repository.ts index 64068b7f02..0abbe665e1 100644 --- a/libs/api/repository/src/lib/gn4/gn4-repository.ts +++ b/libs/api/repository/src/lib/gn4/gn4-repository.ts @@ -41,6 +41,7 @@ import { import { catchError, map, tap } from 'rxjs/operators' import { lt } from 'semver' import { ElasticsearchService } from './elasticsearch' +import { TranslateService } from '@ngx-translate/core' const minPublicationApiVersion = '4.2.5' @@ -59,7 +60,8 @@ export class Gn4Repository implements RecordsRepositoryInterface { private gn4SearchHelper: ElasticsearchService, private gn4Mapper: Gn4Converter, private gn4RecordsApi: RecordsApiService, - private platformService: PlatformServiceInterface + private platformService: PlatformServiceInterface, + private translateService: TranslateService ) {} search({ @@ -365,6 +367,47 @@ export class Gn4Repository implements RecordsRepositoryInterface { return of(draftCount) } + hasRecordChangedSinceDraft(localRecord: CatalogRecord) { + const isUnsaved = this.isRecordNotYetSaved(localRecord.uniqueIdentifier) + const hasDraft = this.recordHasDraft(localRecord.uniqueIdentifier) + + if (isUnsaved || !hasDraft) { + return of([]) + } + + return combineLatest([ + this.getAllDrafts().pipe( + map((drafts) => { + const matchingRecord = drafts.find( + (draft) => draft.uniqueIdentifier === localRecord.uniqueIdentifier + ) + return matchingRecord ? matchingRecord.recordUpdated : null + }) + ), + this.getRecord(localRecord.uniqueIdentifier), + ]).pipe( + map(([draftRecordUpdated, recentRecord]) => { + if (recentRecord.recordUpdated > draftRecordUpdated) { + return [ + this.formatDate(recentRecord.recordUpdated), + recentRecord.extras?.['ownerInfo'].toString().split('|')[0], + ] + } + return [] + }) + ) + } + + formatDate(date: Date): string { + return date.toLocaleDateString(this.translateService.currentLang, { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', + }) + } + private getRecordAsXml(uniqueIdentifier: string): Observable { return this.gn4RecordsApi .getRecordAs( diff --git a/libs/common/domain/src/lib/repository/records-repository.interface.ts b/libs/common/domain/src/lib/repository/records-repository.interface.ts index b2640d069c..03e9e1a549 100644 --- a/libs/common/domain/src/lib/repository/records-repository.interface.ts +++ b/libs/common/domain/src/lib/repository/records-repository.interface.ts @@ -88,4 +88,7 @@ export abstract class RecordsRepositoryInterface { abstract getAllDrafts(): Observable abstract getDraftsCount(): Observable abstract draftsChanged$: Observable + abstract hasRecordChangedSinceDraft( + localRecord: CatalogRecord + ): Observable } diff --git a/libs/feature/editor/src/lib/+state/editor.actions.ts b/libs/feature/editor/src/lib/+state/editor.actions.ts index 85e02ce54e..e88ba495d5 100644 --- a/libs/feature/editor/src/lib/+state/editor.actions.ts +++ b/libs/feature/editor/src/lib/+state/editor.actions.ts @@ -41,3 +41,13 @@ export const setFieldVisibility = createAction( '[Editor] Set field visibility', props<{ field: EditorFieldIdentification; visible: boolean }>() ) + +export const hasRecordChangedSinceDraft = createAction( + '[Editor] Has Record Changed Since Draft', + props<{ record: CatalogRecord }>() +) + +export const hasRecordChangedSinceDraftSuccess = createAction( + '[Editor] Has Record Changed Since Draft Success', + props<{ changes: any[] }>() +) diff --git a/libs/feature/editor/src/lib/+state/editor.effects.ts b/libs/feature/editor/src/lib/+state/editor.effects.ts index cb678bf6df..4513b2e013 100644 --- a/libs/feature/editor/src/lib/+state/editor.effects.ts +++ b/libs/feature/editor/src/lib/+state/editor.effects.ts @@ -126,4 +126,19 @@ export class EditorEffects { map(() => EditorActions.markRecordAsChanged()) ) ) + + hasRecordChangedSinceDraft$ = createEffect(() => + this.actions$.pipe( + ofType(EditorActions.hasRecordChangedSinceDraft), + switchMap(({ record }) => + this.editorService + .hasRecordChangedSinceDraft(record) + .pipe( + map((changes) => + EditorActions.hasRecordChangedSinceDraftSuccess({ changes }) + ) + ) + ) + ) + ) } diff --git a/libs/feature/editor/src/lib/+state/editor.facade.ts b/libs/feature/editor/src/lib/+state/editor.facade.ts index 1b3f6dfb69..e384a875bb 100644 --- a/libs/feature/editor/src/lib/+state/editor.facade.ts +++ b/libs/feature/editor/src/lib/+state/editor.facade.ts @@ -32,6 +32,9 @@ export class EditorFacade { draftSaveSuccess$ = this.actions$.pipe(ofType(EditorActions.draftSaveSuccess)) currentPage$ = this.store.pipe(select(EditorSelectors.selectCurrentPage)) editorConfig$ = this.store.pipe(select(EditorSelectors.selectEditorConfig)) + hasRecordChanged$ = this.store.pipe( + select(EditorSelectors.selectHasRecordChanged) + ) openRecord( record: CatalogRecord, @@ -63,4 +66,8 @@ export class EditorFacade { setFieldVisibility(field: EditorFieldIdentification, visible: boolean) { this.store.dispatch(EditorActions.setFieldVisibility({ field, visible })) } + + hasRecordChangedSinceDraft(record: CatalogRecord) { + this.store.dispatch(EditorActions.hasRecordChangedSinceDraft({ record })) + } } diff --git a/libs/feature/editor/src/lib/+state/editor.reducer.ts b/libs/feature/editor/src/lib/+state/editor.reducer.ts index 29848bb9cd..6a9f5f62b6 100644 --- a/libs/feature/editor/src/lib/+state/editor.reducer.ts +++ b/libs/feature/editor/src/lib/+state/editor.reducer.ts @@ -24,6 +24,7 @@ export interface EditorState { changedSinceSave: boolean editorConfig: EditorConfig currentPage: number + hasRecordChanged: any[] } export interface EditorPartialState { @@ -39,6 +40,7 @@ export const initialEditorState: EditorState = { changedSinceSave: false, editorConfig: DEFAULT_CONFIGURATION, currentPage: 0, + hasRecordChanged: [], } const reducer = createReducer( @@ -104,6 +106,10 @@ const reducer = createReducer( })), })), }, + })), + on(EditorActions.hasRecordChangedSinceDraftSuccess, (state, { changes }) => ({ + ...state, + hasRecordChanged: changes, })) ) diff --git a/libs/feature/editor/src/lib/+state/editor.selectors.ts b/libs/feature/editor/src/lib/+state/editor.selectors.ts index 886daa909a..528f5683b6 100644 --- a/libs/feature/editor/src/lib/+state/editor.selectors.ts +++ b/libs/feature/editor/src/lib/+state/editor.selectors.ts @@ -61,3 +61,8 @@ export const selectRecordSections = createSelector( })) as EditorSectionWithValues[] } ) + +export const selectHasRecordChanged = createSelector( + selectEditorState, + (state: EditorState) => state.hasRecordChanged +) diff --git a/libs/feature/editor/src/lib/services/editor.service.ts b/libs/feature/editor/src/lib/services/editor.service.ts index 64d58af9bf..223eb7a79b 100644 --- a/libs/feature/editor/src/lib/services/editor.service.ts +++ b/libs/feature/editor/src/lib/services/editor.service.ts @@ -59,6 +59,7 @@ export class EditorService { record: CatalogRecord, recordSource: string ): Observable { + record.recordUpdated = new Date() return this.recordsRepository .saveRecordAsDraft(record, recordSource) .pipe(map(() => undefined)) @@ -70,4 +71,8 @@ export class EditorService { this.recordsRepository.clearRecordDraft(record.uniqueIdentifier) return this.recordsRepository.openRecordForEdition(record.uniqueIdentifier) } + + hasRecordChangedSinceDraft(localRecord: CatalogRecord): Observable { + return this.recordsRepository.hasRecordChangedSinceDraft(localRecord) + } }