From d6b674345fd39afcffde1fc6b9da0f52c681daf7 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Wed, 19 Mar 2025 13:10:26 +0100 Subject: [PATCH] Implement feedback --- src/app/app.menus.ts | 22 ++++- ...dit-menu-expandable-section.component.html | 2 +- ...dit-menu-expandable-section.component.scss | 1 - .../menu/providers/access-control.menu.ts | 16 +--- .../menu/providers/admin-search.menu.ts | 9 +- src/app/shared/menu/providers/browse.menu.ts | 5 +- .../menu/providers/coar-notify.menu.spec.ts | 83 +++++++++++++++++ .../shared/menu/providers/coar-notify.menu.ts | 77 ++++++++++++++++ .../menu/providers/comcol-subscribe.menu.ts | 2 +- .../menu/providers/community-list.menu.ts | 2 +- .../menu/providers/create-report.menu.spec.ts | 6 +- .../menu/providers/create-report.menu.ts | 2 +- .../shared/menu/providers/curation.menu.ts | 2 +- .../shared/menu/providers/dso-edit.menu.ts | 2 +- .../shared/menu/providers/dso-option.menu.ts | 4 +- src/app/shared/menu/providers/edit.menu.ts | 2 +- src/app/shared/menu/providers/export.menu.ts | 2 +- src/app/shared/menu/providers/health.menu.ts | 2 +- src/app/shared/menu/providers/import.menu.ts | 2 +- .../shared/menu/providers/item-claim.menu.ts | 3 +- .../shared/menu/providers/item-orcid.menu.ts | 2 +- .../menu/providers/item-versioning.menu.ts | 2 +- .../shared/menu/providers/new.menu.spec.ts | 10 +++ src/app/shared/menu/providers/new.menu.ts | 15 +++- .../menu/providers/notifications.menu.spec.ts | 89 +++++++++++++++++++ .../menu/providers/notifications.menu.ts | 79 ++++++++++++++++ .../shared/menu/providers/processes.menu.ts | 2 +- .../shared/menu/providers/registries.menu.ts | 2 +- .../shared/menu/providers/statistics.menu.ts | 4 +- .../menu/providers/system-wide-alert.menu.ts | 2 +- .../shared/menu/providers/workflow.menu.ts | 2 +- 31 files changed, 406 insertions(+), 49 deletions(-) create mode 100644 src/app/shared/menu/providers/coar-notify.menu.spec.ts create mode 100644 src/app/shared/menu/providers/coar-notify.menu.ts create mode 100644 src/app/shared/menu/providers/notifications.menu.spec.ts create mode 100644 src/app/shared/menu/providers/notifications.menu.ts diff --git a/src/app/app.menus.ts b/src/app/app.menus.ts index 46dba503a9..89e872984a 100644 --- a/src/app/app.menus.ts +++ b/src/app/app.menus.ts @@ -11,6 +11,7 @@ import { MenuRoute } from './shared/menu/menu-route.model'; import { AccessControlMenuProvider } from './shared/menu/providers/access-control.menu'; import { AdminSearchMenuProvider } from './shared/menu/providers/admin-search.menu'; import { BrowseMenuProvider } from './shared/menu/providers/browse.menu'; +import { CoarNotifyMenuProvider } from './shared/menu/providers/coar-notify.menu'; import { SubscribeMenuProvider } from './shared/menu/providers/comcol-subscribe.menu'; import { CommunityListMenuProvider } from './shared/menu/providers/community-list.menu'; import { CreateReportMenuProvider } from './shared/menu/providers/create-report.menu'; @@ -25,12 +26,29 @@ import { ClaimMenuProvider } from './shared/menu/providers/item-claim.menu'; import { OrcidMenuProvider } from './shared/menu/providers/item-orcid.menu'; import { VersioningMenuProvider } from './shared/menu/providers/item-versioning.menu'; import { NewMenuProvider } from './shared/menu/providers/new.menu'; +import { NotificationsMenuProvider } from './shared/menu/providers/notifications.menu'; import { ProcessesMenuProvider } from './shared/menu/providers/processes.menu'; import { RegistriesMenuProvider } from './shared/menu/providers/registries.menu'; import { StatisticsMenuProvider } from './shared/menu/providers/statistics.menu'; import { SystemWideAlertMenuProvider } from './shared/menu/providers/system-wide-alert.menu'; import { WorkflowMenuProvider } from './shared/menu/providers/workflow.menu'; +/** + * Represents and builds the menu structure for the three available menus (public navbar, admin sidebar and the dso edit + * menus). + * The structure consists of a list of menu IDs with each of them having a list of providers that will create the + * sections to be part of the menu matching the ID. + * + * The following menu groups are present in this structure: + * - `MenuID.PUBLIC`: Defines menus accessible by the public in the navigation bar. + * - `MenuID.ADMIN`: Defines menus for administrative users in the sidebar. + * - `MenuID.DSO_EDIT`: Defines dynamic menu options for DSpace Objects that will be present on the DSpace Object's page. + * + * To add more menu sections to a menu (public navbar, admin sidebar or the dso edit menus), + * a new provider can be added to the list with the corresponding menu ID. + * + * The configuration supports route-specific menu providers and hierarchically structured menu options. + */ export const MENUS = buildMenuStructure({ [MenuID.PUBLIC]: [ CommunityListMenuProvider, @@ -42,15 +60,17 @@ export const MENUS = buildMenuStructure({ EditMenuProvider, ImportMenuProvider, ExportMenuProvider, + NotificationsMenuProvider, AccessControlMenuProvider, - CreateReportMenuProvider, AdminSearchMenuProvider, + CreateReportMenuProvider, RegistriesMenuProvider, CurationMenuProvider, ProcessesMenuProvider, WorkflowMenuProvider, HealthMenuProvider, SystemWideAlertMenuProvider, + CoarNotifyMenuProvider, ], [MenuID.DSO_EDIT]: [ DsoOptionMenuProvider.withSubs([ diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html index 9de5214087..83dd66a346 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html @@ -2,7 +2,7 @@
-
    diff --git a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss index 0b222da867..2eb5f61227 100644 --- a/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss +++ b/src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss @@ -3,7 +3,6 @@ } .dso-button-menu { - // todo: random thought to make dso page dropdown buttons clear .dropdown-toggle::after { content: ''; width: 0; diff --git a/src/app/shared/menu/providers/access-control.menu.ts b/src/app/shared/menu/providers/access-control.menu.ts index 1fe396e7b9..9b5c289c5d 100644 --- a/src/app/shared/menu/providers/access-control.menu.ts +++ b/src/app/shared/menu/providers/access-control.menu.ts @@ -23,7 +23,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider'; /** - * Menu provider to create Access Control related menu sections + * Menu provider to create the "Access Control" menu (and subsections) in the admin sidebar */ @Injectable() export class AccessControlMenuProvider extends AbstractExpandableMenuProvider { @@ -52,7 +52,7 @@ export class AccessControlMenuProvider extends AbstractExpandableMenuProvider { this.authorizationService.isAuthorized(FeatureID.AdministratorOf), this.authorizationService.isAuthorized(FeatureID.CanManageGroups), ]).pipe( - map(([isSiteAdmin, canManageGroups]) => { + map(([isSiteAdmin, canManageGroups]: [boolean, boolean]) => { return [ { visible: isSiteAdmin, @@ -78,18 +78,6 @@ export class AccessControlMenuProvider extends AbstractExpandableMenuProvider { link: '/access-control/bulk-access', }, }, - // TODO: enable this menu item once the feature has been implemented - // { - // id: 'access_control_authorizations', - // parentID: 'access_control', - // active: false, - // visible: authorized, - // model: { - // type: MenuItemType.LINK, - // text: 'menu.section.access_control_authorizations', - // link: '' - // } as LinkMenuItemModel, - // }, ]; }), ); diff --git a/src/app/shared/menu/providers/admin-search.menu.ts b/src/app/shared/menu/providers/admin-search.menu.ts index 66100997b3..5e90de9db3 100644 --- a/src/app/shared/menu/providers/admin-search.menu.ts +++ b/src/app/shared/menu/providers/admin-search.menu.ts @@ -8,7 +8,6 @@ import { Injectable } from '@angular/core'; import { - combineLatest, map, Observable, } from 'rxjs'; @@ -22,7 +21,7 @@ import { } from '../menu-provider.model'; /** - * Menu provider to create the Admin search menu section + * Menu provider to create the "Admin Search" menu in the admin sidebar */ @Injectable() export class AdminSearchMenuProvider extends AbstractMenuProvider { @@ -33,10 +32,8 @@ export class AdminSearchMenuProvider extends AbstractMenuProvider { } public getSections(): Observable { - return combineLatest([ - this.authorizationService.isAuthorized(FeatureID.AdministratorOf), - ]).pipe( - map(([isSiteAdmin]) => { + return this.authorizationService.isAuthorized(FeatureID.AdministratorOf).pipe( + map((isSiteAdmin) => { return [ { visible: isSiteAdmin, diff --git a/src/app/shared/menu/providers/browse.menu.ts b/src/app/shared/menu/providers/browse.menu.ts index 6ec004c1e2..378b9481f0 100644 --- a/src/app/shared/menu/providers/browse.menu.ts +++ b/src/app/shared/menu/providers/browse.menu.ts @@ -24,7 +24,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider'; /** - * Menu provider to create the browse menu sections + * Menu provider to create the "All of DSpace" browse menu sections in the public navbar */ @Injectable() export class BrowseMenuProvider extends AbstractExpandableMenuProvider { @@ -47,6 +47,9 @@ export class BrowseMenuProvider extends AbstractExpandableMenuProvider { ); } + /** + * Retrieves subsections by fetching the browse definitions from the backend and mapping them to partial menu sections. + */ getSubSections(): Observable { return this.browseService.getBrowseDefinitions().pipe( getFirstSucceededRemoteData(), diff --git a/src/app/shared/menu/providers/coar-notify.menu.spec.ts b/src/app/shared/menu/providers/coar-notify.menu.spec.ts new file mode 100644 index 0000000000..e65b6a433f --- /dev/null +++ b/src/app/shared/menu/providers/coar-notify.menu.spec.ts @@ -0,0 +1,83 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ + +import { TestBed } from '@angular/core/testing'; +import { of as observableOf } from 'rxjs'; + +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { AuthorizationDataServiceStub } from '../../testing/authorization-service.stub'; +import { LinkMenuItemModel } from '../menu-item/models/link.model'; +import { TextMenuItemModel } from '../menu-item/models/text.model'; +import { MenuItemType } from '../menu-item-type.model'; +import { PartialMenuSection } from '../menu-provider.model'; +import { CoarNotifyMenuProvider } from './coar-notify.menu'; + +describe('CoarNotifyMenuProvider', () => { + const expectedTopSection: PartialMenuSection = { + visible: true, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.coar_notify', + } as TextMenuItemModel, + icon: 'inbox', + }; + + const expectedSubSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.notify_dashboard', + link: '/admin/notify-dashboard', + } as LinkMenuItemModel, + }, + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.services', + link: '/admin/ldn/services', + } as LinkMenuItemModel, + }, + ]; + + let provider: CoarNotifyMenuProvider; + let authorizationServiceStub = new AuthorizationDataServiceStub(); + + beforeEach(() => { + + spyOn(authorizationServiceStub, 'isAuthorized').and.returnValue( + observableOf(true), + ); + TestBed.configureTestingModule({ + providers: [ + CoarNotifyMenuProvider, + { provide: AuthorizationDataService, useValue: authorizationServiceStub }, + ], + }); + provider = TestBed.inject(CoarNotifyMenuProvider); + }); + + it('should be created', () => { + expect(provider).toBeTruthy(); + }); + + it('getTopSection should return expected menu section', (done) => { + provider.getTopSection().subscribe((section) => { + expect(section).toEqual(expectedTopSection); + done(); + }); + }); + + it('getSubSections should return expected menu sections', (done) => { + provider.getSubSections().subscribe((sections) => { + expect(sections).toEqual(expectedSubSections); + done(); + }); + }); +}); diff --git a/src/app/shared/menu/providers/coar-notify.menu.ts b/src/app/shared/menu/providers/coar-notify.menu.ts new file mode 100644 index 0000000000..197ca4c4ee --- /dev/null +++ b/src/app/shared/menu/providers/coar-notify.menu.ts @@ -0,0 +1,77 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ + +import { Injectable } from '@angular/core'; +import { + combineLatest as observableCombineLatest, + Observable, +} from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; +import { LinkMenuItemModel } from '../menu-item/models/link.model'; +import { TextMenuItemModel } from '../menu-item/models/text.model'; +import { MenuItemType } from '../menu-item-type.model'; +import { PartialMenuSection } from '../menu-provider.model'; +import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider'; + +/** + * Menu provider to create the "COAR Notify" menu (and subsections) in the admin sidebar + */ +@Injectable() +export class CoarNotifyMenuProvider extends AbstractExpandableMenuProvider { + constructor( + protected authorizationService: AuthorizationDataService, + ) { + super(); + } + + getSubSections(): Observable { + return observableCombineLatest([ + this.authorizationService.isAuthorized(FeatureID.CoarNotifyEnabled), + this.authorizationService.isAuthorized(FeatureID.AdministratorOf), + ]).pipe( + map(([isCoarNotifyEnabled, isSiteAdmin]: [boolean, boolean]) => { + return [{ + visible: isSiteAdmin && isCoarNotifyEnabled, + model: { + type: MenuItemType.LINK, + text: 'menu.section.notify_dashboard', + link: '/admin/notify-dashboard', + } as LinkMenuItemModel, + }, + /* LDN Services */ + { + visible: isSiteAdmin && isCoarNotifyEnabled, + model: { + type: MenuItemType.LINK, + text: 'menu.section.services', + link: '/admin/ldn/services', + } as LinkMenuItemModel, + }]; + })); + } + + getTopSection(): Observable { + return observableCombineLatest([ + this.authorizationService.isAuthorized(FeatureID.CoarNotifyEnabled), + this.authorizationService.isAuthorized(FeatureID.AdministratorOf), + ]).pipe( + map(([isCoarNotifyEnabled, isSiteAdmin]: [boolean, boolean]) => { + return { + visible: isSiteAdmin && isCoarNotifyEnabled, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.coar_notify', + } as TextMenuItemModel, + icon: 'inbox', + }; + })); + } +} diff --git a/src/app/shared/menu/providers/comcol-subscribe.menu.ts b/src/app/shared/menu/providers/comcol-subscribe.menu.ts index 90a8a9893b..00c2b34694 100644 --- a/src/app/shared/menu/providers/comcol-subscribe.menu.ts +++ b/src/app/shared/menu/providers/comcol-subscribe.menu.ts @@ -23,7 +23,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { DSpaceObjectPageMenuProvider } from './helper-providers/dso.menu'; /** - * Menu provider to create the subscribe menu section + * Menu provider to create the "Subscribe" option in the DSO edit menu */ @Injectable() export class SubscribeMenuProvider extends DSpaceObjectPageMenuProvider { diff --git a/src/app/shared/menu/providers/community-list.menu.ts b/src/app/shared/menu/providers/community-list.menu.ts index 81c2f2af0c..79e893c974 100644 --- a/src/app/shared/menu/providers/community-list.menu.ts +++ b/src/app/shared/menu/providers/community-list.menu.ts @@ -19,7 +19,7 @@ import { } from '../menu-provider.model'; /** - * Menu provider to create the community list menu section + * Menu provider to create the "Communities & Collections" menu section in the public navbar */ @Injectable() export class CommunityListMenuProvider extends AbstractMenuProvider { diff --git a/src/app/shared/menu/providers/create-report.menu.spec.ts b/src/app/shared/menu/providers/create-report.menu.spec.ts index 0e2a8841d9..1f1c09f594 100644 --- a/src/app/shared/menu/providers/create-report.menu.spec.ts +++ b/src/app/shared/menu/providers/create-report.menu.spec.ts @@ -59,10 +59,10 @@ describe('CreateReportMenuProvider', () => { beforeEach(() => { spyOn(authorizationServiceStub, 'isAuthorized').and.callFake((id: FeatureID) => { - if (id === FeatureID.CanManageGroups) { - return observableOf(false); - } else { + if (id === FeatureID.AdministratorOf) { return observableOf(true); + } else { + return observableOf(false); } }); diff --git a/src/app/shared/menu/providers/create-report.menu.ts b/src/app/shared/menu/providers/create-report.menu.ts index 0b326d9355..1d6ff3f4f8 100644 --- a/src/app/shared/menu/providers/create-report.menu.ts +++ b/src/app/shared/menu/providers/create-report.menu.ts @@ -26,7 +26,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider'; /** - * Menu provider to create the report menu sections + * Menu provider to create the "Reports" menu (and subsections) in the admin sidebar */ @Injectable() export class CreateReportMenuProvider extends AbstractExpandableMenuProvider { diff --git a/src/app/shared/menu/providers/curation.menu.ts b/src/app/shared/menu/providers/curation.menu.ts index 16441fae59..e7d09fb182 100644 --- a/src/app/shared/menu/providers/curation.menu.ts +++ b/src/app/shared/menu/providers/curation.menu.ts @@ -23,7 +23,7 @@ import { } from '../menu-provider.model'; /** - * Menu provider to create the curation menu section + * Menu provider to create the "Curation Task" menu in the admin sidebar */ @Injectable() export class CurationMenuProvider extends AbstractMenuProvider { diff --git a/src/app/shared/menu/providers/dso-edit.menu.ts b/src/app/shared/menu/providers/dso-edit.menu.ts index 7ce329152d..400a65f54e 100644 --- a/src/app/shared/menu/providers/dso-edit.menu.ts +++ b/src/app/shared/menu/providers/dso-edit.menu.ts @@ -23,7 +23,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { DSpaceObjectPageMenuProvider } from './helper-providers/dso.menu'; /** - * Menu provider to create the DSO edit menu section + * Menu provider to create the "Edit" option in the DSO edit menu */ @Injectable() export class DSpaceObjectEditMenuProvider extends DSpaceObjectPageMenuProvider { diff --git a/src/app/shared/menu/providers/dso-option.menu.ts b/src/app/shared/menu/providers/dso-option.menu.ts index 2417bce3f0..255480eba3 100644 --- a/src/app/shared/menu/providers/dso-option.menu.ts +++ b/src/app/shared/menu/providers/dso-option.menu.ts @@ -18,8 +18,8 @@ import { PartialMenuSection } from '../menu-provider.model'; import { DSpaceObjectPageMenuProvider } from './helper-providers/dso.menu'; /** - * Menu provider to create the parent wrapper menu of the various DSO page menu sections - * This section will be rendered as a button on the DSO pages if sub providers have been added + * Menu provider to create the "Options" menu wrapper on the DSO pages. + * This section will be rendered as a button on the DSO pages if sub providers have been added. */ @Injectable() export class DsoOptionMenuProvider extends DSpaceObjectPageMenuProvider { diff --git a/src/app/shared/menu/providers/edit.menu.ts b/src/app/shared/menu/providers/edit.menu.ts index 5aee52f027..38346729d4 100644 --- a/src/app/shared/menu/providers/edit.menu.ts +++ b/src/app/shared/menu/providers/edit.menu.ts @@ -25,7 +25,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider'; /** - * Menu provider to create the admin sidebar edit menu sections + * Menu provider to create the "Edit" menu (and subsections) in the admin sidebar */ @Injectable() export class EditMenuProvider extends AbstractExpandableMenuProvider { diff --git a/src/app/shared/menu/providers/export.menu.ts b/src/app/shared/menu/providers/export.menu.ts index e6f47c5f5c..aae7e39d1f 100644 --- a/src/app/shared/menu/providers/export.menu.ts +++ b/src/app/shared/menu/providers/export.menu.ts @@ -28,7 +28,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider'; /** - * Menu provider to create the export menu sections + * Menu provider to create the "Export" menu (and subsections) in the admin sidebar */ @Injectable() export class ExportMenuProvider extends AbstractExpandableMenuProvider { diff --git a/src/app/shared/menu/providers/health.menu.ts b/src/app/shared/menu/providers/health.menu.ts index bd6702acd5..05f2037339 100644 --- a/src/app/shared/menu/providers/health.menu.ts +++ b/src/app/shared/menu/providers/health.menu.ts @@ -22,7 +22,7 @@ import { } from '../menu-provider.model'; /** - * Menu provider to create the health menu section + * Menu provider to create the "Health" menu in the admin sidebar */ @Injectable() export class HealthMenuProvider extends AbstractMenuProvider { diff --git a/src/app/shared/menu/providers/import.menu.ts b/src/app/shared/menu/providers/import.menu.ts index c97020dcea..09d459d2c9 100644 --- a/src/app/shared/menu/providers/import.menu.ts +++ b/src/app/shared/menu/providers/import.menu.ts @@ -26,7 +26,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider'; /** - * Menu provider to create the import menu sections + * Menu provider to create the "Import" menu (and subsections) in the admin sidebar */ @Injectable() export class ImportMenuProvider extends AbstractExpandableMenuProvider { diff --git a/src/app/shared/menu/providers/item-claim.menu.ts b/src/app/shared/menu/providers/item-claim.menu.ts index 5bb5c94db3..2669db8c36 100644 --- a/src/app/shared/menu/providers/item-claim.menu.ts +++ b/src/app/shared/menu/providers/item-claim.menu.ts @@ -29,7 +29,8 @@ import { PartialMenuSection } from '../menu-provider.model'; import { DSpaceObjectPageMenuProvider } from './helper-providers/dso.menu'; /** - * Menu provider to create the menu section on person entity pages to claim a researcher by creating a profile + * Menu provider to create the "Claim" option in the DSO edit menu on person entity pages. + * This option allows to claim a researcher by creating a profile. */ @Injectable() export class ClaimMenuProvider extends DSpaceObjectPageMenuProvider { diff --git a/src/app/shared/menu/providers/item-orcid.menu.ts b/src/app/shared/menu/providers/item-orcid.menu.ts index e9fa4c7beb..75516a9d6e 100644 --- a/src/app/shared/menu/providers/item-orcid.menu.ts +++ b/src/app/shared/menu/providers/item-orcid.menu.ts @@ -23,7 +23,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { DSpaceObjectPageMenuProvider } from './helper-providers/dso.menu'; /** - * Menu provider to create the Orcid synchronisation menu section on person entity pages + * Menu provider to create the Orcid settings related option in the DSO edit menu on person entity pages */ @Injectable() export class OrcidMenuProvider extends DSpaceObjectPageMenuProvider { diff --git a/src/app/shared/menu/providers/item-versioning.menu.ts b/src/app/shared/menu/providers/item-versioning.menu.ts index 4533a71424..6bc04bd704 100644 --- a/src/app/shared/menu/providers/item-versioning.menu.ts +++ b/src/app/shared/menu/providers/item-versioning.menu.ts @@ -22,7 +22,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { DSpaceObjectPageMenuProvider } from './helper-providers/dso.menu'; /** - * Menu provider to create the versioning menu section on item pages + * Menu provider to create the version related options in the DSO edit menu */ @Injectable() export class VersioningMenuProvider extends DSpaceObjectPageMenuProvider { diff --git a/src/app/shared/menu/providers/new.menu.spec.ts b/src/app/shared/menu/providers/new.menu.spec.ts index ecca5594b2..377e7c5196 100644 --- a/src/app/shared/menu/providers/new.menu.spec.ts +++ b/src/app/shared/menu/providers/new.menu.spec.ts @@ -12,6 +12,7 @@ import { of as observableOf } from 'rxjs'; import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; import { AuthorizationDataServiceStub } from '../../testing/authorization-service.stub'; +import { LinkMenuItemModel } from '../menu-item/models/link.model'; import { MenuItemType } from '../menu-item-type.model'; import { PartialMenuSection } from '../menu-provider.model'; import { NewMenuProvider } from './new.menu'; @@ -60,6 +61,15 @@ describe('NewMenuProvider', () => { link: '/processes/new', }, }, + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.services_new', + link: '/admin/ldn/services/new', + } as LinkMenuItemModel, + icon: '', + }, ]; let provider: NewMenuProvider; diff --git a/src/app/shared/menu/providers/new.menu.ts b/src/app/shared/menu/providers/new.menu.ts index 1db687951f..431622a769 100644 --- a/src/app/shared/menu/providers/new.menu.ts +++ b/src/app/shared/menu/providers/new.menu.ts @@ -20,13 +20,14 @@ import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; import { ThemedCreateCollectionParentSelectorComponent } from '../../dso-selector/modal-wrappers/create-collection-parent-selector/themed-create-collection-parent-selector.component'; import { ThemedCreateCommunityParentSelectorComponent } from '../../dso-selector/modal-wrappers/create-community-parent-selector/themed-create-community-parent-selector.component'; import { ThemedCreateItemParentSelectorComponent } from '../../dso-selector/modal-wrappers/create-item-parent-selector/themed-create-item-parent-selector.component'; +import { LinkMenuItemModel } from '../menu-item/models/link.model'; import { TextMenuItemModel } from '../menu-item/models/text.model'; import { MenuItemType } from '../menu-item-type.model'; import { PartialMenuSection } from '../menu-provider.model'; import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider'; /** - * Menu provider to create the admin sidebar new menu sections + * Menu provider to create the "New" menu (and subsections) in the admin sidebar */ @Injectable() export class NewMenuProvider extends AbstractExpandableMenuProvider { @@ -57,7 +58,8 @@ export class NewMenuProvider extends AbstractExpandableMenuProvider { this.authorizationService.isAuthorized(FeatureID.IsCommunityAdmin), this.authorizationService.isAuthorized(FeatureID.AdministratorOf), this.authorizationService.isAuthorized(FeatureID.CanSubmit), - ]).pipe(map(([isCollectionAdmin, isCommunityAdmin, isSiteAdmin, canSubmit]: [boolean, boolean, boolean, boolean]) => { + this.authorizationService.isAuthorized(FeatureID.CoarNotifyEnabled), + ]).pipe(map(([isCollectionAdmin, isCommunityAdmin, isSiteAdmin, canSubmit, isCoarNotifyEnabled]: [boolean, boolean, boolean, boolean, boolean]) => { return [ { @@ -98,6 +100,15 @@ export class NewMenuProvider extends AbstractExpandableMenuProvider { link: '/processes/new', }, }, + { + visible: isSiteAdmin && isCoarNotifyEnabled, + model: { + type: MenuItemType.LINK, + text: 'menu.section.services_new', + link: '/admin/ldn/services/new', + } as LinkMenuItemModel, + icon: '', + }, ]; })); } diff --git a/src/app/shared/menu/providers/notifications.menu.spec.ts b/src/app/shared/menu/providers/notifications.menu.spec.ts new file mode 100644 index 0000000000..3c04dce78f --- /dev/null +++ b/src/app/shared/menu/providers/notifications.menu.spec.ts @@ -0,0 +1,89 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ + +import { TestBed } from '@angular/core/testing'; +import { of as observableOf } from 'rxjs'; + +import { PUBLICATION_CLAIMS_PATH } from '../../../admin/admin-notifications/admin-notifications-routing-paths'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; +import { AuthorizationDataServiceStub } from '../../testing/authorization-service.stub'; +import { LinkMenuItemModel } from '../menu-item/models/link.model'; +import { TextMenuItemModel } from '../menu-item/models/text.model'; +import { MenuItemType } from '../menu-item-type.model'; +import { PartialMenuSection } from '../menu-provider.model'; +import { NotificationsMenuProvider } from './notifications.menu'; + +describe('NotificationsMenuProvider', () => { + const expectedTopSection: PartialMenuSection = { + visible: true, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.notifications', + } as TextMenuItemModel, + icon: 'bell', + }; + + const expectedSubSections: PartialMenuSection[] = [ + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.quality-assurance', + link: '/notifications/quality-assurance', + } as LinkMenuItemModel, + }, + { + visible: true, + model: { + type: MenuItemType.LINK, + text: 'menu.section.notifications_publication-claim', + link: '/admin/notifications/' + PUBLICATION_CLAIMS_PATH, + } as LinkMenuItemModel, + }, + ]; + + let provider: NotificationsMenuProvider; + let authorizationServiceStub = new AuthorizationDataServiceStub(); + + beforeEach(() => { + spyOn(authorizationServiceStub, 'isAuthorized').and.callFake((id: FeatureID) => { + if (id === FeatureID.CanSeeQA || id === FeatureID.AdministratorOf) { + return observableOf(true); + } else { + return observableOf(false); + } + }); + + TestBed.configureTestingModule({ + providers: [ + NotificationsMenuProvider, + { provide: AuthorizationDataService, useValue: authorizationServiceStub }, + ], + }); + provider = TestBed.inject(NotificationsMenuProvider); + }); + + it('should be created', () => { + expect(provider).toBeTruthy(); + }); + + it('getTopSection should return expected menu section', (done) => { + provider.getTopSection().subscribe((section) => { + expect(section).toEqual(expectedTopSection); + done(); + }); + }); + + it('getSubSections should return expected menu sections', (done) => { + provider.getSubSections().subscribe((sections) => { + expect(sections).toEqual(expectedSubSections); + done(); + }); + }); +}); diff --git a/src/app/shared/menu/providers/notifications.menu.ts b/src/app/shared/menu/providers/notifications.menu.ts new file mode 100644 index 0000000000..254cffc299 --- /dev/null +++ b/src/app/shared/menu/providers/notifications.menu.ts @@ -0,0 +1,79 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ + +import { Injectable } from '@angular/core'; +import { + combineLatest as observableCombineLatest, + Observable, +} from 'rxjs'; +import { map } from 'rxjs/operators'; + +import { PUBLICATION_CLAIMS_PATH } from '../../../admin/admin-notifications/admin-notifications-routing-paths'; +import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service'; +import { FeatureID } from '../../../core/data/feature-authorization/feature-id'; +import { LinkMenuItemModel } from '../menu-item/models/link.model'; +import { TextMenuItemModel } from '../menu-item/models/text.model'; +import { MenuItemType } from '../menu-item-type.model'; +import { PartialMenuSection } from '../menu-provider.model'; +import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider'; + +/** + * Menu provider to create the "Notifications" menu (and subsections) in the admin sidebar + */ +@Injectable() +export class NotificationsMenuProvider extends AbstractExpandableMenuProvider { + constructor( + protected authorizationService: AuthorizationDataService, + ) { + super(); + } + + getSubSections(): Observable { + return observableCombineLatest([ + this.authorizationService.isAuthorized(FeatureID.CanSeeQA), + this.authorizationService.isAuthorized(FeatureID.AdministratorOf), + ]).pipe( + map(([canSeeQa, isSiteAdmin]: [boolean, boolean]) => { + return [ + { + visible: canSeeQa, + model: { + type: MenuItemType.LINK, + text: 'menu.section.quality-assurance', + link: '/notifications/quality-assurance', + } as LinkMenuItemModel, + }, + { + visible: isSiteAdmin, + model: { + type: MenuItemType.LINK, + text: 'menu.section.notifications_publication-claim', + link: '/admin/notifications/' + PUBLICATION_CLAIMS_PATH, + } as LinkMenuItemModel, + }, + ]; + })); + } + + getTopSection(): Observable { + return observableCombineLatest([ + this.authorizationService.isAuthorized(FeatureID.CanSeeQA), + this.authorizationService.isAuthorized(FeatureID.AdministratorOf), + ]).pipe( + map(([canSeeQa, isSiteAdmin]: [boolean, boolean]) => { + return { + visible: canSeeQa || isSiteAdmin, + model: { + type: MenuItemType.TEXT, + text: 'menu.section.notifications', + } as TextMenuItemModel, + icon: 'bell', + }; + })); + } +} diff --git a/src/app/shared/menu/providers/processes.menu.ts b/src/app/shared/menu/providers/processes.menu.ts index 9aa57f2b83..540e0a89ce 100644 --- a/src/app/shared/menu/providers/processes.menu.ts +++ b/src/app/shared/menu/providers/processes.menu.ts @@ -22,7 +22,7 @@ import { } from '../menu-provider.model'; /** - * Menu provider to create the scripts and processes menu section + * Menu provider to create the "Processes" menu in the admin sidebar */ @Injectable() export class ProcessesMenuProvider extends AbstractMenuProvider { diff --git a/src/app/shared/menu/providers/registries.menu.ts b/src/app/shared/menu/providers/registries.menu.ts index 5309ddd3ec..9ab7d65d7e 100644 --- a/src/app/shared/menu/providers/registries.menu.ts +++ b/src/app/shared/menu/providers/registries.menu.ts @@ -23,7 +23,7 @@ import { PartialMenuSection } from '../menu-provider.model'; import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider'; /** - * Menu provider to create the registries menu sections + * Menu provider to create the "Registries" menu (and subsections) in the admin sidebar */ @Injectable() export class RegistriesMenuProvider extends AbstractExpandableMenuProvider { diff --git a/src/app/shared/menu/providers/statistics.menu.ts b/src/app/shared/menu/providers/statistics.menu.ts index b7bbd96e29..e318892150 100644 --- a/src/app/shared/menu/providers/statistics.menu.ts +++ b/src/app/shared/menu/providers/statistics.menu.ts @@ -23,9 +23,9 @@ import { PartialMenuSection } from '../menu-provider.model'; import { DSpaceObjectPageMenuProvider } from './helper-providers/dso.menu'; /** - * Menu provider to create the statistics menu section depending on the page it is on + * Menu provider to create the "Statistics" menu section in the public navbar. The menu depends on the page it is on. * When the user is on a DSO page or a derivative, this menu section will contain a link to the statistics of that DSO - * In all other cases the menu section will contain a link to the repository wide statistics + * In all other cases the menu section will contain a link to the repository wide statistics page. */ @Injectable() export class StatisticsMenuProvider extends DSpaceObjectPageMenuProvider { diff --git a/src/app/shared/menu/providers/system-wide-alert.menu.ts b/src/app/shared/menu/providers/system-wide-alert.menu.ts index 27808a5ae2..8614775eb2 100644 --- a/src/app/shared/menu/providers/system-wide-alert.menu.ts +++ b/src/app/shared/menu/providers/system-wide-alert.menu.ts @@ -22,7 +22,7 @@ import { } from '../menu-provider.model'; /** - * Menu provider to create the system wide alert menu section + * Menu provider to create the "System-wide Alert" menu in the admin sidebar */ @Injectable() export class SystemWideAlertMenuProvider extends AbstractMenuProvider { diff --git a/src/app/shared/menu/providers/workflow.menu.ts b/src/app/shared/menu/providers/workflow.menu.ts index c5c1a89da4..1a629f26f3 100644 --- a/src/app/shared/menu/providers/workflow.menu.ts +++ b/src/app/shared/menu/providers/workflow.menu.ts @@ -22,7 +22,7 @@ import { } from '../menu-provider.model'; /** - * Menu provider to create the workflow admin menu section + * Menu provider to create the "Administer Workflow" menu in the admin sidebar */ @Injectable() export class WorkflowMenuProvider extends AbstractMenuProvider {