Merge branch 'feature-relationship-versioning-7.2' into feature-relationship-versioning

This commit is contained in:
Bruno Roemers
2022-06-13 18:46:42 +02:00
7 changed files with 75 additions and 5 deletions

View File

@@ -21,7 +21,7 @@ import {
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { BehaviorSubject, Observable, of } from 'rxjs'; import { BehaviorSubject, Observable, of } from 'rxjs';
import { select, Store } from '@ngrx/store'; import { select, Store } from '@ngrx/store';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbModal, NgbModalConfig } from '@ng-bootstrap/ng-bootstrap';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga'; import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
@@ -48,6 +48,7 @@ import { BreadcrumbsService } from './breadcrumbs/breadcrumbs.service';
import { IdleModalComponent } from './shared/idle-modal/idle-modal.component'; import { IdleModalComponent } from './shared/idle-modal/idle-modal.component';
import { getDefaultThemeConfig } from '../config/config.util'; import { getDefaultThemeConfig } from '../config/config.util';
import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface';
import { ModalBeforeDismiss } from './shared/interfaces/modal-before-dismiss.interface';
@Component({ @Component({
selector: 'ds-app', selector: 'ds-app',
@@ -105,6 +106,7 @@ export class AppComponent implements OnInit, AfterViewInit {
private localeService: LocaleService, private localeService: LocaleService,
private breadcrumbsService: BreadcrumbsService, private breadcrumbsService: BreadcrumbsService,
private modalService: NgbModal, private modalService: NgbModal,
private modalConfig: NgbModalConfig,
@Optional() private cookiesService: KlaroService, @Optional() private cookiesService: KlaroService,
@Optional() private googleAnalyticsService: GoogleAnalyticsService, @Optional() private googleAnalyticsService: GoogleAnalyticsService,
) { ) {
@@ -165,6 +167,16 @@ export class AppComponent implements OnInit, AfterViewInit {
} }
ngOnInit() { ngOnInit() {
/** Implement behavior for interface {@link ModalBeforeDismiss} */
this.modalConfig.beforeDismiss = async function () {
if (typeof this?.componentInstance?.beforeDismiss === 'function') {
return this.componentInstance.beforeDismiss()
}
// fall back to default behavior
return true;
}
this.isAuthBlocking$ = this.store.pipe(select(isAuthenticationBlocking)).pipe( this.isAuthBlocking$ = this.store.pipe(select(isAuthenticationBlocking)).pipe(
distinctUntilChanged() distinctUntilChanged()
); );

View File

@@ -62,6 +62,8 @@ export class VersionedItemComponent extends ItemComponent {
activeModal.componentInstance.createVersionEvent.pipe( activeModal.componentInstance.createVersionEvent.pipe(
switchMap((summary: string) => this.versionHistoryService.createVersion(item._links.self.href, summary)), switchMap((summary: string) => this.versionHistoryService.createVersion(item._links.self.href, summary)),
getFirstCompletedRemoteData(), getFirstCompletedRemoteData(),
// close model (should be displaying loading/waiting indicator) when version creation failed/succeeded
tap(() => activeModal.close()),
// show success/failure notification // show success/failure notification
tap((res: RemoteData<Version>) => { this.itemVersionShared.notifyCreateNewVersion(res); }), tap((res: RemoteData<Version>) => { this.itemVersionShared.notifyCreateNewVersion(res); }),
// get workspace item // get workspace item

View File

@@ -0,0 +1,25 @@
import { NgbModalConfig, NgbModal } from '@ng-bootstrap/ng-bootstrap';
/**
* If a component implementing this interface is used to create a modal (i.e. it is passed to {@link NgbModal#open}),
* and that modal is dismissed, then {@link #beforeDismiss} will be called.
*
* This behavior is implemented for the whole app, by setting a default value for {@link NgbModalConfig#beforeDismiss}
* in {@link AppComponent}.
*
* Docs: https://ng-bootstrap.github.io/#/components/modal/api
*/
export interface ModalBeforeDismiss {
/**
* Callback right before the modal will be dismissed.
* If this function returns:
* - false
* - a promise resolved with false
* - a promise that is rejected
* then the modal won't be dismissed.
* Docs: https://ng-bootstrap.github.io/#/components/modal/api#NgbModalOptions
*/
beforeDismiss(): boolean | Promise<boolean>
}

View File

@@ -1,4 +1,4 @@
<div> <div *ngIf="!(this.submitted$ | async); else waiting">
<div class="modal-header">{{'item.version.create.modal.header' | translate}} <div class="modal-header">{{'item.version.create.modal.header' | translate}}
<button type="button" class="close" (click)="onModalClose()" aria-label="Close"> <button type="button" class="close" (click)="onModalClose()" aria-label="Close">
<span aria-hidden="true">×</span> <span aria-hidden="true">×</span>
@@ -34,3 +34,13 @@
</button> </button>
</div> </div>
</div> </div>
<ng-template #waiting>
<div class="modal-header">{{'item.version.create.modal.submitted.header' | translate}}</div>
<div class="modal-body">
<p>{{'item.version.create.modal.submitted.text' | translate}}</p>
<div class="d-flex justify-content-center">
<ds-loading [showMessage]="false"></ds-loading>
</div>
</div>
</ng-template>

View File

@@ -1,16 +1,19 @@
import { Component, EventEmitter, Output } from '@angular/core'; import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { BehaviorSubject } from 'rxjs';
import { ModalBeforeDismiss } from '../../../interfaces/modal-before-dismiss.interface';
@Component({ @Component({
selector: 'ds-item-versions-summary-modal', selector: 'ds-item-versions-summary-modal',
templateUrl: './item-versions-summary-modal.component.html', templateUrl: './item-versions-summary-modal.component.html',
styleUrls: ['./item-versions-summary-modal.component.scss'] styleUrls: ['./item-versions-summary-modal.component.scss']
}) })
export class ItemVersionsSummaryModalComponent { export class ItemVersionsSummaryModalComponent implements OnInit, ModalBeforeDismiss {
versionNumber: number; versionNumber: number;
newVersionSummary: string; newVersionSummary: string;
firstVersion = true; firstVersion = true;
submitted$: BehaviorSubject<boolean>
@Output() createVersionEvent: EventEmitter<string> = new EventEmitter<string>(); @Output() createVersionEvent: EventEmitter<string> = new EventEmitter<string>();
@@ -19,13 +22,24 @@ export class ItemVersionsSummaryModalComponent {
) { ) {
} }
ngOnInit() {
this.submitted$ = new BehaviorSubject<boolean>(false);
}
onModalClose() { onModalClose() {
this.activeModal.dismiss(); this.activeModal.dismiss();
} }
beforeDismiss(): boolean | Promise<boolean> {
// prevent the modal from being dismissed after version creation is initiated
return !this.submitted$.getValue()
}
onModalSubmit() { onModalSubmit() {
this.createVersionEvent.emit(this.newVersionSummary); this.createVersionEvent.emit(this.newVersionSummary);
this.activeModal.close(); this.submitted$.next(true);
// NOTE: the caller of this modal is responsible for closing it,
// e.g. after the version creation POST request completed.
} }
} }

View File

@@ -342,6 +342,9 @@ export class ItemVersionsComponent implements OnInit {
version.item.pipe(getFirstSucceededRemoteDataPayload()) version.item.pipe(getFirstSucceededRemoteDataPayload())
])), ])),
mergeMap(([summary, item]: [string, Item]) => this.versionHistoryService.createVersion(item._links.self.href, summary)), mergeMap(([summary, item]: [string, Item]) => this.versionHistoryService.createVersion(item._links.self.href, summary)),
getFirstCompletedRemoteData(),
// close model (should be displaying loading/waiting indicator) when version creation failed/succeeded
tap(() => activeModal.close()),
// show success/failure notification // show success/failure notification
tap((newVersionRD: RemoteData<Version>) => { tap((newVersionRD: RemoteData<Version>) => {
this.itemVersionShared.notifyCreateNewVersion(newVersionRD); this.itemVersionShared.notifyCreateNewVersion(newVersionRD);

View File

@@ -2233,6 +2233,10 @@
"item.version.create.modal.form.summary.placeholder": "Insert the summary for the new version", "item.version.create.modal.form.summary.placeholder": "Insert the summary for the new version",
"item.version.create.modal.submitted.header": "Creating new version...",
"item.version.create.modal.submitted.text": "The new version is being created. This may take some time if the item has a lot of relationships.",
"item.version.create.notification.success" : "New version has been created with version number {{version}}", "item.version.create.notification.success" : "New version has been created with version number {{version}}",
"item.version.create.notification.failure" : "New version has not been created", "item.version.create.notification.failure" : "New version has not been created",