TSK-1395: Update Navbar to work without bootstrap 3 (#1288)
* TSK-1395: update navbar * TSK-1395: fixed CI error * TSK-1395: arrange components correctly * TSK-1395: fit navbar to the other components * TSK-1395: optimize code and add tests * TSK-1395: delete comment * TSK-1395: add missing logout function * TSK-1395: modify components
This commit is contained in:
parent
6a8311a32b
commit
7c83c87f32
|
@ -11,5 +11,6 @@
|
|||
"[html]": {
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "vscode.html-language-features"
|
||||
}
|
||||
},
|
||||
"eslint.enable": false
|
||||
}
|
|
@ -14,4 +14,4 @@
|
|||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
import './commands';
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import "./commands";
|
||||
import './commands';
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
|
|
@ -44,4 +44,3 @@ td {
|
|||
.table__access-item-groups {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
/* ACTION TOOLBAR */
|
||||
.classification-details__headline {
|
||||
padding-top: 0.5rem;
|
||||
|
@ -52,7 +51,6 @@
|
|||
color: $invalid;
|
||||
}
|
||||
|
||||
|
||||
/* DETAILED FIELDS */
|
||||
|
||||
.classification__detailed-fields {
|
||||
|
@ -111,4 +109,3 @@
|
|||
input:invalid.dirty {
|
||||
border-color: $invalid;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
align-items: stretch;
|
||||
}
|
||||
taskana-administration-classification-details {
|
||||
width: 100%
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -5,5 +5,5 @@ mat-icon {
|
|||
margin-left: 3px;
|
||||
}
|
||||
button {
|
||||
color: #555
|
||||
color: #555;
|
||||
}
|
||||
|
|
|
@ -6,4 +6,3 @@ svg-icon {
|
|||
fill: #555;
|
||||
top: -5px !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,4 +2,3 @@
|
|||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,29 @@
|
|||
<taskana-shared-nav-bar></taskana-shared-nav-bar>
|
||||
|
||||
<div (window:resize)="onResize()" class="">
|
||||
<div class="taskana-main">
|
||||
<mat-sidenav-container class="sidenav">
|
||||
<mat-sidenav #sidenav mode="over" class="sidenav__drawer" [autoFocus]="false">
|
||||
<div class="sidenav__drawer-logout">
|
||||
<button mat-icon-button data-toggle="tooltip" title="Logout" (click)="logout()" aria-expanded="true"
|
||||
aria-controls="logout">
|
||||
<mat-icon>exit_to_app</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<a class="sidenav__drawer-user-info">
|
||||
<taskana-shared-user-information></taskana-shared-user-information>
|
||||
</a>
|
||||
<taskana-sidenav-list></taskana-sidenav-list>
|
||||
<div class="sidenav__drawer-version">
|
||||
<p> Taskana version: {{version}} </p>
|
||||
</div>
|
||||
</mat-sidenav>
|
||||
<mat-sidenav-content>
|
||||
<taskana-shared-nav-bar></taskana-shared-nav-bar>
|
||||
<div (window:resize)="onResize()" class="">
|
||||
<div class="taskana-main">
|
||||
<router-outlet></router-outlet>
|
||||
<taskana-shared-spinner [isRunning]="requestInProgress" isModal=true></taskana-shared-spinner>
|
||||
<taskana-shared-progress-bar [hidden]="currentProgressValue === 0" currentValue={{currentProgressValue}}></taskana-shared-progress-bar>
|
||||
<taskana-shared-progress-bar [hidden]="currentProgressValue === 0" currentValue={{currentProgressValue}}>
|
||||
</taskana-shared-progress-bar>
|
||||
</div>
|
||||
<taskana-shared-type-ahead></taskana-shared-type-ahead>
|
||||
</div>
|
||||
<taskana-shared-type-ahead></taskana-shared-type-ahead>
|
||||
</div>
|
||||
</mat-sidenav-content>
|
||||
</mat-sidenav-container>
|
|
@ -0,0 +1,57 @@
|
|||
@import '../theme/variables';
|
||||
|
||||
.sidenav {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.sidenav__drawer {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
box-shadow: none;
|
||||
width: 350px;
|
||||
background-color: $dark-green;
|
||||
box-shadow: 3px 0px 10px -1px $dark-green;
|
||||
}
|
||||
|
||||
.sidenav__drawer-list-item {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.sidenav__drawer-logout {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.sidenav__drawer-version {
|
||||
color: $grey;
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
font-size: 12px;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.sidenav__drawer-user-info {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 50px;
|
||||
margin-left: -16px;
|
||||
}
|
||||
|
||||
.mat-icon-button {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.mat-icon {
|
||||
color: white;
|
||||
}
|
||||
|
||||
::ng-deep .mat-drawer-inner-container {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
::ng-deep .mat-drawer {
|
||||
overflow-y: visible !important;
|
||||
}
|
|
@ -1,15 +1,17 @@
|
|||
import { Component, HostListener, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Component, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { NavigationStart, Router } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { MatSidenav } from '@angular/material';
|
||||
import { FormsValidatorService } from 'app/shared/services/forms-validator/forms-validator.service';
|
||||
|
||||
import { SidenavService } from './shared/services/sidenav/sidenav.service';
|
||||
import { RequestInProgressService } from './shared/services/request-in-progress/request-in-progress.service';
|
||||
import { OrientationService } from './shared/services/orientation/orientation.service';
|
||||
import { SelectedRouteService } from './shared/services/selected-route/selected-route';
|
||||
import { UploadService } from './shared/services/upload/upload.service';
|
||||
import { ErrorModel } from './shared/models/error-model';
|
||||
import { NotificationService } from './shared/services/notifications/notification.service';
|
||||
import { TaskanaEngineService } from './shared/services/taskana-engine/taskana-engine.service';
|
||||
import { WindowRefService } from 'app/shared/services/window/window.service';
|
||||
import { environment } from 'environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-root',
|
||||
|
@ -18,7 +20,6 @@ import { NotificationService } from './shared/services/notifications/notificatio
|
|||
})
|
||||
export class AppComponent implements OnInit, OnDestroy {
|
||||
workbasketsRoute = true;
|
||||
|
||||
selectedRoute = '';
|
||||
|
||||
requestInProgress = false;
|
||||
|
@ -29,6 +30,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||
routerSubscription: Subscription;
|
||||
uploadingFileSubscription: Subscription;
|
||||
error: ErrorModel;
|
||||
version: string;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
|
@ -36,8 +38,10 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||
private orientationService: OrientationService,
|
||||
private selectedRouteService: SelectedRouteService,
|
||||
private formsValidatorService: FormsValidatorService,
|
||||
private errorService: NotificationService,
|
||||
public uploadService: UploadService
|
||||
public uploadService: UploadService,
|
||||
private sidenavService: SidenavService,
|
||||
private taskanaEngineService: TaskanaEngineService,
|
||||
private window: WindowRefService
|
||||
) {}
|
||||
|
||||
@HostListener('window:resize', ['$event'])
|
||||
|
@ -45,6 +49,8 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||
this.orientationService.onResize();
|
||||
}
|
||||
|
||||
@ViewChild('sidenav') public sidenav: MatSidenav;
|
||||
|
||||
ngOnInit() {
|
||||
this.routerSubscription = this.router.events.subscribe((event) => {
|
||||
if (event instanceof NavigationStart) {
|
||||
|
@ -65,9 +71,23 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
this.selectedRoute = value;
|
||||
});
|
||||
|
||||
this.uploadingFileSubscription = this.uploadService.getCurrentProgressValue().subscribe((value) => {
|
||||
this.currentProgressValue = value;
|
||||
});
|
||||
|
||||
this.taskanaEngineService.getVersion().subscribe((restVersion) => {
|
||||
this.version = restVersion.version;
|
||||
});
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.taskanaEngineService.logout();
|
||||
this.window.nativeWindow.location.href = environment.taskanaLogoutUrl;
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.sidenavService.setSidenav(this.sidenav);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
|
|
|
@ -13,6 +13,14 @@ import { TabsModule } from 'ngx-bootstrap/tabs';
|
|||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { TreeModule } from 'angular-tree-component';
|
||||
import { SharedModule } from 'app/shared/shared.module';
|
||||
import {
|
||||
MatButtonModule,
|
||||
MatSidenavModule,
|
||||
MatCheckboxModule,
|
||||
MatGridListModule,
|
||||
MatListModule,
|
||||
MatIconModule
|
||||
} from '@angular/material';
|
||||
|
||||
/**
|
||||
* Services
|
||||
|
@ -31,6 +39,8 @@ import { NoAccessComponent } from 'app/shared/components/no-access/no-access.com
|
|||
import { FormsValidatorService } from './shared/services/forms-validator/forms-validator.service';
|
||||
import { UploadService } from './shared/services/upload/upload.service';
|
||||
import { NotificationService } from './shared/services/notifications/notification.service';
|
||||
import { SidenavService } from './shared/services/sidenav/sidenav.service';
|
||||
import { SidenavListComponent } from 'app/shared/components/sidenav-list/sidenav-list.component';
|
||||
/**
|
||||
* Components
|
||||
*/
|
||||
|
@ -62,11 +72,17 @@ const MODULES = [
|
|||
ReactiveFormsModule,
|
||||
TreeModule,
|
||||
SharedModule,
|
||||
MatSidenavModule,
|
||||
MatCheckboxModule,
|
||||
MatGridListModule,
|
||||
MatListModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
NgxsModule.forRoot(STATES, { developmentMode: !environment.production }),
|
||||
NgxsReduxDevtoolsPluginModule.forRoot({ disabled: environment.production, maxAge: 25 })
|
||||
];
|
||||
|
||||
const DECLARATIONS = [AppComponent, NavBarComponent, UserInformationComponent, NoAccessComponent];
|
||||
const DECLARATIONS = [AppComponent, NavBarComponent, UserInformationComponent, NoAccessComponent, SidenavListComponent];
|
||||
|
||||
export function startupServiceFactory(startupService: StartupService): () => Promise<any> {
|
||||
return (): Promise<any> => startupService.load();
|
||||
|
@ -97,7 +113,8 @@ export function startupServiceFactory(startupService: StartupService): () => Pro
|
|||
FormsValidatorService,
|
||||
UploadService,
|
||||
NotificationService,
|
||||
ClassificationCategoriesService
|
||||
ClassificationCategoriesService,
|
||||
SidenavService
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
.master-detail {
|
||||
min-width: 100vw;
|
||||
}
|
||||
|
|
|
@ -1,78 +1,11 @@
|
|||
<nav class="navbar">
|
||||
<div class="navbar no-border-radius navbar-inverse no-gutter col-xs-12">
|
||||
<div class="pull-left col-sm-3 col-md-4">
|
||||
<button type="button" *ngIf="!showNavbar" class="btn btn-default navbar-toggle show pull-left" (click)="toggleNavBar();"
|
||||
aria-expanded="true" aria-controls="navbar" data-toggle="tooltip" title="Menu">
|
||||
<span class="material-icons md-24 white">menu</span>
|
||||
</button>
|
||||
<span> </span>
|
||||
</div>
|
||||
<div class="col-xs-6 col-sm-5 col-md-4">
|
||||
<ul class="nav logo">
|
||||
<svg-icon class="logo white hidden-xs" src="./assets/icons/logo-copy.svg"></svg-icon>
|
||||
<h2 class="navbar-brand no-margin"> {{title}}</h2>
|
||||
</ul>
|
||||
</div>
|
||||
<div *ngIf="showDomainSelector()" class="pull-right domain-form">
|
||||
<div class="dropdown clearfix btn-group">
|
||||
<label class="control-label hidden-xs">Working on </label>
|
||||
<button type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
{{selectedDomain? selectedDomain: 'MASTER DOMAIN'}}
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu" aria-labelledby="dropdownMenu">
|
||||
<li>
|
||||
<a *ngFor="let domain of domains" (click)="switchDomain(domain)">
|
||||
<label>{{domain? domain: 'MASTER DOMAIN'}}</label>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="navbar navbar__inverse">
|
||||
<div class="navbar__button">
|
||||
<button mat-icon-button class="navbar_button-toggle" (click)="toggleSidenav()">
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div [@toggleRight]="showNavbar" *ngIf="showNavbar" class="navbar-inverse sidenav full-height col-xs-9 col-sm-3"
|
||||
data-html="false" aria-expanded="true">
|
||||
<div class="row">
|
||||
<ul class="nav">
|
||||
<svg-icon class="logo white visible-xs" src="./assets/icons/logo.svg"></svg-icon>
|
||||
<h2 class="navbar-brand no-margin logo visible-xs"> {{title}}</h2>
|
||||
<button type="button" class="btn btn-default logout navbar-toggle show pull-right" data-toggle="tooltip" title="Logout"
|
||||
(click)="logout()" aria-expanded="true" aria-controls="logout">
|
||||
<span class="material-icons md-20 white ">exit_to_app</span>
|
||||
</button>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="nav-content">
|
||||
<taskana-shared-user-information></taskana-shared-user-information>
|
||||
<div *ngIf="administrationAccess" class="row menu">
|
||||
<span (click)="toggleNavBar()" routerLink="taskana/administration/workbaskets" aria-controls="administration"
|
||||
routerLinkActive="active">Administration</span>
|
||||
<div class="row submenu" [ngClass]="{'selected': selectedRoute.indexOf('workbaskets') !== -1 }">
|
||||
<span (click)="toggleNavBar()" class="col-xs-6" routerLink="taskana/administration/workbaskets" aria-controls="Workbaskets"
|
||||
routerLinkActive="active">Workbaskets</span>
|
||||
</div>
|
||||
<div class="row submenu" [ngClass]="{'selected': selectedRoute.indexOf('classifications') !== -1}">
|
||||
<span (click)="toggleNavBar()" class="col-xs-6" routerLink="taskana/administration/classifications" aria-controls="Classifications"
|
||||
routerLinkActive="active">Classifications</span>
|
||||
</div>
|
||||
<div class="row submenu" [ngClass]="{'selected': selectedRoute.indexOf('access-items-management') !== -1}">
|
||||
<span (click)="toggleNavBar()" class="col-xs-6" routerLink="taskana/administration/access-items-management"
|
||||
aria-controls="Access items" routerLinkActive="active">Access items</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="monitorAccess" class="row menu" [ngClass]="{'selected': selectedRoute.indexOf('monitor') !== -1}">
|
||||
<span (click)="toggleNavBar()" routerLink="{{monitorUrl}}" aria-controls="Monitor" routerLinkActive="active">Monitor</span>
|
||||
</div>
|
||||
<div *ngIf="workplaceAccess" class="row menu" [ngClass]="{'selected': selectedRoute.indexOf('workplace') !== -1 || selectedRoute === ''}">
|
||||
<span (click)="toggleNavBar()" routerLink="{{workplaceUrl}}" aria-controls="Workplace" routerLinkActive="active">Workplace</span>
|
||||
</div>
|
||||
<div *ngIf="historyAccess" class="row menu" [ngClass]="{'selected': selectedRoute.indexOf('history') !== -1}">
|
||||
<span (click)="toggleNavBar()" routerLink="{{historyUrl}}" aria-controls="history" routerLinkActive="active">History</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-version">
|
||||
<p id="taskana-version"> Taskana version: {{version}} </p>
|
||||
</div>
|
||||
<div class="navbar__logo">
|
||||
<svg-icon class="navbar__logo-icon" src="./assets/icons/logo-copy.svg"></svg-icon>
|
||||
<h2 class="navbar__title">{{title}}</h2>
|
||||
</div>
|
||||
<div *ngIf="showNavbar" class="backdrop" (click)="toggleNavBar()"></div>
|
||||
</nav>
|
||||
</nav>
|
|
@ -2,103 +2,7 @@
|
|||
|
||||
.navbar.main:before {
|
||||
@include degraded-bar(right, 100%, 3px);
|
||||
}
|
||||
|
||||
.navbar-inverse {
|
||||
top: 0;
|
||||
border: none;
|
||||
background-color: $dark-green;
|
||||
box-shadow: 0px 1px 5px -1px black;
|
||||
}
|
||||
|
||||
.navbar-toggle {
|
||||
margin: 3px 0px;
|
||||
font-size: 20px;
|
||||
&.logout {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
button.navbar-toggle:hover > span {
|
||||
color: $aquamarine;
|
||||
}
|
||||
ul.nav > p {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.navbar-inverse .navbar-toggle,
|
||||
.navbar-toggle:hover,
|
||||
.navbar-inverse .navbar-toggle:focus {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
svg-icon.logo {
|
||||
float: left;
|
||||
width: 150px;
|
||||
height: 50px;
|
||||
padding: 5px;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
h2.navbar-brand {
|
||||
vertical-align: middle;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
padding: 15px 0px 0px 0px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.domain-form {
|
||||
margin: 13px;
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
> div {
|
||||
cursor: pointer;
|
||||
> button {
|
||||
color: white;
|
||||
background-color: $dark-green;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
border-bottom: 1px solid $dark-green;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.nav-version {
|
||||
color: $grey;
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/*
|
||||
* All side bar links styling.
|
||||
*/
|
||||
.nav-sidebar > li > a {
|
||||
padding-right: 20px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.menu > span:hover,
|
||||
.submenu > span:hover {
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sidenav {
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
box-shadow: none;
|
||||
height: 100%;
|
||||
background-color: $dark-green;
|
||||
box-shadow: 3px 0px 10px -1px $dark-green;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
|
@ -106,40 +10,53 @@ h2.navbar-brand {
|
|||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.menu,
|
||||
.submenu > span {
|
||||
margin-top: 15px;
|
||||
font-size: 20px;
|
||||
.navbar__inverse {
|
||||
border: none;
|
||||
background-color: $dark-green;
|
||||
box-shadow: 0px 1px 5px -1px black;
|
||||
width: 100%;
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.menu,
|
||||
.submenu > span {
|
||||
padding-left: 12px;
|
||||
color: $grey;
|
||||
.navbar__buttom {
|
||||
flex-grow: 1;
|
||||
display: flex !important;
|
||||
order: 1;
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.navbar__logo {
|
||||
display: flex !important;
|
||||
flex-grow: 6;
|
||||
position: relative;
|
||||
left: 40%;
|
||||
margin-top: -3px;
|
||||
order: 2;
|
||||
}
|
||||
|
||||
h2.navbar__title {
|
||||
display: flex !important;
|
||||
flex-grow: 5;
|
||||
color: white;
|
||||
margin-top: 10px;
|
||||
order: 3;
|
||||
margin-left: 2%;
|
||||
font-size: large;
|
||||
@media only screen and (max-width: 700px) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
svg-icon.navbar__logo-icon {
|
||||
float: left;
|
||||
width: 150px;
|
||||
height: 50px;
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.mat-icon-button {
|
||||
outline: none;
|
||||
}
|
||||
.menu.selected,
|
||||
.submenu.selected {
|
||||
background-color: transparent;
|
||||
& > span {
|
||||
padding-left: 10px;
|
||||
border-left: $pallete-green 5px solid;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.menu > .submenu {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $grey;
|
||||
&:hover {
|
||||
color: white;
|
||||
}
|
||||
text-decoration: none;
|
||||
.mat-icon {
|
||||
color: white;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { NavBarComponent } from './nav-bar.component';
|
||||
import { SelectedRouteService } from '../../../shared/services/selected-route/selected-route';
|
||||
import { MatIconModule } from '@angular/material';
|
||||
import { SidenavService } from '../../../shared/services/sidenav/sidenav.service';
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { of } from 'rxjs/internal/observable/of';
|
||||
|
||||
const SidenavServiceSpy = jest.fn().mockImplementation(
|
||||
(): Partial<SidenavService> => ({
|
||||
toggleSidenav: jest.fn().mockReturnValue(of())
|
||||
})
|
||||
);
|
||||
|
||||
const SelectedRouteServiceSpy = jest.fn().mockImplementation(
|
||||
(): Partial<SelectedRouteService> => ({
|
||||
getSelectedRoute: jest.fn().mockReturnValue(of())
|
||||
})
|
||||
);
|
||||
|
||||
describe('NavBarComponent', () => {
|
||||
let component: NavBarComponent;
|
||||
let fixture: ComponentFixture<NavBarComponent>;
|
||||
let debugElement: DebugElement;
|
||||
var route = '';
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [NavBarComponent],
|
||||
imports: [MatIconModule, HttpClientTestingModule, AngularSvgIconModule],
|
||||
providers: [
|
||||
{ provide: SidenavService, useClass: SidenavServiceSpy },
|
||||
{ provide: SelectedRouteService, useClass: SelectedRouteServiceSpy }
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NavBarComponent);
|
||||
debugElement = fixture.debugElement;
|
||||
component = fixture.debugElement.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should set title to workbasket if workbasket ist selected', () => {
|
||||
route = 'workbaskets';
|
||||
fixture.detectChanges();
|
||||
component.setTitle(route);
|
||||
expect(component.title).toBe('Workbaskets');
|
||||
});
|
||||
|
||||
it('should toggle sidenav when button clicked', () => {
|
||||
fixture.detectChanges();
|
||||
expect(component.toggle).toBe(false);
|
||||
const button = debugElement.query(By.css('.navbar_button-toggle')).nativeElement;
|
||||
expect(button).toBeTruthy();
|
||||
button.click();
|
||||
expect(component.toggle).toBe(true);
|
||||
});
|
||||
});
|
|
@ -1,105 +1,44 @@
|
|||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { environment } from 'environments/environment';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { SelectedRouteService } from 'app/shared/services/selected-route/selected-route';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { DomainService } from 'app/shared/services/domain/domain.service';
|
||||
import { BusinessAdminGuard } from 'app/shared/guards/business-admin.guard';
|
||||
import { MonitorGuard } from 'app/shared/guards/monitor.guard';
|
||||
import { WindowRefService } from 'app/shared/services/window/window.service';
|
||||
import { UserGuard } from 'app/shared/guards/user.guard';
|
||||
import { expandRight } from 'app/shared/animations/expand.animation';
|
||||
import { TaskanaEngineService } from '../../services/taskana-engine/taskana-engine.service';
|
||||
import { SidenavService } from '../../services/sidenav/sidenav.service';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-shared-nav-bar',
|
||||
templateUrl: './nav-bar.component.html',
|
||||
styleUrls: ['./nav-bar.component.scss'],
|
||||
animations: [expandRight]
|
||||
})
|
||||
export class NavBarComponent implements OnInit, OnDestroy {
|
||||
export class NavBarComponent implements OnInit {
|
||||
selectedRoute = '';
|
||||
route: string;
|
||||
title = '';
|
||||
|
||||
titleAdministration = 'Administration';
|
||||
titleWorkbaskets = 'Workbaskets';
|
||||
titleClassifications = 'Classifications';
|
||||
titleAccessItems = 'Access items';
|
||||
titleMonitor = 'Monitor';
|
||||
titleWorkplace = 'Workplace';
|
||||
titleHistory = 'History';
|
||||
showNavbar = false;
|
||||
domains: Array<string> = [];
|
||||
selectedDomain: string;
|
||||
version: string;
|
||||
|
||||
adminUrl = 'taskana/administration';
|
||||
monitorUrl = 'taskana/monitor';
|
||||
workplaceUrl = 'taskana/workplace';
|
||||
historyUrl = 'taskana/history';
|
||||
|
||||
administrationAccess = false;
|
||||
monitorAccess = false;
|
||||
workplaceAccess = false;
|
||||
historyAccess = false;
|
||||
toggle: boolean = false;
|
||||
|
||||
selectedRouteSubscription: Subscription;
|
||||
getDomainsSubscription: Subscription;
|
||||
|
||||
constructor(
|
||||
private selectedRouteService: SelectedRouteService,
|
||||
private domainService: DomainService,
|
||||
private taskanaEngineService: TaskanaEngineService,
|
||||
private window: WindowRefService
|
||||
) {}
|
||||
constructor(private selectedRouteService: SelectedRouteService, private sidenavService: SidenavService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.selectedRouteSubscription = this.selectedRouteService.getSelectedRoute().subscribe((value: string) => {
|
||||
this.selectedRoute = value;
|
||||
this.setTitle(value);
|
||||
});
|
||||
this.getDomainsSubscription = this.domainService.getDomains().subscribe((domains) => {
|
||||
this.domains = domains;
|
||||
});
|
||||
|
||||
this.domainService.getSelectedDomain().subscribe((domain) => {
|
||||
this.selectedDomain = domain;
|
||||
});
|
||||
|
||||
this.taskanaEngineService.getVersion().subscribe((restVersion) => {
|
||||
this.version = restVersion.version;
|
||||
});
|
||||
|
||||
this.administrationAccess = this.taskanaEngineService.hasRole(BusinessAdminGuard.roles);
|
||||
this.monitorAccess = this.taskanaEngineService.hasRole(MonitorGuard.roles);
|
||||
this.workplaceAccess = this.taskanaEngineService.hasRole(UserGuard.roles);
|
||||
|
||||
this.taskanaEngineService.isHistoryProviderEnabled().subscribe((value) => {
|
||||
this.historyAccess = value;
|
||||
});
|
||||
}
|
||||
|
||||
switchDomain(domain) {
|
||||
this.domainService.switchDomain(domain);
|
||||
toggleSidenav() {
|
||||
this.toggle = !this.toggle;
|
||||
this.sidenavService.toggleSidenav();
|
||||
}
|
||||
|
||||
toggleNavBar() {
|
||||
this.showNavbar = !this.showNavbar;
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.taskanaEngineService.logout().subscribe(() => {});
|
||||
this.window.nativeWindow.location.href = environment.taskanaLogoutUrl;
|
||||
}
|
||||
|
||||
showDomainSelector(): boolean {
|
||||
return (
|
||||
this.selectedRoute.indexOf('administration') !== -1 ||
|
||||
this.selectedRoute.indexOf('workbaskets') !== -1 ||
|
||||
this.selectedRoute.indexOf('classifications') !== -1
|
||||
);
|
||||
}
|
||||
|
||||
private setTitle(value: string = 'workbaskets') {
|
||||
setTitle(value: string = 'workbaskets') {
|
||||
if (value.indexOf('workbaskets') === 0) {
|
||||
this.title = this.titleWorkbaskets;
|
||||
} else if (value.indexOf('classifications') === 0) {
|
||||
|
@ -114,13 +53,4 @@ export class NavBarComponent implements OnInit, OnDestroy {
|
|||
this.title = this.titleHistory;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.selectedRouteSubscription) {
|
||||
this.selectedRouteSubscription.unsubscribe();
|
||||
}
|
||||
if (this.getDomainsSubscription) {
|
||||
this.getDomainsSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<mat-nav-list>
|
||||
<a mat-list-item class="list-item list-item__admin" [routerLink]=[workbasketsUrl] [routerLinkActive]="['active']"
|
||||
*ngIf="administrationAccess" (click)="toggleSidenav()">Administration</a>
|
||||
<a mat-list-item class="list-item list-item__admin-workbaskets" [routerLink]=[workbasketsUrl]
|
||||
[routerLinkActive]="['active']" *ngIf="administrationAccess" (click)="toggleSidenav()">Workbaskets</a>
|
||||
<a mat-list-item class="list-item list-item__admin-classifications" [routerLink]=[classificationUrl]
|
||||
[routerLinkActive]="['active']" *ngIf="administrationAccess" (click)="toggleSidenav()">Classifications</a>
|
||||
<a mat-list-item class="list-item list-item__admin-acces-items" [routerLink]=[accessUrl]
|
||||
[routerLinkActive]="['active']" (click)="toggleSidenav()" *ngIf="administrationAccess">Access Items</a>
|
||||
<a mat-list-item class="list-item list-item__monitor" [routerLink]=[monitorUrl] [routerLinkActive]="['active']"
|
||||
*ngIf="monitorAccess" (click)="toggleSidenav()">Monitor</a>
|
||||
<a mat-list-item class="list-item list-item__workplace" [routerLink]=[workplaceUrl] [routerLinkActive]="['active']"
|
||||
*ngIf="workplaceAccess" (click)="toggleSidenav()">Workplace</a>
|
||||
<a mat-list-item class="list-item list-item__history" [routerLink]=[historyUrl] [routerLinkActive]="['active']"
|
||||
*ngIf="historyAccess" (click)="toggleSidenav()">History</a>
|
||||
</mat-nav-list>
|
|
@ -0,0 +1,35 @@
|
|||
@import '../../../../theme/variables';
|
||||
|
||||
.list-item {
|
||||
color: $grey;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
color: $grey;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
color: $grey;
|
||||
}
|
||||
|
||||
.list-item__admin-workbaskets {
|
||||
color: $grey;
|
||||
margin-left: 30px;
|
||||
}
|
||||
.list-item__admin-classifications {
|
||||
color: $grey;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.list-item__admin-acces-items {
|
||||
color: $grey;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
::ng-deep .mat-drawer-container {
|
||||
background-color: white;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { Component, DebugElement } from '@angular/core';
|
||||
import { SidenavListComponent } from './sidenav-list.component';
|
||||
import { SidenavService } from '../../../shared/services/sidenav/sidenav.service';
|
||||
import {
|
||||
MatButtonModule,
|
||||
MatSidenavModule,
|
||||
MatCheckboxModule,
|
||||
MatGridListModule,
|
||||
MatListModule,
|
||||
MatIconModule
|
||||
} from '@angular/material';
|
||||
import { BrowserModule, By } from '@angular/platform-browser';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { TaskanaEngineService } from '../../services/taskana-engine/taskana-engine.service';
|
||||
import { TaskanaEngineServiceMock } from '../../services/taskana-engine/taskana-engine.mock.service';
|
||||
import { of } from 'rxjs/internal/observable/of';
|
||||
|
||||
const SidenavServiceSpy = jest.fn().mockImplementation(
|
||||
(): Partial<SidenavService> => ({
|
||||
toggleSidenav: jest.fn().mockReturnValue(of())
|
||||
})
|
||||
);
|
||||
|
||||
const TaskanaEngingeServiceSpy = jest.fn().mockImplementation(
|
||||
(): Partial<TaskanaEngineServiceMock> => ({
|
||||
hasRole: jest.fn().mockReturnValue(of()),
|
||||
isHistoryProviderEnabled: jest.fn().mockReturnValue(of())
|
||||
})
|
||||
);
|
||||
|
||||
describe('SidenavListComponent', () => {
|
||||
let component: SidenavListComponent;
|
||||
let fixture: ComponentFixture<SidenavListComponent>;
|
||||
let debugElement: DebugElement;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [SidenavListComponent],
|
||||
imports: [
|
||||
MatButtonModule,
|
||||
MatSidenavModule,
|
||||
MatCheckboxModule,
|
||||
MatGridListModule,
|
||||
MatListModule,
|
||||
MatIconModule,
|
||||
BrowserModule,
|
||||
RouterModule,
|
||||
RouterTestingModule,
|
||||
HttpClientTestingModule
|
||||
],
|
||||
providers: [
|
||||
{ provide: SidenavService, useClass: SidenavServiceSpy },
|
||||
{ provide: TaskanaEngineService, useClass: TaskanaEngingeServiceSpy }
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SidenavListComponent);
|
||||
debugElement = fixture.debugElement;
|
||||
component = fixture.debugElement.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show all links if user has all permissions', () => {
|
||||
component.administrationAccess = true;
|
||||
component.monitorAccess = true;
|
||||
component.workplaceAccess = true;
|
||||
component.historyAccess = true;
|
||||
fixture.detectChanges();
|
||||
const menuList = debugElement.queryAll(By.css('.list-item'));
|
||||
expect(menuList.length).toBe(7);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should show all links if user has only monitor access', () => {
|
||||
component.administrationAccess = false;
|
||||
component.monitorAccess = true;
|
||||
component.workplaceAccess = false;
|
||||
component.historyAccess = false;
|
||||
fixture.detectChanges();
|
||||
const menuList = debugElement.queryAll(By.css('.list-item'));
|
||||
expect(menuList.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should toggle sidenav when link clicked', () => {
|
||||
component.toggle = true;
|
||||
fixture.detectChanges();
|
||||
const button = debugElement.query(By.css('.list-item__admin-workbaskets')).nativeElement;
|
||||
expect(button).toBeTruthy();
|
||||
button.click();
|
||||
expect(component.toggle).toBe(false);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,45 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { BusinessAdminGuard } from 'app/shared/guards/business-admin.guard';
|
||||
import { MonitorGuard } from 'app/shared/guards/monitor.guard';
|
||||
import { UserGuard } from 'app/shared/guards/user.guard';
|
||||
import { TaskanaEngineService } from '../../services/taskana-engine/taskana-engine.service';
|
||||
import { SidenavService } from '../../services/sidenav/sidenav.service';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-sidenav-list',
|
||||
templateUrl: './sidenav-list.component.html',
|
||||
styleUrls: ['./sidenav-list.component.scss']
|
||||
})
|
||||
export class SidenavListComponent implements OnInit {
|
||||
toggle: boolean = false;
|
||||
|
||||
monitorUrl = 'taskana/monitor';
|
||||
workplaceUrl = 'taskana/workplace';
|
||||
historyUrl = 'taskana/history';
|
||||
accessUrl = 'taskana/administration/access-items-management';
|
||||
classificationUrl = 'taskana/administration/classifications';
|
||||
workbasketsUrl = 'taskana/administration/workbaskets';
|
||||
|
||||
administrationAccess = false;
|
||||
monitorAccess = false;
|
||||
workplaceAccess = false;
|
||||
historyAccess = false;
|
||||
|
||||
admin_url_list: any[];
|
||||
|
||||
constructor(private taskanaEngineService: TaskanaEngineService, private sidenavService: SidenavService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.administrationAccess = this.taskanaEngineService.hasRole(BusinessAdminGuard.roles);
|
||||
this.monitorAccess = this.taskanaEngineService.hasRole(MonitorGuard.roles);
|
||||
this.workplaceAccess = this.taskanaEngineService.hasRole(UserGuard.roles);
|
||||
this.taskanaEngineService.isHistoryProviderEnabled().subscribe((value) => {
|
||||
this.historyAccess = value;
|
||||
});
|
||||
}
|
||||
|
||||
toggleSidenav() {
|
||||
this.toggle = !this.toggle;
|
||||
this.sidenavService.toggleSidenav();
|
||||
}
|
||||
}
|
|
@ -1,16 +1,14 @@
|
|||
<div class="row">
|
||||
<div class="icon">
|
||||
<div class="icon-wrap col-xs-offset-5">
|
||||
<svg-icon class="blue big" src="./assets/icons/user.svg"></svg-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-info white">
|
||||
<span>Logged as: {{userInformation?.userId}}</span>
|
||||
<button type="button" class="btn btn-default white pull-right transparent" (click)="toggleRoles();" aria-expanded="true" aria-controls="roles">
|
||||
<span>Roles</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="white pull-right roles col-xs-12" [@toggleDown]="showRoles">
|
||||
<span><i>{{roles}}</i></span>
|
||||
<div class="icon">
|
||||
<div class="icon__wrap">
|
||||
<svg-icon class="blue big" src="./assets/icons/user.svg"></svg-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-info">
|
||||
<span>Logged as: {{userInformation?.userId}}</span>
|
||||
<button mat-button class="user-info__button" (click)="toggleRoles();" aria-expanded="true" aria-controls="roles">
|
||||
<span>Roles</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="roles" [@toggleDown]="showRoles">
|
||||
<span><i>{{roles}}</i></span>
|
||||
</div>
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
.user-info {
|
||||
margin-top: 85px;
|
||||
color: white;
|
||||
> span {
|
||||
margin: 0 15px 0 15px;
|
||||
font-size: 20px;
|
||||
|
@ -18,13 +19,15 @@
|
|||
|
||||
.icon {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
& > .icon-wrap {
|
||||
position: absolute;
|
||||
|
||||
& > .icon__wrap {
|
||||
border-radius: 50%;
|
||||
border: solid 2px #22a39f;
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
overflow: hidden;
|
||||
left: 35%;
|
||||
//overflow: hidden;
|
||||
background-color: #175263;
|
||||
position: absolute;
|
||||
-webkit-box-shadow: 0px 3px 3px #416b6a;
|
||||
|
@ -36,7 +39,7 @@
|
|||
overflow: hidden;
|
||||
background-color: white;
|
||||
position: absolute;
|
||||
margin: 2px;
|
||||
margin: 7px -0px 0px 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +56,11 @@
|
|||
box-shadow: 0px 3px 3px #416b6a;
|
||||
}
|
||||
|
||||
.user-info_roles {
|
||||
margin-left: 16px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
button.transparent {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
|
@ -68,3 +76,14 @@ button.transparent {
|
|||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-button {
|
||||
border: none;
|
||||
outline: none;
|
||||
left: 28%;
|
||||
}
|
||||
|
||||
.roles {
|
||||
margin-left: 16px;
|
||||
color: white;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { Component, DebugElement } from '@angular/core';
|
||||
import { UserInformationComponent } from './user-information.component';
|
||||
import { BrowserModule, By } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { TaskanaEngineService } from '../../services/taskana-engine/taskana-engine.service';
|
||||
import { TaskanaEngineServiceMock } from '../../services/taskana-engine/taskana-engine.mock.service';
|
||||
import { of } from 'rxjs/internal/observable/of';
|
||||
import { expandDown } from '../../animations/expand.animation';
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { fromEventPattern } from 'rxjs';
|
||||
|
||||
const TaskanaEngingeServiceSpy = jest.fn().mockImplementation(
|
||||
(): Partial<TaskanaEngineServiceMock> => ({
|
||||
hasRole: jest.fn().mockReturnValue(of()),
|
||||
isHistoryProviderEnabled: jest.fn().mockReturnValue(of())
|
||||
})
|
||||
);
|
||||
|
||||
describe('UserInformationComponent', () => {
|
||||
let component: UserInformationComponent;
|
||||
let fixture: ComponentFixture<UserInformationComponent>;
|
||||
let debugElement: DebugElement;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [UserInformationComponent],
|
||||
imports: [BrowserModule, AngularSvgIconModule, HttpClientTestingModule, BrowserAnimationsModule],
|
||||
providers: [{ provide: TaskanaEngineService, useClass: TaskanaEngingeServiceSpy }]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(UserInformationComponent);
|
||||
debugElement = fixture.debugElement;
|
||||
component = fixture.debugElement.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should toggle roles when roles clicked', () => {
|
||||
fixture.detectChanges();
|
||||
expect(component.showRoles).toBe(false);
|
||||
const button = debugElement.query(By.css('.user-info__button')).nativeElement;
|
||||
expect(button).toBeTruthy();
|
||||
button.click();
|
||||
expect(component.showRoles).toBe(true);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,15 @@
|
|||
import { TestBed, inject } from '@angular/core/testing';
|
||||
|
||||
import { SidenavService } from './sidenav.service';
|
||||
|
||||
describe('SidenavService', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [SidenavService]
|
||||
});
|
||||
});
|
||||
|
||||
it('should be created', inject([SidenavService], (service: SidenavService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { MatSidenav } from '@angular/material';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SidenavService {
|
||||
private sidenav: MatSidenav;
|
||||
state: boolean = false;
|
||||
|
||||
public setSidenav(sidenav: MatSidenav) {
|
||||
this.sidenav = sidenav;
|
||||
}
|
||||
|
||||
public toggleSidenav(): void {
|
||||
this.sidenav.toggle();
|
||||
this.state = this.sidenav.opened;
|
||||
}
|
||||
}
|
|
@ -10,8 +10,9 @@
|
|||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<taskana-root></taskana-root>
|
||||
<taskana-root></taskana-root>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
|
@ -5,13 +5,8 @@
|
|||
"baseUrl": "",
|
||||
"types": []
|
||||
},
|
||||
"files": [
|
||||
"main.ts",
|
||||
"polyfills.ts"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.d.ts"
|
||||
],
|
||||
"files": ["main.ts", "polyfills.ts"],
|
||||
"include": ["src/**/*.d.ts"],
|
||||
"angularCompilerOptions": {
|
||||
"enableIvy": false
|
||||
}
|
||||
|
|
|
@ -2,19 +2,10 @@
|
|||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/spec",
|
||||
"types": [
|
||||
"jest",
|
||||
"node"
|
||||
],
|
||||
"types": ["jest", "node"],
|
||||
"esModuleInterop": true,
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"files": [
|
||||
"src/test.ts",
|
||||
"src/polyfills.ts"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
"files": ["src/test.ts", "src/polyfills.ts"],
|
||||
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue