Merge pull request #3994 from tsiegleauq/corner-button
Enhanced head bar no 3
This commit is contained in:
commit
321bdeaa46
13205
client/package-lock.json
generated
13205
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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="!nav && !editMode" (click)="onBackButton()">
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</button>
|
||||
|
||||
<!-- Exit / Back button -->
|
||||
<button mat-icon-button class="on-transition-fade" *ngIf="backButton && !editMode" (click)="onBackButton()">
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</button>
|
||||
<!-- Cancel edit button -->
|
||||
<button mat-icon-button class="on-transition-fade" *ngIf="editMode" (click)="sendMainEvent()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
|
||||
<!-- Cancel edit button -->
|
||||
<button mat-icon-button class="on-transition-fade" *ngIf="editMode" (click)="toggleEditMode()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
|
||||
<div class="toolbar-left-text">
|
||||
<!-- Title slot -->
|
||||
<ng-content select=".title-slot"></ng-content>
|
||||
</div>
|
||||
<div class="toolbar-left-text on-transition-fade">
|
||||
<!-- Title slot -->
|
||||
<ng-content select=".title-slot"></ng-content>
|
||||
</div>
|
||||
<div class="toolbar-right on-transition-fade" [ngClass]="{'toolbar-right-scroll': stickyToolbar, 'toolbar-right-top': !stickyToolbar}">
|
||||
</div>
|
||||
<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>
|
||||
|
||||
<!-- 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>
|
||||
<!-- Extra controls slot -->
|
||||
<div class="extra-controls-wrapper on-transition-fade">
|
||||
<ng-content select=".extra-controls-slot"></ng-content>
|
||||
</div>
|
||||
|
||||
</mat-toolbar-row>
|
||||
<!-- 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>
|
||||
|
||||
<!-- Menu button slot -->
|
||||
<ng-content class="on-transition-fade" *ngIf="!editMode" select=".menu-slot"></ng-content>
|
||||
</div>
|
||||
</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>
|
||||
|
@ -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 {
|
||||
|
@ -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,20 +114,11 @@ 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);
|
||||
}
|
||||
this.saveEvent.next(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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 -->
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
@ -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">
|
||||
|
@ -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 -->
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user