Skip to content

Commit d6b6743

Browse files
committed
Implement feedback
1 parent b009e0b commit d6b6743

31 files changed

Lines changed: 406 additions & 49 deletions

src/app/app.menus.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { MenuRoute } from './shared/menu/menu-route.model';
1111
import { AccessControlMenuProvider } from './shared/menu/providers/access-control.menu';
1212
import { AdminSearchMenuProvider } from './shared/menu/providers/admin-search.menu';
1313
import { BrowseMenuProvider } from './shared/menu/providers/browse.menu';
14+
import { CoarNotifyMenuProvider } from './shared/menu/providers/coar-notify.menu';
1415
import { SubscribeMenuProvider } from './shared/menu/providers/comcol-subscribe.menu';
1516
import { CommunityListMenuProvider } from './shared/menu/providers/community-list.menu';
1617
import { CreateReportMenuProvider } from './shared/menu/providers/create-report.menu';
@@ -25,12 +26,29 @@ import { ClaimMenuProvider } from './shared/menu/providers/item-claim.menu';
2526
import { OrcidMenuProvider } from './shared/menu/providers/item-orcid.menu';
2627
import { VersioningMenuProvider } from './shared/menu/providers/item-versioning.menu';
2728
import { NewMenuProvider } from './shared/menu/providers/new.menu';
29+
import { NotificationsMenuProvider } from './shared/menu/providers/notifications.menu';
2830
import { ProcessesMenuProvider } from './shared/menu/providers/processes.menu';
2931
import { RegistriesMenuProvider } from './shared/menu/providers/registries.menu';
3032
import { StatisticsMenuProvider } from './shared/menu/providers/statistics.menu';
3133
import { SystemWideAlertMenuProvider } from './shared/menu/providers/system-wide-alert.menu';
3234
import { WorkflowMenuProvider } from './shared/menu/providers/workflow.menu';
3335

36+
/**
37+
* Represents and builds the menu structure for the three available menus (public navbar, admin sidebar and the dso edit
38+
* menus).
39+
* The structure consists of a list of menu IDs with each of them having a list of providers that will create the
40+
* sections to be part of the menu matching the ID.
41+
*
42+
* The following menu groups are present in this structure:
43+
* - `MenuID.PUBLIC`: Defines menus accessible by the public in the navigation bar.
44+
* - `MenuID.ADMIN`: Defines menus for administrative users in the sidebar.
45+
* - `MenuID.DSO_EDIT`: Defines dynamic menu options for DSpace Objects that will be present on the DSpace Object's page.
46+
*
47+
* To add more menu sections to a menu (public navbar, admin sidebar or the dso edit menus),
48+
* a new provider can be added to the list with the corresponding menu ID.
49+
*
50+
* The configuration supports route-specific menu providers and hierarchically structured menu options.
51+
*/
3452
export const MENUS = buildMenuStructure({
3553
[MenuID.PUBLIC]: [
3654
CommunityListMenuProvider,
@@ -42,15 +60,17 @@ export const MENUS = buildMenuStructure({
4260
EditMenuProvider,
4361
ImportMenuProvider,
4462
ExportMenuProvider,
63+
NotificationsMenuProvider,
4564
AccessControlMenuProvider,
46-
CreateReportMenuProvider,
4765
AdminSearchMenuProvider,
66+
CreateReportMenuProvider,
4867
RegistriesMenuProvider,
4968
CurationMenuProvider,
5069
ProcessesMenuProvider,
5170
WorkflowMenuProvider,
5271
HealthMenuProvider,
5372
SystemWideAlertMenuProvider,
73+
CoarNotifyMenuProvider,
5474
],
5575
[MenuID.DSO_EDIT]: [
5676
DsoOptionMenuProvider.withSubs([

src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<div class="dso-button-menu mb-1" ngbDropdown container="body" placement="bottom-right">
33
<div class="d-flex flex-row flex-nowrap"
44
[ngbTooltip]="itemModel.text | translate" container="body">
5-
<button [attr.aria-label]="itemModel.text | translate" [title]="itemModel.text | translate" class="btn btn-dark btn-sm" ngbDropdownToggle [dsBtnDisabled]="section.model?.disabled">
5+
<button [attr.aria-label]="itemModel.text | translate" [title]="itemModel.text | translate" class="btn btn-dark btn-sm" ngbDropdownToggle [dsBtnDisabled]="section.model?.disabled" role="menuitem">
66
<i class="fas fa-{{section.icon}} fa-fw"></i>
77
</button>
88
<ul ngbDropdownMenu class="dso-edit-menu-dropdown p-1">

src/app/shared/dso-page/dso-edit-menu/dso-edit-expandable-menu-section/dso-edit-menu-expandable-section.component.scss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
}
44

55
.dso-button-menu {
6-
// todo: random thought to make dso page dropdown buttons clear
76
.dropdown-toggle::after {
87
content: '';
98
width: 0;

src/app/shared/menu/providers/access-control.menu.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { PartialMenuSection } from '../menu-provider.model';
2323
import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider';
2424

2525
/**
26-
* Menu provider to create Access Control related menu sections
26+
* Menu provider to create the "Access Control" menu (and subsections) in the admin sidebar
2727
*/
2828
@Injectable()
2929
export class AccessControlMenuProvider extends AbstractExpandableMenuProvider {
@@ -52,7 +52,7 @@ export class AccessControlMenuProvider extends AbstractExpandableMenuProvider {
5252
this.authorizationService.isAuthorized(FeatureID.AdministratorOf),
5353
this.authorizationService.isAuthorized(FeatureID.CanManageGroups),
5454
]).pipe(
55-
map(([isSiteAdmin, canManageGroups]) => {
55+
map(([isSiteAdmin, canManageGroups]: [boolean, boolean]) => {
5656
return [
5757
{
5858
visible: isSiteAdmin,
@@ -78,18 +78,6 @@ export class AccessControlMenuProvider extends AbstractExpandableMenuProvider {
7878
link: '/access-control/bulk-access',
7979
},
8080
},
81-
// TODO: enable this menu item once the feature has been implemented
82-
// {
83-
// id: 'access_control_authorizations',
84-
// parentID: 'access_control',
85-
// active: false,
86-
// visible: authorized,
87-
// model: {
88-
// type: MenuItemType.LINK,
89-
// text: 'menu.section.access_control_authorizations',
90-
// link: ''
91-
// } as LinkMenuItemModel,
92-
// },
9381
];
9482
}),
9583
);

src/app/shared/menu/providers/admin-search.menu.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import { Injectable } from '@angular/core';
1010
import {
11-
combineLatest,
1211
map,
1312
Observable,
1413
} from 'rxjs';
@@ -22,7 +21,7 @@ import {
2221
} from '../menu-provider.model';
2322

2423
/**
25-
* Menu provider to create the Admin search menu section
24+
* Menu provider to create the "Admin Search" menu in the admin sidebar
2625
*/
2726
@Injectable()
2827
export class AdminSearchMenuProvider extends AbstractMenuProvider {
@@ -33,10 +32,8 @@ export class AdminSearchMenuProvider extends AbstractMenuProvider {
3332
}
3433

3534
public getSections(): Observable<PartialMenuSection[]> {
36-
return combineLatest([
37-
this.authorizationService.isAuthorized(FeatureID.AdministratorOf),
38-
]).pipe(
39-
map(([isSiteAdmin]) => {
35+
return this.authorizationService.isAuthorized(FeatureID.AdministratorOf).pipe(
36+
map((isSiteAdmin) => {
4037
return [
4138
{
4239
visible: isSiteAdmin,

src/app/shared/menu/providers/browse.menu.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { PartialMenuSection } from '../menu-provider.model';
2424
import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider';
2525

2626
/**
27-
* Menu provider to create the browse menu sections
27+
* Menu provider to create the "All of DSpace" browse menu sections in the public navbar
2828
*/
2929
@Injectable()
3030
export class BrowseMenuProvider extends AbstractExpandableMenuProvider {
@@ -47,6 +47,9 @@ export class BrowseMenuProvider extends AbstractExpandableMenuProvider {
4747
);
4848
}
4949

50+
/**
51+
* Retrieves subsections by fetching the browse definitions from the backend and mapping them to partial menu sections.
52+
*/
5053
getSubSections(): Observable<PartialMenuSection[]> {
5154
return this.browseService.getBrowseDefinitions().pipe(
5255
getFirstSucceededRemoteData(),
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* The contents of this file are subject to the license and copyright
3+
* detailed in the LICENSE and NOTICE files at the root of the source
4+
* tree and available online at
5+
*
6+
* http://www.dspace.org/license/
7+
*/
8+
9+
import { TestBed } from '@angular/core/testing';
10+
import { of as observableOf } from 'rxjs';
11+
12+
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
13+
import { AuthorizationDataServiceStub } from '../../testing/authorization-service.stub';
14+
import { LinkMenuItemModel } from '../menu-item/models/link.model';
15+
import { TextMenuItemModel } from '../menu-item/models/text.model';
16+
import { MenuItemType } from '../menu-item-type.model';
17+
import { PartialMenuSection } from '../menu-provider.model';
18+
import { CoarNotifyMenuProvider } from './coar-notify.menu';
19+
20+
describe('CoarNotifyMenuProvider', () => {
21+
const expectedTopSection: PartialMenuSection = {
22+
visible: true,
23+
model: {
24+
type: MenuItemType.TEXT,
25+
text: 'menu.section.coar_notify',
26+
} as TextMenuItemModel,
27+
icon: 'inbox',
28+
};
29+
30+
const expectedSubSections: PartialMenuSection[] = [
31+
{
32+
visible: true,
33+
model: {
34+
type: MenuItemType.LINK,
35+
text: 'menu.section.notify_dashboard',
36+
link: '/admin/notify-dashboard',
37+
} as LinkMenuItemModel,
38+
},
39+
{
40+
visible: true,
41+
model: {
42+
type: MenuItemType.LINK,
43+
text: 'menu.section.services',
44+
link: '/admin/ldn/services',
45+
} as LinkMenuItemModel,
46+
},
47+
];
48+
49+
let provider: CoarNotifyMenuProvider;
50+
let authorizationServiceStub = new AuthorizationDataServiceStub();
51+
52+
beforeEach(() => {
53+
54+
spyOn(authorizationServiceStub, 'isAuthorized').and.returnValue(
55+
observableOf(true),
56+
);
57+
TestBed.configureTestingModule({
58+
providers: [
59+
CoarNotifyMenuProvider,
60+
{ provide: AuthorizationDataService, useValue: authorizationServiceStub },
61+
],
62+
});
63+
provider = TestBed.inject(CoarNotifyMenuProvider);
64+
});
65+
66+
it('should be created', () => {
67+
expect(provider).toBeTruthy();
68+
});
69+
70+
it('getTopSection should return expected menu section', (done) => {
71+
provider.getTopSection().subscribe((section) => {
72+
expect(section).toEqual(expectedTopSection);
73+
done();
74+
});
75+
});
76+
77+
it('getSubSections should return expected menu sections', (done) => {
78+
provider.getSubSections().subscribe((sections) => {
79+
expect(sections).toEqual(expectedSubSections);
80+
done();
81+
});
82+
});
83+
});
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* The contents of this file are subject to the license and copyright
3+
* detailed in the LICENSE and NOTICE files at the root of the source
4+
* tree and available online at
5+
*
6+
* http://www.dspace.org/license/
7+
*/
8+
9+
import { Injectable } from '@angular/core';
10+
import {
11+
combineLatest as observableCombineLatest,
12+
Observable,
13+
} from 'rxjs';
14+
import { map } from 'rxjs/operators';
15+
16+
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
17+
import { FeatureID } from '../../../core/data/feature-authorization/feature-id';
18+
import { LinkMenuItemModel } from '../menu-item/models/link.model';
19+
import { TextMenuItemModel } from '../menu-item/models/text.model';
20+
import { MenuItemType } from '../menu-item-type.model';
21+
import { PartialMenuSection } from '../menu-provider.model';
22+
import { AbstractExpandableMenuProvider } from './helper-providers/expandable-menu-provider';
23+
24+
/**
25+
* Menu provider to create the "COAR Notify" menu (and subsections) in the admin sidebar
26+
*/
27+
@Injectable()
28+
export class CoarNotifyMenuProvider extends AbstractExpandableMenuProvider {
29+
constructor(
30+
protected authorizationService: AuthorizationDataService,
31+
) {
32+
super();
33+
}
34+
35+
getSubSections(): Observable<PartialMenuSection[]> {
36+
return observableCombineLatest([
37+
this.authorizationService.isAuthorized(FeatureID.CoarNotifyEnabled),
38+
this.authorizationService.isAuthorized(FeatureID.AdministratorOf),
39+
]).pipe(
40+
map(([isCoarNotifyEnabled, isSiteAdmin]: [boolean, boolean]) => {
41+
return [{
42+
visible: isSiteAdmin && isCoarNotifyEnabled,
43+
model: {
44+
type: MenuItemType.LINK,
45+
text: 'menu.section.notify_dashboard',
46+
link: '/admin/notify-dashboard',
47+
} as LinkMenuItemModel,
48+
},
49+
/* LDN Services */
50+
{
51+
visible: isSiteAdmin && isCoarNotifyEnabled,
52+
model: {
53+
type: MenuItemType.LINK,
54+
text: 'menu.section.services',
55+
link: '/admin/ldn/services',
56+
} as LinkMenuItemModel,
57+
}];
58+
}));
59+
}
60+
61+
getTopSection(): Observable<PartialMenuSection> {
62+
return observableCombineLatest([
63+
this.authorizationService.isAuthorized(FeatureID.CoarNotifyEnabled),
64+
this.authorizationService.isAuthorized(FeatureID.AdministratorOf),
65+
]).pipe(
66+
map(([isCoarNotifyEnabled, isSiteAdmin]: [boolean, boolean]) => {
67+
return {
68+
visible: isSiteAdmin && isCoarNotifyEnabled,
69+
model: {
70+
type: MenuItemType.TEXT,
71+
text: 'menu.section.coar_notify',
72+
} as TextMenuItemModel,
73+
icon: 'inbox',
74+
};
75+
}));
76+
}
77+
}

src/app/shared/menu/providers/comcol-subscribe.menu.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { PartialMenuSection } from '../menu-provider.model';
2323
import { DSpaceObjectPageMenuProvider } from './helper-providers/dso.menu';
2424

2525
/**
26-
* Menu provider to create the subscribe menu section
26+
* Menu provider to create the "Subscribe" option in the DSO edit menu
2727
*/
2828
@Injectable()
2929
export class SubscribeMenuProvider extends DSpaceObjectPageMenuProvider {

src/app/shared/menu/providers/community-list.menu.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
} from '../menu-provider.model';
2020

2121
/**
22-
* Menu provider to create the community list menu section
22+
* Menu provider to create the "Communities & Collections" menu section in the public navbar
2323
*/
2424
@Injectable()
2525
export class CommunityListMenuProvider extends AbstractMenuProvider {

0 commit comments

Comments
 (0)