Enhanced head bar no 3

This commit is contained in:
Sean Engelhardt 2018-11-06 15:35:51 +01:00
parent 3fde4dc81f
commit 41f2adbc33
18 changed files with 118 additions and 13419 deletions

13205
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
import { BehaviorSubject } from 'rxjs';
/**
* Viewport Service
@ -8,16 +9,15 @@ import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/l
*
* ## Example:
*
* Provide the service via constructor and just use it like
* Provide the service via constructor and just use it like this this
*
* ```html
* <div *ngIf="!vp.isMobile">Will only be shown of not mobile</div>
* ```
* or
* ```ts
* if (this.vp.isMobile) {
* ...
* }
* this.vp.isMobileSubject.subscribe(mobile => (this.isMobile = mobile));
*
* ```
*/
@Injectable({
@ -25,9 +25,15 @@ import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/l
})
export class ViewportService {
/**
* True if Viewport equals mobile or small resolution.
* Simple boolean to determine whether the client is in mobile view or not
* Use in HTML with automatic change detection
*/
private _isMobile = false;
public isMobile: boolean;
/**
* Returns a subject that contains whether the viewport os mobile or not
*/
public isMobileSubject = new BehaviorSubject<boolean>(false);
/**
* Get the BreakpointObserver
@ -45,14 +51,12 @@ export class ViewportService {
.observe([Breakpoints.Small, Breakpoints.HandsetPortrait])
.subscribe((state: BreakpointState) => {
if (state.matches) {
this._isMobile = true;
this.isMobile = true;
this.isMobileSubject.next(true);
} else {
this._isMobile = false;
this.isMobile = false;
this.isMobileSubject.next(false);
}
});
}
public get isMobile(): boolean {
return this._isMobile;
}
}

View File

@ -1,58 +1,51 @@
<mat-toolbar color='primary' [ngClass]="{'during-scroll': stickyToolbar}">
<mat-toolbar-row [ngClass]="{'hidden-bar': stickyToolbar}">
<mat-toolbar color='primary' *ngIf="!vp.isMobile"></mat-toolbar>
<mat-toolbar color='primary' class="sticky-toolbar">
<div class="toolbar-left">
<!-- Nav menu -->
<button mat-icon-button *ngIf="vp.isMobile && nav" (click)='clickHamburgerMenu()'>
<button mat-icon-button class="on-transition-fade" *ngIf="vp.isMobile && nav" (click)='clickHamburgerMenu()'>
<mat-icon>menu</mat-icon>
</button>
</mat-toolbar-row>
<mat-toolbar-row [ngClass]="{'during-scroll': stickyToolbar}">
<div class="toolbar-left on-transition-fade">
<!-- Fab Button "Plus" -->
<button mat-fab class="head-button" *ngIf="plusButton && !editMode" (click)=clickPlusButton()>
<mat-icon>add</mat-icon>
</button>
<!-- Exit / Back button -->
<button mat-icon-button class="on-transition-fade" *ngIf="backButton && !editMode" (click)="onBackButton()">
<button mat-icon-button class="on-transition-fade" *ngIf="!nav && !editMode" (click)="onBackButton()">
<mat-icon>arrow_back</mat-icon>
</button>
<!-- Cancel edit button -->
<button mat-icon-button class="on-transition-fade" *ngIf="editMode" (click)="toggleEditMode()">
<button mat-icon-button class="on-transition-fade" *ngIf="editMode" (click)="sendMainEvent()">
<mat-icon>close</mat-icon>
</button>
<div class="toolbar-left-text">
<div class="toolbar-left-text on-transition-fade">
<!-- Title slot -->
<ng-content select=".title-slot"></ng-content>
</div>
</div>
<div class="toolbar-right on-transition-fade" [ngClass]="{'toolbar-right-scroll': stickyToolbar, 'toolbar-right-top': !stickyToolbar}">
<div class=spacer></div>
<div class="toolbar-right">
<!-- Extra controls slot -->
<div class="extra-controls-wrapper on-transition-fade">
<ng-content select=".extra-controls-slot"></ng-content>
</div>
<!-- Main action button - desktop -->
<button mat-mini-fab color="accent" class="on-transition-fade" *ngIf="mainButton && !editMode && !vp.isMobile"
(click)="sendMainEvent()">
<mat-icon>{{ buttonIcon }}</mat-icon>
</button>
<!-- Save button -->
<button mat-button *ngIf="editMode" (click)="save()">
<strong translate class="upper">Save</strong>
</button>
<!-- Edit button-->
<button mat-icon-button *ngIf="!editMode && allowEdit" (click)="toggleEditMode()">
<mat-icon>{{ editIcon }}</mat-icon>
</button>
<!-- Menu button slot -->
<ng-content *ngIf="!editMode" select=".menu-slot"></ng-content>
<ng-content class="on-transition-fade" *ngIf="!editMode" select=".menu-slot"></ng-content>
</div>
</mat-toolbar-row>
</mat-toolbar>
<!-- fake mat-toolbar to keep the distance when the real one gets a fixed position -->
<div class="fake-bar" [ngClass]="{'hidden-bar': !stickyToolbar}"></div>
<!-- Main action button - mobile-->
<button mat-fab class="head-button on-transition-fade" *ngIf="mainButton && !editMode && vp.isMobile" (click)=sendMainEvent()>
<mat-icon>{{ buttonIcon }}</mat-icon>
</button>

View File

@ -1,46 +1,26 @@
.during-scroll {
.head-button {
position: fixed;
z-index: 1;
right: 25px;
bottom: 25px;
}
.sticky-toolbar {
position: -webkit-sticky;
position: sticky;
top: 0px;
z-index: 2;
}
.toolbar-left {
position: absolute;
display: inherit;
.head-button {
bottom: -30px;
}
display: contents;
.toolbar-left-text {
margin: auto 0 5px 20px;
display: initial;
margin-left: 10px;
}
}
.toolbar-right {
display: inherit;
}
.toolbar-right-scroll {
position: fixed;
right: 30px; // fixed and absolute somehow have different ideas of distance
}
.toolbar-right-top {
position: absolute;
right: 15px;
}
// to hide the first mat-toolbar-row while scrolling and the fake-bar while on top
.hidden-bar {
display: none;
position: inline;
}
// fake bar to simulate the size of the other one, show it when the position changes to fixed
.fake-bar {
width: 100%;
height: 120px; // height of two normal mat-toolbars
z-index: -1;
display: contents;
}
.extra-controls-wrapper {

View File

@ -1,8 +1,6 @@
import { Component, Input, Output, EventEmitter, OnInit, NgZone } from '@angular/core';
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Location } from '@angular/common';
import { Router, ActivatedRoute } from '@angular/router';
import { ScrollDispatcher, CdkScrollable } from '@angular/cdk/scrolling';
import { map } from 'rxjs/operators';
import { ViewportService } from '../../../core/services/viewport.service';
import { MainMenuService } from '../../../core/services/main-menu.service';
@ -21,10 +19,24 @@ import { MainMenuService } from '../../../core/services/main-menu.service';
*
* ```html
* <os-head-bar
* appName="Files"
* plusButton=true
* (plusButtonClicked)=onPlusButton()
* (ellipsisMenuItem)=onEllipsisItem($event)>
* [nav]="false"
* [mainButton]="opCanEdit()"
* [buttonIcon]="edit"
* [editMode]="editMotion"
* (mainEvent)="setEditMode(!editMotion)"
* (saveEvent)="saveMotion()">
*
* <!-- Title -->
* <div class="title-slot">
* My Component Title
* </div>
*
* <!-- Menu -->
* <div class="menu-slot">
* <button type="button" mat-icon-button [matMenuTriggerFor]="myComponentMenu">
* <mat-icon>more_vert</mat-icon>
* </button>
* </div>
* </os-head-bar>
* ```
*/
@ -33,12 +45,7 @@ import { MainMenuService } from '../../../core/services/main-menu.service';
templateUrl: './head-bar.component.html',
styleUrls: ['./head-bar.component.scss']
})
export class HeadBarComponent implements OnInit {
/**
* determine weather the toolbar should be sticky or not
*/
public stickyToolbar = false;
export class HeadBarComponent {
/**
* Determine if the the navigation "hamburger" icon should be displayed in mobile mode
*/
@ -46,16 +53,10 @@ export class HeadBarComponent implements OnInit {
public nav = true;
/**
* Show or hide edit features
* Custom icon if necessary
*/
@Input()
public allowEdit = false;
/**
* Custom edit icon if necessary
*/
@Input()
public editIcon = 'edit';
public buttonIcon = 'add';
/**
* Determine edit mode
@ -64,16 +65,10 @@ export class HeadBarComponent implements OnInit {
public editMode = false;
/**
* Determine if there should be a plus button.
* Determine if there should be the main action button
*/
@Input()
public plusButton = false;
/**
* Determine if there should be a back button.
*/
@Input()
public backButton = false;
public mainButton = false;
/**
* Set to true if the component should use location.back instead
@ -83,16 +78,10 @@ export class HeadBarComponent implements OnInit {
public goBack = false;
/**
* Emit a signal to the parent component if the plus button was clicked
* Emit a signal to the parent component if the main button was clicked
*/
@Output()
public plusButtonClicked = new EventEmitter<boolean>();
/**
* Sends a signal if a detail view should be edited or editing should be canceled
*/
@Output()
public editEvent = new EventEmitter<boolean>();
public mainEvent = new EventEmitter<void>();
/**
* Sends a signal if a detail view should be saved
@ -105,8 +94,6 @@ export class HeadBarComponent implements OnInit {
*/
public constructor(
public vp: ViewportService,
private scrollDispatcher: ScrollDispatcher,
private ngZone: NgZone,
private menu: MainMenuService,
private router: Router,
private route: ActivatedRoute,
@ -116,8 +103,8 @@ export class HeadBarComponent implements OnInit {
/**
* Emits a signal to the parent if
*/
public clickPlusButton(): void {
this.plusButtonClicked.emit(true);
public sendMainEvent(): void {
this.mainEvent.next();
}
/**
@ -127,21 +114,12 @@ export class HeadBarComponent implements OnInit {
this.menu.toggleMenu();
}
/**
* Toggle edit mode and send a signal to listeners
*/
public toggleEditMode(): void {
this.editEvent.next(!this.editMode);
}
/**
* Send a save signal and set edit mode
*/
public save(): void {
if (this.editMode) {
this.saveEvent.next(true);
}
}
/**
* Exits the view to return to the previous page or
@ -154,36 +132,4 @@ export class HeadBarComponent implements OnInit {
this.router.navigate(['../'], { relativeTo: this.route });
}
}
/**
* Init function. Subscribe to the scrollDispatcher and decide when to set the top bar to fixed
*
* Not working for now.
*/
public ngOnInit(): void {
this.scrollDispatcher
.scrolled()
.pipe(map((event: CdkScrollable) => this.getScrollPosition(event)))
.subscribe(scrollTop => {
this.ngZone.run(() => {
if (scrollTop > 60) {
this.stickyToolbar = true;
} else {
this.stickyToolbar = false;
}
});
});
}
/**
* returns the scroll position
* @param event
*/
public getScrollPosition(event: CdkScrollable): number {
if (event) {
return event.getElementRef().nativeElement.scrollTop;
} else {
return window.scrollY;
}
}
}

View File

@ -1,4 +1,4 @@
<os-head-bar plusButton=true (plusButtonClicked)=onPlusButton()>
<os-head-bar [mainButton]="true" (mainEvent)=onPlusButton()>
<!-- Title -->
<div class="title-slot">
<h2 translate>Agenda</h2>

View File

@ -1,4 +1,4 @@
<os-head-bar [backButton]=true [goBack]=true>
<os-head-bar [nav]=false [goBack]=true>
<div class="title-slot">
<h2 translate>Legal Notice</h2>
</div>

View File

@ -1,4 +1,4 @@
<os-head-bar [backButton]=true [goBack]=true>
<os-head-bar [nav]=false [goBack]=true>
<div class="title-slot">
<h2 translate>Privacy Policy</h2>
</div>

View File

@ -1,17 +1,8 @@
<os-head-bar [nav]="false" [backButton]=true [allowEdit]="false">
<os-head-bar [nav]="false" [mainButton]="true" (mainEvent)="onPlusButton()">
<!-- Title -->
<div class="title-slot">
<h2 translate>Categories</h2>
</div>
<!-- Use the menu slot for an add button -->
<div class="menu-slot">
<button type="button" mat-icon-button (click)="onPlusButton()">
<mat-icon>add</mat-icon>
</button>
</div>
</os-head-bar>
<div class="custom-table-header"></div>

View File

@ -1,8 +1,14 @@
<ng-container *ngIf="vp.isMobile ; then mobileView; else desktopView"></ng-container>
<ng-template #title><ng-content select=".meta-text-block-title"></ng-content></ng-template>
<ng-template #content><ng-content select=".meta-text-block-content"></ng-content></ng-template>
<ng-template #actionRow><ng-content select=".meta-text-block-action-row"></ng-content></ng-template>
<ng-template #title>
<ng-content select=".meta-text-block-title"></ng-content>
</ng-template>
<ng-template #content>
<ng-content select=".meta-text-block-content"></ng-content>
</ng-template>
<ng-template #actionRow>
<ng-content select=".meta-text-block-action-row"></ng-content>
</ng-template>
<ng-template #mobileView>
<mat-expansion-panel>
@ -42,4 +48,3 @@
</mat-card-content>
</mat-card>
</ng-template>

View File

@ -1,17 +1,8 @@
<os-head-bar [nav]="false" [backButton]=true [allowEdit]="false">
<os-head-bar [nav]="false" [mainButton]="true" (mainEvent)="onPlusButton()">
<!-- Title -->
<div class="title-slot">
<h2 translate>Comments</h2>
</div>
<!-- Use the menu slot for an add button -->
<div class="menu-slot">
<button type="button" mat-icon-button (click)="onPlusButton()">
<mat-icon>add</mat-icon>
</button>
</div>
</os-head-bar>
<div class="head-spacer"></div>

View File

@ -1,4 +1,4 @@
<os-head-bar [nav]="false" [backButton]=true [allowEdit]="opCanEdit()" [editMode]="editMotion" (editEvent)="setEditMode($event)"
<os-head-bar [mainButton]="opCanEdit()" buttonIcon="edit" [nav]="false" [editMode]="editMotion" (mainEvent)="setEditMode(!editMotion)"
(saveEvent)="saveMotion()">
<!-- Title -->

View File

@ -1,4 +1,4 @@
<os-head-bar plusButton=true (plusButtonClicked)=onPlusButton()>
<os-head-bar [mainButton]="true" (mainEvent)=onPlusButton()>
<!-- Title -->
<div class="title-slot">
<h2 translate>Motions</h2>

View File

@ -1,4 +1,4 @@
<os-head-bar [nav]="false" [backButton]=true [allowEdit]="false">
<os-head-bar [nav]="false" [mainButton]="true" (mainEvent)="onPlusButton()">
<!-- Title -->
<div class="title-slot">
@ -7,10 +7,6 @@
<!-- Use the menu slot for an add button -->
<div class="menu-slot">
<button type="button" mat-icon-button (click)="onPlusButton()">
<mat-icon>add</mat-icon>
</button>
<button type="button" mat-icon-button [matMenuTriggerFor]="commentMenu">
<mat-icon>more_vert</mat-icon>
</button>

View File

@ -1,5 +1,4 @@
<os-head-bar [nav]="false" [backButton]=true [allowEdit]="true" [editMode]="editTag" editIcon="add" (editEvent)="setEditMode($event)"
(saveEvent)="saveTag()">
<os-head-bar [mainButton]="true" [nav]="true" [editMode]="editTag" (mainEvent)="setEditMode(!editTag)" (saveEvent)="saveTag()">
<!-- Title -->
<div class="title-slot">

View File

@ -1,5 +1,4 @@
<os-head-bar [nav]="false" [backButton]=true [allowEdit]="true" [editMode]="editGroup" editIcon="add" (editEvent)="setEditMode($event)"
(saveEvent)="saveGroup()">
<os-head-bar [mainButton]="true" [nav]="false" [editMode]="editGroup" (mainEvent)="setEditMode(!editGroup)" (saveEvent)="saveGroup()">
<!-- Title -->
<div class="title-slot">

View File

@ -1,4 +1,4 @@
<os-head-bar [nav]="false" [backButton]=true [allowEdit]="isAllowed('manage')" [editMode]="editUser" (editEvent)="setEditMode($event)"
<os-head-bar [mainButton]="isAllowed('manage')" buttonIcon="edit" [nav]="false" [editMode]="editUser" (mainEvent)="setEditMode(!editUser)"
(saveEvent)="saveUser()">
<!-- Title -->

View File

@ -1,4 +1,4 @@
<os-head-bar plusButton=true (plusButtonClicked)=onPlusButton()>
<os-head-bar mainButton=true (mainEvent)=onPlusButton()>
<!-- Title -->
<div class="title-slot">
<h2 translate>Users</h2>