diff --git a/src/app/item-page/full/full-item-page.component.html b/src/app/item-page/full/full-item-page.component.html
index d2655c4ad0..e71dd92f96 100644
--- a/src/app/item-page/full/full-item-page.component.html
+++ b/src/app/item-page/full/full-item-page.component.html
@@ -4,19 +4,21 @@
-
-
-
-
+
-
-
-
+
+
+
{{mdEntry.key}} |
@@ -24,14 +26,16 @@
{{mdValue.language}} |
-
-
-
-
-
-
+
+
+
+
+
diff --git a/src/app/item-page/full/full-item-page.component.spec.ts b/src/app/item-page/full/full-item-page.component.spec.ts
index b4ab926667..c7643a940e 100644
--- a/src/app/item-page/full/full-item-page.component.spec.ts
+++ b/src/app/item-page/full/full-item-page.component.spec.ts
@@ -11,12 +11,15 @@ import { ActivatedRouteStub } from '../../shared/testing/active-router.stub';
import { VarDirective } from '../../shared/utils/var.directive';
import { RouterTestingModule } from '@angular/router/testing';
import { Item } from '../../core/shared/item.model';
-import { of as observableOf } from 'rxjs';
+import { BehaviorSubject, of as observableOf } from 'rxjs';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { By } from '@angular/platform-browser';
import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
import { AuthService } from '../../core/auth/auth.service';
import { createPaginatedList } from '../../shared/testing/utils.test';
+import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
+import { createRelationshipsObservable } from '../simple/item-types/shared/item.component.spec';
+import { RemoteData } from '../../core/data/remote-data';
const mockItem: Item = Object.assign(new Item(), {
bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
@@ -30,6 +33,13 @@ const mockItem: Item = Object.assign(new Item(), {
}
});
+const mockWithdrawnItem: Item = Object.assign(new Item(), {
+ bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
+ metadata: [],
+ relationships: createRelationshipsObservable(),
+ isWithdrawn: true
+});
+
const metadataServiceStub = {
/* tslint:disable:no-empty */
processRemoteData: () => {
@@ -44,6 +54,7 @@ describe('FullItemPageComponent', () => {
let authService: AuthService;
let routeStub: ActivatedRouteStub;
let routeData;
+ let authorizationDataService: AuthorizationDataService;
@@ -61,6 +72,10 @@ describe('FullItemPageComponent', () => {
data: observableOf(routeData)
});
+ authorizationDataService = jasmine.createSpyObj('authorizationDataService', {
+ isAuthorized: observableOf(false),
+ });
+
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot({
loader: {
@@ -74,6 +89,7 @@ describe('FullItemPageComponent', () => {
{ provide: ItemDataService, useValue: {} },
{ provide: MetadataService, useValue: metadataServiceStub },
{ provide: AuthService, useValue: authService },
+ { provide: AuthorizationDataService, useValue: authorizationDataService },
],
schemas: [NO_ERRORS_SCHEMA]
@@ -111,4 +127,53 @@ describe('FullItemPageComponent', () => {
expect(simpleViewBtn).toBeFalsy();
});
}));
+
+ describe('when the item is withdrawn and the user is an admin', () => {
+ beforeEach(() => {
+ comp.isAdmin$ = observableOf(true);
+ comp.itemRD$ = new BehaviorSubject>(createSuccessfulRemoteDataObject(mockWithdrawnItem));
+ fixture.detectChanges();
+ });
+
+ it('should display the item', () => {
+ const objectLoader = fixture.debugElement.query(By.css('.full-item-info'));
+ expect(objectLoader.nativeElement).toBeDefined();
+ });
+ });
+ describe('when the item is withdrawn and the user is not an admin', () => {
+ beforeEach(() => {
+ comp.itemRD$ = new BehaviorSubject>(createSuccessfulRemoteDataObject(mockWithdrawnItem));
+ fixture.detectChanges();
+ });
+
+ it('should not display the item', () => {
+ const objectLoader = fixture.debugElement.query(By.css('.full-item-info'));
+ expect(objectLoader).toBeNull();
+ });
+ });
+
+ describe('when the item is not withdrawn and the user is an admin', () => {
+ beforeEach(() => {
+ comp.isAdmin$ = observableOf(true);
+ comp.itemRD$ = new BehaviorSubject>(createSuccessfulRemoteDataObject(mockItem));
+ fixture.detectChanges();
+ });
+
+ it('should display the item', () => {
+ const objectLoader = fixture.debugElement.query(By.css('.full-item-info'));
+ expect(objectLoader.nativeElement).toBeDefined();
+ });
+ });
+
+ describe('when the item is not withdrawn and the user is not an admin', () => {
+ beforeEach(() => {
+ comp.itemRD$ = new BehaviorSubject>(createSuccessfulRemoteDataObject(mockItem));
+ fixture.detectChanges();
+ });
+
+ it('should display the item', () => {
+ const objectLoader = fixture.debugElement.query(By.css('.full-item-info'));
+ expect(objectLoader.nativeElement).toBeDefined();
+ });
+ });
});
diff --git a/src/app/item-page/full/full-item-page.component.ts b/src/app/item-page/full/full-item-page.component.ts
index 7f1b6de614..369769c77d 100644
--- a/src/app/item-page/full/full-item-page.component.ts
+++ b/src/app/item-page/full/full-item-page.component.ts
@@ -15,6 +15,7 @@ import { fadeInOut } from '../../shared/animations/fade';
import { hasValue } from '../../shared/empty.util';
import { AuthService } from '../../core/auth/auth.service';
import { Location } from '@angular/common';
+import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
/**
@@ -46,8 +47,9 @@ export class FullItemPageComponent extends ItemPageComponent implements OnInit,
router: Router,
items: ItemDataService,
authService: AuthService,
+ authorizationService: AuthorizationDataService,
private _location: Location) {
- super(route, router, items, authService);
+ super(route, router, items, authService, authorizationService);
}
/*** AoT inheritance fix, will hopefully be resolved in the near future **/
diff --git a/src/app/item-page/simple/item-page.component.html b/src/app/item-page/simple/item-page.component.html
index e843155d10..3e834b53db 100644
--- a/src/app/item-page/simple/item-page.component.html
+++ b/src/app/item-page/simple/item-page.component.html
@@ -4,7 +4,7 @@
-
+
diff --git a/src/app/item-page/simple/item-page.component.spec.ts b/src/app/item-page/simple/item-page.component.spec.ts
index ff5a1e38d5..2ad0bbb272 100644
--- a/src/app/item-page/simple/item-page.component.spec.ts
+++ b/src/app/item-page/simple/item-page.component.spec.ts
@@ -21,6 +21,7 @@ import {
} from '../../shared/remote-data.utils';
import { AuthService } from '../../core/auth/auth.service';
import { createPaginatedList } from '../../shared/testing/utils.test';
+import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
const mockItem: Item = Object.assign(new Item(), {
bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
@@ -28,10 +29,18 @@ const mockItem: Item = Object.assign(new Item(), {
relationships: createRelationshipsObservable()
});
+const mockWithdrawnItem: Item = Object.assign(new Item(), {
+ bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
+ metadata: [],
+ relationships: createRelationshipsObservable(),
+ isWithdrawn: true
+});
+
describe('ItemPageComponent', () => {
let comp: ItemPageComponent;
let fixture: ComponentFixture;
let authService: AuthService;
+ let authorizationDataService: AuthorizationDataService;
const mockMetadataService = {
/* tslint:disable:no-empty */
@@ -48,6 +57,9 @@ describe('ItemPageComponent', () => {
isAuthenticated: observableOf(true),
setRedirectUrl: {}
});
+ authorizationDataService = jasmine.createSpyObj('authorizationDataService', {
+ isAuthorized: observableOf(false),
+ });
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot({
@@ -63,6 +75,7 @@ describe('ItemPageComponent', () => {
{ provide: MetadataService, useValue: mockMetadataService },
{ provide: Router, useValue: {} },
{ provide: AuthService, useValue: authService },
+ { provide: AuthorizationDataService, useValue: authorizationDataService },
],
schemas: [NO_ERRORS_SCHEMA]
@@ -102,4 +115,53 @@ describe('ItemPageComponent', () => {
});
});
+ describe('when the item is withdrawn and the user is an admin', () => {
+ beforeEach(() => {
+ comp.isAdmin$ = observableOf(true);
+ comp.itemRD$ = createSuccessfulRemoteDataObject$(mockWithdrawnItem);
+ fixture.detectChanges();
+ });
+
+ it('should display the item', () => {
+ const objectLoader = fixture.debugElement.query(By.css('ds-listable-object-component-loader'));
+ expect(objectLoader.nativeElement).toBeDefined();
+ });
+ });
+ describe('when the item is withdrawn and the user is not an admin', () => {
+ beforeEach(() => {
+ comp.itemRD$ = createSuccessfulRemoteDataObject$(mockWithdrawnItem);
+ fixture.detectChanges();
+ });
+
+ it('should not display the item', () => {
+ const objectLoader = fixture.debugElement.query(By.css('ds-listable-object-component-loader'));
+ expect(objectLoader).toBeNull();
+ });
+ });
+
+ describe('when the item is not withdrawn and the user is an admin', () => {
+ beforeEach(() => {
+ comp.isAdmin$ = observableOf(true);
+ comp.itemRD$ = createSuccessfulRemoteDataObject$(mockItem);
+ fixture.detectChanges();
+ });
+
+ it('should display the item', () => {
+ const objectLoader = fixture.debugElement.query(By.css('ds-listable-object-component-loader'));
+ expect(objectLoader.nativeElement).toBeDefined();
+ });
+ });
+
+ describe('when the item is not withdrawn and the user is not an admin', () => {
+ beforeEach(() => {
+ comp.itemRD$ = createSuccessfulRemoteDataObject$(mockItem);
+ fixture.detectChanges();
+ });
+
+ it('should display the item', () => {
+ const objectLoader = fixture.debugElement.query(By.css('ds-listable-object-component-loader'));
+ expect(objectLoader.nativeElement).toBeDefined();
+ });
+ });
+
});
diff --git a/src/app/item-page/simple/item-page.component.ts b/src/app/item-page/simple/item-page.component.ts
index cc23ba86d5..0559dc2219 100644
--- a/src/app/item-page/simple/item-page.component.ts
+++ b/src/app/item-page/simple/item-page.component.ts
@@ -1,4 +1,4 @@
-import { map } from 'rxjs/operators';
+import { map, switchMap } from 'rxjs/operators';
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
@@ -13,6 +13,8 @@ import { getAllSucceededRemoteDataPayload, redirectOn4xx } from '../../core/shar
import { ViewMode } from '../../core/shared/view-mode.model';
import { AuthService } from '../../core/auth/auth.service';
import { getItemPageRoute } from '../item-page-routing-paths';
+import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
+import { FeatureID } from '../../core/data/feature-authorization/feature-id';
/**
* This component renders a simple item page.
@@ -48,11 +50,17 @@ export class ItemPageComponent implements OnInit {
*/
itemPageRoute$: Observable;
+ /**
+ * Whether the current user is an admin or not
+ */
+ isAdmin$: Observable;
+
constructor(
protected route: ActivatedRoute,
private router: Router,
private items: ItemDataService,
private authService: AuthService,
+ private authorizationService: AuthorizationDataService
) { }
/**
@@ -67,5 +75,7 @@ export class ItemPageComponent implements OnInit {
getAllSucceededRemoteDataPayload(),
map((item) => getItemPageRoute(item))
);
+
+ this.isAdmin$ = this.authorizationService.isAuthorized(FeatureID.AdministratorOf);
}
}
diff --git a/src/app/shared/item/item-alerts/item-alerts.component.html b/src/app/shared/item/item-alerts/item-alerts.component.html
index fce5c038e5..740ea2595d 100644
--- a/src/app/shared/item/item-alerts/item-alerts.component.html
+++ b/src/app/shared/item/item-alerts/item-alerts.component.html
@@ -1,8 +1,13 @@