mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-12 04:23:04 +00:00
Merged cdl7 into CST-12043-primary-bitstream-flag
This commit is contained in:
@@ -12,8 +12,7 @@ import { Router } from '@angular/router';
|
|||||||
* Represents a non-expandable section in the admin sidebar
|
* Represents a non-expandable section in the admin sidebar
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
/* eslint-disable @angular-eslint/component-selector */
|
selector: 'ds-admin-sidebar-section',
|
||||||
selector: 'li[ds-admin-sidebar-section]',
|
|
||||||
templateUrl: './admin-sidebar-section.component.html',
|
templateUrl: './admin-sidebar-section.component.html',
|
||||||
styleUrls: ['./admin-sidebar-section.component.scss'],
|
styleUrls: ['./admin-sidebar-section.component.scss'],
|
||||||
|
|
||||||
|
@@ -26,10 +26,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<ng-container *ngFor="let section of (sections | async)">
|
<li *ngFor="let section of (sections | async)">
|
||||||
<ng-container
|
<ng-container
|
||||||
*ngComponentOutlet="(sectionMap$ | async).get(section.id).component; injector: (sectionMap$ | async).get(section.id).injector;"></ng-container>
|
*ngComponentOutlet="(sectionMap$ | async).get(section.id).component; injector: (sectionMap$ | async).get(section.id).injector;"></ng-container>
|
||||||
</ng-container>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-nav">
|
<div class="navbar-nav">
|
||||||
|
@@ -15,8 +15,7 @@ import { Router } from '@angular/router';
|
|||||||
* Represents a expandable section in the sidebar
|
* Represents a expandable section in the sidebar
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
/* eslint-disable @angular-eslint/component-selector */
|
selector: 'ds-expandable-admin-sidebar-section',
|
||||||
selector: 'li[ds-expandable-admin-sidebar-section]',
|
|
||||||
templateUrl: './expandable-admin-sidebar-section.component.html',
|
templateUrl: './expandable-admin-sidebar-section.component.html',
|
||||||
styleUrls: ['./expandable-admin-sidebar-section.component.scss'],
|
styleUrls: ['./expandable-admin-sidebar-section.component.scss'],
|
||||||
animations: [rotate, slide, bgColor]
|
animations: [rotate, slide, bgColor]
|
||||||
|
@@ -7,6 +7,7 @@ import { ServerSyncBufferEffects } from './cache/server-sync-buffer.effects';
|
|||||||
import { ObjectUpdatesEffects } from './data/object-updates/object-updates.effects';
|
import { ObjectUpdatesEffects } from './data/object-updates/object-updates.effects';
|
||||||
import { RouteEffects } from './services/route.effects';
|
import { RouteEffects } from './services/route.effects';
|
||||||
import { RouterEffects } from './router/router.effects';
|
import { RouterEffects } from './router/router.effects';
|
||||||
|
import { MenuEffects } from '../shared/menu/menu.effects';
|
||||||
|
|
||||||
export const coreEffects = [
|
export const coreEffects = [
|
||||||
RequestEffects,
|
RequestEffects,
|
||||||
@@ -18,4 +19,5 @@ export const coreEffects = [
|
|||||||
ObjectUpdatesEffects,
|
ObjectUpdatesEffects,
|
||||||
RouteEffects,
|
RouteEffects,
|
||||||
RouterEffects,
|
RouterEffects,
|
||||||
|
MenuEffects,
|
||||||
];
|
];
|
||||||
|
@@ -661,7 +661,9 @@ describe('RequestService', () => {
|
|||||||
spyOn(service, 'getByHref').and.returnValue(observableOf(staleRE));
|
spyOn(service, 'getByHref').and.returnValue(observableOf(staleRE));
|
||||||
spyOn(store, 'dispatch');
|
spyOn(store, 'dispatch');
|
||||||
service.setStaleByHref(href).subscribe(() => {
|
service.setStaleByHref(href).subscribe(() => {
|
||||||
expect(store.dispatch).toHaveBeenCalledWith(new RequestStaleAction(uuid));
|
const requestStaleAction = new RequestStaleAction(uuid);
|
||||||
|
requestStaleAction.lastUpdated = jasmine.any(Number) as any;
|
||||||
|
expect(store.dispatch).toHaveBeenCalledWith(requestStaleAction);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit, ElementRef } from '@angular/core';
|
||||||
import { ContextHelpService } from '../../shared/context-help.service';
|
import { ContextHelpService } from '../../shared/context-help.service';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, Subscription } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -15,12 +15,23 @@ import { map } from 'rxjs/operators';
|
|||||||
export class ContextHelpToggleComponent implements OnInit {
|
export class ContextHelpToggleComponent implements OnInit {
|
||||||
buttonVisible$: Observable<boolean>;
|
buttonVisible$: Observable<boolean>;
|
||||||
|
|
||||||
|
subscriptions: Subscription[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private contextHelpService: ContextHelpService,
|
protected elRef: ElementRef,
|
||||||
) { }
|
protected contextHelpService: ContextHelpService,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.buttonVisible$ = this.contextHelpService.tooltipCount$().pipe(map(x => x > 0));
|
this.buttonVisible$ = this.contextHelpService.tooltipCount$().pipe(map(x => x > 0));
|
||||||
|
this.subscriptions.push(this.buttonVisible$.subscribe((showContextHelpToggle: boolean) => {
|
||||||
|
if (showContextHelpToggle) {
|
||||||
|
this.elRef.nativeElement.classList.remove('d-none');
|
||||||
|
} else {
|
||||||
|
this.elRef.nativeElement.classList.add('d-none');
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick() {
|
onClick() {
|
||||||
|
@@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
<nav role="navigation" [attr.aria-label]="'nav.user.description' | translate" class="navbar navbar-light navbar-expand-md flex-shrink-0 px-0">
|
<nav role="navigation" [attr.aria-label]="'nav.user.description' | translate" class="navbar navbar-light navbar-expand-md flex-shrink-0 px-0">
|
||||||
<ds-themed-search-navbar></ds-themed-search-navbar>
|
<ds-themed-search-navbar></ds-themed-search-navbar>
|
||||||
<ds-lang-switch></ds-lang-switch>
|
<ds-themed-lang-switch></ds-themed-lang-switch>
|
||||||
<ds-context-help-toggle></ds-context-help-toggle>
|
<ds-context-help-toggle></ds-context-help-toggle>
|
||||||
<ds-themed-auth-nav-menu></ds-themed-auth-nav-menu>
|
<ds-themed-auth-nav-menu></ds-themed-auth-nav-menu>
|
||||||
<ds-impersonate-navbar></ds-impersonate-navbar>
|
<ds-impersonate-navbar></ds-impersonate-navbar>
|
||||||
<div class="pl-2">
|
<div *ngIf="isXsOrSm$ | async" class="pl-2">
|
||||||
<button class="navbar-toggler" type="button" (click)="toggleNavbar()"
|
<button class="navbar-toggler px-0" type="button" (click)="toggleNavbar()"
|
||||||
aria-controls="collapsingNav"
|
aria-controls="collapsingNav"
|
||||||
aria-expanded="false" [attr.aria-label]="'nav.toggle' | translate">
|
aria-expanded="false" [attr.aria-label]="'nav.toggle' | translate">
|
||||||
<span class="navbar-toggler-icon fas fa-bars fa-fw" aria-hidden="true"></span>
|
<span class="navbar-toggler-icon fas fa-bars fa-fw" aria-hidden="true"></span>
|
||||||
|
@@ -20,3 +20,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
display: flex;
|
||||||
|
gap: calc(var(--bs-spacer) / 3);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
@@ -10,6 +10,8 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
|||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { MenuService } from '../shared/menu/menu.service';
|
import { MenuService } from '../shared/menu/menu.service';
|
||||||
import { MenuServiceStub } from '../shared/testing/menu-service.stub';
|
import { MenuServiceStub } from '../shared/testing/menu-service.stub';
|
||||||
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
|
import { HostWindowServiceStub } from '../shared/testing/host-window-service.stub';
|
||||||
|
|
||||||
let comp: HeaderComponent;
|
let comp: HeaderComponent;
|
||||||
let fixture: ComponentFixture<HeaderComponent>;
|
let fixture: ComponentFixture<HeaderComponent>;
|
||||||
@@ -26,6 +28,7 @@ describe('HeaderComponent', () => {
|
|||||||
ReactiveFormsModule],
|
ReactiveFormsModule],
|
||||||
declarations: [HeaderComponent],
|
declarations: [HeaderComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) },
|
||||||
{ provide: MenuService, useValue: menuService }
|
{ provide: MenuService, useValue: menuService }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
@@ -40,7 +43,7 @@ describe('HeaderComponent', () => {
|
|||||||
fixture = TestBed.createComponent(HeaderComponent);
|
fixture = TestBed.createComponent(HeaderComponent);
|
||||||
|
|
||||||
comp = fixture.componentInstance;
|
comp = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when the toggle button is clicked', () => {
|
describe('when the toggle button is clicked', () => {
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { MenuService } from '../shared/menu/menu.service';
|
import { MenuService } from '../shared/menu/menu.service';
|
||||||
import { MenuID } from '../shared/menu/menu-id.model';
|
import { MenuID } from '../shared/menu/menu-id.model';
|
||||||
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the header with the logo and simple navigation
|
* Represents the header with the logo and simple navigation
|
||||||
@@ -11,20 +12,25 @@ import { MenuID } from '../shared/menu/menu-id.model';
|
|||||||
styleUrls: ['header.component.scss'],
|
styleUrls: ['header.component.scss'],
|
||||||
templateUrl: 'header.component.html',
|
templateUrl: 'header.component.html',
|
||||||
})
|
})
|
||||||
export class HeaderComponent {
|
export class HeaderComponent implements OnInit {
|
||||||
/**
|
/**
|
||||||
* Whether user is authenticated.
|
* Whether user is authenticated.
|
||||||
* @type {Observable<string>}
|
* @type {Observable<string>}
|
||||||
*/
|
*/
|
||||||
public isAuthenticated: Observable<boolean>;
|
public isAuthenticated: Observable<boolean>;
|
||||||
public showAuth = false;
|
public isXsOrSm$: Observable<boolean>;
|
||||||
menuID = MenuID.PUBLIC;
|
menuID = MenuID.PUBLIC;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private menuService: MenuService
|
protected menuService: MenuService,
|
||||||
|
protected windowService: HostWindowService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.isXsOrSm$ = this.windowService.isXsOrSm();
|
||||||
|
}
|
||||||
|
|
||||||
public toggleNavbar(): void {
|
public toggleNavbar(): void {
|
||||||
this.menuService.toggleMenu(this.menuID);
|
this.menuService.toggleMenu(this.menuID);
|
||||||
}
|
}
|
||||||
|
@@ -14,9 +14,9 @@
|
|||||||
</a>
|
</a>
|
||||||
<ul @slide *ngIf="(active | async)" (click)="deactivateSection($event)"
|
<ul @slide *ngIf="(active | async)" (click)="deactivateSection($event)"
|
||||||
class="m-0 shadow-none border-top-0 dropdown-menu show">
|
class="m-0 shadow-none border-top-0 dropdown-menu show">
|
||||||
<ng-container *ngFor="let subSection of (subSections$ | async)">
|
<li *ngFor="let subSection of (subSections$ | async)">
|
||||||
<ng-container
|
<ng-container
|
||||||
*ngComponentOutlet="(sectionMap$ | async).get(subSection.id).component; injector: (sectionMap$ | async).get(subSection.id).injector;"></ng-container>
|
*ngComponentOutlet="(sectionMap$ | async).get(subSection.id).component; injector: (sectionMap$ | async).get(subSection.id).injector;"></ng-container>
|
||||||
</ng-container>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -4,7 +4,6 @@ import { MenuService } from '../../shared/menu/menu.service';
|
|||||||
import { slide } from '../../shared/animations/slide';
|
import { slide } from '../../shared/animations/slide';
|
||||||
import { first } from 'rxjs/operators';
|
import { first } from 'rxjs/operators';
|
||||||
import { HostWindowService } from '../../shared/host-window.service';
|
import { HostWindowService } from '../../shared/host-window.service';
|
||||||
import { rendersSectionForMenu } from '../../shared/menu/menu-section.decorator';
|
|
||||||
import { MenuID } from '../../shared/menu/menu-id.model';
|
import { MenuID } from '../../shared/menu/menu-id.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -16,7 +15,6 @@ import { MenuID } from '../../shared/menu/menu-id.model';
|
|||||||
styleUrls: ['./expandable-navbar-section.component.scss'],
|
styleUrls: ['./expandable-navbar-section.component.scss'],
|
||||||
animations: [slide]
|
animations: [slide]
|
||||||
})
|
})
|
||||||
@rendersSectionForMenu(MenuID.PUBLIC, true)
|
|
||||||
export class ExpandableNavbarSectionComponent extends NavbarSectionComponent implements OnInit {
|
export class ExpandableNavbarSectionComponent extends NavbarSectionComponent implements OnInit {
|
||||||
/**
|
/**
|
||||||
* This section resides in the Public Navbar
|
* This section resides in the Public Navbar
|
||||||
|
@@ -8,8 +8,7 @@ import { MenuID } from '../../shared/menu/menu-id.model';
|
|||||||
* Themed wrapper for ExpandableNavbarSectionComponent
|
* Themed wrapper for ExpandableNavbarSectionComponent
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
/* eslint-disable @angular-eslint/component-selector */
|
selector: 'ds-themed-expandable-navbar-section',
|
||||||
selector: 'li[ds-themed-expandable-navbar-section]',
|
|
||||||
styleUrls: [],
|
styleUrls: [],
|
||||||
templateUrl: '../../shared/theme-support/themed.component.html',
|
templateUrl: '../../shared/theme-support/themed.component.html',
|
||||||
})
|
})
|
||||||
|
@@ -8,8 +8,7 @@ import { MenuID } from '../../shared/menu/menu-id.model';
|
|||||||
* Represents a non-expandable section in the navbar
|
* Represents a non-expandable section in the navbar
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
/* eslint-disable @angular-eslint/component-selector */
|
selector: 'ds-navbar-section',
|
||||||
selector: 'li[ds-navbar-section]',
|
|
||||||
templateUrl: './navbar-section.component.html',
|
templateUrl: './navbar-section.component.html',
|
||||||
styleUrls: ['./navbar-section.component.scss']
|
styleUrls: ['./navbar-section.component.scss']
|
||||||
})
|
})
|
||||||
|
@@ -8,9 +8,9 @@
|
|||||||
<li *ngIf="(isXsOrSm$ | async) && (isAuthenticated$ | async)">
|
<li *ngIf="(isXsOrSm$ | async) && (isAuthenticated$ | async)">
|
||||||
<ds-user-menu [inExpandableNavbar]="true"></ds-user-menu>
|
<ds-user-menu [inExpandableNavbar]="true"></ds-user-menu>
|
||||||
</li>
|
</li>
|
||||||
<ng-container *ngFor="let section of (sections | async)">
|
<li *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>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
<div class="d-flex flex-row-reverse">
|
<div class="d-flex flex-row-reverse">
|
||||||
<button (click)="submit()"
|
<button (click)="submit()"
|
||||||
[disabled]="!message || message.length === 0 || !subject || subject.length === 0"
|
[disabled]="!subject || subject.length === 0"
|
||||||
class="btn btn-primary"
|
class="btn btn-primary"
|
||||||
title="{{'grant-deny-request-copy.email.send' | translate }}">
|
title="{{'grant-deny-request-copy.email.send' | translate }}">
|
||||||
<i class="fas fa-envelope"></i> {{'grant-deny-request-copy.email.send' | translate }}
|
<i class="fas fa-envelope"></i> {{'grant-deny-request-copy.email.send' | translate }}
|
||||||
|
@@ -1,9 +1,12 @@
|
|||||||
<div id="search-navbar-container" [title]="'nav.search' | translate" (dsClickOutside)="collapse()">
|
<div id="search-navbar-container" [title]="'nav.search' | translate" (dsClickOutside)="collapse()">
|
||||||
<div class="d-inline-block position-relative">
|
<div class="d-inline-block position-relative">
|
||||||
<form [formGroup]="searchForm" (ngSubmit)="onSubmit(searchForm.value)" autocomplete="on">
|
<form [formGroup]="searchForm" (ngSubmit)="onSubmit(searchForm.value)" autocomplete="on" class="d-flex">
|
||||||
<input #searchInput [@toggleAnimation]="isExpanded" [attr.aria-label]="('nav.search' | translate)" name="query"
|
<input #searchInput [@toggleAnimation]="isExpanded" [attr.aria-label]="('nav.search' | translate)" name="query"
|
||||||
formControlName="query" type="text" placeholder="{{searchExpanded ? ('nav.search' | translate) : ''}}"
|
formControlName="query" type="text" placeholder="{{searchExpanded ? ('nav.search' | translate) : ''}}"
|
||||||
class="d-inline-block bg-transparent position-absolute form-control dropdown-menu-right p-1" [attr.data-test]="'header-search-box' | dsBrowserOnly">
|
class="bg-transparent position-absolute form-control dropdown-menu-right pl-1 pr-4"
|
||||||
|
[class.display]="searchExpanded ? 'inline-block' : 'none'"
|
||||||
|
[tabIndex]="searchExpanded ? 0 : -1"
|
||||||
|
[attr.data-test]="'header-search-box' | dsBrowserOnly">
|
||||||
<button class="submit-icon btn btn-link btn-link-inline" [attr.aria-label]="'nav.search.button' | translate" type="button" (click)="searchExpanded ? onSubmit(searchForm.value) : expand()" [attr.data-test]="'header-search-icon' | dsBrowserOnly">
|
<button class="submit-icon btn btn-link btn-link-inline" [attr.aria-label]="'nav.search.button' | translate" type="button" (click)="searchExpanded ? onSubmit(searchForm.value) : expand()" [attr.data-test]="'header-search-icon' | dsBrowserOnly">
|
||||||
<em class="fas fa-search fa-lg fa-fw"></em>
|
<em class="fas fa-search fa-lg fa-fw"></em>
|
||||||
</button>
|
</button>
|
||||||
|
@@ -12,6 +12,7 @@ input[type="text"] {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
border: 0 !important;
|
||||||
|
|
||||||
color: var(--ds-header-icon-color);
|
color: var(--ds-header-icon-color);
|
||||||
&:hover, &:focus {
|
&:hover, &:focus {
|
||||||
|
@@ -55,7 +55,7 @@ export const slideSidebarPadding = trigger('slideSidebarPadding', [
|
|||||||
|
|
||||||
export const expandSearchInput = trigger('toggleAnimation', [
|
export const expandSearchInput = trigger('toggleAnimation', [
|
||||||
state('collapsed', style({
|
state('collapsed', style({
|
||||||
width: '30px',
|
width: '0',
|
||||||
opacity: '0'
|
opacity: '0'
|
||||||
})),
|
})),
|
||||||
state('expanded', style({
|
state('expanded', style({
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
<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"
|
<a href="javascript:void(0);" class="dropdownLogin px-0.5" [attr.aria-label]="'nav.login' |translate"
|
||||||
(click)="$event.preventDefault()" [attr.data-test]="'login-menu' | dsBrowserOnly"
|
(click)="$event.preventDefault()" [attr.data-test]="'login-menu' | dsBrowserOnly"
|
||||||
ngbDropdownToggle>{{ 'nav.login' | translate }}</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
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li *ngIf="!(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item">
|
<li *ngIf="!(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item">
|
||||||
<a routerLink="/login" routerLinkActive="active" class="loginLink px-1">
|
<a routerLink="/login" routerLinkActive="active" class="loginLink px-0.5">
|
||||||
{{ 'nav.login' | translate }}<span class="sr-only">(current)</span>
|
{{ 'nav.login' | translate }}<span class="sr-only">(current)</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@@ -13,7 +13,6 @@ import { hasValue } from '../../../empty.util';
|
|||||||
* Represents an expandable section in the dso edit menus
|
* Represents an expandable section in the dso edit menus
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
/* tslint:disable:component-selector */
|
|
||||||
selector: 'ds-dso-edit-menu-expandable-section',
|
selector: 'ds-dso-edit-menu-expandable-section',
|
||||||
templateUrl: './dso-edit-menu-expandable-section.component.html',
|
templateUrl: './dso-edit-menu-expandable-section.component.html',
|
||||||
styleUrls: ['./dso-edit-menu-expandable-section.component.scss'],
|
styleUrls: ['./dso-edit-menu-expandable-section.component.scss'],
|
||||||
|
@@ -10,7 +10,6 @@ import { MenuSection } from '../../../menu/menu-section.model';
|
|||||||
* Represents a non-expandable section in the dso edit menus
|
* Represents a non-expandable section in the dso edit menus
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
/* tslint:disable:component-selector */
|
|
||||||
selector: 'ds-dso-edit-menu-section',
|
selector: 'ds-dso-edit-menu-section',
|
||||||
templateUrl: './dso-edit-menu-section.component.html',
|
templateUrl: './dso-edit-menu-section.component.html',
|
||||||
styleUrls: ['./dso-edit-menu-section.component.scss']
|
styleUrls: ['./dso-edit-menu-section.component.scss']
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<ul class="navbar-nav" *ngIf="(isAuthenticated$ | async) && isImpersonating">
|
<ul class="navbar-nav" *ngIf="isImpersonating$ | async">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<button class="btn btn-sm btn-dark" ngbTooltip="{{'nav.stop-impersonating' | translate}}" (click)="stopImpersonating()">
|
<button class="btn btn-sm btn-dark" ngbTooltip="{{'nav.stop-impersonating' | translate}}" (click)="stopImpersonating()">
|
||||||
<i class="fa fa-user-secret"></i>
|
<i class="fa fa-user-secret"></i>
|
||||||
|
@@ -14,6 +14,7 @@ import { authReducer } from '../../core/auth/auth.reducer';
|
|||||||
import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model';
|
import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model';
|
||||||
import { EPersonMock } from '../testing/eperson.mock';
|
import { EPersonMock } from '../testing/eperson.mock';
|
||||||
import { AppState, storeModuleConfig } from '../../app.reducer';
|
import { AppState, storeModuleConfig } from '../../app.reducer';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
|
||||||
describe('ImpersonateNavbarComponent', () => {
|
describe('ImpersonateNavbarComponent', () => {
|
||||||
let component: ImpersonateNavbarComponent;
|
let component: ImpersonateNavbarComponent;
|
||||||
@@ -65,7 +66,7 @@ describe('ImpersonateNavbarComponent', () => {
|
|||||||
|
|
||||||
describe('when the user is impersonating another user', () => {
|
describe('when the user is impersonating another user', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
component.isImpersonating = true;
|
component.isImpersonating$ = observableOf(true);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit, ElementRef } from '@angular/core';
|
||||||
import { select, Store } from '@ngrx/store';
|
import { select, Store } from '@ngrx/store';
|
||||||
import { AppState } from '../../app.reducer';
|
import { AppState } from '../../app.reducer';
|
||||||
import { AuthService } from '../../core/auth/auth.service';
|
import { AuthService } from '../../core/auth/auth.service';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, Subscription } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
import { isAuthenticated } from '../../core/auth/selectors';
|
import { isAuthenticated } from '../../core/auth/selectors';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -13,24 +14,32 @@ import { isAuthenticated } from '../../core/auth/selectors';
|
|||||||
* Navbar component for actions to take concerning impersonating users
|
* Navbar component for actions to take concerning impersonating users
|
||||||
*/
|
*/
|
||||||
export class ImpersonateNavbarComponent implements OnInit {
|
export class ImpersonateNavbarComponent implements OnInit {
|
||||||
/**
|
|
||||||
* Whether or not the user is authenticated.
|
|
||||||
* @type {Observable<string>}
|
|
||||||
*/
|
|
||||||
isAuthenticated$: Observable<boolean>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the user currently impersonating another user?
|
* Is the user currently impersonating another user?
|
||||||
*/
|
*/
|
||||||
isImpersonating: boolean;
|
isImpersonating$: Observable<boolean>;
|
||||||
|
|
||||||
constructor(private store: Store<AppState>,
|
subscriptions: Subscription[] = [];
|
||||||
private authService: AuthService) {
|
|
||||||
|
constructor(
|
||||||
|
protected elRef: ElementRef,
|
||||||
|
protected store: Store<AppState>,
|
||||||
|
protected authService: AuthService,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.isAuthenticated$ = this.store.pipe(select(isAuthenticated));
|
this.isImpersonating$ = this.store.pipe(select(isAuthenticated)).pipe(
|
||||||
this.isImpersonating = this.authService.isImpersonating();
|
map((isUserAuthenticated: boolean) => isUserAuthenticated && this.authService.isImpersonating()),
|
||||||
|
);
|
||||||
|
this.subscriptions.push(this.isImpersonating$.subscribe((isImpersonating: boolean) => {
|
||||||
|
if (isImpersonating) {
|
||||||
|
this.elRef.nativeElement.classList.remove('d-none');
|
||||||
|
} else {
|
||||||
|
this.elRef.nativeElement.classList.add('d-none');
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div ngbDropdown class="navbar-nav" *ngIf="moreThanOneLanguage" display="dynamic" placement="bottom-right">
|
<div ngbDropdown class="navbar-nav" *ngIf="moreThanOneLanguage" display="dynamic" placement="bottom-right">
|
||||||
<a href="javascript:void(0);" role="button"
|
<a href="javascript:void(0);" role="button"
|
||||||
[attr.aria-label]="'nav.language' |translate"
|
[attr.aria-label]="'nav.language' |translate"
|
||||||
[title]="'nav.language' | translate" class="px-1"
|
[title]="'nav.language' | translate"
|
||||||
(click)="$event.preventDefault()" data-toggle="dropdown" ngbDropdownToggle
|
(click)="$event.preventDefault()" data-toggle="dropdown" ngbDropdownToggle
|
||||||
tabindex="0">
|
tabindex="0">
|
||||||
<i class="fas fa-globe-asia fa-lg fa-fw"></i>
|
<i class="fas fa-globe-asia fa-lg fa-fw"></i>
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit, ElementRef } from '@angular/core';
|
||||||
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { LangConfig } from '../../../config/lang-config.interface';
|
import { LangConfig } from '../../../config/lang-config.interface';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { LocaleService } from '../../core/locale/locale.service';
|
import { LocaleService } from '../../core/locale/locale.service';
|
||||||
@@ -25,6 +23,7 @@ export class LangSwitchComponent implements OnInit {
|
|||||||
moreThanOneLanguage: boolean;
|
moreThanOneLanguage: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
public el: ElementRef,
|
||||||
public translate: TranslateService,
|
public translate: TranslateService,
|
||||||
private localeService: LocaleService
|
private localeService: LocaleService
|
||||||
) {
|
) {
|
||||||
@@ -33,6 +32,9 @@ export class LangSwitchComponent implements OnInit {
|
|||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.activeLangs = environment.languages.filter((MyLangConfig) => MyLangConfig.active === true);
|
this.activeLangs = environment.languages.filter((MyLangConfig) => MyLangConfig.active === true);
|
||||||
this.moreThanOneLanguage = (this.activeLangs.length > 1);
|
this.moreThanOneLanguage = (this.activeLangs.length > 1);
|
||||||
|
if (!this.moreThanOneLanguage) {
|
||||||
|
this.el.nativeElement.parentElement.classList.add('d-none');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
27
src/app/shared/lang-switch/themed-lang-switch.component.ts
Normal file
27
src/app/shared/lang-switch/themed-lang-switch.component.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { ThemedComponent } from '../theme-support/themed.component';
|
||||||
|
import { LangSwitchComponent } from './lang-switch.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Themed wrapper for {@link LangSwitchComponent}
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-themed-lang-switch',
|
||||||
|
styleUrls: [],
|
||||||
|
templateUrl: '../theme-support/themed.component.html',
|
||||||
|
})
|
||||||
|
export class ThemedLangSwitchComponent extends ThemedComponent<LangSwitchComponent> {
|
||||||
|
|
||||||
|
protected getComponentName(): string {
|
||||||
|
return 'LangSwitchComponent';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected importThemedComponent(themeName: string): Promise<any> {
|
||||||
|
return import(`../../../themes/${themeName}/app/shared/lang-switch/lang-switch.component`);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected importUnthemedComponent(): Promise<any> {
|
||||||
|
return import(`./lang-switch.component`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -18,6 +18,7 @@ export const MenuActionTypes = {
|
|||||||
EXPAND_MENU: type('dspace/menu/EXPAND_MENU'),
|
EXPAND_MENU: type('dspace/menu/EXPAND_MENU'),
|
||||||
SHOW_MENU: type('dspace/menu/SHOW_MENU'),
|
SHOW_MENU: type('dspace/menu/SHOW_MENU'),
|
||||||
HIDE_MENU: type('dspace/menu/HIDE_MENU'),
|
HIDE_MENU: type('dspace/menu/HIDE_MENU'),
|
||||||
|
REINIT_MENUS: type('dspace/menu/REINIT_MENUS'),
|
||||||
COLLAPSE_MENU_PREVIEW: type('dspace/menu/COLLAPSE_MENU_PREVIEW'),
|
COLLAPSE_MENU_PREVIEW: type('dspace/menu/COLLAPSE_MENU_PREVIEW'),
|
||||||
EXPAND_MENU_PREVIEW: type('dspace/menu/EXPAND_MENU_PREVIEW'),
|
EXPAND_MENU_PREVIEW: type('dspace/menu/EXPAND_MENU_PREVIEW'),
|
||||||
ADD_SECTION: type('dspace/menu-section/ADD_SECTION'),
|
ADD_SECTION: type('dspace/menu-section/ADD_SECTION'),
|
||||||
@@ -115,6 +116,13 @@ export class ExpandMenuPreviewAction implements Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action used to re-initialise the menus
|
||||||
|
*/
|
||||||
|
export class ReinitMenuAction implements Action {
|
||||||
|
type = MenuActionTypes.REINIT_MENUS;
|
||||||
|
}
|
||||||
|
|
||||||
// MENU SECTION ACTIONS
|
// MENU SECTION ACTIONS
|
||||||
/**
|
/**
|
||||||
* Action used to perform state changes for a section of a certain menu
|
* Action used to perform state changes for a section of a certain menu
|
||||||
@@ -224,4 +232,5 @@ export type MenuAction =
|
|||||||
| DeactivateMenuSectionAction
|
| DeactivateMenuSectionAction
|
||||||
| ToggleActiveMenuSectionAction
|
| ToggleActiveMenuSectionAction
|
||||||
| CollapseMenuPreviewAction
|
| CollapseMenuPreviewAction
|
||||||
| ExpandMenuPreviewAction;
|
| ExpandMenuPreviewAction
|
||||||
|
| ReinitMenuAction;
|
||||||
|
41
src/app/shared/menu/menu.effects.spec.ts
Normal file
41
src/app/shared/menu/menu.effects.spec.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
import { provideMockActions } from '@ngrx/effects/testing';
|
||||||
|
import { cold, hot } from 'jasmine-marbles';
|
||||||
|
import { MenuEffects } from './menu.effects';
|
||||||
|
import { ReinitMenuAction } from './menu.actions';
|
||||||
|
import { StoreAction, StoreActionTypes } from '../../store.actions';
|
||||||
|
|
||||||
|
describe('MenuEffects', () => {
|
||||||
|
let menuEffects: MenuEffects;
|
||||||
|
let actions: Observable<any>;
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [
|
||||||
|
MenuEffects,
|
||||||
|
provideMockActions(() => actions),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
menuEffects = TestBed.inject(MenuEffects);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('reinitDSOMenus', () => {
|
||||||
|
describe('When a REHYDRATE action is triggered', () => {
|
||||||
|
let action;
|
||||||
|
beforeEach(() => {
|
||||||
|
action = new StoreAction(StoreActionTypes.REHYDRATE, null);
|
||||||
|
});
|
||||||
|
it('should return a ReinitMenuAction', () => {
|
||||||
|
actions = hot('--a-', {a: action});
|
||||||
|
const expected = cold('--b-', {b: new ReinitMenuAction});
|
||||||
|
|
||||||
|
expect(menuEffects.reinitDSOMenus).toBeObservable(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
23
src/app/shared/menu/menu.effects.ts
Normal file
23
src/app/shared/menu/menu.effects.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||||
|
|
||||||
|
import { StoreActionTypes } from '../../store.actions';
|
||||||
|
import { ReinitMenuAction } from './menu.actions';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MenuEffects {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the store is rehydrated in the browser, re-initialise the menus to ensure
|
||||||
|
* the menus with functions are loaded correctly.
|
||||||
|
*/
|
||||||
|
reinitDSOMenus = createEffect(() => this.actions$
|
||||||
|
.pipe(ofType(StoreActionTypes.REHYDRATE),
|
||||||
|
map(() => new ReinitMenuAction())
|
||||||
|
));
|
||||||
|
|
||||||
|
constructor(private actions$: Actions) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -9,7 +9,7 @@ import {
|
|||||||
ExpandMenuAction,
|
ExpandMenuAction,
|
||||||
ExpandMenuPreviewAction,
|
ExpandMenuPreviewAction,
|
||||||
HideMenuAction,
|
HideMenuAction,
|
||||||
HideMenuSectionAction,
|
HideMenuSectionAction, ReinitMenuAction,
|
||||||
RemoveMenuSectionAction,
|
RemoveMenuSectionAction,
|
||||||
ShowMenuAction,
|
ShowMenuAction,
|
||||||
ShowMenuSectionAction,
|
ShowMenuSectionAction,
|
||||||
@@ -317,6 +317,17 @@ describe('menusReducer', () => {
|
|||||||
// is mutated, and any uncaught exception will cause the test to fail
|
// is mutated, and any uncaught exception will cause the test to fail
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should reset the menu state to the initial state when performing the REINIT_MENUS action without affecting the previous state', () => {
|
||||||
|
dummyState[MenuID.ADMIN].visible = true;
|
||||||
|
const state = dummyState;
|
||||||
|
deepFreeze([state]);
|
||||||
|
|
||||||
|
const action = new ReinitMenuAction();
|
||||||
|
const menusState = menusReducer(state, action);
|
||||||
|
expect(menusState).toEqual(initialMenusState);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
it('should set add a new section for the correct menu in response to the ADD_SECTION action', () => {
|
it('should set add a new section for the correct menu in response to the ADD_SECTION action', () => {
|
||||||
const state = dummyState;
|
const state = dummyState;
|
||||||
const action = new AddMenuSectionAction(menuID, visibleSection1);
|
const action = new AddMenuSectionAction(menuID, visibleSection1);
|
||||||
|
@@ -26,36 +26,39 @@ import { MenuID } from './menu-id.model';
|
|||||||
* @returns {MenusState} The new, reducer MenusState
|
* @returns {MenusState} The new, reducer MenusState
|
||||||
*/
|
*/
|
||||||
export function menusReducer(state: MenusState = initialMenusState, action: MenuAction): MenusState {
|
export function menusReducer(state: MenusState = initialMenusState, action: MenuAction): MenusState {
|
||||||
const menuState: MenuState = state[action.menuID];
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case MenuActionTypes.COLLAPSE_MENU: {
|
case MenuActionTypes.COLLAPSE_MENU: {
|
||||||
const newMenuState = Object.assign({}, menuState, { collapsed: true });
|
const newMenuState = Object.assign({}, state[action.menuID], { collapsed: true });
|
||||||
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
||||||
}
|
}
|
||||||
case MenuActionTypes.EXPAND_MENU: {
|
case MenuActionTypes.EXPAND_MENU: {
|
||||||
const newMenuState = Object.assign({}, menuState, { collapsed: false });
|
const newMenuState = Object.assign({}, state[action.menuID], { collapsed: false });
|
||||||
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
||||||
}
|
}
|
||||||
case MenuActionTypes.COLLAPSE_MENU_PREVIEW: {
|
case MenuActionTypes.COLLAPSE_MENU_PREVIEW: {
|
||||||
const newMenuState = Object.assign({}, menuState, { previewCollapsed: true });
|
const newMenuState = Object.assign({}, state[action.menuID], { previewCollapsed: true });
|
||||||
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
||||||
}
|
}
|
||||||
case MenuActionTypes.EXPAND_MENU_PREVIEW: {
|
case MenuActionTypes.EXPAND_MENU_PREVIEW: {
|
||||||
const newMenuState = Object.assign({}, menuState, { previewCollapsed: false });
|
const newMenuState = Object.assign({}, state[action.menuID], { previewCollapsed: false });
|
||||||
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
||||||
}
|
}
|
||||||
case MenuActionTypes.TOGGLE_MENU: {
|
case MenuActionTypes.TOGGLE_MENU: {
|
||||||
|
const menuState = state[action.menuID];
|
||||||
const newMenuState = Object.assign({}, menuState, { collapsed: !menuState.collapsed });
|
const newMenuState = Object.assign({}, menuState, { collapsed: !menuState.collapsed });
|
||||||
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
||||||
}
|
}
|
||||||
case MenuActionTypes.SHOW_MENU: {
|
case MenuActionTypes.SHOW_MENU: {
|
||||||
const newMenuState = Object.assign({}, menuState, { visible: true });
|
const newMenuState = Object.assign({}, state[action.menuID], { visible: true });
|
||||||
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
||||||
}
|
}
|
||||||
case MenuActionTypes.HIDE_MENU: {
|
case MenuActionTypes.HIDE_MENU: {
|
||||||
const newMenuState = Object.assign({}, menuState, { visible: false });
|
const newMenuState = Object.assign({}, state[action.menuID], { visible: false });
|
||||||
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
return Object.assign({}, state, { [action.menuID]: newMenuState });
|
||||||
}
|
}
|
||||||
|
case MenuActionTypes.REINIT_MENUS: {
|
||||||
|
return Object.assign({}, initialMenusState);
|
||||||
|
}
|
||||||
case MenuActionTypes.ADD_SECTION: {
|
case MenuActionTypes.ADD_SECTION: {
|
||||||
return addSection(state, action as AddMenuSectionAction);
|
return addSection(state, action as AddMenuSectionAction);
|
||||||
}
|
}
|
||||||
@@ -230,7 +233,7 @@ function toggleActiveSection(state: MenusState, action: ToggleActiveMenuSectionA
|
|||||||
* @param {MenuSection} section The section that will be added or replaced in the state
|
* @param {MenuSection} section The section that will be added or replaced in the state
|
||||||
* @returns {MenusState} The new reduced state
|
* @returns {MenusState} The new reduced state
|
||||||
*/
|
*/
|
||||||
function putSectionState(state: MenusState, action: MenuAction, section: MenuSection): MenusState {
|
function putSectionState(state: MenusState, action: MenuSectionAction, section: MenuSection): MenusState {
|
||||||
const menuState: MenuState = state[action.menuID];
|
const menuState: MenuState = state[action.menuID];
|
||||||
const newSections = Object.assign({}, menuState.sections, {
|
const newSections = Object.assign({}, menuState.sections, {
|
||||||
[section.id]: section
|
[section.id]: section
|
||||||
|
@@ -41,6 +41,7 @@ describe('MenuService', () => {
|
|||||||
let routeDataMenuSection: MenuSection;
|
let routeDataMenuSection: MenuSection;
|
||||||
let routeDataMenuSectionResolved: MenuSection;
|
let routeDataMenuSectionResolved: MenuSection;
|
||||||
let routeDataMenuChildSection: MenuSection;
|
let routeDataMenuChildSection: MenuSection;
|
||||||
|
let routeDataMenuOverwrittenChildSection: MenuSection;
|
||||||
let toBeRemovedMenuSection: MenuSection;
|
let toBeRemovedMenuSection: MenuSection;
|
||||||
let alreadyPresentMenuSection: MenuSection;
|
let alreadyPresentMenuSection: MenuSection;
|
||||||
let route;
|
let route;
|
||||||
@@ -127,6 +128,17 @@ describe('MenuService', () => {
|
|||||||
link: ''
|
link: ''
|
||||||
} as LinkMenuItemModel
|
} as LinkMenuItemModel
|
||||||
};
|
};
|
||||||
|
routeDataMenuOverwrittenChildSection = {
|
||||||
|
id: 'mockChildSection',
|
||||||
|
parentID: 'mockSection',
|
||||||
|
active: false,
|
||||||
|
visible: true,
|
||||||
|
model: {
|
||||||
|
type: MenuItemType.LINK,
|
||||||
|
text: 'menu.section.mockChildOverwrittenSection',
|
||||||
|
link: ''
|
||||||
|
} as LinkMenuItemModel
|
||||||
|
};
|
||||||
toBeRemovedMenuSection = {
|
toBeRemovedMenuSection = {
|
||||||
id: 'toBeRemovedSection',
|
id: 'toBeRemovedSection',
|
||||||
active: false,
|
active: false,
|
||||||
@@ -167,7 +179,17 @@ describe('MenuService', () => {
|
|||||||
[MenuID.PUBLIC]: routeDataMenuChildSection
|
[MenuID.PUBLIC]: routeDataMenuChildSection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
firstChild: {
|
||||||
|
snapshot: {
|
||||||
|
data: {
|
||||||
|
menu: {
|
||||||
|
[MenuID.PUBLIC]: routeDataMenuOverwrittenChildSection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -541,7 +563,7 @@ describe('MenuService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('buildRouteMenuSections', () => {
|
describe('buildRouteMenuSections', () => {
|
||||||
it('should add and remove menu sections depending on the current route', () => {
|
it('should add and remove menu sections depending on the current route and overwrite menu sections when they have the same ID with the child route version', () => {
|
||||||
spyOn(service, 'addSection');
|
spyOn(service, 'addSection');
|
||||||
spyOn(service, 'removeSection');
|
spyOn(service, 'removeSection');
|
||||||
|
|
||||||
@@ -550,7 +572,8 @@ describe('MenuService', () => {
|
|||||||
service.buildRouteMenuSections(MenuID.PUBLIC);
|
service.buildRouteMenuSections(MenuID.PUBLIC);
|
||||||
|
|
||||||
expect(service.addSection).toHaveBeenCalledWith(MenuID.PUBLIC, routeDataMenuSectionResolved);
|
expect(service.addSection).toHaveBeenCalledWith(MenuID.PUBLIC, routeDataMenuSectionResolved);
|
||||||
expect(service.addSection).toHaveBeenCalledWith(MenuID.PUBLIC, routeDataMenuChildSection);
|
expect(service.addSection).not.toHaveBeenCalledWith(MenuID.PUBLIC, routeDataMenuChildSection);
|
||||||
|
expect(service.addSection).toHaveBeenCalledWith(MenuID.PUBLIC, routeDataMenuOverwrittenChildSection);
|
||||||
expect(service.addSection).not.toHaveBeenCalledWith(MenuID.PUBLIC, alreadyPresentMenuSection);
|
expect(service.addSection).not.toHaveBeenCalledWith(MenuID.PUBLIC, alreadyPresentMenuSection);
|
||||||
expect(service.removeSection).toHaveBeenCalledWith(MenuID.PUBLIC, toBeRemovedMenuSection.id);
|
expect(service.removeSection).toHaveBeenCalledWith(MenuID.PUBLIC, toBeRemovedMenuSection.id);
|
||||||
});
|
});
|
||||||
|
@@ -399,7 +399,8 @@ export class MenuService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!last) {
|
if (!last) {
|
||||||
return [...menuSections, ...this.resolveRouteMenuSections(route.firstChild, menuID)];
|
const childMenuSections = this.resolveRouteMenuSections(route.firstChild, menuID);
|
||||||
|
return [...menuSections.filter(menu => !(childMenuSections).map(childMenu => childMenu.id).includes(menu.id)), ...childMenuSections];
|
||||||
} else {
|
} else {
|
||||||
return [...menuSections];
|
return [...menuSections];
|
||||||
}
|
}
|
||||||
|
@@ -281,6 +281,7 @@ import {
|
|||||||
} from '../item-page/simple/field-components/specific-field/title/themed-item-page-field.component';
|
} from '../item-page/simple/field-components/specific-field/title/themed-item-page-field.component';
|
||||||
import { BitstreamListItemComponent } from './object-list/bitstream-list-item/bitstream-list-item.component';
|
import { BitstreamListItemComponent } from './object-list/bitstream-list-item/bitstream-list-item.component';
|
||||||
import { NgxPaginationModule } from 'ngx-pagination';
|
import { NgxPaginationModule } from 'ngx-pagination';
|
||||||
|
import { ThemedLangSwitchComponent } from './lang-switch/themed-lang-switch.component';
|
||||||
|
|
||||||
const MODULES = [
|
const MODULES = [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@@ -332,6 +333,7 @@ const COMPONENTS = [
|
|||||||
DsSelectComponent,
|
DsSelectComponent,
|
||||||
ErrorComponent,
|
ErrorComponent,
|
||||||
LangSwitchComponent,
|
LangSwitchComponent,
|
||||||
|
ThemedLangSwitchComponent,
|
||||||
LoadingComponent,
|
LoadingComponent,
|
||||||
ThemedLoadingComponent,
|
ThemedLoadingComponent,
|
||||||
LogInComponent,
|
LogInComponent,
|
||||||
|
@@ -267,3 +267,29 @@ ul.dso-edit-menu-dropdown > li .nav-item.nav-link {
|
|||||||
.table td {
|
.table td {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pt-0\.5 {
|
||||||
|
padding-top: 0.125rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pr-0\.5 {
|
||||||
|
padding-right: 0.125rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pb-0\.5 {
|
||||||
|
padding-bottom: 0.125rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pl-0\.5 {
|
||||||
|
padding-left: 0.125rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.px-0\.5 {
|
||||||
|
padding-left: 0.125rem !important;
|
||||||
|
padding-right: 0.125rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-0\.5 {
|
||||||
|
padding-top: 0.125rem !important;
|
||||||
|
padding-bottom: 0.125rem !important;
|
||||||
|
}
|
||||||
|
@@ -0,0 +1,12 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { LangSwitchComponent as BaseComponent } from '../../../../../app/shared/lang-switch/lang-switch.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-lang-switch',
|
||||||
|
// styleUrls: ['./lang-switch.component.scss'],
|
||||||
|
styleUrls: ['../../../../../app/shared/lang-switch/lang-switch.component.scss'],
|
||||||
|
// templateUrl: './lang-switch.component.html',
|
||||||
|
templateUrl: '../../../../../app/shared/lang-switch/lang-switch.component.html',
|
||||||
|
})
|
||||||
|
export class LangSwitchComponent extends BaseComponent {
|
||||||
|
}
|
@@ -54,6 +54,7 @@ import {
|
|||||||
ItemSearchResultListElementComponent
|
ItemSearchResultListElementComponent
|
||||||
} from './app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
|
} from './app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
|
||||||
import { TopLevelCommunityListComponent } from './app/home-page/top-level-community-list/top-level-community-list.component';
|
import { TopLevelCommunityListComponent } from './app/home-page/top-level-community-list/top-level-community-list.component';
|
||||||
|
import { LangSwitchComponent } from './app/shared/lang-switch/lang-switch.component';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,6 +92,7 @@ const DECLARATIONS = [
|
|||||||
EditCollectionSelectorComponent,
|
EditCollectionSelectorComponent,
|
||||||
EditCommunitySelectorComponent,
|
EditCommunitySelectorComponent,
|
||||||
EditItemSelectorComponent,
|
EditItemSelectorComponent,
|
||||||
|
LangSwitchComponent,
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
<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>
|
</div>
|
||||||
<div class="d-flex flex-grow-1 ml-auto justify-content-end align-items-center">
|
<div class="navbar-buttons d-flex flex-grow-1 ml-auto justify-content-end align-items-center">
|
||||||
<ds-themed-search-navbar></ds-themed-search-navbar>
|
<ds-themed-search-navbar></ds-themed-search-navbar>
|
||||||
<ds-lang-switch></ds-lang-switch>
|
<ds-themed-lang-switch></ds-themed-lang-switch>
|
||||||
<ds-context-help-toggle></ds-context-help-toggle>
|
<ds-context-help-toggle></ds-context-help-toggle>
|
||||||
<ds-themed-auth-nav-menu></ds-themed-auth-nav-menu>
|
<ds-themed-auth-nav-menu></ds-themed-auth-nav-menu>
|
||||||
<ds-impersonate-navbar></ds-impersonate-navbar>
|
<ds-impersonate-navbar></ds-impersonate-navbar>
|
||||||
|
@@ -24,3 +24,9 @@
|
|||||||
color: var(--ds-header-icon-color-hover);
|
color: var(--ds-header-icon-color-hover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navbar-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: calc(var(--bs-spacer) / 3);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
@@ -10,15 +10,17 @@
|
|||||||
<li *ngIf="(isXsOrSm$ | async) && (isAuthenticated$ | async)">
|
<li *ngIf="(isXsOrSm$ | async) && (isAuthenticated$ | async)">
|
||||||
<ds-user-menu [inExpandableNavbar]="true"></ds-user-menu>
|
<ds-user-menu [inExpandableNavbar]="true"></ds-user-menu>
|
||||||
</li>
|
</li>
|
||||||
<ng-container *ngFor="let section of (sections | async)">
|
<li *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>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<ds-search-navbar class="navbar-collapsed"></ds-search-navbar>
|
<div class="navbar-buttons">
|
||||||
<ds-lang-switch class="navbar-collapsed"></ds-lang-switch>
|
<ds-themed-search-navbar class="navbar-collapsed"></ds-themed-search-navbar>
|
||||||
<ds-context-help-toggle class="navbar-collapsed"></ds-context-help-toggle>
|
<ds-themed-lang-switch class="navbar-collapsed"></ds-themed-lang-switch>
|
||||||
<ds-themed-auth-nav-menu class="navbar-collapsed"></ds-themed-auth-nav-menu>
|
<ds-context-help-toggle class="navbar-collapsed"></ds-context-help-toggle>
|
||||||
<ds-impersonate-navbar class="navbar-collapsed"></ds-impersonate-navbar>
|
<ds-themed-auth-nav-menu class="navbar-collapsed"></ds-themed-auth-nav-menu>
|
||||||
|
<ds-impersonate-navbar class="navbar-collapsed"></ds-impersonate-navbar>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
@@ -54,3 +54,9 @@ a.navbar-brand img {
|
|||||||
color: var(--ds-navbar-link-color-hover);
|
color: var(--ds-navbar-link-color-hover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navbar-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: calc(var(--bs-spacer) / 3);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
119
yarn.lock
119
yarn.lock
@@ -451,13 +451,21 @@
|
|||||||
resolved "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz"
|
resolved "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz"
|
||||||
integrity sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==
|
integrity sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==
|
||||||
|
|
||||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.21.4":
|
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6":
|
||||||
version "7.21.4"
|
version "7.21.4"
|
||||||
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz"
|
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz"
|
||||||
integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==
|
integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/highlight" "^7.18.6"
|
"@babel/highlight" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/code-frame@^7.22.13":
|
||||||
|
version "7.22.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
|
||||||
|
integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
|
||||||
|
dependencies:
|
||||||
|
"@babel/highlight" "^7.22.13"
|
||||||
|
chalk "^2.4.2"
|
||||||
|
|
||||||
"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.1", "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.21.4":
|
"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.1", "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.21.4":
|
||||||
version "7.21.4"
|
version "7.21.4"
|
||||||
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz"
|
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz"
|
||||||
@@ -535,7 +543,7 @@
|
|||||||
"@jridgewell/gen-mapping" "^0.3.2"
|
"@jridgewell/gen-mapping" "^0.3.2"
|
||||||
jsesc "^2.5.1"
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
"@babel/generator@^7.18.9", "@babel/generator@^7.19.3", "@babel/generator@^7.21.4":
|
"@babel/generator@^7.18.9", "@babel/generator@^7.19.3":
|
||||||
version "7.21.4"
|
version "7.21.4"
|
||||||
resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz"
|
resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz"
|
||||||
integrity sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==
|
integrity sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==
|
||||||
@@ -545,6 +553,16 @@
|
|||||||
"@jridgewell/trace-mapping" "^0.3.17"
|
"@jridgewell/trace-mapping" "^0.3.17"
|
||||||
jsesc "^2.5.1"
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
|
"@babel/generator@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
|
||||||
|
integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.23.0"
|
||||||
|
"@jridgewell/gen-mapping" "^0.3.2"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.17"
|
||||||
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
"@babel/helper-annotate-as-pure@7.18.6", "@babel/helper-annotate-as-pure@^7.18.6":
|
"@babel/helper-annotate-as-pure@7.18.6", "@babel/helper-annotate-as-pure@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz"
|
resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz"
|
||||||
@@ -610,6 +628,11 @@
|
|||||||
resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz"
|
resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz"
|
||||||
integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
|
integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
|
||||||
|
|
||||||
|
"@babel/helper-environment-visitor@^7.22.20":
|
||||||
|
version "7.22.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
|
||||||
|
integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
|
||||||
|
|
||||||
"@babel/helper-explode-assignable-expression@^7.18.6":
|
"@babel/helper-explode-assignable-expression@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz"
|
resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz"
|
||||||
@@ -625,6 +648,14 @@
|
|||||||
"@babel/template" "^7.20.7"
|
"@babel/template" "^7.20.7"
|
||||||
"@babel/types" "^7.21.0"
|
"@babel/types" "^7.21.0"
|
||||||
|
|
||||||
|
"@babel/helper-function-name@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
|
||||||
|
integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/template" "^7.22.15"
|
||||||
|
"@babel/types" "^7.23.0"
|
||||||
|
|
||||||
"@babel/helper-hoist-variables@^7.18.6":
|
"@babel/helper-hoist-variables@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz"
|
resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz"
|
||||||
@@ -632,6 +663,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.18.6"
|
"@babel/types" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/helper-hoist-variables@^7.22.5":
|
||||||
|
version "7.22.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
|
||||||
|
integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
"@babel/helper-member-expression-to-functions@^7.20.7", "@babel/helper-member-expression-to-functions@^7.21.0":
|
"@babel/helper-member-expression-to-functions@^7.20.7", "@babel/helper-member-expression-to-functions@^7.21.0":
|
||||||
version "7.21.0"
|
version "7.21.0"
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz"
|
resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz"
|
||||||
@@ -715,16 +753,33 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.18.6"
|
"@babel/types" "^7.18.6"
|
||||||
|
|
||||||
|
"@babel/helper-split-export-declaration@^7.22.6":
|
||||||
|
version "7.22.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
|
||||||
|
integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
"@babel/helper-string-parser@^7.19.4":
|
"@babel/helper-string-parser@^7.19.4":
|
||||||
version "7.19.4"
|
version "7.19.4"
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz"
|
resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz"
|
||||||
integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==
|
integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==
|
||||||
|
|
||||||
|
"@babel/helper-string-parser@^7.22.5":
|
||||||
|
version "7.22.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
|
||||||
|
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
|
||||||
|
|
||||||
"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1":
|
"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1":
|
||||||
version "7.19.1"
|
version "7.19.1"
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz"
|
resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz"
|
||||||
integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
|
integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier@^7.22.20":
|
||||||
|
version "7.22.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
|
||||||
|
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
|
||||||
|
|
||||||
"@babel/helper-validator-option@^7.18.6", "@babel/helper-validator-option@^7.21.0":
|
"@babel/helper-validator-option@^7.18.6", "@babel/helper-validator-option@^7.21.0":
|
||||||
version "7.21.0"
|
version "7.21.0"
|
||||||
resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz"
|
resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz"
|
||||||
@@ -758,11 +813,25 @@
|
|||||||
chalk "^2.0.0"
|
chalk "^2.0.0"
|
||||||
js-tokens "^4.0.0"
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
"@babel/parser@^7.10.3", "@babel/parser@^7.14.7", "@babel/parser@^7.18.9", "@babel/parser@^7.19.3", "@babel/parser@^7.20.7", "@babel/parser@^7.21.4":
|
"@babel/highlight@^7.22.13":
|
||||||
|
version "7.22.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
|
||||||
|
integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-validator-identifier" "^7.22.20"
|
||||||
|
chalk "^2.4.2"
|
||||||
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
|
"@babel/parser@^7.10.3", "@babel/parser@^7.14.7", "@babel/parser@^7.18.9", "@babel/parser@^7.19.3", "@babel/parser@^7.20.7":
|
||||||
version "7.21.4"
|
version "7.21.4"
|
||||||
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz"
|
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz"
|
||||||
integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==
|
integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==
|
||||||
|
|
||||||
|
"@babel/parser@^7.22.15", "@babel/parser@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
|
||||||
|
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
|
||||||
|
|
||||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
|
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz"
|
resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz"
|
||||||
@@ -1403,19 +1472,28 @@
|
|||||||
"@babel/parser" "^7.20.7"
|
"@babel/parser" "^7.20.7"
|
||||||
"@babel/types" "^7.20.7"
|
"@babel/types" "^7.20.7"
|
||||||
|
|
||||||
"@babel/traverse@^7.10.3", "@babel/traverse@^7.18.9", "@babel/traverse@^7.19.3", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2":
|
"@babel/template@^7.22.15":
|
||||||
version "7.21.4"
|
version "7.22.15"
|
||||||
resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
|
||||||
integrity sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==
|
integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.21.4"
|
"@babel/code-frame" "^7.22.13"
|
||||||
"@babel/generator" "^7.21.4"
|
"@babel/parser" "^7.22.15"
|
||||||
"@babel/helper-environment-visitor" "^7.18.9"
|
"@babel/types" "^7.22.15"
|
||||||
"@babel/helper-function-name" "^7.21.0"
|
|
||||||
"@babel/helper-hoist-variables" "^7.18.6"
|
"@babel/traverse@^7.10.3", "@babel/traverse@^7.18.9", "@babel/traverse@^7.19.3", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2":
|
||||||
"@babel/helper-split-export-declaration" "^7.18.6"
|
version "7.23.2"
|
||||||
"@babel/parser" "^7.21.4"
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
|
||||||
"@babel/types" "^7.21.4"
|
integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "^7.22.13"
|
||||||
|
"@babel/generator" "^7.23.0"
|
||||||
|
"@babel/helper-environment-visitor" "^7.22.20"
|
||||||
|
"@babel/helper-function-name" "^7.23.0"
|
||||||
|
"@babel/helper-hoist-variables" "^7.22.5"
|
||||||
|
"@babel/helper-split-export-declaration" "^7.22.6"
|
||||||
|
"@babel/parser" "^7.23.0"
|
||||||
|
"@babel/types" "^7.23.0"
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
globals "^11.1.0"
|
globals "^11.1.0"
|
||||||
|
|
||||||
@@ -1428,6 +1506,15 @@
|
|||||||
"@babel/helper-validator-identifier" "^7.19.1"
|
"@babel/helper-validator-identifier" "^7.19.1"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
|
"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0":
|
||||||
|
version "7.23.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
|
||||||
|
integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-string-parser" "^7.22.5"
|
||||||
|
"@babel/helper-validator-identifier" "^7.22.20"
|
||||||
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@colors/colors@1.5.0":
|
"@colors/colors@1.5.0":
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz"
|
resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz"
|
||||||
@@ -3849,7 +3936,7 @@ chalk@^1.1.1:
|
|||||||
strip-ansi "^3.0.0"
|
strip-ansi "^3.0.0"
|
||||||
supports-color "^2.0.0"
|
supports-color "^2.0.0"
|
||||||
|
|
||||||
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1:
|
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
|
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
|
||||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||||
|
Reference in New Issue
Block a user