mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
200 lines
5.9 KiB
TypeScript
200 lines
5.9 KiB
TypeScript
import {
|
|
Component,
|
|
Input,
|
|
OnDestroy,
|
|
OnInit,
|
|
} from '@angular/core';
|
|
import {
|
|
ActivatedRoute,
|
|
Data,
|
|
Router,
|
|
} from '@angular/router';
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
import {
|
|
combineLatest as observableCombineLatest,
|
|
Observable,
|
|
Subscription,
|
|
} from 'rxjs';
|
|
import {
|
|
map,
|
|
switchMap,
|
|
take,
|
|
tap,
|
|
} from 'rxjs/operators';
|
|
|
|
import { environment } from '../../../../environments/environment';
|
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
|
import { FieldUpdate } from '../../../core/data/object-updates/field-update.model';
|
|
import { FieldUpdates } from '../../../core/data/object-updates/field-updates.model';
|
|
import { ObjectUpdatesService } from '../../../core/data/object-updates/object-updates.service';
|
|
import { RemoteData } from '../../../core/data/remote-data';
|
|
import { Item } from '../../../core/shared/item.model';
|
|
import { getAllSucceededRemoteData } from '../../../core/shared/operators';
|
|
import { hasValue } from '../../../shared/empty.util';
|
|
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
|
import { AbstractTrackableComponent } from '../../../shared/trackable/abstract-trackable.component';
|
|
import { getItemPageLinksToFollow } from '../../item.resolver';
|
|
import { getItemPageRoute } from '../../item-page-routing-paths';
|
|
|
|
@Component({
|
|
selector: 'ds-abstract-item-update',
|
|
template: '',
|
|
standalone: true,
|
|
})
|
|
/**
|
|
* Abstract component for managing object updates of an item
|
|
*/
|
|
export class AbstractItemUpdateComponent extends AbstractTrackableComponent implements OnInit, OnDestroy {
|
|
/**
|
|
* The item to display the edit page for
|
|
*/
|
|
@Input() item: Item;
|
|
/**
|
|
* The current values and updates for all this item's fields
|
|
* Should be initialized in the initializeUpdates method of the child component
|
|
*/
|
|
updates$: Observable<FieldUpdates>;
|
|
|
|
/**
|
|
* Route to the item's page
|
|
*/
|
|
itemPageRoute: string;
|
|
|
|
/**
|
|
* A subscription that checks when the item is deleted in cache and reloads the item by sending a new request
|
|
* This is used to update the item in cache after bitstreams are deleted
|
|
*/
|
|
itemUpdateSubscription: Subscription;
|
|
|
|
constructor(
|
|
public itemService: ItemDataService,
|
|
public objectUpdatesService: ObjectUpdatesService,
|
|
public router: Router,
|
|
public notificationsService: NotificationsService,
|
|
public translateService: TranslateService,
|
|
public route: ActivatedRoute,
|
|
) {
|
|
super(objectUpdatesService, notificationsService, translateService, router);
|
|
}
|
|
|
|
/**
|
|
* Initialize common properties between item-update components
|
|
*/
|
|
ngOnInit(): void {
|
|
if (hasValue(this.item)) {
|
|
this.setItem(this.item);
|
|
} else {
|
|
// The item wasn't provided through an input, retrieve it from the route instead.
|
|
this.itemUpdateSubscription = observableCombineLatest([this.route.data, this.route.parent.data]).pipe(
|
|
map(([data, parentData]: [Data, Data]) => Object.assign({}, data, parentData)),
|
|
map((data: any) => data.dso),
|
|
tap((rd: RemoteData<Item>) => {
|
|
this.item = rd.payload;
|
|
}),
|
|
switchMap((rd: RemoteData<Item>) => {
|
|
return this.itemService.findByHref(rd.payload._links.self.href, true, true, ...getItemPageLinksToFollow());
|
|
}),
|
|
getAllSucceededRemoteData(),
|
|
).subscribe((rd: RemoteData<Item>) => {
|
|
this.setItem(rd.payload);
|
|
});
|
|
}
|
|
super.ngOnInit();
|
|
|
|
this.discardTimeOut = environment.item.edit.undoTimeout;
|
|
this.hasChanges().pipe(take(1)).subscribe((hasChanges) => {
|
|
if (!hasChanges) {
|
|
this.initializeOriginalFields();
|
|
} else {
|
|
this.checkLastModified();
|
|
}
|
|
});
|
|
|
|
this.initializeNotificationsPrefix();
|
|
this.initializeUpdates();
|
|
}
|
|
|
|
setItem(item: Item) {
|
|
this.item = item;
|
|
this.itemPageRoute = getItemPageRoute(this.item);
|
|
this.postItemInit();
|
|
this.initializeUpdates();
|
|
}
|
|
|
|
ngOnDestroy() {
|
|
if (hasValue(this.itemUpdateSubscription)) {
|
|
this.itemUpdateSubscription.unsubscribe();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Actions to perform after the item has been initialized
|
|
* Abstract method: Should be overwritten in the sub class
|
|
*/
|
|
postItemInit(): void {
|
|
// Overwrite in subclasses
|
|
}
|
|
|
|
/**
|
|
* Initialize the values and updates of the current item's fields
|
|
* Abstract method: Should be overwritten in the sub class
|
|
*/
|
|
initializeUpdates(): void {
|
|
// Overwrite in subclasses
|
|
}
|
|
|
|
/**
|
|
* Initialize the prefix for notification messages
|
|
* Abstract method: Should be overwritten in the sub class
|
|
*/
|
|
initializeNotificationsPrefix(): void {
|
|
// Overwrite in subclasses
|
|
}
|
|
|
|
/**
|
|
* Sends all initial values of this item to the object updates service
|
|
* Abstract method: Should be overwritten in the sub class
|
|
*/
|
|
initializeOriginalFields(): void {
|
|
// Overwrite in subclasses
|
|
}
|
|
|
|
/**
|
|
* Submit the current changes
|
|
* Abstract method: Should be overwritten in the sub class
|
|
*/
|
|
submit(): void {
|
|
// Overwrite in subclasses
|
|
}
|
|
|
|
/**
|
|
* Prevent unnecessary rerendering so fields don't lose focus
|
|
*/
|
|
trackUpdate(index, update: FieldUpdate) {
|
|
return update && update.field ? update.field.uuid : undefined;
|
|
}
|
|
|
|
/**
|
|
* Check if the current page is entirely valid
|
|
*/
|
|
public isValid() {
|
|
return this.objectUpdatesService.isValidPage(this.url);
|
|
}
|
|
|
|
/**
|
|
* Checks if the current item is still in sync with the version in the store
|
|
* If it's not, a notification is shown and the changes are removed
|
|
*/
|
|
private checkLastModified() {
|
|
const currentVersion = this.item.lastModified;
|
|
this.objectUpdatesService.getLastModified(this.url).pipe(take(1)).subscribe(
|
|
(updateVersion: Date) => {
|
|
if (updateVersion.getDate() !== currentVersion.getDate()) {
|
|
this.notificationsService.warning(this.getNotificationTitle('outdated'), this.getNotificationContent('outdated'));
|
|
this.initializeOriginalFields();
|
|
}
|
|
},
|
|
);
|
|
}
|
|
}
|