97183 Hide sidebar items w/o appropriate permissions.

See https://github.com/DSpace/dspace-angular/issues/1643

Sidebar now omits "New" and/or "Edit" options in the sidebar if the user does
not have permissions to respectively create new Items or edit Items.

If this results in an empty sidebar, the sidebar is hidden in its entirety.
This commit is contained in:
Koen Pauwels
2022-12-06 11:30:46 +01:00
parent 627da93e23
commit 68bac1f400
5 changed files with 80 additions and 43 deletions

View File

@@ -100,6 +100,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
}
}
});
this.menuVisible = this.menuService.isMenuVisibleWithVisibleSections(this.menuID);
}
@HostListener('focusin')

View File

@@ -29,5 +29,7 @@ export enum FeatureID {
CanViewUsageStatistics = 'canViewUsageStatistics',
CanSendFeedback = 'canSendFeedback',
CanClaimItem = 'canClaimItem',
CanSynchronizeWithORCID = 'canSynchronizeWithORCID'
CanSynchronizeWithORCID = 'canSynchronizeWithORCID',
CanSubmit = 'canSubmit',
CanEditItem = 'canEditItem',
}

View File

@@ -167,10 +167,11 @@ export class MenuResolver implements Resolve<boolean> {
combineLatest([
this.authorizationService.isAuthorized(FeatureID.IsCollectionAdmin),
this.authorizationService.isAuthorized(FeatureID.IsCommunityAdmin),
this.authorizationService.isAuthorized(FeatureID.AdministratorOf)
]).subscribe(([isCollectionAdmin, isCommunityAdmin, isSiteAdmin]) => {
const menuList = [
/* News */
this.authorizationService.isAuthorized(FeatureID.AdministratorOf),
this.authorizationService.isAuthorized(FeatureID.CanSubmit),
this.authorizationService.isAuthorized(FeatureID.CanEditItem),
]).subscribe(([isCollectionAdmin, isCommunityAdmin, isSiteAdmin, canSubmit, canEditItem]) => {
const newSubMenuList = [
{
id: 'new_community',
parentID: 'new',
@@ -201,7 +202,7 @@ export class MenuResolver implements Resolve<boolean> {
id: 'new_item',
parentID: 'new',
active: false,
visible: true,
visible: canSubmit,
model: {
type: MenuItemType.ONCLICK,
text: 'menu.section.new_item',
@@ -221,30 +222,8 @@ export class MenuResolver implements Resolve<boolean> {
link: '/processes/new'
} as LinkMenuItemModel,
},
{
id: 'new',
active: false,
visible: true,
model: {
type: MenuItemType.TEXT,
text: 'menu.section.new'
} as TextMenuItemModel,
icon: 'plus',
index: 0
},
// TODO: enable this menu item once the feature has been implemented
// {
// id: 'new_item_version',
// parentID: 'new',
// active: false,
// visible: true,
// model: {
// type: MenuItemType.LINK,
// text: 'menu.section.new_item_version',
// link: ''
// } as LinkMenuItemModel,
// },
];
const editSubMenuList = [
/* Edit */
{
id: 'edit_community',
@@ -276,7 +255,7 @@ export class MenuResolver implements Resolve<boolean> {
id: 'edit_item',
parentID: 'edit',
active: false,
visible: true,
visible: canEditItem,
model: {
type: MenuItemType.ONCLICK,
text: 'menu.section.edit_item',
@@ -285,17 +264,47 @@ export class MenuResolver implements Resolve<boolean> {
}
} as OnClickMenuItemModel,
},
{
];
const newSubMenu = {
id: 'new',
active: false,
visible: newSubMenuList.map(subMenu => subMenu.visible).reduce((x,y) => x || y),
model: {
type: MenuItemType.TEXT,
text: 'menu.section.new'
} as TextMenuItemModel,
icon: 'plus',
index: 0
}
const editSubMenu = {
id: 'edit',
active: false,
visible: true,
visible: editSubMenuList.map(subMenu => subMenu.visible).reduce((x,y) => x || y),
model: {
type: MenuItemType.TEXT,
text: 'menu.section.edit'
} as TextMenuItemModel,
icon: 'pencil-alt',
index: 1
},
}
const menuList = [
...newSubMenuList,
newSubMenu,
...editSubMenuList,
editSubMenu,
// TODO: enable this menu item once the feature has been implemented
// {
// id: 'new_item_version',
// parentID: 'new',
// active: false,
// visible: true,
// model: {
// type: MenuItemType.LINK,
// text: 'menu.section.new_item_version',
// link: ''
// } as LinkMenuItemModel,
// },
/* Statistics */
// TODO: enable this menu item once the feature has been implemented

View File

@@ -61,7 +61,7 @@ export class RootComponent implements OnInit {
}
ngOnInit() {
this.sidebarVisible = this.menuService.isMenuVisible(MenuID.ADMIN);
this.sidebarVisible = this.menuService.isMenuVisibleWithVisibleSections(MenuID.ADMIN);
this.collapsedSidebarWidth = this.cssService.getVariable('collapsedSidebarWidth');
this.totalSidebarWidth = this.cssService.getVariable('totalSidebarWidth');

View File

@@ -181,6 +181,18 @@ export class MenuService {
);
}
/**
* Check if a given menu is visible and has visible sections
* @param {MenuID} menuID The ID of the menu that is to be checked
* @returns {Observable<boolean>} Emits true if the given menu is
* visible and has visible sections, emits false when it's hidden
*/
isMenuVisibleWithVisibleSections(menuID: MenuID): Observable<boolean> {
return observableCombineLatest([this.isMenuVisible(menuID), this.menuHasVisibleSections(menuID)]).pipe(
map(([menuVisible, visibleSections]) => menuVisible && visibleSections)
);
}
/**
* Check if a given menu is visible
* @param {MenuID} menuID The ID of the menu that is to be checked
@@ -192,6 +204,19 @@ export class MenuService {
);
}
/**
* Check if a menu has at least one section that is visible.
* @param {MenuID} menuID The ID of the menu that is to be checked
* @returns {Observable<boolean>} Emits true if the given menu has visible sections, emits false otherwise
*/
menuHasVisibleSections(menuID: MenuID): Observable<boolean> {
return this.getMenu(menuID).pipe(
map((state: MenuState) => hasValue(state)
? Object.values(state.sections).map(section => section.visible).reduce((x,y) => x || y, false)
: undefined)
);
}
/**
* Expands a given menu
* @param {MenuID} menuID The ID of the menu