mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-12 04:23:04 +00:00
[CST-7119] User menu fixes and improvements
This commit is contained in:

committed by
Davide Negretti

parent
273c754370
commit
c75f5f7c81
@@ -1,4 +1,4 @@
|
|||||||
<div class="nav-item dropdown expandable-navbar-section"
|
<div class="nav-item dropdown expandable-navbar-section text-md-center"
|
||||||
*ngVar="(active | async) as isActive"
|
*ngVar="(active | async) as isActive"
|
||||||
(keyup.enter)="isActive ? deactivateSection($event) : activateSection($event)"
|
(keyup.enter)="isActive ? deactivateSection($event) : activateSection($event)"
|
||||||
(keyup.space)="isActive ? deactivateSection($event) : activateSection($event)"
|
(keyup.space)="isActive ? deactivateSection($event) : activateSection($event)"
|
||||||
|
@@ -1,3 +1,10 @@
|
|||||||
|
.expandable-navbar-section {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown-menu {
|
.dropdown-menu {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
<div class="nav-item navbar-section">
|
<div class="nav-item navbar-section text-md-center">
|
||||||
<ng-container *ngComponentOutlet="(sectionMap$ | async).get(section.id).component; injector: (sectionMap$ | async).get(section.id).injector;"></ng-container>
|
<ng-container *ngComponentOutlet="(sectionMap$ | async).get(section.id).component; injector: (sectionMap$ | async).get(section.id).injector;"></ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
.navbar-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
<nav [ngClass]="{'open': !(menuCollapsed | async)}" [@slideMobileNav]="!(windowService.isXsOrSm() | async) ? 'default' : ((menuCollapsed | async) ? 'collapsed' : 'expanded')"
|
<nav [ngClass]="{'open': !(menuCollapsed | async)}" [@slideMobileNav]="!(windowService.isXsOrSm() | async) ? 'default' : ((menuCollapsed | async) ? 'collapsed' : 'expanded')"
|
||||||
class="navbar navbar-light navbar-expand-md p-md-0 navbar-container" role="navigation" [attr.aria-label]="'nav.main.description' | translate">
|
class="navbar navbar-light navbar-expand-md p-md-0 navbar-container" role="navigation" [attr.aria-label]="'nav.main.description' | translate">
|
||||||
<!-- TODO remove navbar-container class when https://github.com/twbs/bootstrap/issues/24726 is fixed -->
|
<!-- TODO remove navbar-container class when https://github.com/twbs/bootstrap/issues/24726 is fixed -->
|
||||||
<div class="container">
|
<div class="navbar-inner-container w-100" [class.container]="!(isXsOrSm$ | async)">
|
||||||
<div class="reset-padding-md w-100">
|
<div class="reset-padding-md w-100">
|
||||||
<div id="collapsingNav">
|
<div id="collapsingNav">
|
||||||
<ul class="navbar-nav navbar-navigation mr-auto shadow-none">
|
<ul class="navbar-nav navbar-navigation mr-auto shadow-none">
|
||||||
|
<li *ngIf="(isXsOrSm$ | async) && (isAuthenticated$ | async)">
|
||||||
|
<ds-user-menu [inExpandableNavbar]="true"></ds-user-menu>
|
||||||
|
</li>
|
||||||
<ng-container *ngFor="let section of (sections | async)">
|
<ng-container *ngFor="let section of (sections | async)">
|
||||||
<ng-container *ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container>
|
<ng-container *ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@@ -27,7 +27,7 @@ nav.navbar {
|
|||||||
/* TODO remove when https://github.com/twbs/bootstrap/issues/24726 is fixed */
|
/* TODO remove when https://github.com/twbs/bootstrap/issues/24726 is fixed */
|
||||||
.navbar-expand-md.navbar-container {
|
.navbar-expand-md.navbar-container {
|
||||||
@media screen and (max-width: map-get($grid-breakpoints, md)-0.02) {
|
@media screen and (max-width: map-get($grid-breakpoints, md)-0.02) {
|
||||||
> .container {
|
> .navbar-inner-container {
|
||||||
padding: 0 var(--bs-spacer);
|
padding: 0 var(--bs-spacer);
|
||||||
}
|
}
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@@ -22,9 +22,17 @@ import { Item } from '../core/shared/item.model';
|
|||||||
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
||||||
import { ThemeService } from '../shared/theme-support/theme.service';
|
import { ThemeService } from '../shared/theme-support/theme.service';
|
||||||
import { getMockThemeService } from '../shared/mocks/theme-service.mock';
|
import { getMockThemeService } from '../shared/mocks/theme-service.mock';
|
||||||
|
import { Store, StoreModule } from '@ngrx/store';
|
||||||
|
import { AppState, storeModuleConfig } from '../app.reducer';
|
||||||
|
import { authReducer } from '../core/auth/auth.reducer';
|
||||||
|
import { provideMockStore } from '@ngrx/store/testing';
|
||||||
|
import { AuthTokenInfo } from '../core/auth/models/auth-token-info.model';
|
||||||
|
import { EPersonMock } from '../shared/testing/eperson.mock';
|
||||||
|
|
||||||
let comp: NavbarComponent;
|
let comp: NavbarComponent;
|
||||||
let fixture: ComponentFixture<NavbarComponent>;
|
let fixture: ComponentFixture<NavbarComponent>;
|
||||||
|
let store: Store<AppState>;
|
||||||
|
let initialState: any;
|
||||||
|
|
||||||
const authorizationService = jasmine.createSpyObj('authorizationService', {
|
const authorizationService = jasmine.createSpyObj('authorizationService', {
|
||||||
isAuthorized: observableOf(true)
|
isAuthorized: observableOf(true)
|
||||||
@@ -83,10 +91,24 @@ describe('NavbarComponent', () => {
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
initialState = {
|
||||||
|
core: {
|
||||||
|
auth: {
|
||||||
|
authenticated: true,
|
||||||
|
loaded: true,
|
||||||
|
blocking: false,
|
||||||
|
loading: false,
|
||||||
|
authToken: new AuthTokenInfo('test_token'),
|
||||||
|
userId: EPersonMock.id,
|
||||||
|
authMethods: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
TranslateModule.forRoot(),
|
TranslateModule.forRoot(),
|
||||||
|
StoreModule.forRoot({ auth: authReducer }, storeModuleConfig),
|
||||||
NoopAnimationsModule,
|
NoopAnimationsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
RouterTestingModule],
|
RouterTestingModule],
|
||||||
@@ -99,6 +121,7 @@ describe('NavbarComponent', () => {
|
|||||||
{ provide: ActivatedRoute, useValue: routeStub },
|
{ provide: ActivatedRoute, useValue: routeStub },
|
||||||
{ provide: BrowseService, useValue: { getBrowseDefinitions: createSuccessfulRemoteDataObject$(buildPaginatedList(undefined, browseDefinitions)) } },
|
{ provide: BrowseService, useValue: { getBrowseDefinitions: createSuccessfulRemoteDataObject$(buildPaginatedList(undefined, browseDefinitions)) } },
|
||||||
{ provide: AuthorizationDataService, useValue: authorizationService },
|
{ provide: AuthorizationDataService, useValue: authorizationService },
|
||||||
|
provideMockStore({ initialState }),
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
})
|
})
|
||||||
@@ -107,7 +130,7 @@ describe('NavbarComponent', () => {
|
|||||||
|
|
||||||
// synchronous beforeEach
|
// synchronous beforeEach
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
store = TestBed.inject(Store);
|
||||||
fixture = TestBed.createComponent(NavbarComponent);
|
fixture = TestBed.createComponent(NavbarComponent);
|
||||||
|
|
||||||
comp = fixture.componentInstance;
|
comp = fixture.componentInstance;
|
||||||
|
@@ -8,6 +8,10 @@ import { ActivatedRoute } from '@angular/router';
|
|||||||
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
|
||||||
import { MenuID } from '../shared/menu/menu-id.model';
|
import { MenuID } from '../shared/menu/menu-id.model';
|
||||||
import { ThemeService } from '../shared/theme-support/theme.service';
|
import { ThemeService } from '../shared/theme-support/theme.service';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { select, Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '../app.reducer';
|
||||||
|
import { isAuthenticated } from '../core/auth/selectors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component representing the public navbar
|
* Component representing the public navbar
|
||||||
@@ -25,18 +29,29 @@ export class NavbarComponent extends MenuComponent {
|
|||||||
*/
|
*/
|
||||||
menuID = MenuID.PUBLIC;
|
menuID = MenuID.PUBLIC;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether user is authenticated.
|
||||||
|
* @type {Observable<string>}
|
||||||
|
*/
|
||||||
|
public isAuthenticated$: Observable<boolean>;
|
||||||
|
|
||||||
|
public isXsOrSm$: Observable<boolean>;
|
||||||
|
|
||||||
constructor(protected menuService: MenuService,
|
constructor(protected menuService: MenuService,
|
||||||
protected injector: Injector,
|
protected injector: Injector,
|
||||||
public windowService: HostWindowService,
|
public windowService: HostWindowService,
|
||||||
public browseService: BrowseService,
|
public browseService: BrowseService,
|
||||||
public authorizationService: AuthorizationDataService,
|
public authorizationService: AuthorizationDataService,
|
||||||
public route: ActivatedRoute,
|
public route: ActivatedRoute,
|
||||||
protected themeService: ThemeService
|
protected themeService: ThemeService,
|
||||||
|
private store: Store<AppState>,
|
||||||
) {
|
) {
|
||||||
super(menuService, injector, authorizationService, route, themeService);
|
super(menuService, injector, authorizationService, route, themeService);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
super.ngOnInit();
|
super.ngOnInit();
|
||||||
|
this.isXsOrSm$ = this.windowService.isXsOrSm();
|
||||||
|
this.isAuthenticated$ = this.store.pipe(select(isAuthenticated));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
<div class="outer-wrapper" [class.d-none]="shouldShowFullscreenLoader">
|
<div class="outer-wrapper" [class.d-none]="shouldShowFullscreenLoader" [@slideSidebarPadding]="{
|
||||||
<ds-themed-admin-sidebar></ds-themed-admin-sidebar>
|
|
||||||
<div class="inner-wrapper" [@slideSidebarPadding]="{
|
|
||||||
value: (!(sidebarVisible | async) ? 'hidden' : (slideSidebarOver | async) ? 'shown' : 'expanded'),
|
value: (!(sidebarVisible | async) ? 'hidden' : (slideSidebarOver | async) ? 'shown' : 'expanded'),
|
||||||
params: {collapsedSidebarWidth: (collapsedSidebarWidth | async), totalSidebarWidth: (totalSidebarWidth | async)}
|
params: {collapsedSidebarWidth: (collapsedSidebarWidth | async), totalSidebarWidth: (totalSidebarWidth | async)}
|
||||||
}">
|
}">
|
||||||
|
<ds-themed-admin-sidebar></ds-themed-admin-sidebar>
|
||||||
|
<div class="inner-wrapper">
|
||||||
<ds-themed-header-navbar-wrapper></ds-themed-header-navbar-wrapper>
|
<ds-themed-header-navbar-wrapper></ds-themed-header-navbar-wrapper>
|
||||||
<main class="main-content">
|
<main class="main-content">
|
||||||
<ds-themed-breadcrumbs></ds-themed-breadcrumbs>
|
<ds-themed-breadcrumbs></ds-themed-breadcrumbs>
|
||||||
|
@@ -2,11 +2,11 @@
|
|||||||
<li *ngIf="!(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item"
|
<li *ngIf="!(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item"
|
||||||
(click)="$event.stopPropagation();">
|
(click)="$event.stopPropagation();">
|
||||||
<div ngbDropdown #loginDrop display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
|
<div ngbDropdown #loginDrop display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
|
||||||
<a href="javascript:void(0);" class="dropdownLogin px-1 " [attr.aria-label]="'nav.login' |translate" (click)="$event.preventDefault()" [attr.data-test]="'login-menu' | dsBrowserOnly" ngbDropdownToggle>
|
<a href="javascript:void(0);" class="dropdownLogin px-1" [attr.aria-label]="'nav.login' |translate"
|
||||||
{{ 'nav.login' | translate }}
|
(click)="$event.preventDefault()" [attr.data-test]="'login-menu' | dsBrowserOnly"
|
||||||
</a>
|
ngbDropdownToggle>{{ 'nav.login' | translate }}</a>
|
||||||
<div class="loginDropdownMenu" [ngClass]="{'pl-3 pr-3': (loading | async)}" ngbDropdownMenu
|
<div class="loginDropdownMenu" [ngClass]="{'pl-3 pr-3': (loading | async)}" ngbDropdownMenu
|
||||||
[attr.aria-label]="'nav.login' |translate">
|
[attr.aria-label]="'nav.login' | translate">
|
||||||
<ds-log-in
|
<ds-log-in
|
||||||
[isStandalonePage]="false"></ds-log-in>
|
[isStandalonePage]="false"></ds-log-in>
|
||||||
</div>
|
</div>
|
||||||
@@ -19,16 +19,16 @@
|
|||||||
</li>
|
</li>
|
||||||
<li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item">
|
<li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item">
|
||||||
<div ngbDropdown display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
|
<div ngbDropdown display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
|
||||||
<a href="javascript:void(0);" role="button" [attr.aria-label]="'nav.logout' |translate" (click)="$event.preventDefault()" [title]="'nav.logout' | translate" class="px-1" [attr.data-test]="'user-menu' | dsBrowserOnly" ngbDropdownToggle>
|
<a href="javascript:void(0);" role="button" [attr.aria-label]="'nav.user-profile-menu-and-logout' |translate" (click)="$event.preventDefault()" [title]="'nav.user-profile-menu-and-logout' | translate" class="px-1" [attr.data-test]="'user-menu' | dsBrowserOnly" ngbDropdownToggle>
|
||||||
<i class="fas fa-user-circle fa-lg fa-fw"></i></a>
|
<i class="fas fa-user-circle fa-lg fa-fw"></i></a>
|
||||||
<div class="logoutDropdownMenu" ngbDropdownMenu [attr.aria-label]="'nav.logout' |translate">
|
<div class="logoutDropdownMenu" ngbDropdownMenu [attr.aria-label]="'nav.user-profile-menu-and-logout' |translate">
|
||||||
<ds-user-menu></ds-user-menu>
|
<ds-user-menu></ds-user-menu>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li *ngIf="(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item">
|
<li *ngIf="(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item">
|
||||||
<a id="logoutLink" role="button" [attr.aria-label]="'nav.logout' |translate" [title]="'nav.logout' | translate" routerLink="/logout" routerLinkActive="active" class="px-1">
|
<a id="logoutLink" role="button" [attr.aria-label]="'nav.logout' |translate" [title]="'nav.logout' | translate" routerLink="/logout" routerLinkActive="active" class="px-1">
|
||||||
<i class="fas fa-user-circle fa-lg fa-fw"></i>
|
<i class="fas fa-sign-out-alt fa-lg fa-fw"></i>
|
||||||
<span class="sr-only">(current)</span>
|
<span class="sr-only">(current)</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
<ds-themed-loading *ngIf="(loading$ | async)"></ds-themed-loading>
|
<ds-themed-loading *ngIf="(loading$ | async)"></ds-themed-loading>
|
||||||
<div *ngIf="!(loading$ | async)">
|
<div *ngIf="!(loading$ | async)">
|
||||||
<span class="dropdown-item-text">{{(user$ | async)?.name}} ({{(user$ | async)?.email}})</span>
|
<span class="dropdown-item-text" [class.pl-0]="inExpandableNavbar">
|
||||||
<a class="dropdown-item" [routerLink]="[profileRoute]" routerLinkActive="active">{{'nav.profile' | translate}}</a>
|
{{(user$ | async)?.name}}<br>
|
||||||
<a class="dropdown-item" [routerLink]="[mydspaceRoute]" routerLinkActive="active">{{'nav.mydspace' | translate}}</a>
|
<span class="text-muted">{{(user$ | async)?.email}}</span>
|
||||||
|
</span>
|
||||||
|
<a [ngClass]="inExpandableNavbar ? 'nav-item nav-link' : 'dropdown-item'" [routerLink]="[profileRoute]" routerLinkActive="active">{{'nav.profile' | translate}}</a>
|
||||||
|
<a [ngClass]="inExpandableNavbar ? 'nav-item nav-link' : 'dropdown-item'" [routerLink]="[mydspaceRoute]" routerLinkActive="active">{{'nav.mydspace' | translate}}</a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<ds-log-out></ds-log-out>
|
<ds-log-out *ngIf="!inExpandableNavbar" data-test="log-out-component"></ds-log-out>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -162,10 +162,24 @@ describe('UserMenuComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should display user name and email', () => {
|
it('should display user name and email', () => {
|
||||||
const user = 'User Test (test@test.com)';
|
const username = 'User Test';
|
||||||
|
const email = 'test@test.com';
|
||||||
const span = deUserMenu.query(By.css('.dropdown-item-text'));
|
const span = deUserMenu.query(By.css('.dropdown-item-text'));
|
||||||
expect(span).toBeDefined();
|
expect(span).toBeDefined();
|
||||||
expect(span.nativeElement.innerHTML).toBe(user);
|
expect(span.nativeElement.innerHTML).toContain(username);
|
||||||
|
expect(span.nativeElement.innerHTML).toContain(email);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create logout component', () => {
|
||||||
|
const components = fixture.debugElement.query(By.css('[data-test="log-out-component"]'));
|
||||||
|
expect(components).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not create logout component', () => {
|
||||||
|
component.inExpandableNavbar = true;
|
||||||
|
fixture.detectChanges();
|
||||||
|
const components = fixture.debugElement.query(By.css('[data-test="log-out-component"]'));
|
||||||
|
expect(components).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { select, Store } from '@ngrx/store';
|
import { select, Store } from '@ngrx/store';
|
||||||
@@ -20,6 +20,11 @@ import { getProfileModuleRoute } from '../../../app-routing-paths';
|
|||||||
})
|
})
|
||||||
export class UserMenuComponent implements OnInit {
|
export class UserMenuComponent implements OnInit {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The input flag to show user details in navbar expandable menu
|
||||||
|
*/
|
||||||
|
@Input() inExpandableNavbar = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the authentication is loading.
|
* True if the authentication is loading.
|
||||||
* @type {Observable<boolean>}
|
* @type {Observable<boolean>}
|
||||||
|
@@ -2862,7 +2862,9 @@
|
|||||||
|
|
||||||
"nav.login": "Log In",
|
"nav.login": "Log In",
|
||||||
|
|
||||||
"nav.logout": "User profile menu and Log Out",
|
"nav.user-profile-menu-and-logout": "User profile menu and Log Out",
|
||||||
|
|
||||||
|
"nav.logout": "Log Out",
|
||||||
|
|
||||||
"nav.main.description": "Main navigation bar",
|
"nav.main.description": "Main navigation bar",
|
||||||
|
|
||||||
|
@@ -1,12 +1,15 @@
|
|||||||
<nav [ngClass]="{'open': !(menuCollapsed | async)}" [@slideMobileNav]="!(windowService.isXsOrSm() | async) ? 'default' : ((menuCollapsed | async) ? 'collapsed' : 'expanded')"
|
<nav [ngClass]="{'open': !(menuCollapsed | async)}" [@slideMobileNav]="!(windowService.isXsOrSm() | async) ? 'default' : ((menuCollapsed | async) ? 'collapsed' : 'expanded')"
|
||||||
class="navbar navbar-expand-md navbar-light p-0 navbar-container" role="navigation" [attr.aria-label]="'nav.main.description' | translate">
|
class="navbar navbar-expand-md navbar-light p-0 navbar-container" role="navigation" [attr.aria-label]="'nav.main.description' | translate">
|
||||||
<div class="container h-100">
|
<div class="navbar-inner-container w-100 h-100" [class.container]="!(isXsOrSm$ | async)">
|
||||||
<a class="navbar-brand my-2" routerLink="/home">
|
<a class="navbar-brand my-2" routerLink="/home">
|
||||||
<img src="assets/images/dspace-logo.svg" [attr.alt]="'menu.header.image.logo' | translate" />
|
<img src="assets/images/dspace-logo.svg" [attr.alt]="'menu.header.image.logo' | translate" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div id="collapsingNav" class="w-100 h-100">
|
<div id="collapsingNav" class="w-100 h-100">
|
||||||
<ul class="navbar-nav navbar-navigation me-auto mb-2 mb-lg-0 h-100 d-flex align-items-center">
|
<ul class="navbar-nav me-auto mb-2 mb-lg-0 h-100">
|
||||||
|
<li *ngIf="(isXsOrSm$ | async) && (isAuthenticated$ | async)">
|
||||||
|
<ds-user-menu [inExpandableNavbar]="true"></ds-user-menu>
|
||||||
|
</li>
|
||||||
<ng-container *ngFor="let section of (sections | async)">
|
<ng-container *ngFor="let section of (sections | async)">
|
||||||
<ng-container *ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container>
|
<ng-container *ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@@ -29,7 +29,7 @@ nav.navbar {
|
|||||||
/* TODO remove when https://github.com/twbs/bootstrap/issues/24726 is fixed */
|
/* TODO remove when https://github.com/twbs/bootstrap/issues/24726 is fixed */
|
||||||
.navbar-expand-md.navbar-container {
|
.navbar-expand-md.navbar-container {
|
||||||
@media screen and (max-width: map-get($grid-breakpoints, md)-0.02) {
|
@media screen and (max-width: map-get($grid-breakpoints, md)-0.02) {
|
||||||
> .container {
|
> .navbar-inner-container {
|
||||||
padding: 0 var(--bs-spacer);
|
padding: 0 var(--bs-spacer);
|
||||||
a.navbar-brand {
|
a.navbar-brand {
|
||||||
display: none;
|
display: none;
|
||||||
|
@@ -21,12 +21,3 @@
|
|||||||
font-size: 1.1rem
|
font-size: 1.1rem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
|
||||||
.navbar-navigation > li {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user