diff --git a/src/app/collection-page/collection-page.component.html b/src/app/collection-page/collection-page.component.html
index 02c63d316d8..3cbd08f1325 100644
--- a/src/app/collection-page/collection-page.component.html
+++ b/src/app/collection-page/collection-page.component.html
@@ -34,9 +34,6 @@
-
-
-
diff --git a/src/app/community-page/community-page.component.html b/src/app/community-page/community-page.component.html
index 6d5262d9338..671bf28fd1c 100644
--- a/src/app/community-page/community-page.component.html
+++ b/src/app/community-page/community-page.component.html
@@ -21,9 +21,6 @@
-
-
-
diff --git a/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts b/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts
index abfe618174b..e28a416f230 100644
--- a/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts
+++ b/src/app/shared/dso-page/dso-edit-menu.resolver.spec.ts
@@ -1,6 +1,6 @@
import { TestBed, waitForAsync } from '@angular/core/testing';
import { MenuServiceStub } from '../testing/menu-service.stub';
-import { of as observableOf } from 'rxjs';
+import { combineLatest, map, of as observableOf } from 'rxjs';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
@@ -16,10 +16,13 @@ import { Item } from '../../core/shared/item.model';
import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
import { MenuID } from '../menu/menu-id.model';
import { MenuItemType } from '../menu/menu-item-type.model';
-import { TextMenuItemModel } from '../menu/menu-item/models/text.model';
import { LinkMenuItemModel } from '../menu/menu-item/models/link.model';
import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service';
import { NotificationsService } from '../notifications/notifications.service';
+import { DSpaceObject } from '../../core/shared/dspace-object.model';
+import { Community } from '../../core/shared/community.model';
+import { Collection } from '../../core/shared/collection.model';
+import flatten from 'lodash/flatten';
describe('DSOEditMenuResolver', () => {
@@ -37,25 +40,44 @@ describe('DSOEditMenuResolver', () => {
let notificationsService;
let translate;
- const route = {
- data: {
- menu: {
- 'statistics': [{
- id: 'statistics-dummy-1',
- active: false,
- visible: true,
- model: null
- }]
- }
- },
- params: {id: 'test-uuid'},
+ const dsoRoute = (dso: DSpaceObject) => {
+ return {
+ data: {
+ menu: {
+ 'statistics': [{
+ id: 'statistics-dummy-1',
+ active: false,
+ visible: true,
+ model: null
+ }]
+ }
+ },
+ params: {id: dso.uuid},
+ };
};
const state = {
url: 'test-url'
};
- const testObject = Object.assign(new Item(), {uuid: 'test-uuid', type: 'item', _links: {self: {href: 'self-link'}}});
+ const testCommunity: Community = Object.assign(new Community(), {
+ uuid: 'test-community-uuid',
+ type: 'community',
+ _links: {self: {href: 'self-link'}},
+ });
+ const testCollection: Collection = Object.assign(new Collection(), {
+ uuid: 'test-collection-uuid',
+ type: 'collection',
+ _links: {self: {href: 'self-link'}},
+ });
+ const testItem: Item = Object.assign(new Item(), {
+ uuid: 'test-item-uuid',
+ type: 'item',
+ _links: {self: {href: 'self-link'}},
+ });
+
+ let testObject: DSpaceObject;
+ let route;
const dummySections1 = [{
id: 'dummy-1',
@@ -90,6 +112,10 @@ describe('DSOEditMenuResolver', () => {
}];
beforeEach(waitForAsync(() => {
+ // test with Items unless specified otherwise
+ testObject = testItem;
+ route = dsoRoute(testItem);
+
menuService = new MenuServiceStub();
spyOn(menuService, 'getMenu').and.returnValue(observableOf(MENU_STATE));
@@ -154,16 +180,17 @@ describe('DSOEditMenuResolver', () => {
{
...route.data.menu,
[MenuID.DSO_EDIT]: [
- ...dummySections1.map((menu) => Object.assign(menu, {id: menu.id + '-test-uuid'})),
- ...dummySections2.map((menu) => Object.assign(menu, {id: menu.id + '-test-uuid'}))
+ ...dummySections1.map((menu) => Object.assign(menu, {id: menu.id + '-test-item-uuid'})),
+ ...dummySections2.map((menu) => Object.assign(menu, {id: menu.id + '-test-item-uuid'}))
]
}
);
- expect(dSpaceObjectDataService.findById).toHaveBeenCalledWith('test-uuid', true, false);
+ expect(dSpaceObjectDataService.findById).toHaveBeenCalledWith('test-item-uuid', true, false);
expect(resolver.getDsoMenus).toHaveBeenCalled();
done();
});
});
+
it('should create all menus when a dso is found based on the route scope query param when no id param is present', (done) => {
spyOn(resolver, 'getDsoMenus').and.returnValue(
[observableOf(dummySections1), observableOf(dummySections2)]
@@ -198,6 +225,7 @@ describe('DSOEditMenuResolver', () => {
done();
});
});
+
it('should return the statistics menu when no dso is found', (done) => {
(dSpaceObjectDataService.findById as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$());
@@ -211,49 +239,165 @@ describe('DSOEditMenuResolver', () => {
});
});
});
+
describe('getDsoMenus', () => {
- it('should return as first part the item version, orcid and claim list ', (done) => {
- const result = resolver.getDsoMenus(testObject, route, state);
- result[0].subscribe((menuList) => {
- expect(menuList.length).toEqual(3);
- expect(menuList[0].id).toEqual('orcid-dso');
- expect(menuList[0].active).toEqual(false);
- // Visible should be false due to the item not being of type person
- expect(menuList[0].visible).toEqual(false);
- expect(menuList[0].model.type).toEqual(MenuItemType.LINK);
-
- expect(menuList[1].id).toEqual('version-dso');
- expect(menuList[1].active).toEqual(false);
- expect(menuList[1].visible).toEqual(true);
- expect(menuList[1].model.type).toEqual(MenuItemType.ONCLICK);
- expect((menuList[1].model as TextMenuItemModel).text).toEqual('message');
- expect(menuList[1].model.disabled).toEqual(false);
- expect(menuList[1].icon).toEqual('code-branch');
-
- expect(menuList[2].id).toEqual('claim-dso');
- expect(menuList[2].active).toEqual(false);
- // Visible should be false due to the item not being of type person
- expect(menuList[2].visible).toEqual(false);
- expect(menuList[2].model.type).toEqual(MenuItemType.ONCLICK);
- expect((menuList[2].model as TextMenuItemModel).text).toEqual('item.page.claim.button');
- done();
+ describe('for Communities', () => {
+ beforeEach(() => {
+ testObject = testCommunity;
+ dSpaceObjectDataService.findById.and.returnValue(createSuccessfulRemoteDataObject$(testCommunity));
+ route = dsoRoute(testCommunity);
+ });
+
+ it('should not return Item-specific entries', (done) => {
+ const result = resolver.getDsoMenus(testObject, route, state);
+ combineLatest(result).pipe(map(flatten)).subscribe((menu) => {
+ const orcidEntry = menu.find(entry => entry.id === 'orcid-dso');
+ expect(orcidEntry).toBeFalsy();
+
+ const versionEntry = menu.find(entry => entry.id === 'version-dso');
+ expect(versionEntry).toBeFalsy();
+
+ const claimEntry = menu.find(entry => entry.id === 'claim-dso');
+ expect(claimEntry).toBeFalsy();
+
+ done();
+ });
+ });
+
+ it('should return Community/Collection-specific entries', (done) => {
+ const result = resolver.getDsoMenus(testObject, route, state);
+ combineLatest(result).pipe(map(flatten)).subscribe((menu) => {
+ const subscribeEntry = menu.find(entry => entry.id === 'subscribe');
+ expect(subscribeEntry).toBeTruthy();
+ expect(subscribeEntry.active).toBeFalse();
+ expect(subscribeEntry.visible).toBeTrue();
+ expect(subscribeEntry.model.type).toEqual(MenuItemType.ONCLICK);
+ done();
+ });
});
+ it('should return as third part the common list ', (done) => {
+ const result = resolver.getDsoMenus(testObject, route, state);
+ combineLatest(result).pipe(map(flatten)).subscribe((menu) => {
+ const editEntry = menu.find(entry => entry.id === 'edit-dso');
+ expect(editEntry).toBeTruthy();
+ expect(editEntry.active).toBeFalse();
+ expect(editEntry.visible).toBeTrue();
+ expect(editEntry.model.type).toEqual(MenuItemType.LINK);
+ expect((editEntry.model as LinkMenuItemModel).link).toEqual(
+ '/communities/test-community-uuid/edit/metadata'
+ );
+ done();
+ });
+ });
});
- it('should return as second part the common list ', (done) => {
- const result = resolver.getDsoMenus(testObject, route, state);
- result[1].subscribe((menuList) => {
- expect(menuList.length).toEqual(1);
- expect(menuList[0].id).toEqual('edit-dso');
- expect(menuList[0].active).toEqual(false);
- expect(menuList[0].visible).toEqual(true);
- expect(menuList[0].model.type).toEqual(MenuItemType.LINK);
- expect((menuList[0].model as LinkMenuItemModel).text).toEqual('item.page.edit');
- expect((menuList[0].model as LinkMenuItemModel).link).toEqual('/items/test-uuid/edit/metadata');
- expect(menuList[0].icon).toEqual('pencil-alt');
- done();
+
+ describe('for Collections', () => {
+ beforeEach(() => {
+ testObject = testCollection;
+ dSpaceObjectDataService.findById.and.returnValue(createSuccessfulRemoteDataObject$(testCollection));
+ route = dsoRoute(testCollection);
+ });
+
+ it('should not return Item-specific entries', (done) => {
+ const result = resolver.getDsoMenus(testObject, route, state);
+ combineLatest(result).pipe(map(flatten)).subscribe((menu) => {
+ const orcidEntry = menu.find(entry => entry.id === 'orcid-dso');
+ expect(orcidEntry).toBeFalsy();
+
+ const versionEntry = menu.find(entry => entry.id === 'version-dso');
+ expect(versionEntry).toBeFalsy();
+
+ const claimEntry = menu.find(entry => entry.id === 'claim-dso');
+ expect(claimEntry).toBeFalsy();
+
+ done();
+ });
+ });
+
+ it('should return Community/Collection-specific entries', (done) => {
+ const result = resolver.getDsoMenus(testObject, route, state);
+ combineLatest(result).pipe(map(flatten)).subscribe((menu) => {
+ const subscribeEntry = menu.find(entry => entry.id === 'subscribe');
+ expect(subscribeEntry).toBeTruthy();
+ expect(subscribeEntry.active).toBeFalse();
+ expect(subscribeEntry.visible).toBeTrue();
+ expect(subscribeEntry.model.type).toEqual(MenuItemType.ONCLICK);
+ done();
+ });
+ });
+
+ it('should return as third part the common list ', (done) => {
+ const result = resolver.getDsoMenus(testObject, route, state);
+ combineLatest(result).pipe(map(flatten)).subscribe((menu) => {
+ const editEntry = menu.find(entry => entry.id === 'edit-dso');
+ expect(editEntry).toBeTruthy();
+ expect(editEntry.active).toBeFalse();
+ expect(editEntry.visible).toBeTrue();
+ expect(editEntry.model.type).toEqual(MenuItemType.LINK);
+ expect((editEntry.model as LinkMenuItemModel).link).toEqual(
+ '/collections/test-collection-uuid/edit/metadata'
+ );
+ done();
+ });
});
+ });
+
+ describe('for Items', () => {
+ beforeEach(() => {
+ testObject = testItem;
+ dSpaceObjectDataService.findById.and.returnValue(createSuccessfulRemoteDataObject$(testItem));
+ route = dsoRoute(testItem);
+ });
+
+ it('should return Item-specific entries', (done) => {
+ const result = resolver.getDsoMenus(testObject, route, state);
+ combineLatest(result).pipe(map(flatten)).subscribe((menu) => {
+ const orcidEntry = menu.find(entry => entry.id === 'orcid-dso');
+ expect(orcidEntry).toBeTruthy();
+ expect(orcidEntry.active).toBeFalse();
+ expect(orcidEntry.visible).toBeFalse();
+ expect(orcidEntry.model.type).toEqual(MenuItemType.LINK);
+
+ const versionEntry = menu.find(entry => entry.id === 'version-dso');
+ expect(versionEntry).toBeTruthy();
+ expect(versionEntry.active).toBeFalse();
+ expect(versionEntry.visible).toBeTrue();
+ expect(versionEntry.model.type).toEqual(MenuItemType.ONCLICK);
+ expect(versionEntry.model.disabled).toBeFalse();
+ const claimEntry = menu.find(entry => entry.id === 'claim-dso');
+ expect(claimEntry).toBeTruthy();
+ expect(claimEntry.active).toBeFalse();
+ expect(claimEntry.visible).toBeFalse();
+ expect(claimEntry.model.type).toEqual(MenuItemType.ONCLICK);
+ done();
+ });
+ });
+
+ it('should not return Community/Collection-specific entries', (done) => {
+ const result = resolver.getDsoMenus(testObject, route, state);
+ combineLatest(result).pipe(map(flatten)).subscribe((menu) => {
+ const subscribeEntry = menu.find(entry => entry.id === 'subscribe');
+ expect(subscribeEntry).toBeFalsy();
+ done();
+ });
+ });
+
+ it('should return as third part the common list ', (done) => {
+ const result = resolver.getDsoMenus(testObject, route, state);
+ combineLatest(result).pipe(map(flatten)).subscribe((menu) => {
+ const editEntry = menu.find(entry => entry.id === 'edit-dso');
+ expect(editEntry).toBeTruthy();
+ expect(editEntry.active).toBeFalse();
+ expect(editEntry.visible).toBeTrue();
+ expect(editEntry.model.type).toEqual(MenuItemType.LINK);
+ expect((editEntry.model as LinkMenuItemModel).link).toEqual(
+ '/items/test-item-uuid/edit/metadata'
+ );
+ done();
+ });
+ });
});
});
});
diff --git a/src/app/shared/dso-page/dso-edit-menu.resolver.ts b/src/app/shared/dso-page/dso-edit-menu.resolver.ts
index 80a69c2830d..1ade4578405 100644
--- a/src/app/shared/dso-page/dso-edit-menu.resolver.ts
+++ b/src/app/shared/dso-page/dso-edit-menu.resolver.ts
@@ -21,6 +21,9 @@ import { getDSORoute } from '../../app-routing-paths';
import { ResearcherProfileDataService } from '../../core/profile/researcher-profile-data.service';
import { NotificationsService } from '../notifications/notifications.service';
import { TranslateService } from '@ngx-translate/core';
+import { SubscriptionModalComponent } from '../subscriptions/subscription-modal/subscription-modal.component';
+import { Community } from '../../core/shared/community.model';
+import { Collection } from '../../core/shared/collection.model';
/**
* Creates the menus for the dspace object pages
@@ -84,6 +87,7 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection
getDsoMenus(dso, route, state): Observable[] {
return [
this.getItemMenu(dso),
+ this.getComColMenu(dso),
this.getCommonMenu(dso, state)
];
}
@@ -178,6 +182,39 @@ export class DSOEditMenuResolver implements Resolve<{ [key: string]: MenuSection
}
}
+ /**
+ * Get Community/Collection-specific menus
+ */
+ protected getComColMenu(dso): Observable {
+ if (dso instanceof Community || dso instanceof Collection) {
+ return combineLatest([
+ this.authorizationService.isAuthorized(FeatureID.CanSubscribe, dso.self),
+ ]).pipe(
+ map(([canSubscribe]) => {
+ return [
+ {
+ id: 'subscribe',
+ active: false,
+ visible: canSubscribe,
+ model: {
+ type: MenuItemType.ONCLICK,
+ text: 'subscriptions.tooltip',
+ function: () => {
+ const modalRef = this.modalService.open(SubscriptionModalComponent);
+ modalRef.componentInstance.dso = dso;
+ }
+ } as OnClickMenuItemModel,
+ icon: 'bell',
+ index: 4
+ },
+ ];
+ })
+ );
+ } else {
+ return observableOf([]);
+ }
+ }
+
/**
* Claim a researcher by creating a profile
* Shows notifications and/or hides the menu section on success/error
diff --git a/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.html b/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.html
deleted file mode 100644
index 15135009fcd..00000000000
--- a/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
diff --git a/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.scss b/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.scss
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.spec.ts b/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.spec.ts
deleted file mode 100644
index 726854778dc..00000000000
--- a/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.spec.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { DsoPageSubscriptionButtonComponent } from './dso-page-subscription-button.component';
-import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
-import { of as observableOf } from 'rxjs';
-import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
-import { By } from '@angular/platform-browser';
-import { DebugElement } from '@angular/core';
-import { Item } from '../../../core/shared/item.model';
-import { ITEM } from '../../../core/shared/item.resource-type';
-import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
-import { TranslateLoaderMock } from '../../mocks/translate-loader.mock';
-
-describe('DsoPageSubscriptionButtonComponent', () => {
- let component: DsoPageSubscriptionButtonComponent;
- let fixture: ComponentFixture;
- let de: DebugElement;
-
- const authorizationService = jasmine.createSpyObj('authorizationService', {
- isAuthorized: jasmine.createSpy('isAuthorized') // observableOf(true)
- });
-
- const mockItem = Object.assign(new Item(), {
- id: 'fake-id',
- uuid: 'fake-id',
- handle: 'fake/handle',
- lastModified: '2018',
- type: ITEM,
- _links: {
- self: {
- href: 'https://localhost:8000/items/fake-id'
- }
- }
- });
-
- beforeEach(async () => {
- await TestBed.configureTestingModule({
- imports: [
- NgbModalModule,
- TranslateModule.forRoot({
- loader: {
- provide: TranslateLoader,
- useClass: TranslateLoaderMock
- }
- })
- ],
- declarations: [ DsoPageSubscriptionButtonComponent ],
- providers: [
- { provide: AuthorizationDataService, useValue: authorizationService },
- ]
- })
- .compileComponents();
- });
-
- beforeEach(() => {
- fixture = TestBed.createComponent(DsoPageSubscriptionButtonComponent);
- component = fixture.componentInstance;
- de = fixture.debugElement;
- component.dso = mockItem;
- });
-
- describe('when is authorized', () => {
- beforeEach(() => {
- authorizationService.isAuthorized.and.returnValue(observableOf(true));
- fixture.detectChanges();
- });
-
- it('should display subscription button', () => {
- expect(de.query(By.css(' [data-test="subscription-button"]'))).toBeTruthy();
- });
- });
-
- describe('when is not authorized', () => {
- beforeEach(() => {
- authorizationService.isAuthorized.and.returnValue(observableOf(false));
- fixture.detectChanges();
- });
-
- it('should not display subscription button', () => {
- expect(de.query(By.css(' [data-test="subscription-button"]'))).toBeNull();
- });
- });
-});
diff --git a/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.ts b/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.ts
deleted file mode 100644
index 54cd9e6bb0d..00000000000
--- a/src/app/shared/dso-page/dso-page-subscription-button/dso-page-subscription-button.component.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { Component, Input, OnInit } from '@angular/core';
-
-import { Observable, of } from 'rxjs';
-import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
-
-import { DSpaceObject } from '../../../core/shared/dspace-object.model';
-import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
-import { SubscriptionModalComponent } from '../../subscriptions/subscription-modal/subscription-modal.component';
-import { FeatureID } from '../../../core/data/feature-authorization/feature-id';
-
-@Component({
- selector: 'ds-dso-page-subscription-button',
- templateUrl: './dso-page-subscription-button.component.html',
- styleUrls: ['./dso-page-subscription-button.component.scss']
-})
-/**
- * Display a button that opens the modal to manage subscriptions
- */
-export class DsoPageSubscriptionButtonComponent implements OnInit {
-
- /**
- * Whether the current user is authorized to edit the DSpaceObject
- */
- isAuthorized$: Observable = of(false);
-
- /**
- * Reference to NgbModal
- */
- public modalRef: NgbModalRef;
-
- /**
- * DSpaceObject that is being viewed
- */
- @Input() dso: DSpaceObject;
-
- constructor(
- protected authorizationService: AuthorizationDataService,
- private modalService: NgbModal,
- ) {
- }
-
- /**
- * check if the current DSpaceObject can be subscribed by the user
- */
- ngOnInit(): void {
- this.isAuthorized$ = this.authorizationService.isAuthorized(FeatureID.CanSubscribe, this.dso.self);
- }
-
- /**
- * Open the modal to subscribe to the related DSpaceObject
- */
- public openSubscriptionModal() {
- this.modalRef = this.modalService.open(SubscriptionModalComponent);
- this.modalRef.componentInstance.dso = this.dso;
- }
-
-}
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index 0f7871f7f9b..c6e2ddc3f37 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -273,9 +273,6 @@ import {
AdvancedClaimedTaskActionRatingComponent
} from './mydspace-actions/claimed-task/rating/advanced-claimed-task-action-rating.component';
import { ClaimedTaskActionsDeclineTaskComponent } from './mydspace-actions/claimed-task/decline-task/claimed-task-actions-decline-task.component';
-import {
- DsoPageSubscriptionButtonComponent
-} from './dso-page/dso-page-subscription-button/dso-page-subscription-button.component';
import { EpersonGroupListComponent } from './eperson-group-list/eperson-group-list.component';
import { EpersonSearchBoxComponent } from './eperson-group-list/eperson-search-box/eperson-search-box.component';
import { GroupSearchBoxComponent } from './eperson-group-list/group-search-box/group-search-box.component';
@@ -395,7 +392,6 @@ const COMPONENTS = [
ItemPageTitleFieldComponent,
ThemedSearchNavbarComponent,
ListableNotificationObjectComponent,
- DsoPageSubscriptionButtonComponent,
MetadataFieldWrapperComponent,
ContextHelpWrapperComponent,
EpersonGroupListComponent,