made sidebar's info-items configurable

This commit is contained in:
Sofia Papacharalampous 2024-07-02 18:05:26 +03:00
parent b4a5f7cc7e
commit 1f76807169
5 changed files with 205 additions and 64 deletions

View File

@ -0,0 +1,78 @@
export class Sidebar {
private _infoItems: SidebarItem[];
get infoItems(): SidebarItem[] {
return this._infoItems;
}
private _footerItems: SidebarItem[];
get footerItems(): SidebarItem[] {
return this._footerItems;
}
public static parseValue(value: any): Sidebar {
const sidebarItemsObj: Sidebar = new Sidebar();
sidebarItemsObj._infoItems = [];
for (let infoItem of value.infoItems) {
const infoItemObj: SidebarItem = SidebarItem.parseValue(infoItem);
sidebarItemsObj._infoItems.push(infoItemObj);
}
sidebarItemsObj._footerItems = [];
for (let footerItem of value.footerItems) {
const footerItemObj: SidebarItem = SidebarItem.parseValue(footerItem);
sidebarItemsObj._footerItems.push(footerItemObj);
}
return sidebarItemsObj;
}
}
export class SidebarItem {
private _routerPath: string;
get routerPath(): string {
return this._routerPath;
}
private _title: string;
get title(): string {
return this._title;
}
private _icon: string;
get icon(): string {
return this._icon;
}
private _externalUrl?: string|null;
get externalUrl(): string|null {
return this._externalUrl;
}
private _accessLevel: AccessLevel;
get accessLevel(): AccessLevel {
return this._accessLevel;
}
get isExternalLink(): boolean {
return this.externalUrl != null && this.externalUrl != '';
}
public static parseValue(value: any): SidebarItem {
const obj: SidebarItem = new SidebarItem();
obj._routerPath = value.routerPath;
obj._title = value.title;
obj._icon = value.icon;
obj._externalUrl = value.externalUrl;
obj._accessLevel = value.accessLevel ?? AccessLevel.Public;
return obj;
}
}
export enum AccessLevel {
Authenticated = "authenticated",
Unauthenticated = "unauthenticated",
Public = "public",
}

View File

@ -12,6 +12,7 @@ import { Guid } from '@common/types/guid';
import { AuthProviders } from '@app/core/model/configuration-models/auth-providers.model';
import { AnalyticsProviders } from '@app/core/model/configuration-models/analytics-providers.model';
import { CssColorsTenantConfiguration } from '@app/core/model/tenant-configuaration/tenant-configuration';
import { Sidebar } from '@app/core/model/configuration-models/sidebar.model';
@Injectable({
providedIn: 'root',
@ -161,6 +162,11 @@ export class ConfigurationService extends BaseComponent {
return this._analyticsProviders;
}
private _sidebar: Sidebar;
get sidebar(): Sidebar {
return this._sidebar;
}
private _researcherId: any;
get researcherId(): boolean {
return this._researcherId;
@ -259,6 +265,7 @@ export class ConfigurationService extends BaseComponent {
this._newReleaseNotificationVersionCode = config.newReleaseNotification?.versionCode;
this._authProviders = AuthProviders.parseValue(config.authProviders);
this._analyticsProviders = AnalyticsProviders.parseValue(config.analytics);
this._sidebar = Sidebar.parseValue(config.sidebar);
this._researcherId = config.referenceTypes.researcherId;
this._grantId = config.referenceTypes.grantId;
this._organizationId = config.referenceTypes.organizationId;

View File

@ -4,35 +4,42 @@
<div *ngIf="showItem(groupMenuItem);">
<hr *ngIf="!firstGroup">
<mat-list-item routerLinkActive="active" [isActiveMatchOptions]="{ paths: 'exact', queryParams: 'ignored' }" *ngFor="let groupMenuRoute of groupMenuItem.routes; let first = first" class="nav-item" [ngClass]="{'mt-4': first && firstGroup}">
<a class="new-dmp nav-link nav-row" *ngIf="groupMenuRoute.path !== '/contact-support' && groupMenuRoute.path !== '/co-branding' && groupMenuRoute.path !== '/feedback' && groupMenuRoute.path !== '/descriptions'" [routerLink]="[routerUtils.generateUrl(groupMenuRoute.path)]" [ngClass]="{'dmp-tour': groupMenuRoute.path == '/plans'}">
<i class="material-symbols-outlined icon">{{ groupMenuRoute.icon }}</i>
<i *ngIf="groupMenuRoute.path == '/plans'" class="material-symbols-outlined icon-mask">person</i>
<span [ngClass]="{'pl-0': groupMenuRoute.path == '/plans'}" style="text-wrap: wrap;">{{groupMenuRoute.title | translate}}</span>
</a>
<a class="nav-link nav-row" *ngIf="groupMenuRoute.path === '/descriptions'" [routerLink]="[routerUtils.generateUrl(groupMenuRoute.path)]">
<span class="mb-3 inner-line"></span>
<div class="pl-0 pt-1 pb-1 container-fluid nav-subrow description-tour">
<i class="mb-1 material-symbols-outlined icon">{{ groupMenuRoute.icon }}</i>
<i class="mb-1 material-symbols-outlined icon-mask">person</i>
<span class="pl-0 mt-1" style="text-wrap: wrap;">{{groupMenuRoute.title | translate}}</span>
</div>
</a>
<a class="nav-link nav-row" *ngIf="groupMenuRoute.path === '/co-branding'" href="/splash/resources/co-branding.html">
<i class="material-symbols-outlined icon">{{ groupMenuRoute.icon }}</i>
<span>{{groupMenuRoute.title | translate}} <span class="material-symbols-outlined icon-external">open_in_new</span></span>
</a>
<a class="nav-link nav-row" *ngIf="groupMenuRoute.path === '/contact-support' && this.isAuthenticated()" [routerLink]="[routerUtils.generateUrl(groupMenuRoute.path)]">
<i class="material-symbols-outlined icon">{{ groupMenuRoute.icon }}</i>
<span>{{groupMenuRoute.title | translate}}</span>
</a>
<a class="nav-link nav-row" *ngIf="groupMenuRoute.path === '/contact-support' && !this.isAuthenticated()" href="/splash/contact.html">
<i class="material-symbols-outlined icon">{{ groupMenuRoute.icon }}</i>
<span>{{groupMenuRoute.title | translate}} <span class="material-symbols-outlined icon-external">open_in_new</span></span>
</a>
<a class="nav-link nav-row" *ngIf="groupMenuRoute.path === '/feedback'" (click)="openFeedback(groupMenuRoute)">
<i class="material-symbols-outlined icon">{{ groupMenuRoute.icon }}</i>
<span>{{groupMenuRoute.title | translate}} <span class="material-symbols-outlined icon-external">open_in_new</span></span>
</a>
<ng-container *ngIf="groupMenuRoute.routeType == routeType.System; else infoItems">
<a class="new-dmp nav-link nav-row" *ngIf="groupMenuRoute.path !== '/descriptions'; else description" [routerLink]="[routerUtils.generateUrl(groupMenuRoute.path)]" [ngClass]="{'dmp-tour': groupMenuRoute.path == '/plans'}">
<i class="material-symbols-outlined icon">{{ groupMenuRoute.icon }}</i>
<i *ngIf="groupMenuRoute.path == '/plans'" class="material-symbols-outlined icon-mask">person</i>
<span [ngClass]="{'pl-0': groupMenuRoute.path == '/plans'}" style="text-wrap: wrap;">{{groupMenuRoute.title | translate}}</span>
</a>
<ng-template #description>
<a class="nav-link nav-row" *ngIf="groupMenuRoute.path === '/descriptions'" [routerLink]="[routerUtils.generateUrl(groupMenuRoute.path)]">
<span class="mb-3 inner-line"></span>
<div class="pl-0 pt-1 pb-1 container-fluid nav-subrow description-tour">
<i class="mb-1 material-symbols-outlined icon">{{ groupMenuRoute.icon }}</i>
<i class="mb-1 material-symbols-outlined icon-mask">person</i>
<span class="pl-0 mt-1" style="text-wrap: wrap;">{{groupMenuRoute.title | translate}}</span>
</div>
</a>
</ng-template>
</ng-container>
<ng-template #infoItems>
<ng-container *ngIf="groupMenuRoute.path && groupMenuRoute.path != ''; else externalLink">
<a class="nav-link nav-row" [routerLink]="[routerUtils.generateUrl(groupMenuRoute.path)]">
<i class="material-symbols-outlined icon">{{ groupMenuRoute.icon }}</i>
<span>{{groupMenuRoute.title | translate}}</span>
</a>
</ng-container>
<ng-template #externalLink>
<a class="nav-link nav-row" *ngIf="groupMenuRoute.externalUrl && groupMenuRoute.externalUrl!=''" href="{{groupMenuRoute.externalUrl}}" target="_blank">
<i class="material-symbols-outlined icon">{{ groupMenuRoute.icon }}</i>
<span>{{groupMenuRoute.title | translate}} <span class="material-symbols-outlined icon-external">open_in_new</span></span>
</a>
</ng-template>
</ng-template>
</mat-list-item>
</div>
</mat-list>

View File

@ -10,14 +10,21 @@ import { AuthService } from '../../core/services/auth/auth.service';
import { LanguageDialogComponent } from '../language/dialog/language-dialog.component';
import { UserDialogComponent } from '../navbar/user-dialog/user-dialog.component';
import { RouterUtilsService } from '@app/core/services/router/router-utils.service';
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
import { AccessLevel } from '@app/core/model/configuration-models/sidebar.model';
enum RouteType {
System = 0,
Configurable = 1,
}
declare interface RouteInfo {
path: string;
title: string;
icon: string;
url?: string;
externalUrl?: string;
routeType: RouteType;
}
declare interface GroupMenuItem {
class GroupMenuItem {
title: string;
routes: RouteInfo[];
}
@ -37,6 +44,7 @@ export class SidebarComponent implements OnInit {
infoItems: GroupMenuItem;
groupMenuItems: GroupMenuItem[] = [];
currentRoute: string;
routeType = RouteType;
constructor(
public translate: TranslateService,
@ -46,6 +54,7 @@ export class SidebarComponent implements OnInit {
private location: Location,
private analyticsService: AnalyticsService,
public routerUtils: RouterUtilsService,
private configurationService: ConfigurationService,
) { }
ngOnInit() {
@ -68,7 +77,7 @@ export class SidebarComponent implements OnInit {
title: 'SIDE-BAR.GENERAL',
routes: [],
}
this.generalItems.routes.push({ path: '/home', title: 'SIDE-BAR.DASHBOARD', icon: 'home' });
this.generalItems.routes.push({ path: '/home', title: 'SIDE-BAR.DASHBOARD', icon: 'home', routeType: RouteType.System });
this.groupMenuItems.push(this.generalItems);
@ -77,8 +86,8 @@ export class SidebarComponent implements OnInit {
routes: [],
}
if (this.authentication.hasPermission(AppPermission.ViewMyDmpPage)) this.dmpItems.routes.push({ path: '/plans', title: 'SIDE-BAR.MY-DMPS', icon: 'library_books' });
if (this.authentication.hasPermission(AppPermission.ViewMyDescriptionPage)) this.dmpItems.routes.push({ path: '/descriptions', title: 'SIDE-BAR.MY-DESCRIPTIONS', icon: 'dns' });
if (this.authentication.hasPermission(AppPermission.ViewMyDmpPage)) this.dmpItems.routes.push({ path: '/plans', title: 'SIDE-BAR.MY-DMPS', icon: 'library_books', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewMyDescriptionPage)) this.dmpItems.routes.push({ path: '/descriptions', title: 'SIDE-BAR.MY-DESCRIPTIONS', icon: 'dns', routeType: RouteType.System });
this.groupMenuItems.push(this.dmpItems);
this.descriptionItems = {
@ -86,8 +95,8 @@ export class SidebarComponent implements OnInit {
routes: [],
}
if (this.authentication.hasPermission(AppPermission.ViewPublicDmpPage)) this.descriptionItems.routes.push({ path: '/explore-plans', title: 'SIDE-BAR.PUBLIC-DMPS', icon: 'library_books' });
if (this.authentication.hasPermission(AppPermission.ViewPublicDescriptionPage)) this.descriptionItems.routes.push({ path: '/explore-descriptions', title: 'SIDE-BAR.PUBLIC-DESC', icon: 'dns' });
if (this.authentication.hasPermission(AppPermission.ViewPublicDmpPage)) this.descriptionItems.routes.push({ path: '/explore-plans', title: 'SIDE-BAR.PUBLIC-DMPS', icon: 'library_books', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewPublicDescriptionPage)) this.descriptionItems.routes.push({ path: '/explore-descriptions', title: 'SIDE-BAR.PUBLIC-DESC', icon: 'dns', routeType: RouteType.System });
this.groupMenuItems.push(this.descriptionItems);
this.publicItems = {
@ -95,8 +104,8 @@ export class SidebarComponent implements OnInit {
routes: [],
}
if (!this.isAuthenticated()) {
this.publicItems.routes.push({ path: '/explore-plans', title: 'SIDE-BAR.PUBLIC-DMPS', icon: 'library_books' });
this.publicItems.routes.push({ path: '/explore-descriptions', title: 'SIDE-BAR.PUBLIC-DESC', icon: 'dns' });
this.publicItems.routes.push({ path: '/explore-plans', title: 'SIDE-BAR.PUBLIC-DMPS', icon: 'library_books', routeType: RouteType.System });
this.publicItems.routes.push({ path: '/explore-descriptions', title: 'SIDE-BAR.PUBLIC-DESC', icon: 'dns', routeType: RouteType.System });
}
this.groupMenuItems.push(this.publicItems);
@ -104,32 +113,40 @@ export class SidebarComponent implements OnInit {
title: 'SIDE-BAR.ADMIN',
routes: [],
}
if (this.authentication.hasPermission(AppPermission.ViewDmpBlueprintPage)) this.adminItems.routes.push({ path: '/dmp-blueprints', title: 'SIDE-BAR.DMP-BLUEPRINTS', icon: 'library_books' });
if (this.authentication.hasPermission(AppPermission.ViewDescriptionTemplatePage)) this.adminItems.routes.push({ path: '/description-templates', title: 'SIDE-BAR.DESCRIPTION-TEMPLATES', icon: 'description' });
if (this.authentication.hasPermission(AppPermission.ViewDescriptionTemplateTypePage)) this.adminItems.routes.push({ path: '/description-template-type', title: 'SIDE-BAR.DESCRIPTION-TEMPLATE-TYPES', icon: 'stack' });
if (this.authentication.hasPermission(AppPermission.ViewEntityLockPage)) this.adminItems.routes.push({ path: '/entity-locks', title: 'SIDE-BAR.ENTITY-LOCKS', icon: 'lock_person' });
if (this.authentication.hasPermission(AppPermission.ViewReferencePage)) this.adminItems.routes.push({ path: '/references', title: 'SIDE-BAR.REFERENCES', icon: 'dataset_linked' });
if (this.authentication.hasPermission(AppPermission.ViewReferenceTypePage)) this.adminItems.routes.push({ path: '/reference-type', title: 'SIDE-BAR.REFERENCE-TYPES', icon: 'add_link' });
if (this.authentication.hasPermission(AppPermission.ViewPrefillingSourcePage)) this.adminItems.routes.push({ path: '/prefilling-sources', title: 'SIDE-BAR.PREFILLING-SOURCES', icon: 'quick_reference_all' });
if (this.authentication.hasPermission(AppPermission.ViewTenantPage)) this.adminItems.routes.push({ path: '/tenants', title: 'SIDE-BAR.TENANTS', icon: 'tenancy' });
if (this.authentication.hasPermission(AppPermission.ViewTenantConfigurationPage)) this.adminItems.routes.push({ path: '/tenant-configuration', title: 'SIDE-BAR.TENANT-CONFIGURATION', icon: 'settings' });
if (this.authentication.hasPermission(AppPermission.ViewUserPage)) this.adminItems.routes.push({ path: '/users', title: 'SIDE-BAR.USERS', icon: 'people' });
if (this.authentication.hasPermission(AppPermission.ViewTenantUserPage)) this.adminItems.routes.push({ path: '/tenant-users', title: 'SIDE-BAR.TENANT-USERS', icon: 'people' });
if (this.authentication.hasPermission(AppPermission.ViewLanguagePage)) this.adminItems.routes.push({ path: '/languages', title: 'SIDE-BAR.LANGUAGES', icon: 'language' });
if (this.authentication.hasPermission(AppPermission.ViewSupportiveMaterialPage)) this.adminItems.routes.push({ path: '/supportive-material', title: 'SIDE-BAR.SUPPORTIVE-MATERIAL', icon: 'help_center' });
if (this.authentication.hasPermission(AppPermission.ViewNotificationTemplatePage)) this.adminItems.routes.push({ path: '/notification-templates', title: 'SIDE-BAR.NOTIFICATION-TEMPLATES', icon: 'grid_guides' });
if (this.authentication.hasPermission(AppPermission.ViewNotificationPage)) this.adminItems.routes.push({ path: '/notifications', title: 'SIDE-BAR.NOTIFICATIONS', icon: 'notifications' });
if (this.authentication.hasPermission(AppPermission.ViewStatusPage)) this.adminItems.routes.push({ path: '/annotation-statuses', title: 'SIDE-BAR.ANNOTATION-STATUSES', icon: 'notifications' });
if (this.authentication.hasPermission(AppPermission.ViewMaintenancePage)) this.adminItems.routes.push({ path: '/maintenance-tasks', title: 'SIDE-BAR.MAINTENANCE', icon: 'build' });
if (this.authentication.hasPermission(AppPermission.ViewDmpBlueprintPage)) this.adminItems.routes.push({ path: '/dmp-blueprints', title: 'SIDE-BAR.DMP-BLUEPRINTS', icon: 'library_books', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewDescriptionTemplatePage)) this.adminItems.routes.push({ path: '/description-templates', title: 'SIDE-BAR.DESCRIPTION-TEMPLATES', icon: 'description', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewDescriptionTemplateTypePage)) this.adminItems.routes.push({ path: '/description-template-type', title: 'SIDE-BAR.DESCRIPTION-TEMPLATE-TYPES', icon: 'stack', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewEntityLockPage)) this.adminItems.routes.push({ path: '/entity-locks', title: 'SIDE-BAR.ENTITY-LOCKS', icon: 'lock_person', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewReferencePage)) this.adminItems.routes.push({ path: '/references', title: 'SIDE-BAR.REFERENCES', icon: 'dataset_linked', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewReferenceTypePage)) this.adminItems.routes.push({ path: '/reference-type', title: 'SIDE-BAR.REFERENCE-TYPES', icon: 'add_link', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewPrefillingSourcePage)) this.adminItems.routes.push({ path: '/prefilling-sources', title: 'SIDE-BAR.PREFILLING-SOURCES', icon: 'quick_reference_all', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewTenantPage)) this.adminItems.routes.push({ path: '/tenants', title: 'SIDE-BAR.TENANTS', icon: 'tenancy', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewTenantConfigurationPage)) this.adminItems.routes.push({ path: '/tenant-configuration', title: 'SIDE-BAR.TENANT-CONFIGURATION', icon: 'settings', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewUserPage)) this.adminItems.routes.push({ path: '/users', title: 'SIDE-BAR.USERS', icon: 'people', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewTenantUserPage)) this.adminItems.routes.push({ path: '/tenant-users', title: 'SIDE-BAR.TENANT-USERS', icon: 'people', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewLanguagePage)) this.adminItems.routes.push({ path: '/languages', title: 'SIDE-BAR.LANGUAGES', icon: 'language', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewSupportiveMaterialPage)) this.adminItems.routes.push({ path: '/supportive-material', title: 'SIDE-BAR.SUPPORTIVE-MATERIAL', icon: 'help_center', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewNotificationTemplatePage)) this.adminItems.routes.push({ path: '/notification-templates', title: 'SIDE-BAR.NOTIFICATION-TEMPLATES', icon: 'grid_guides', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewNotificationPage)) this.adminItems.routes.push({ path: '/notifications', title: 'SIDE-BAR.NOTIFICATIONS', icon: 'notifications', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewStatusPage)) this.adminItems.routes.push({ path: '/annotation-statuses', title: 'SIDE-BAR.ANNOTATION-STATUSES', icon: 'notifications', routeType: RouteType.System });
if (this.authentication.hasPermission(AppPermission.ViewMaintenancePage)) this.adminItems.routes.push({ path: '/maintenance-tasks', title: 'SIDE-BAR.MAINTENANCE', icon: 'build', routeType: RouteType.System });
this.groupMenuItems.push(this.adminItems);
let infoItems: RouteInfo[] = this.configurationService?.sidebar?.infoItems.map(infoItem => {
if (infoItem.accessLevel == AccessLevel.Authenticated && !this.isAuthenticated()) return null;
if (infoItem.accessLevel == AccessLevel.Unauthenticated && this.isAuthenticated()) return null;
if (infoItem.isExternalLink) {
return { title: infoItem.title, icon: infoItem.icon, externalUrl: infoItem.externalUrl, routeType: RouteType.Configurable } as RouteInfo;
} else {
return { title: infoItem.title, icon: infoItem.icon, path: infoItem.routerPath, routeType: RouteType.Configurable } as RouteInfo;
}
})?.filter(x => x!=null);
this.infoItems = {
title: "",
routes: [],
routes: infoItems ?? []
}
this.infoItems.routes.push({ path: '/co-branding', title: 'SIDE-BAR.CO-BRANDING', icon: 'toll' });
this.infoItems.routes.push({ path: '/contact-support', title: 'SIDE-BAR.SUPPORT', icon: 'help' });
this.infoItems.routes.push({ path: '/feedback', title: 'SIDE-BAR.FEEDBACK', icon: 'feedback', url: 'https://docs.google.com/forms/d/12RSCrUjdSDp2LZLpjDKOi44cN1fLDD2q1-F66SqZIis/viewform?edit_requested=true' });
this.groupMenuItems.push(this.infoItems);
}
@ -189,9 +206,4 @@ export class SidebarComponent implements OnInit {
});
}
}
public openFeedback(groupMenuRoute: RouteInfo) {
window.open(groupMenuRoute.url, '_blank');
}
}

View File

@ -79,5 +79,42 @@
},
"deposit":{
"recordUrlIdPlaceholder": "{doi_id}"
},
"sidebar": {
"infoItems": [
{
"title": "SIDE-BAR.CO-BRANDING",
"icon": "toll",
"externalUrl": "/splash/resources/co-branding.html",
"accessLevel": "public"
},
{
"title": "SIDE-BAR.SUPPORT",
"icon": "help",
"routerPath": "/contact-support",
"accessLevel": "authenticated"
},
{
"title": "SIDE-BAR.SUPPORT",
"icon": "help",
"externalUrl": "/splash/contact.html",
"accessLevel": "unauthenticated"
},
{
"title": "SIDE-BAR.FEEDBACK",
"icon": "feedback",
"externalUrl": "https://docs.google.com/forms/d/12RSCrUjdSDp2LZLpjDKOi44cN1fLDD2q1-F66SqZIis/viewform?edit_requested=true",
"accessLevel": "public"
}
],
"footerItems": [
{
"routerPath": "/feedback",
"title": "SIDE-BAR.FEEDBACK",
"icon": "feedback",
"externalUrl": "https://docs.google.com/forms/d/12RSCrUjdSDp2LZLpjDKOi44cN1fLDD2q1-F66SqZIis/viewform?edit_requested=true",
"accessLevel": true
}
]
}
}