Add sidebar navigation

pull/57/head
HardiReady 2019-02-24 02:08:56 +01:00
parent 430d4ce7da
commit e9ca404f85
12 changed files with 269 additions and 177 deletions

View File

@ -2,10 +2,14 @@
<mat-sidenav-container>
<mat-sidenav-content>
<app-header (sidenavToggle)="sidenav.toggle()"></app-header>
<main>
<div>
<router-outlet></router-outlet>
</mat-sidenav-content>
<mat-sidenav #sidenav role="navigation">
<app-sidenav-list (sidenavClose)="sidenav.close()"></app-sidenav-list>
</mat-sidenav>
</mat-sidenav-container>
<div (click)="sidenav.close()">
<router-outlet></router-outlet>
<div id="left">
<router-outlet name="left"></router-outlet>
</div>
@ -14,12 +18,6 @@
<router-outlet name="right"></router-outlet>
</div>
</div>
</main>
</mat-sidenav-content>
<mat-sidenav #sidenav role="navigation">
<app-sidenav-list (sidenavClose)="sidenav.close()"></app-sidenav-list>
</mat-sidenav>
</mat-sidenav-container>
<div *ngIf="loading" class="load-indicator">
<div class="opt-loader"></div>

View File

@ -1,73 +1,24 @@
@import "style/load-indicator.scss";
mat-sidenav-container, mat-sidenav-content, mat-sidenav {
height: 100%;
height: 100vh;
display: inline;
background: #fdfdfd;
}
mat-sidenav {
top: 50px;
width: 250px;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
li {
display: inline;
}
.content {
padding-left: 15px;
padding-right: 15px;
}
.scrollable-menu {
height: auto;
max-height: 200px;
overflow-x: hidden;
}
#scrollTopBtn {
position: fixed;
bottom: 20px;
right: 30px;
z-index: 99;
background: rgba(16, 16, 16, 0.8);
}
#scrollTopBtn:hover {
&:hover {
background: #101010;
}
.unprocessed {
-webkit-animation-name: color-blink; /* Safari 4.0 - 8.0 */
-webkit-animation-duration: 4s; /* Safari 4.0 - 8.0 */
animation-name: color-blink;
animation-duration: 4s;
animation-iteration-count: infinite;
}
.unprocessed-child {
background-color: orange;
}
/* Safari 4.0 - 8.0 */
@-webkit-keyframes color-blink {
from {
background-color: #222222;
}
to {
background-color: orange;
}
}
@keyframes color-blink {
from {
background-color: #222222;
}
to {
background-color: orange;
}
}

View File

@ -22,7 +22,7 @@ import {HttpClientModule} from '@angular/common/http';
import {SpinnerService} from './services/user-interface/spinner/spinner.service';
import {SettingsService} from './services/settings.service';
import {HttpGateway} from './services/http-gateway';
import {MatListModule, MatSidenavModule, MatToolbarModule} from '@angular/material';
import {MatListModule, MatMenuModule, MatSidenavModule, MatToolbarModule} from '@angular/material';
import {FlexLayoutModule} from '@angular/flex-layout';
@NgModule({
@ -37,6 +37,7 @@ import {FlexLayoutModule} from '@angular/flex-layout';
MatSidenavModule,
MatToolbarModule,
MatListModule,
MatMenuModule,
FlexLayoutModule,
],

View File

@ -29,85 +29,82 @@
<li routerLinkActive="active">
<a routerLink='{{config.statsPath}}' class="link">{{'navigation.top.statistics' | translate}}</a>
</li>
<li *ngIf="loginService.hasPermission(2)"
class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">
<li *ngIf="loginService.hasPermission(2)">
<mat-list-item [matMenuTriggerFor]="menuManagement">
<a matline>
{{'navigation.top.management' | translate}}
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li routerLinkActive="active">
<a routerLink='{{config.manageUserPath}}' class="link">{{'navigation.top.management.users' | translate}}</a>
</mat-list-item>
<mat-menu #menuManagement="matMenu">
<button routerLink='{{config.manageUserPath}}' mat-menu-item>
{{'navigation.top.management.users' | translate}}
</button>
<button routerLink='{{config.manageSquadPath}}' mat-menu-item>
{{'navigation.top.management.squads' | translate}}
</button>
<button routerLink='{{config.manageDecorationPath}}' mat-menu-item>
{{'navigation.top.management.decorations' | translate}}
</button>
<button routerLink='{{config.manageRankPath}}' mat-menu-item>
{{'navigation.top.management.ranks' | translate}}
</button>
</mat-menu>
</li>
<li routerLinkActive="active">
<a routerLink='{{config.manageSquadPath}}'
class="link">{{'navigation.top.management.squads' | translate}}</a>
</li>
<li routerLinkActive="active">
<a routerLink='{{config.manageDecorationPath}}'
class="link">{{'navigation.top.management.decorations' | translate}}</a>
</li>
<li routerLinkActive="active">
<a routerLink='{{config.manageRankPath}}' class="link">{{'navigation.top.management.ranks' | translate}}</a>
</li>
</ul>
</li>
<li *ngIf="loginService.hasPermission(1) && !loginService.hasPermission(2) && loginService.hasSquad()"
class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">
<li *ngIf="loginService.hasPermission(1) && !loginService.hasPermission(2) && loginService.hasSquad()">
<mat-list-item [matMenuTriggerFor]="menuSqlRequest">
<a matline>
{{'navigation.top.request' | translate}}
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>
<a routerLink="{{config.request}}/{{config.sqlDashboardPath}}">{{'navigation.top.request.open' | translate}}</a>
</mat-list-item>
<mat-menu #menuSqlRequest="matMenu">
<button routerLink="{{config.request}}/{{config.sqlDashboardPath}}" mat-menu-item>
{{'navigation.top.request.open' | translate}}
</button>
<button routerLink="{{config.request}}/{{config.requestPromotionPath}}" mat-menu-item>
{{'navigation.top.request.promotion' | translate}}
</button>
<button routerLink="{{config.request}}/{{config.requestAwardPath}}" mat-menu-item>
{{'navigation.top.request.award' | translate}}
</button>
</mat-menu>
</li>
<li>
<a routerLink="{{config.request}}/{{config.requestPromotionPath}}">{{'navigation.top.request.promotion' | translate}}</a>
</li>
<li>
<a routerLink="{{config.request}}/{{config.requestAwardPath}}">{{'navigation.top.request.award' | translate}}</a>
</li>
</ul>
</li>
<li *ngIf="loginService.hasPermission(2) && loginService.hasSquad()" class="dropdown">
<a href="#"
[ngClass]="{'unprocessed': promotionService.hasUnprocessedPromotion || awardingService.hasUnprocessedAwards}"
class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">
<li *ngIf="loginService.hasPermission(2) && loginService.hasSquad()">
<mat-list-item [matMenuTriggerFor]="menuRequests">
<a [ngClass]="{'unprocessed': promotionService.hasUnprocessedPromotion || awardingService.hasUnprocessedAwards}"
matline>
{{'navigation.top.request.manage' | translate}}
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>
<a [ngClass]="{'unprocessed-child': promotionService.hasUnprocessedPromotion}"
routerLink="{{config.request}}/{{config.confirmPromotionPath}}">{{'navigation.top.request.promotion' | translate}}</a>
</li>
<li>
<a [ngClass]="{'unprocessed-child': awardingService.hasUnprocessedAwards}"
routerLink="{{config.request}}/{{config.confirmAwardPath}}">{{'navigation.top.request.award' | translate}}</a>
</li>
</ul>
</mat-list-item>
<mat-menu #menuRequests="matMenu">
<button [ngClass]="{'unprocessed-child': promotionService.hasUnprocessedPromotion}"
routerLink="{{config.request}}/{{config.confirmPromotionPath}}" mat-menu-item>
{{'navigation.top.request.promotion' | translate}}
</button>
<button [ngClass]="{'unprocessed-child': awardingService.hasUnprocessedAwards}"
routerLink="{{config.request}}/{{config.confirmAwardPath}}" mat-menu-item>
{{'navigation.top.request.award' | translate}}
</button>
</mat-menu>
</li>
</ul>
</div>
<div fxFlex fxLayout fxLayoutAlign="end" fxHide.lt-lg>
<ul fxLayout fxLayoutGap="15px" class="navigation-items">
<li *ngIf="loginService.hasPermission(4)"
class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">
<li *ngIf="loginService.hasPermission(4)">
<mat-list-item [matMenuTriggerFor]="menuAdmin">
<a matline>
{{'navigation.top.admin' | translate}}
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li routerLinkActive="active">
<a routerLink='{{config.adminPanelAppUsersPath}}'
class="link">{{'navigation.top.management.users' | translate}}</a>
</li>
</ul>
</mat-list-item>
<mat-menu #menuAdmin="matMenu">
<button routerLink='{{config.adminPanelAppUsersPath}}' mat-menu-item>
{{'navigation.top.management.users' | translate}}
</button>
</mat-menu>
</li>
<li *ngIf="loginService.isLoggedIn()" class="link" style="cursor: pointer">
<a (click)="logout()">{{'navigation.top.logout' | translate}}</a>
@ -115,19 +112,23 @@
<li *ngIf="!loginService.isLoggedIn()" routerLinkActive="active">
<a routerLink='{{config.loginPath}}' class="link">{{'navigation.top.login' | translate}}</a>
</li>
<li class="dropdown" *ngIf="features.localization">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">
<span class="text-uppercase">{{language}}</span>
<li *ngIf="features.localization">
<mat-list-item [matMenuTriggerFor]="menuLanguage">
<a class="text-uppercase" matline>
{{language}}
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li *ngFor="let lang of languages" style="cursor: pointer">
<a (click)="setLanguage(lang)">
<mat-icon svgIcon="flag-{{lang}}"></mat-icon>
</a>
</li>
</ul>
</mat-list-item>
<mat-menu #menuLanguage="matMenu">
<button mat-menu-item (click)="setLanguage(languages[0])">
<mat-icon svgIcon="flag-{{languages[0]}}"></mat-icon>
<span class="text-uppercase">{{languages[0]}}</span>
</button>
<button mat-menu-item (click)="setLanguage(languages[1])">
<mat-icon svgIcon="flag-{{languages[1]}}"></mat-icon>
<span class="text-uppercase">{{languages[1]}}</span>
</button>
</mat-menu>
</li>
</ul>
</div>

View File

@ -3,15 +3,19 @@ li {
line-height: 46px;
}
li > a {
li a {
font-size: 16px;
text-decoration: none;
color: #9d9d9d;
padding: 16px 5px;
}
li mat-list-item {
cursor: pointer;
}
li:hover, li.active {
> a {
a {
color: white;
}
}
@ -55,3 +59,34 @@ mat-toolbar{
margin: auto;
}
}
.unprocessed {
-webkit-animation-name: color-blink; /* Safari 4.0 - 8.0 */
-webkit-animation-duration: 4s; /* Safari 4.0 - 8.0 */
animation-name: color-blink;
animation-duration: 4s;
animation-iteration-count: infinite;
}
.unprocessed-child {
background-color: orange;
}
/* Safari 4.0 - 8.0 */
@-webkit-keyframes color-blink {
from {
background-color: #222222;
}
to {
background-color: orange;
}
}
@keyframes color-blink {
from {
background-color: #222222;
}
to {
background-color: orange;
}
}

View File

@ -1,11 +1,104 @@
<mat-nav-list>
<a mat-list-item routerLink="/home" (click)="onSidenavClose()">
<mat-icon>home</mat-icon> <span class="nav-caption">Home</span>
<a mat-list-item routerLink='{{config.overviewPath}}' (click)="onSidenavClose()">
<span class="nav-caption">{{'navigation.top.overview' | translate}}</span>
</a>
<a mat-list-item routerLink="/owner" (click)="onSidenavClose()">
<mat-icon>assignment_ind</mat-icon> <span class="nav-caption">Owner Actions</span>
<a mat-list-item [routerLink]="[config.publicPath.concat('/').concat(config.rankPath)]"
(click)="onSidenavClose()">
<span class="nav-caption">{{'navigation.top.ranks' | translate}}</span>
</a>
<a mat-list-item routerLink="#" (click)="onSidenavClose()">
<mat-icon>account_balance</mat-icon><span class="nav-caption">Account Actions</span>
<a mat-list-item [routerLink]="[config.publicPath.concat('/').concat(config.decorationPath)]"
(click)="onSidenavClose()">
<span class="nav-caption">{{'navigation.top.decorations' | translate}}</span>
</a>
<a mat-list-item routerLink='{{config.statsPath}}' (click)="onSidenavClose()">
<span class="nav-caption">{{'navigation.top.statistics' | translate}}</span>
</a>
<mat-list-item *ngIf="loginService.hasPermission(2)"
[matMenuTriggerFor]="menuManagement">
<a matline>
<span class="nav-caption">{{'navigation.top.management' | translate}}</span>
<span class="caret"></span>
</a>
</mat-list-item>
<mat-menu #menuManagement="matMenu">
<button routerLink='{{config.manageUserPath}}' mat-menu-item (click)="onSidenavClose()">
{{'navigation.top.management.users' | translate}}
</button>
<button routerLink='{{config.manageSquadPath}}' mat-menu-item (click)="onSidenavClose()">
{{'navigation.top.management.squads' | translate}}
</button>
<button routerLink='{{config.manageDecorationPath}}' mat-menu-item (click)="onSidenavClose()">
{{'navigation.top.management.decorations' | translate}}
</button>
<button routerLink='{{config.manageRankPath}}' mat-menu-item (click)="onSidenavClose()">
{{'navigation.top.management.ranks' | translate}}
</button>
</mat-menu>
<mat-list-item *ngIf="loginService.hasPermission(1) && !loginService.hasPermission(2) && loginService.hasSquad()"
[matMenuTriggerFor]="menuSqlRequest">
<a matline>
<span class="nav-caption">{{'navigation.top.request' | translate}}</span>
<span class="caret"></span>
</a>
</mat-list-item>
<mat-menu #menuSqlRequest="matMenu">
<button routerLink="{{config.request}}/{{config.sqlDashboardPath}}" mat-menu-item (click)="onSidenavClose()">
{{'navigation.top.request.open' | translate}}
</button>
<button routerLink="{{config.request}}/{{config.requestPromotionPath}}" mat-menu-item (click)="onSidenavClose()">
{{'navigation.top.request.promotion' | translate}}
</button>
<button routerLink="{{config.request}}/{{config.requestAwardPath}}" mat-menu-item (click)="onSidenavClose()">
{{'navigation.top.request.award' | translate}}
</button>
</mat-menu>
<mat-list-item *ngIf="loginService.hasPermission(2) && loginService.hasSquad()"
[matMenuTriggerFor]="menuRequests">
<a [ngClass]="{'unprocessed': promotionService.hasUnprocessedPromotion || awardingService.hasUnprocessedAwards}"
matline>
<span class="nav-caption">{{'navigation.top.request.manage' | translate}}</span>
<span class="caret"></span>
</a>
</mat-list-item>
<mat-menu #menuRequests="matMenu">
<button [ngClass]="{'unprocessed-child': promotionService.hasUnprocessedPromotion}"
routerLink="{{config.request}}/{{config.confirmPromotionPath}}" mat-menu-item (click)="onSidenavClose()">
{{'navigation.top.request.promotion' | translate}}
</button>
<button [ngClass]="{'unprocessed-child': awardingService.hasUnprocessedAwards}"
routerLink="{{config.request}}/{{config.confirmAwardPath}}" mat-menu-item (click)="onSidenavClose()">
{{'navigation.top.request.award' | translate}}
</button>
</mat-menu>
<mat-divider style="margin-bottom: 50%;"></mat-divider>
<mat-list-item *ngIf="loginService.hasPermission(4)" [matMenuTriggerFor]="menuAdmin">
<a matline>
<span class="nav-caption">{{'navigation.top.admin' | translate}}</span>
<span class="caret"></span>
</a>
</mat-list-item>
<mat-menu #menuAdmin="matMenu">
<button routerLink='{{config.adminPanelAppUsersPath}}' mat-menu-item (click)="onSidenavClose()">
{{'navigation.top.management.users' | translate}}
</button>
</mat-menu>
<a mat-list-item *ngIf="loginService.isLoggedIn()"
(click)="logout(); onSidenavClose()">
<span class="nav-caption">{{'navigation.top.logout' | translate}}</span>
</a>
<a mat-list-item *ngIf="!loginService.isLoggedIn()"
routerLink='{{config.loginPath}}' (click)="onSidenavClose()">
<span class="nav-caption">{{'navigation.top.login' | translate}}</span>
</a>
<a mat-list-item href="https://www.opt4.net/dashboard">
<span class="nav-caption">{{'navigation.top.board' | translate}}</span>
</a>
</mat-nav-list>

View File

@ -1,4 +1,8 @@
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {RouteConfig} from '../../app.config';
import {LoginService} from '../../services/app-user-service/login-service';
import {PromotionService} from '../../services/army-management/promotion.service';
import {AwardingService} from '../../services/army-management/awarding.service';
@Component({
selector: 'app-sidenav-list',
@ -9,7 +13,12 @@ export class SidenavListComponent implements OnInit {
@Output() sidenavClose = new EventEmitter();
constructor() { }
config = RouteConfig;
constructor(public loginService: LoginService,
private promotionService: PromotionService,
private awardingService: AwardingService) {
}
ngOnInit() {
}

View File

@ -2,3 +2,7 @@
width: 100%;
padding-bottom: 20px;
}
input.form-control {
z-index: 0;
}

View File

@ -47,8 +47,7 @@
[selected]="war._id == selectedWarId">
</cc-war-item>
</div>
</div>
<div class="fill-vertical-border"
[ngClass]="{collapsed: collapsed}">
</div>
</div>

View File

@ -88,9 +88,6 @@
}
.fill-vertical-border {
width: 20%;
top: 0;
z-index: -20;
position: fixed;
border-right: 1px solid #dadada;
height: 100vh;

View File

@ -48,12 +48,16 @@ form {
#left {
max-width: 20%;
min-width: min-content;
min-width: 345px;
margin: 0;
position: static;
float: left;
border-right: thin solid #dadada;
box-shadow: #dadada 1px 1px 6px;
@media all and (max-width: 599px) {
// TODO
}
}
#right {