@Input() idlClass: string;
@Input() persistKeyPfx: string;
@Input() readonlyFields: string;
+ @Input() enableUndelete: boolean;
}
describe('Component: BasicAdminPage', () => {
const data = [{
schema: 'schema1',
table: 'table1',
- defaultNewRecord: { field1: 'value1' }
+ defaultNewRecord: { field1: 'value1' },
+ enableUndelete: true
}];
const parentRoute = { url: of('') };
const snapshot = { parent: { url: [{ path: '' }] } };
By.directive(MockAdminPageComponent)).componentInstance;
expect(adminPage.defaultNewRecord.a[0]).toEqual('value1');
});
+ it('sets enableUndelete from routing data', () => {
+ const adminPage: MockAdminPageComponent = fixture.debugElement.query(
+ By.directive(MockAdminPageComponent)).componentInstance;
+ expect(adminPage.enableUndelete).toEqual(true);
+ });
});
fieldOrder="{{fieldOrder}}"
readonlyFields="{{readonlyFields}}"
[defaultNewRecord]="defaultNewRecordIdl"
+ [enableUndelete]="enableUndelete"
[disableOrgFilter]="disableOrgFilter"></eg-admin-page>
</ng-container>
`
// Tell the admin page to disable and hide the automagic org unit filter
disableOrgFilter: boolean;
+ enableUndelete: boolean;
+
private getParams$: Observable<ParamMap>;
private getRouteData$: Observable<any>;
private getParentUrl$: Observable<any>;
this.table = data['table'];
}
this.disableOrgFilter = data['disableOrgFilter'];
+ this.enableUndelete = data['enableUndelete'];
this.fieldOrder = data['fieldOrder'];
this.readonlyFields = data['readonlyFields'];
this.defaultNewRecord = data['defaultNewRecord'];
data: [{
schema: 'asset',
table: 'copy_location',
+ enableUndelete: true,
readonlyFields: 'deleted',
fieldOrder: 'owning_lib,name,opac_visible,circulate,holdable,hold_verify,checkin_alert,deleted,label_prefix,label_suffix,url,id'}]
}, {
<ng-template #deleteSuccessStrTmpl i18n>{{idlClassDef.label}} Successfully Deleted</ng-template>
<eg-string #deleteSuccessString [template]="deleteSuccessStrTmpl"></eg-string>
+<ng-template #undeleteFailedStrTmpl i18n>Undelete of {{idlClassDef.label}} failed or was not allowed</ng-template>
+<eg-string #undeleteFailedString [template]="undeleteFailedStrTmpl"></eg-string>
+
+<ng-template #undeleteSuccessStrTmpl i18n>{{idlClassDef.label}} Successfully undeleted</ng-template>
+<eg-string #undeleteSuccessString [template]="undeleteSuccessStrTmpl"></eg-string>
+
<ng-template #createStrTmpl i18n>{{idlClassDef.label}} Successfully Created</ng-template>
<eg-string #createString [template]="createStrTmpl"></eg-string>
</eg-grid-toolbar-button>
<eg-grid-toolbar-action label="Edit Selected" i18n-label (onClick)="editSelected($event)">
</eg-grid-toolbar-action>
- <eg-grid-toolbar-action label="Delete Selected" i18n-label (onClick)="deleteSelected($event)">
+ <eg-grid-toolbar-action label="Delete Selected" i18n-label (onClick)="deleteSelected($event)"
+ [disableOnRows]="shouldDisableDelete">
+ </eg-grid-toolbar-action>
+ <eg-grid-toolbar-action label="Undelete Selected" i18n-label (onClick)="undeleteSelected($event)"
+ [disableOnRows]="shouldDisableUndelete" *ngIf="enableUndelete">
</eg-grid-toolbar-action>
<ng-container *ngFor="let cf of configFields">
<eg-grid-column name="{{cf.name}}" [cellTemplate]="configFieldLink">
--- /dev/null
+import { ActivatedRoute } from "@angular/router";
+import { AdminPageComponent } from "./admin-page.component";
+import { Location } from '@angular/common';
+import { FormatService } from "@eg/core/format.service";
+import { IdlService } from "@eg/core/idl.service";
+import { OrgService } from "@eg/core/org.service";
+import { AuthService } from "@eg/core/auth.service";
+import { PcrudService } from "@eg/core/pcrud.service";
+import { PermService } from "@eg/core/perm.service";
+import { ToastService } from "@eg/share/toast/toast.service";
+
+describe('CopyAttrsComponent', () => {
+ let component: AdminPageComponent;
+
+ const routeMock = jasmine.createSpyObj<ActivatedRoute>(['snapshot']);
+ const locationMock = jasmine.createSpyObj<Location>(['prepareExternalUrl']);
+ const formatMock = jasmine.createSpyObj<FormatService>(['transform']);
+ const idlMock = jasmine.createSpyObj<IdlService>(['classes']);
+ const orgMock = jasmine.createSpyObj<OrgService>(['get']);
+ const authMock = jasmine.createSpyObj<AuthService>(['user']);
+ const pcrudMock = jasmine.createSpyObj<PcrudService>(['retrieveAll']);
+ const permMock = jasmine.createSpyObj<PermService>(['hasWorkPermAt']);
+ const toastMock = jasmine.createSpyObj<ToastService>(['success']);
+ beforeEach(() => {
+ component = new AdminPageComponent(routeMock, locationMock, formatMock,
+ idlMock, orgMock, authMock, pcrudMock, permMock, toastMock);
+ })
+
+ describe('#shouldDisableDelete', () => {
+ it('returns true if one of the rows is already deleted', () => {
+ const rows = [
+ {isdeleted: () => true, a: [], classname: '', _isfieldmapper: true },
+ {isdeleted: () => false, a: [], classname: '', _isfieldmapper: true }
+ ];
+ expect(component.shouldDisableDelete(rows)).toBe(true);
+ });
+ it('returns true if no rows selected', () => {
+ expect(component.shouldDisableDelete([])).toBe(true);
+ })
+ it('returns false (i.e. you _should_ display delete) if no selected rows are deleted', () => {
+ const rows = [
+ {isdeleted: () => false, deleted: () => 'f', a: [], classname: '', _isfieldmapper: true }
+ ];
+ expect(component.shouldDisableDelete(rows)).toBe(false);
+ })
+ });
+ describe('#shouldDisableUndelete', () => {
+ it('returns true if none of the rows are deleted', () => {
+ const rows = [
+ {isdeleted: () => false, a: [], classname: '', _isfieldmapper: true },
+ {deleted: () => 'f', a: [], classname: '', _isfieldmapper: true }
+ ];
+ expect(component.shouldDisableUndelete(rows)).toBe(true);
+ });
+ it('returns true if no rows selected', () => {
+ expect(component.shouldDisableUndelete([])).toBe(true);
+ })
+ it('returns false (i.e. you _should_ display undelete) if all selected rows are deleted', () => {
+ const rows = [
+ {deleted: () => 't', a: [], classname: '', _isfieldmapper: true }
+ ];
+ expect(component.shouldDisableUndelete(rows)).toBe(false);
+ })
+ });
+});
// Disable the auto-matic org unit field filter
@Input() disableOrgFilter: boolean;
+ // Give the grid an option to undelete any deleted rows
+ @Input() enableUndelete: boolean;
+
// Include objects linking to org units which are ancestors
// of the selected org unit.
@Input() includeOrgAncestors: boolean;
@ViewChild('updateFailedString', { static: true }) updateFailedString: StringComponent;
@ViewChild('deleteFailedString', { static: true }) deleteFailedString: StringComponent;
@ViewChild('deleteSuccessString', { static: true }) deleteSuccessString: StringComponent;
+ @ViewChild('undeleteFailedString', { static: true }) undeleteFailedString: StringComponent;
+ @ViewChild('undeleteSuccessString', { static: true }) undeleteSuccessString: StringComponent;
@ViewChild('translator', { static: true }) translator: TranslateComponent;
idlClassDef: any;
editOneThing(idlThings.shift());
}
+ undeleteSelected(idlThings: IdlObject[]) {
+ idlThings.forEach(idlThing => idlThing.deleted(false));
+ this.pcrud.update(idlThings).subscribe(
+ val => {
+ this.undeleteSuccessString.current()
+ .then(str => this.toast.success(str));
+ },
+ err => {
+ this.undeleteFailedString.current()
+ .then(str => this.toast.danger(str));
+ },
+ () => this.grid.reload()
+ );
+ }
+
deleteSelected(idlThings: IdlObject[]) {
idlThings.forEach(idlThing => idlThing.isdeleted(true));
this.pcrud.autoApply(idlThings).subscribe(
);
}
+ shouldDisableDelete(rows: IdlObject[]): boolean {
+ if (rows.length === 0) {
+ return true;
+ } else {
+ const deletedRows = rows.filter((row) => {
+ if (row.deleted && row.deleted() === 't') {
+ return true;
+ } else if (row.isdeleted) {
+ return row.isdeleted();
+ }
+ });
+ return deletedRows.length > 0;
+ }
+ }
+
+ shouldDisableUndelete(rows: IdlObject[]): boolean {
+ if (rows.length === 0) {
+ return true;
+ } else {
+ const deletedRows = rows.filter((row) => {
+ if (row.deleted && row.deleted() === 't') {
+ return true;
+ } else if (row.isdeleted) {
+ return row.isdeleted();
+ }
+ });
+ return deletedRows.length !== rows.length;
+ }
+ }
+
createNew() {
this.editDialog.mode = 'create';
// We reuse the same editor for all actions. Be sure