mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge pull request #3127 from alexandrevryghem/w2p-113560_edit-item-add-relationships-one-by-one_contribute-main
[Port main] Remove Bitstreams on edit-item-page doesn't work
This commit is contained in:
@@ -24,11 +24,13 @@ export const ROUTES: Route[] = [
|
|||||||
{
|
{
|
||||||
// Resolve XMLUI bitstream download URLs
|
// Resolve XMLUI bitstream download URLs
|
||||||
path: 'handle/:prefix/:suffix/:filename',
|
path: 'handle/:prefix/:suffix/:filename',
|
||||||
|
component: BitstreamDownloadPageComponent,
|
||||||
canActivate: [legacyBitstreamURLRedirectGuard],
|
canActivate: [legacyBitstreamURLRedirectGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Resolve JSPUI bitstream download URLs
|
// Resolve JSPUI bitstream download URLs
|
||||||
path: ':prefix/:suffix/:sequence_id/:filename',
|
path: ':prefix/:suffix/:sequence_id/:filename',
|
||||||
|
component: BitstreamDownloadPageComponent,
|
||||||
canActivate: [legacyBitstreamURLRedirectGuard],
|
canActivate: [legacyBitstreamURLRedirectGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="d-inline-block float-right space-children-mr">
|
<div class="d-inline-block float-right space-children-mr">
|
||||||
<button class=" btn btn-danger" *ngIf="(isReinstatable() | async) !== true"
|
<button class=" btn btn-danger" *ngIf="(isReinstatable$ | async) !== true"
|
||||||
[disabled]="(hasChanges() | async) !== true"
|
[disabled]="(hasChanges$ | async) !== true"
|
||||||
(click)="discard()"><i
|
(click)="discard()"><i
|
||||||
class="fas fa-times"></i>
|
class="fas fa-times"></i>
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-warning" *ngIf="isReinstatable() | async"
|
<button class="btn btn-warning" *ngIf="isReinstatable$ | async"
|
||||||
(click)="reinstate()"><i
|
(click)="reinstate()"><i
|
||||||
class="fas fa-undo-alt"></i>
|
class="fas fa-undo-alt"></i>
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.reinstate-button" | translate}}</span>
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.reinstate-button" | translate}}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-primary"
|
<button class="btn btn-primary"
|
||||||
[disabled]="(hasChanges() | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
|
[disabled]="(hasChanges$ | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
|
||||||
(click)="onSubmit()"><i
|
(click)="onSubmit()"><i
|
||||||
class="fas fa-save"></i>
|
class="fas fa-save"></i>
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.save-button" | translate}}</span>
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.save-button" | translate}}</span>
|
||||||
@@ -44,19 +44,19 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="d-inline-block float-right ml-1 space-children-mr">
|
<div class="d-inline-block float-right ml-1 space-children-mr">
|
||||||
<button class=" btn btn-danger" *ngIf="(isReinstatable() | async) !== true"
|
<button class=" btn btn-danger" *ngIf="(isReinstatable$ | async) !== true"
|
||||||
[disabled]="(hasChanges() | async) !== true"
|
[disabled]="(hasChanges$ | async) !== true"
|
||||||
(click)="discard()"><i
|
(click)="discard()"><i
|
||||||
class="fas fa-times"></i>
|
class="fas fa-times"></i>
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.discard-button" | translate}}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-warning" *ngIf="isReinstatable() | async"
|
<button class="btn btn-warning" *ngIf="isReinstatable$ | async"
|
||||||
(click)="reinstate()"><i
|
(click)="reinstate()"><i
|
||||||
class="fas fa-undo-alt"></i>
|
class="fas fa-undo-alt"></i>
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.reinstate-button" | translate}}</span>
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.reinstate-button" | translate}}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-primary"
|
<button class="btn btn-primary"
|
||||||
[disabled]="(hasChanges() | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
|
[disabled]="(hasChanges$ | async) !== true || !isValid() || (initialHarvestType === harvestTypeNone && contentSource.harvestType === initialHarvestType)"
|
||||||
(click)="onSubmit()"><i
|
(click)="onSubmit()"><i
|
||||||
class="fas fa-save"></i>
|
class="fas fa-save"></i>
|
||||||
<span class="d-none d-sm-inline"> {{"item.edit.metadata.save-button" | translate}}</span>
|
<span class="d-none d-sm-inline"> {{"item.edit.metadata.save-button" | translate}}</span>
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ds-collection-source-controls
|
<ds-collection-source-controls
|
||||||
[isEnabled]="(hasChanges() | async) !== true"
|
[isEnabled]="(hasChanges$ | async) !== true"
|
||||||
[shouldShow]="contentSource?.harvestType !== harvestTypeNone"
|
[shouldShow]="contentSource?.harvestType !== harvestTypeNone"
|
||||||
[collection]="(collectionRD$ |async)?.payload"
|
[collection]="(collectionRD$ |async)?.payload"
|
||||||
>
|
>
|
||||||
|
@@ -249,11 +249,6 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
|||||||
*/
|
*/
|
||||||
formGroup: UntypedFormGroup;
|
formGroup: UntypedFormGroup;
|
||||||
|
|
||||||
/**
|
|
||||||
* Subscription to update the current form
|
|
||||||
*/
|
|
||||||
updateSub: Subscription;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The content harvesting type used when harvesting is disabled
|
* The content harvesting type used when harvesting is disabled
|
||||||
*/
|
*/
|
||||||
@@ -273,28 +268,29 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
|||||||
*/
|
*/
|
||||||
displayedNotifications: INotification[] = [];
|
displayedNotifications: INotification[] = [];
|
||||||
|
|
||||||
public constructor(public objectUpdatesService: ObjectUpdatesService,
|
subs: Subscription[] = [];
|
||||||
public notificationsService: NotificationsService,
|
|
||||||
protected location: Location,
|
public constructor(
|
||||||
protected formService: DynamicFormService,
|
public objectUpdatesService: ObjectUpdatesService,
|
||||||
protected translate: TranslateService,
|
public notificationsService: NotificationsService,
|
||||||
protected route: ActivatedRoute,
|
public translateService: TranslateService,
|
||||||
protected router: Router,
|
public router: Router,
|
||||||
protected collectionService: CollectionDataService,
|
protected location: Location,
|
||||||
protected requestService: RequestService) {
|
protected formService: DynamicFormService,
|
||||||
super(objectUpdatesService, notificationsService, translate);
|
protected route: ActivatedRoute,
|
||||||
|
protected collectionService: CollectionDataService,
|
||||||
|
protected requestService: RequestService,
|
||||||
|
) {
|
||||||
|
super(objectUpdatesService, notificationsService, translateService, router);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize properties to setup the Field Update and Form
|
* Initialize properties to setup the Field Update and Form
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
super.ngOnInit();
|
||||||
this.notificationsPrefix = 'collection.edit.tabs.source.notifications.';
|
this.notificationsPrefix = 'collection.edit.tabs.source.notifications.';
|
||||||
this.discardTimeOut = environment.collection.edit.undoTimeout;
|
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.formGroup = this.formService.createFormGroup(this.formModel);
|
||||||
this.collectionRD$ = this.route.parent.data.pipe(first(), map((data) => data.dso));
|
this.collectionRD$ = this.route.parent.data.pipe(first(), map((data) => data.dso));
|
||||||
|
|
||||||
@@ -308,10 +304,9 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.updateFieldTranslations();
|
this.updateFieldTranslations();
|
||||||
this.translate.onLangChange
|
this.subs.push(this.translateService.onLangChange.subscribe(() => {
|
||||||
.subscribe(() => {
|
this.updateFieldTranslations();
|
||||||
this.updateFieldTranslations();
|
}));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -326,7 +321,7 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
|||||||
this.update$ = this.objectUpdatesService.getFieldUpdates(this.url, [initialContentSource]).pipe(
|
this.update$ = this.objectUpdatesService.getFieldUpdates(this.url, [initialContentSource]).pipe(
|
||||||
map((updates: FieldUpdates) => updates[initialContentSource.uuid]),
|
map((updates: FieldUpdates) => updates[initialContentSource.uuid]),
|
||||||
);
|
);
|
||||||
this.updateSub = this.update$.subscribe((update: FieldUpdate) => {
|
this.subs.push(this.update$.subscribe((update: FieldUpdate) => {
|
||||||
if (update) {
|
if (update) {
|
||||||
const field = update.field as ContentSource;
|
const field = update.field as ContentSource;
|
||||||
let configId;
|
let configId;
|
||||||
@@ -353,7 +348,7 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
|||||||
}
|
}
|
||||||
this.contentSource.metadataConfigId = configId;
|
this.contentSource.metadataConfigId = configId;
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -387,18 +382,18 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
|||||||
* @param fieldModel
|
* @param fieldModel
|
||||||
*/
|
*/
|
||||||
private updateFieldTranslation(fieldModel: DynamicFormControlModel) {
|
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)) {
|
if (isNotEmpty(fieldModel.validators)) {
|
||||||
fieldModel.errorMessages = {};
|
fieldModel.errorMessages = {};
|
||||||
Object.keys(fieldModel.validators).forEach((key) => {
|
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 (fieldModel instanceof DynamicOptionControlModel) {
|
||||||
if (isNotEmpty(fieldModel.options)) {
|
if (isNotEmpty(fieldModel.options)) {
|
||||||
fieldModel.options.forEach((option) => {
|
fieldModel.options.forEach((option) => {
|
||||||
if (hasNoValue(option.label)) {
|
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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -515,8 +510,6 @@ export class CollectionSourceComponent extends AbstractTrackableComponent implem
|
|||||||
* Make sure open subscriptions are closed
|
* Make sure open subscriptions are closed
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this.updateSub) {
|
this.subs.forEach((sub: Subscription) => sub.unsubscribe());
|
||||||
this.updateSub.unsubscribe();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -55,10 +55,6 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl
|
|||||||
*/
|
*/
|
||||||
updates$: Observable<FieldUpdates>;
|
updates$: Observable<FieldUpdates>;
|
||||||
|
|
||||||
hasChanges$: Observable<boolean>;
|
|
||||||
|
|
||||||
isReinstatable$: Observable<boolean>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route to the item's page
|
* Route to the item's page
|
||||||
*/
|
*/
|
||||||
@@ -78,7 +74,7 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl
|
|||||||
public translateService: TranslateService,
|
public translateService: TranslateService,
|
||||||
public route: ActivatedRoute,
|
public route: ActivatedRoute,
|
||||||
) {
|
) {
|
||||||
super(objectUpdatesService, notificationsService, translateService);
|
super(objectUpdatesService, notificationsService, translateService, router);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,11 +99,9 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl
|
|||||||
this.setItem(rd.payload);
|
this.setItem(rd.payload);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
super.ngOnInit();
|
||||||
|
|
||||||
this.discardTimeOut = environment.item.edit.undoTimeout;
|
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) => {
|
this.hasChanges().pipe(first()).subscribe((hasChanges) => {
|
||||||
if (!hasChanges) {
|
if (!hasChanges) {
|
||||||
this.initializeOriginalFields();
|
this.initializeOriginalFields();
|
||||||
|
@@ -20,6 +20,7 @@ import {
|
|||||||
} from '@ngx-translate/core';
|
} from '@ngx-translate/core';
|
||||||
import { Operation } from 'fast-json-patch';
|
import { Operation } from 'fast-json-patch';
|
||||||
import {
|
import {
|
||||||
|
combineLatest,
|
||||||
Observable,
|
Observable,
|
||||||
Subscription,
|
Subscription,
|
||||||
zip as observableZip,
|
zip as observableZip,
|
||||||
@@ -273,7 +274,7 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme
|
|||||||
*/
|
*/
|
||||||
isReinstatable(): Observable<boolean> {
|
isReinstatable(): Observable<boolean> {
|
||||||
return this.bundles$.pipe(
|
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)),
|
map((reinstatable: boolean[]) => reinstatable.includes(true)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -283,7 +284,7 @@ export class ItemBitstreamsComponent extends AbstractItemUpdateComponent impleme
|
|||||||
*/
|
*/
|
||||||
hasChanges(): Observable<boolean> {
|
hasChanges(): Observable<boolean> {
|
||||||
return this.bundles$.pipe(
|
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)),
|
map((hasChanges: boolean[]) => hasChanges.includes(true)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import {
|
|||||||
TestBed,
|
TestBed,
|
||||||
waitForAsync,
|
waitForAsync,
|
||||||
} from '@angular/core/testing';
|
} from '@angular/core/testing';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { getTestScheduler } from 'jasmine-marbles';
|
import { getTestScheduler } from 'jasmine-marbles';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf } from 'rxjs';
|
||||||
@@ -16,6 +17,7 @@ import {
|
|||||||
} from '../notifications/models/notification.model';
|
} from '../notifications/models/notification.model';
|
||||||
import { NotificationType } from '../notifications/models/notification-type';
|
import { NotificationType } from '../notifications/models/notification-type';
|
||||||
import { NotificationsService } from '../notifications/notifications.service';
|
import { NotificationsService } from '../notifications/notifications.service';
|
||||||
|
import { RouterStub } from '../testing/router.stub';
|
||||||
import { AbstractTrackableComponent } from './abstract-trackable.component';
|
import { AbstractTrackableComponent } from './abstract-trackable.component';
|
||||||
|
|
||||||
describe('AbstractTrackableComponent', () => {
|
describe('AbstractTrackableComponent', () => {
|
||||||
@@ -35,6 +37,7 @@ describe('AbstractTrackableComponent', () => {
|
|||||||
success: successNotification,
|
success: successNotification,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
let router: RouterStub;
|
||||||
|
|
||||||
const url = 'http://test-url.com/test-url';
|
const url = 'http://test-url.com/test-url';
|
||||||
|
|
||||||
@@ -50,6 +53,8 @@ describe('AbstractTrackableComponent', () => {
|
|||||||
isValidPage: observableOf(true),
|
isValidPage: observableOf(true),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
router = new RouterStub();
|
||||||
|
router.url = url;
|
||||||
|
|
||||||
scheduler = getTestScheduler();
|
scheduler = getTestScheduler();
|
||||||
|
|
||||||
@@ -58,6 +63,7 @@ describe('AbstractTrackableComponent', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: ObjectUpdatesService, useValue: objectUpdatesService },
|
{ provide: ObjectUpdatesService, useValue: objectUpdatesService },
|
||||||
{ provide: NotificationsService, useValue: notificationsService },
|
{ provide: NotificationsService, useValue: notificationsService },
|
||||||
|
{ provide: Router, useValue: router },
|
||||||
], schemas: [
|
], schemas: [
|
||||||
NO_ERRORS_SCHEMA,
|
NO_ERRORS_SCHEMA,
|
||||||
],
|
],
|
||||||
@@ -67,7 +73,6 @@ describe('AbstractTrackableComponent', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(AbstractTrackableComponent);
|
fixture = TestBed.createComponent(AbstractTrackableComponent);
|
||||||
comp = fixture.componentInstance;
|
comp = fixture.componentInstance;
|
||||||
comp.url = url;
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,8 @@
|
|||||||
import { Component } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
OnInit,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
@@ -13,7 +17,7 @@ import { NotificationsService } from '../notifications/notifications.service';
|
|||||||
template: '',
|
template: '',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
})
|
})
|
||||||
export class AbstractTrackableComponent {
|
export class AbstractTrackableComponent implements OnInit {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time span for being able to undo discarding changes
|
* The time span for being able to undo discarding changes
|
||||||
@@ -23,14 +27,25 @@ export class AbstractTrackableComponent {
|
|||||||
public url: string;
|
public url: string;
|
||||||
public notificationsPrefix = 'static-pages.form.notification';
|
public notificationsPrefix = 'static-pages.form.notification';
|
||||||
|
|
||||||
|
hasChanges$: Observable<boolean>;
|
||||||
|
|
||||||
|
isReinstatable$: Observable<boolean>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public objectUpdatesService: ObjectUpdatesService,
|
public objectUpdatesService: ObjectUpdatesService,
|
||||||
public notificationsService: NotificationsService,
|
public notificationsService: NotificationsService,
|
||||||
public translateService: TranslateService,
|
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
|
* 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
|
* Shows a notification to remind the user that they can undo this
|
||||||
|
Reference in New Issue
Block a user