inserting fixed footer (with @tsiegleauq)

This commit is contained in:
Jochen Saalfeld 2018-09-04 11:35:50 +02:00
parent 1b02b7c692
commit 9f226c75ee
No known key found for this signature in database
GPG Key ID: 8ACD4E8264B67DF4
15 changed files with 369 additions and 134 deletions

View File

@ -2,6 +2,8 @@ import { trigger, animate, transition, style, query, stagger, group } from '@ang
export const pageTransition = trigger('pageTransition', [ export const pageTransition = trigger('pageTransition', [
transition('* => *', [ transition('* => *', [
/** this will avoid the dom-copy-effect */
query(':enter, :leave', style({ position: 'absolute', width: '100%' }), { optional: true }),
/** keep the dom clean - let all items "just" enter */ /** keep the dom clean - let all items "just" enter */
query(':enter mat-card', [style({ opacity: 0 })], { optional: true }), query(':enter mat-card', [style({ opacity: 0 })], { optional: true }),
query(':enter .on-transition-fade', [style({ opacity: 0 })], { optional: true }), query(':enter .on-transition-fade', [style({ opacity: 0 })], { optional: true }),
@ -11,19 +13,63 @@ export const pageTransition = trigger('pageTransition', [
/** parallel vanishing */ /** parallel vanishing */
group([ group([
/** animate fade out for the selected components */ /** animate fade out for the selected components */
query(':leave .on-transition-fade', [style({ opacity: 1 }), animate('0.2s', style({ opacity: 0 }))], { query(
optional: true ':leave .on-transition-fade',
}), [
/** how the material cards are leaving */ style({ opacity: 1 }),
query(':leave mat-card', [style({ opacity: 1 }), animate('0.2s', style({ opacity: 0 }))], { animate(
optional: true '200ms ease-in-out',
}), style({
query(':leave mat-row', [style({ opacity: 1 }), animate('0.2s', style({ opacity: 0 }))], { transform: 'translateY(0%)',
optional: true opacity: 0
}),
query(':leave mat-expansion-panel', [style({ opacity: 1 }), animate('0.2s', style({ opacity: 0 }))], {
optional: true
}) })
)
],
{ optional: true }
),
/** how the material cards are leaving */
query(
':leave mat-card',
[
style({ transform: 'translateY(0%)', opacity: 1 }),
animate(
'200ms ease-in-out',
style({
transform: 'translateY(0%)',
opacity: 0
})
)
],
{ optional: true }
),
query(
':leave mat-row',
[
style({ transform: 'translateY(0%)', opacity: 1 }),
animate(
'200ms ease-in-out',
style({
transform: 'translateY(0%)',
opacity: 0
})
)
],
{ optional: true }
),
query(
':leave mat-expansion-panel',
[
style({ transform: 'translateY(0%)', opacity: 1 }),
animate(
'200ms ease-in-out',
style({
transform: 'translateY(0%)',
opacity: 0
})
)
],
{ optional: true }
)
]), ]),
/** parallel appearing */ /** parallel appearing */

View File

@ -0,0 +1,12 @@
<mat-toolbar color='primary' class="footer">
<mat-toolbar-row>
<button mat-button class="footer-link" [routerLink]="['/legalnotice']">
<span translate>Legal Notice</span>
</button>
<button mat-button class="footer-link" [routerLink]="['/privacypolicy']">
<span translate>Privacy Policy</span>
</button>
<span class="footer-right">© <span translate>Copyright by</span>&#160;<a href='https://openslides.org/'>OpenSlides</a>
</span>
</mat-toolbar-row>
</mat-toolbar>

View File

@ -0,0 +1,11 @@
.footer-link,
.footer-right {
font-size: 12px;
z-index: inherit;
}
.footer-right {
a {
color: white;
}
}

View File

@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FooterComponent } from './footer.component';
describe('FooterComponent', () => {
let component: FooterComponent;
let fixture: ComponentFixture<FooterComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [FooterComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FooterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,29 @@
import { Component, OnInit } from '@angular/core';
/**
* Reusable footer Apps.
*
* ## Examples:
*
* ### Usage of the selector:
*
* ```html
* <os-footer></os-footer>
* ```
*/
@Component({
selector: 'os-footer',
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.scss']
})
export class FooterComponent implements OnInit {
/**
* Empty constructor
*/
public constructor() {}
/**
* empty onInit
*/
public ngOnInit() {}
}

View File

@ -35,6 +35,9 @@ import { TranslateModule } from '@ngx-translate/core';
import { PermsDirective } from './directives/perms.directive'; import { PermsDirective } from './directives/perms.directive';
import { DomChangeDirective } from './directives/dom-change.directive'; import { DomChangeDirective } from './directives/dom-change.directive';
import { HeadBarComponent } from './components/head-bar/head-bar.component'; import { HeadBarComponent } from './components/head-bar/head-bar.component';
import { FooterComponent } from './components/footer/footer.component';
import { RouterModule } from '@angular/router';
library.add(fas); library.add(fas);
@ -70,7 +73,8 @@ library.add(fas);
MatSnackBarModule, MatSnackBarModule,
MatDialogModule, MatDialogModule,
TranslateModule.forChild(), TranslateModule.forChild(),
FontAwesomeModule FontAwesomeModule,
RouterModule
], ],
exports: [ exports: [
FormsModule, FormsModule,
@ -96,8 +100,9 @@ library.add(fas);
TranslateModule, TranslateModule,
PermsDirective, PermsDirective,
DomChangeDirective, DomChangeDirective,
FooterComponent,
HeadBarComponent HeadBarComponent
], ],
declarations: [PermsDirective, DomChangeDirective, HeadBarComponent] declarations: [PermsDirective, DomChangeDirective, HeadBarComponent, FooterComponent]
}) })
export class SharedModule {} export class SharedModule {}

View File

@ -1,8 +1,11 @@
<!-- The actual form --> <!-- The actual form -->
<mat-toolbar class="login-logo-bar" color="primary"> <header>
<mat-toolbar class="login-logo-bar" color="primary">
<img src='/assets/img/openslides-logo-h-dark-transparent.svg' alt='OpenSlides-logo'> <img src='/assets/img/openslides-logo-h-dark-transparent.svg' alt='OpenSlides-logo'>
</mat-toolbar> </mat-toolbar>
<div class="form-wrapper"> </header>
<main>
<div class="form-wrapper">
<mat-spinner *ngIf="inProcess"></mat-spinner> <mat-spinner *ngIf="inProcess"></mat-spinner>
<form [formGroup]="loginForm" class="login-form" (ngSubmit)="formLogin()"> <form [formGroup]="loginForm" class="login-form" (ngSubmit)="formLogin()">
@ -24,8 +27,12 @@
<br> <br>
<!-- TODO: Next to each other...--> <!-- TODO: Next to each other...-->
<button mat-raised-button color="primary" class='login-button' type="submit" translate>Login</button> <button mat-raised-button color="primary" class='login-button' type="submit" translate>Login</button>
<button mat-raised-button *ngIf="areGuestsEnabled()" color="primary" class='login-button' <button mat-raised-button *ngIf="areGuestsEnabled()" color="primary" class='login-button' type="button" (click)="guestLogin()" translate>Login as Guest</button>
type="button" (click)="guestLogin()" translate>Login as Guest</button>
</form> </form>
</div> </div>
</main>
<footer class="page-footer">
<os-footer></os-footer>
</footer>

View File

@ -2,15 +2,21 @@ mat-form-field {
width: 100%; width: 100%;
} }
.login-logo-bar { header {
height: 45% !important; width: 100%;
flex: 1;
mat-toolbar {
min-height: 200px !important;
}
.login-logo-bar {
img { img {
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
width: 90%; width: 90%;
height: 90%;
max-width: 400px; max-width: 400px;
} }
}
} }
.forgot-password-button { .forgot-password-button {
@ -29,7 +35,6 @@ mat-form-field {
.form-wrapper { .form-wrapper {
padding-left: 30px; padding-left: 30px;
padding-right: 30px; padding-right: 30px;
mat-spinner { mat-spinner {
position: absolute; position: absolute;
left: 0; left: 0;
@ -44,3 +49,7 @@ mat-form-field {
margin: 0 auto; margin: 0 auto;
max-width: 400px; max-width: 400px;
} }
footer {
bottom: 0; //black magic to keep the toolbar active here
}

View File

@ -0,0 +1,3 @@
mat-card {
height: 100%;
}

View File

@ -80,26 +80,9 @@
<span translate>Projector</span> <span translate>Projector</span>
</a> </a>
</mat-nav-list> </mat-nav-list>
<footer>
<button mat-button>
<a routerLink='/legalnotice' (click)='toggleSideNav()'>
<span translate>Legal Notice</span>
</a>
</button>
<button mat-button>
<a routerLink='/privacypolicy' (click)='toggleSideNav()'>
<span translate>Privacy Policy</span>
</a>
</button>
<br>
<span align="center">© Copyright by
<a href='https://openslides.org/'>OpenSlides</a>
</span>
</footer>
</mat-sidenav> </mat-sidenav>
<div class="content">
<header>
<!-- the first toolbar row is (still) a global element <!-- the first toolbar row is (still) a global element
the second one shall be handled by the apps --> the second one shall be handled by the apps -->
<mat-toolbar color='primary'> <mat-toolbar color='primary'>
@ -115,9 +98,15 @@
<fa-icon icon='search'></fa-icon> <fa-icon icon='search'></fa-icon>
</button> </button>
</mat-toolbar> </mat-toolbar>
</header>
<!-- continue with <mat-toolbar> in the app--> <div class="relax">
<main [@pageTransition]="o.isActivated ? o.activatedRoute : ''"> <main [@pageTransition]="o.isActivated ? o.activatedRoute : ''">
<router-outlet #o="outlet"></router-outlet> <router-outlet #o="outlet"></router-outlet>
</main> </main>
<footer>
<os-footer></os-footer>
</footer>
</div>
</div>
</mat-sidenav-container> </mat-sidenav-container>

View File

@ -1,12 +1,3 @@
mat-sidenav-container {
height: 100%;
main {
flex: 1;
position: relative;
}
}
.projector-button { .projector-button {
position: fixed; position: fixed;
bottom: 10px; bottom: 10px;
@ -25,14 +16,30 @@ mat-sidenav-container {
box-shadow: 3px 0px 10px 0px rgba(0, 0, 0, 0.2); box-shadow: 3px 0px 10px 0px rgba(0, 0, 0, 0.2);
} }
footer { .content {
position: fixed; min-height: 100%;
bottom: 0; position: relative;
}
span { mat-sidenav-container {
// width: 100%; height: 100vh;
width: 100%;
}
.relax {
position: initial;
padding-bottom: 70px;
}
main {
display: flex;
flex-direction: column;
width: 100%;
position: relative;
z-index: 50;
flex: 1;
> *:not(router-outlet) {
flex: 1;
display: block; display: block;
text-align: center;
margin-bottom: 5px;
} }
} }

View File

@ -1,21 +1,56 @@
{ {
"Agenda": "Tagesordnung", "Agenda": "Tagesordnung",
"Assignments": "Wahlen", "Assignments": "Wahlen",
"Category": "",
"Change Password": "Passwort ändern", "Change Password": "Passwort ändern",
"Content": "",
"Cookies": "",
"Copyright by": "Copyright by",
"Database": "",
"DeleteMotion": "",
"Deleting Files": "",
"Edit Profile": "Profil bearbeiten", "Edit Profile": "Profil bearbeiten",
"English": "Englisch", "English": "Englisch",
"Export As": {
"0": {
"0": {
"0": ""
}
}
},
"FILTER": "",
"Files": "Dateien", "Files": "Dateien",
"French": "Französisch", "French": "Französisch",
"German": "Deutsch", "German": "Deutsch",
"Hello user": "Hallo {{user}}",
"Home": "Startseite", "Home": "Startseite",
"Identifier": "",
"Legal Notice": "Impressum", "Legal Notice": "Impressum",
"Log In": "Anmelden", "Logfiles": "",
"Login": "",
"Login as Guest": "",
"Logout": "Abmelden", "Logout": "Abmelden",
"Meta information": "",
"Motion": "",
"Motions": "Anträge", "Motions": "Anträge",
"OK": "",
"Offline mode: You can use OpenSlides but changes are not saved": {
"0": ""
},
"Origin": "",
"Participants": "Teilnehmer", "Participants": "Teilnehmer",
"Personal note": "",
"Privacy Policy": "Datenschutz", "Privacy Policy": "Datenschutz",
"Project": "",
"Projector": "",
"Reason": "",
"Reset State": "",
"Reset recommendation": "",
"SORT": "",
"Settings": "Einstellungen", "Settings": "Einstellungen",
"Users": "Benutzer", "State": "",
"Welcome to OpenSlides": "Willkommen bei OpenSlides" "Submitters": "",
"Supporters": "",
"The assembly may decide:": "",
"Welcome to OpenSlides": "Willkommen bei OpenSlides",
"by": ""
} }

View File

@ -1,21 +1,56 @@
{ {
"Agenda": "", "Agenda": "",
"Assignments": "", "Assignments": "",
"Category": "",
"Change Password": "", "Change Password": "",
"Content": "",
"Cookies": "",
"Copyright by": "",
"Database": "",
"DeleteMotion": "",
"Deleting Files": "",
"Edit Profile": "", "Edit Profile": "",
"English": "", "English": "",
"Export As": {
"0": {
"0": {
"0": ""
}
}
},
"FILTER": "",
"Files": "", "Files": "",
"French": "", "French": "",
"German": "", "German": "",
"Hello user": "Hello {{user}}",
"Home": "", "Home": "",
"Identifier": "",
"Legal Notice": "", "Legal Notice": "",
"Log In": "", "Logfiles": "",
"Login": "",
"Login as Guest": "",
"Logout": "", "Logout": "",
"Meta information": "",
"Motion": "",
"Motions": "", "Motions": "",
"OK": "",
"Offline mode: You can use OpenSlides but changes are not saved": {
"0": ""
},
"Origin": "",
"Participants": "", "Participants": "",
"Personal note": "",
"Privacy Policy": "", "Privacy Policy": "",
"Project": "",
"Projector": "",
"Reason": "",
"Reset State": "",
"Reset recommendation": "",
"SORT": "",
"Settings": "", "Settings": "",
"Users": "", "State": "",
"Welcome to OpenSlides": "" "Submitters": "",
"Supporters": "",
"The assembly may decide:": "",
"Welcome to OpenSlides": "",
"by": ""
} }

View File

@ -1,21 +1,56 @@
{ {
"Agenda": "", "Agenda": "",
"Assignments": "", "Assignments": "",
"Category": "",
"Change Password": "", "Change Password": "",
"Content": "",
"Cookies": "",
"Copyright by": "",
"Database": "",
"DeleteMotion": "",
"Deleting Files": "",
"Edit Profile": "", "Edit Profile": "",
"English": "", "English": "",
"Export As": {
"0": {
"0": {
"0": ""
}
}
},
"FILTER": "",
"Files": "", "Files": "",
"French": "", "French": "",
"German": "", "German": "",
"Hello user": "",
"Home": "", "Home": "",
"Identifier": "",
"Legal Notice": "", "Legal Notice": "",
"Log In": "", "Logfiles": "",
"Login": "",
"Login as Guest": "",
"Logout": "", "Logout": "",
"Meta information": "",
"Motion": "",
"Motions": "", "Motions": "",
"OK": "",
"Offline mode: You can use OpenSlides but changes are not saved": {
"0": ""
},
"Origin": "",
"Participants": "", "Participants": "",
"Personal note": "",
"Privacy Policy": "", "Privacy Policy": "",
"Project": "",
"Projector": "",
"Reason": "",
"Reset State": "",
"Reset recommendation": "",
"SORT": "",
"Settings": "", "Settings": "",
"Users": "", "State": "",
"Welcome to OpenSlides": "" "Submitters": "",
"Supporters": "",
"The assembly may decide:": "",
"Welcome to OpenSlides": "",
"by": ""
} }

View File

@ -1,11 +1,9 @@
@import '~@angular/material/theming'; @import '~@angular/material/theming';
@include mat-core(); @include mat-core();
/** Import brand theme and (new) component themes */ /** Import brand theme and (new) component themes */
@import './assets/styles/openslides-theme'; @import './assets/styles/openslides-theme';
@import './app/site/site.component.scss-theme'; @import './app/site/site.component.scss-theme';
@mixin openslides-components-theme($theme) { @mixin openslides-components-theme($theme) {
@include os-site-theme($theme); @include os-site-theme($theme);
/** More components are added here */ /** More components are added here */
@ -13,35 +11,16 @@
@include angular-material-theme($openslides-theme); @include angular-material-theme($openslides-theme);
@include openslides-components-theme($openslides-theme); @include openslides-components-theme($openslides-theme);
* { * {
font-family: Arial, Helvetica, sans-serif !important; font-family: Arial, Helvetica, sans-serif !important;
} }
html,
body {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
padding: 0;
height: 100% !important;
}
body { body {
// background: #e8eaed; // background: #e8eaed;
margin: 0 auto; margin: 0 auto;
padding: 0; padding: 0;
} }
router-outlet ~ * {
position: absolute;
height: 100% !important;
width: 100%;
}
/**the plus button in Motion, Agenda, etc*/ /**the plus button in Motion, Agenda, etc*/
.generic-plus-button { .generic-plus-button {
bottom: -30px; bottom: -30px;
@ -52,6 +31,7 @@ router-outlet ~ * {
bottom: -28px; bottom: -28px;
z-index: 100; z-index: 100;
} }
.os-card { .os-card {
max-width: 90%; max-width: 90%;
margin-top: 10px; margin-top: 10px;
@ -83,3 +63,11 @@ router-outlet ~ * {
.on-transition-fade { .on-transition-fade {
z-index: 100; z-index: 100;
} }
footer {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
z-index: 1;
}