mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge branch 'refs/heads/w2p-113560_edit-item-add-relationships-one-by-one_contribute-7.6' into w2p-113560_edit-item-add-relationships-one-by-one_contribute-7_x
This commit is contained in:
@@ -1,18 +1,18 @@
|
||||
<div class="container-fluid">
|
||||
<div class="d-inline-block float-right space-children-mr">
|
||||
<button class=" btn btn-danger" *ngIf="!(isReinstatable() | async)"
|
||||
[disabled]="!(hasChanges() | async)"
|
||||
<button class=" btn btn-danger" *ngIf="(isReinstatable$ | async) !== true"
|
||||
[disabled]="(hasChanges$ | async) !== true"
|
||||
(click)="discard()"><i
|
||||
class="fas fa-times"></i>
|
||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
||||
</button>
|
||||
<button class="btn btn-warning" *ngIf="isReinstatable() | async"
|
||||
<button class="btn btn-warning" *ngIf="isReinstatable$ | async"
|
||||
(click)="reinstate()"><i
|
||||
class="fas fa-undo-alt"></i>
|
||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.reinstate-button" | translate}}</span>
|
||||
</button>
|
||||
<button class="btn btn-primary"
|
||||
[disabled]="!(hasChanges() | async) || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
|
||||
[disabled]="(hasChanges$ | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
|
||||
(click)="onSubmit()"><i
|
||||
class="fas fa-save"></i>
|
||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.save-button" | translate}}</span>
|
||||
@@ -44,19 +44,19 @@
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-inline-block float-right ml-1 space-children-mr">
|
||||
<button class=" btn btn-danger" *ngIf="!(isReinstatable() | async)"
|
||||
[disabled]="!(hasChanges() | async)"
|
||||
<button class=" btn btn-danger" *ngIf="(isReinstatable$ | async) !== true"
|
||||
[disabled]="(hasChanges$ | async) !== true"
|
||||
(click)="discard()"><i
|
||||
class="fas fa-times"></i>
|
||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
||||
</button>
|
||||
<button class="btn btn-warning" *ngIf="isReinstatable() | async"
|
||||
<button class="btn btn-warning" *ngIf="isReinstatable$ | async"
|
||||
(click)="reinstate()"><i
|
||||
class="fas fa-undo-alt"></i>
|
||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.reinstate-button" | translate}}</span>
|
||||
</button>
|
||||
<button class="btn btn-primary"
|
||||
[disabled]="!(hasChanges() | async) || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
|
||||
[disabled]="(hasChanges$ | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
|
||||
(click)="onSubmit()"><i
|
||||
class="fas fa-save"></i>
|
||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.save-button" | translate}}</span>
|
||||
@@ -66,7 +66,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<ds-collection-source-controls
|
||||
[isEnabled]="!(hasChanges()|async)"
|
||||
[isEnabled]="(hasChanges$ | async) !== true"
|
||||
[shouldShow]="contentSource?.harvestType !== harvestTypeNone"
|
||||
[collection]="(collectionRD$ |async)?.payload"
|
||||
>
|
||||
|
@@ -204,11 +204,6 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
||||
*/
|
||||
formGroup: UntypedFormGroup;
|
||||
|
||||
/**
|
||||
* Subscription to update the current form
|
||||
*/
|
||||
updateSub: Subscription;
|
||||
|
||||
/**
|
||||
* The content harvesting type used when harvesting is disabled
|
||||
*/
|
||||
@@ -228,28 +223,29 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
||||
*/
|
||||
displayedNotifications: INotification[] = [];
|
||||
|
||||
public constructor(public objectUpdatesService: ObjectUpdatesService,
|
||||
public notificationsService: NotificationsService,
|
||||
protected location: Location,
|
||||
protected formService: DynamicFormService,
|
||||
protected translate: TranslateService,
|
||||
protected route: ActivatedRoute,
|
||||
protected router: Router,
|
||||
protected collectionService: CollectionDataService,
|
||||
protected requestService: RequestService) {
|
||||
super(objectUpdatesService, notificationsService, translate);
|
||||
subs: Subscription[] = [];
|
||||
|
||||
public constructor(
|
||||
public objectUpdatesService: ObjectUpdatesService,
|
||||
public notificationsService: NotificationsService,
|
||||
public translateService: TranslateService,
|
||||
public router: Router,
|
||||
protected location: Location,
|
||||
protected formService: DynamicFormService,
|
||||
protected route: ActivatedRoute,
|
||||
protected collectionService: CollectionDataService,
|
||||
protected requestService: RequestService,
|
||||
) {
|
||||
super(objectUpdatesService, notificationsService, translateService, router);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize properties to setup the Field Update and Form
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
super.ngOnInit();
|
||||
this.notificationsPrefix = 'collection.edit.tabs.source.notifications.';
|
||||
this.discardTimeOut = environment.collection.edit.undoTimeout;
|
||||
this.url = this.router.url;
|
||||
if (this.url.indexOf('?') > 0) {
|
||||
this.url = this.url.substr(0, this.url.indexOf('?'));
|
||||
}
|
||||
this.formGroup = this.formService.createFormGroup(this.formModel);
|
||||
this.collectionRD$ = this.route.parent.data.pipe(first(), map((data) => data.dso));
|
||||
|
||||
@@ -263,10 +259,9 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
||||
});
|
||||
|
||||
this.updateFieldTranslations();
|
||||
this.translate.onLangChange
|
||||
.subscribe(() => {
|
||||
this.updateFieldTranslations();
|
||||
});
|
||||
this.subs.push(this.translateService.onLangChange.subscribe(() => {
|
||||
this.updateFieldTranslations();
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,7 +276,7 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
||||
this.update$ = this.objectUpdatesService.getFieldUpdates(this.url, [initialContentSource]).pipe(
|
||||
map((updates: FieldUpdates) => updates[initialContentSource.uuid])
|
||||
);
|
||||
this.updateSub = this.update$.subscribe((update: FieldUpdate) => {
|
||||
this.subs.push(this.update$.subscribe((update: FieldUpdate) => {
|
||||
if (update) {
|
||||
const field = update.field as ContentSource;
|
||||
let configId;
|
||||
@@ -308,7 +303,7 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
||||
}
|
||||
this.contentSource.metadataConfigId = configId;
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,18 +337,18 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
||||
* @param fieldModel
|
||||
*/
|
||||
private updateFieldTranslation(fieldModel: DynamicFormControlModel) {
|
||||
fieldModel.label = this.translate.instant(this.LABEL_KEY_PREFIX + fieldModel.id);
|
||||
fieldModel.label = this.translateService.instant(this.LABEL_KEY_PREFIX + fieldModel.id);
|
||||
if (isNotEmpty(fieldModel.validators)) {
|
||||
fieldModel.errorMessages = {};
|
||||
Object.keys(fieldModel.validators).forEach((key) => {
|
||||
fieldModel.errorMessages[key] = this.translate.instant(this.ERROR_KEY_PREFIX + fieldModel.id + '.' + key);
|
||||
fieldModel.errorMessages[key] = this.translateService.instant(this.ERROR_KEY_PREFIX + fieldModel.id + '.' + key);
|
||||
});
|
||||
}
|
||||
if (fieldModel instanceof DynamicOptionControlModel) {
|
||||
if (isNotEmpty(fieldModel.options)) {
|
||||
fieldModel.options.forEach((option) => {
|
||||
if (hasNoValue(option.label)) {
|
||||
option.label = this.translate.instant(this.OPTIONS_KEY_PREFIX + fieldModel.id + '.' + option.value);
|
||||
option.label = this.translateService.instant(this.OPTIONS_KEY_PREFIX + fieldModel.id + '.' + option.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -470,8 +465,6 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
||||
* Make sure open subscriptions are closed
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
if (this.updateSub) {
|
||||
this.updateSub.unsubscribe();
|
||||
}
|
||||
this.subs.forEach((sub: Subscription) => sub.unsubscribe());
|
||||
}
|
||||
}
|
||||
|
@@ -35,10 +35,6 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl
|
||||
*/
|
||||
updates$: Observable<FieldUpdates>;
|
||||
|
||||
hasChanges$: Observable<boolean>;
|
||||
|
||||
isReinstatable$: Observable<boolean>;
|
||||
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
@@ -58,7 +54,7 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl
|
||||
public translateService: TranslateService,
|
||||
public route: ActivatedRoute
|
||||
) {
|
||||
super(objectUpdatesService, notificationsService, translateService);
|
||||
super(objectUpdatesService, notificationsService, translateService, router);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,11 +79,9 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl
|
||||
this.setItem(rd.payload);
|
||||
});
|
||||
}
|
||||
super.ngOnInit();
|
||||
|
||||
this.discardTimeOut = environment.item.edit.undoTimeout;
|
||||
this.url = this.router.url.split('?')[0];
|
||||
this.hasChanges$ = this.hasChanges();
|
||||
this.isReinstatable$ = this.isReinstatable();
|
||||
this.hasChanges().pipe(first()).subscribe((hasChanges) => {
|
||||
if (!hasChanges) {
|
||||
this.initializeOriginalFields();
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { ChangeDetectorRef, Component, NgZone, OnDestroy } from '@angular/core';
|
||||
import { AbstractItemUpdateComponent } from '../abstract-item-update/abstract-item-update.component';
|
||||
import { filter, map, switchMap, take } from 'rxjs/operators';
|
||||
import { Observable, Subscription, zip as observableZip } from 'rxjs';
|
||||
import { Observable, Subscription, zip as observableZip, combineLatest } from 'rxjs';
|
||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
@@ -222,7 +222,7 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme
|
||||
*/
|
||||
isReinstatable(): Observable<boolean> {
|
||||
return this.bundles$.pipe(
|
||||
switchMap((bundles: Bundle[]) => observableZip(...bundles.map((bundle: Bundle) => this.objectUpdatesService.isReinstatable(bundle.self)))),
|
||||
switchMap((bundles: Bundle[]) => combineLatest(bundles.map((bundle: Bundle) => this.objectUpdatesService.isReinstatable(bundle.self)))),
|
||||
map((reinstatable: boolean[]) => reinstatable.includes(true))
|
||||
);
|
||||
}
|
||||
@@ -232,7 +232,7 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme
|
||||
*/
|
||||
hasChanges(): Observable<boolean> {
|
||||
return this.bundles$.pipe(
|
||||
switchMap((bundles: Bundle[]) => observableZip(...bundles.map((bundle: Bundle) => this.objectUpdatesService.hasUpdates(bundle.self)))),
|
||||
switchMap((bundles: Bundle[]) => combineLatest(bundles.map((bundle: Bundle) => this.objectUpdatesService.hasUpdates(bundle.self)))),
|
||||
map((hasChanges: boolean[]) => hasChanges.includes(true))
|
||||
);
|
||||
}
|
||||
|
@@ -9,6 +9,8 @@ import { NotificationsService } from '../notifications/notifications.service';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { TestScheduler } from 'rxjs/testing';
|
||||
import { getTestScheduler } from 'jasmine-marbles';
|
||||
import { RouterStub } from '../testing/router.stub';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
describe('AbstractTrackableComponent', () => {
|
||||
let comp: AbstractTrackableComponent;
|
||||
@@ -27,6 +29,7 @@ describe('AbstractTrackableComponent', () => {
|
||||
success: successNotification
|
||||
}
|
||||
);
|
||||
let router: RouterStub;
|
||||
|
||||
const url = 'http://test-url.com/test-url';
|
||||
|
||||
@@ -42,6 +45,8 @@ describe('AbstractTrackableComponent', () => {
|
||||
isValidPage: observableOf(true)
|
||||
}
|
||||
);
|
||||
router = new RouterStub();
|
||||
router.url = url;
|
||||
|
||||
scheduler = getTestScheduler();
|
||||
|
||||
@@ -51,6 +56,7 @@ describe('AbstractTrackableComponent', () => {
|
||||
providers: [
|
||||
{ provide: ObjectUpdatesService, useValue: objectUpdatesService },
|
||||
{ provide: NotificationsService, useValue: notificationsService },
|
||||
{ provide: Router, useValue: router },
|
||||
], schemas: [
|
||||
NO_ERRORS_SCHEMA
|
||||
]
|
||||
@@ -60,7 +66,6 @@ describe('AbstractTrackableComponent', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AbstractTrackableComponent);
|
||||
comp = fixture.componentInstance;
|
||||
comp.url = url;
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
@@ -2,7 +2,8 @@ import { ObjectUpdatesService } from '../../core/data/object-updates/object-upda
|
||||
import { NotificationsService } from '../notifications/notifications.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
/**
|
||||
* Abstract Component that is able to track changes made in the inheriting component using the ObjectUpdateService
|
||||
@@ -11,7 +12,7 @@ import { Component } from '@angular/core';
|
||||
selector: 'ds-abstract-trackable',
|
||||
template: ''
|
||||
})
|
||||
export class AbstractTrackableComponent {
|
||||
export class AbstractTrackableComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* The time span for being able to undo discarding changes
|
||||
@@ -21,14 +22,25 @@ export class AbstractTrackableComponent {
|
||||
public url: string;
|
||||
public notificationsPrefix = 'static-pages.form.notification';
|
||||
|
||||
hasChanges$: Observable<boolean>;
|
||||
|
||||
isReinstatable$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
public objectUpdatesService: ObjectUpdatesService,
|
||||
public notificationsService: NotificationsService,
|
||||
public translateService: TranslateService,
|
||||
public router: Router,
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.url = this.router.url.split('?')[0];
|
||||
this.hasChanges$ = this.hasChanges();
|
||||
this.isReinstatable$ = this.isReinstatable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the object updates service to discard all current changes to this item
|
||||
* Shows a notification to remind the user that they can undo this
|
||||
|
Reference in New Issue
Block a user