adding and implementing logo component

This commit is contained in:
Jochen Saalfeld 2019-01-16 15:54:34 +01:00
parent 460b3dcac9
commit f8cfb418f6
No known key found for this signature in database
GPG Key ID: 8ACD4E8264B67DF4
8 changed files with 248 additions and 15 deletions

View File

@ -0,0 +1,3 @@
<div *ngIf="getImage() != ''" class="logo-container">
<img [src]="getImage()">
</div>

View File

@ -0,0 +1,10 @@
img {
max-width: 100%;
height: auto;
max-height: 100%;
}
.logo-container {
width: 100%;
text-align: center;
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { E2EImportsModule } from 'e2e-imports.module';
import { LogoComponent } from './logo.component';
describe('LogoComponent', () => {
let component: LogoComponent;
let fixture: ComponentFixture<LogoComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [E2EImportsModule]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LogoComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,155 @@
import { Component, OnInit, Input } from '@angular/core';
import { MediaManageService } from '../../../site/mediafiles/services/media-manage.service';
/**
* Reusable Logo component for Apps.
*
* Following actions are possible:
* * "logo_projector_main"
* * "logo_projector_header"
* * "logo_web_header"
* * "logo_pdf_header_L"
* * "logo_pdf_header_R"
* * "logo_pdf_footer_L"
* * "logo_pdf_footer_R"
* * "logo_pdf_ballot_paper"
*
* ## Examples:
*
* ### Usage of the selector:
*
* ```html
* <os-logo
* inputAction="logo_projector_main"
* [footer]="false"
* [alignment]="right">
* </os-logo>
* ```
*
* Sidenote: The footer variable is optional. Only if you want
* alternating logos, i.E. in the sidenav. the Alignment is also
* optional.
*/
@Component({
selector: 'os-logo',
templateUrl: './logo.component.html',
styleUrls: ['./logo.component.scss']
})
export class LogoComponent implements OnInit {
/**
* Constant path of the dark logo
*/
public static STANDARD_LOGO = '/assets/img/openslides-logo-h.svg';
/**
* Holds the actions for logos. Updated via an observable
*/
public logoActions: string[];
/**
* decides based on the actionString how to display the logo
*/
@Input()
public inputAction: string;
/**
* determines if the current picture is displayed in the footer.
* Optional.
*/
@Input()
public footer = false;
/**
* influences text-alignment in the .logo-container css class
*/
@Input()
public alignment = 'center';
/**
* The consotructor
*
* @param mmservice The Media Manage Service
*/
public constructor(private mmservice: MediaManageService) {}
/**
* Initialization function
*/
public ngOnInit(): void {
this.mmservice.getLogoActions().subscribe(action => {
this.logoActions = action;
});
}
/**
* gets the image based on the inputAction and location.
* Possible inputActions are in the class description.
*
* @returns path to image
*/
public getImage(): string {
if (this.footer) {
const path = this.getFooterImage(this.inputAction);
return path;
} else {
const path = this.getHeaderImage(this.inputAction, this.alignment);
return path;
}
}
/**
* gets the header image based on logo action
*
* @param logoAction the logo action to be used
* @param alignment the alignment of the logo (optional)
* @returns path to image
*/
protected getHeaderImage(logoAction: string, alignment: string = 'center'): string {
if (alignment !== 'center') {
this.setAlignment(alignment);
}
let path = '';
/* check if datastore is loaded and custom logo can be read */
if (this.logoActions === undefined) {
return '';
}
if (this.mmservice !== undefined) {
if (this.mmservice.isImageConfigObject(this.mmservice.getMediaConfig(logoAction))) {
const imageConfig = this.mmservice.getMediaConfig(logoAction);
path = imageConfig.path;
}
}
if (path === '') {
path = LogoComponent.STANDARD_LOGO;
}
return path;
}
/**
* Changes the alignment from center to either 'left' or 'right'
*
* @param alignment either 'right' or 'left'
*/
private setAlignment(alignment: string): void {
if (alignment === 'left' || alignment === 'right') {
const cssLogoContainer = document.getElementsByClassName('logo-container') as HTMLCollectionOf<HTMLElement>;
if (cssLogoContainer.length !== 0) {
cssLogoContainer[0].style.textAlign = alignment;
}
}
}
/**
* Returns the image-path for the footer
*
* @param logoAction the logo action to be used
* @returns '' if no logo is set and path to standard logo if a custom
* logo was set
*/
protected getFooterImage(logoAction: string): string {
if (this.getHeaderImage(logoAction) === LogoComponent.STANDARD_LOGO || this.getHeaderImage(logoAction) === '') {
return '';
} else {
return LogoComponent.STANDARD_LOGO;
}
}
}

View File

@ -70,6 +70,7 @@ import { ChoiceDialogComponent } from './components/choice-dialog/choice-dialog.
import { OsSortFilterBarComponent } from './components/os-sort-filter-bar/os-sort-filter-bar.component'; import { OsSortFilterBarComponent } from './components/os-sort-filter-bar/os-sort-filter-bar.component';
import { OsSortBottomSheetComponent } from './components/os-sort-filter-bar/os-sort-bottom-sheet/os-sort-bottom-sheet.component'; import { OsSortBottomSheetComponent } from './components/os-sort-filter-bar/os-sort-bottom-sheet/os-sort-bottom-sheet.component';
import { FilterMenuComponent } from './components/os-sort-filter-bar/filter-menu/filter-menu.component'; import { FilterMenuComponent } from './components/os-sort-filter-bar/filter-menu/filter-menu.component';
import { LogoComponent } from './components/logo/logo.component';
/** /**
* Share Module for all "dumb" components and pipes. * Share Module for all "dumb" components and pipes.
@ -171,7 +172,8 @@ import { FilterMenuComponent } from './components/os-sort-filter-bar/filter-menu
EditorModule, EditorModule,
SortingTreeComponent, SortingTreeComponent,
TreeModule, TreeModule,
OsSortFilterBarComponent OsSortFilterBarComponent,
LogoComponent
], ],
declarations: [ declarations: [
PermsDirective, PermsDirective,
@ -188,7 +190,8 @@ import { FilterMenuComponent } from './components/os-sort-filter-bar/filter-menu
ChoiceDialogComponent, ChoiceDialogComponent,
OsSortFilterBarComponent, OsSortFilterBarComponent,
OsSortBottomSheetComponent, OsSortBottomSheetComponent,
FilterMenuComponent FilterMenuComponent,
LogoComponent
], ],
providers: [ providers: [
{ provide: DateAdapter, useClass: OpenSlidesDateAdapter }, { provide: DateAdapter, useClass: OpenSlidesDateAdapter },

View File

@ -79,6 +79,18 @@ export class MediaManageService {
return this.httpService.put<void>(restPath, payload); return this.httpService.put<void>(restPath, payload);
} }
/**
* Checks if an image is an imageConfig Object
*
* @param object instance of something to check
* @returns boolean if an object is a ImageConfigObject
*/
public isImageConfigObject(object: any): object is ImageConfigObject {
if (object !== undefined) {
return (<ImageConfigObject>object).path !== undefined;
}
}
/** /**
* Get all actions that can be executed on images * Get all actions that can be executed on images
* *

View File

@ -10,10 +10,14 @@
disableClose="!vp.isMobile" disableClose="!vp.isMobile"
class="side-panel" class="side-panel"
> >
<mat-toolbar class="nav-toolbar"> <div class="nav-toolbar">
<!-- logo --> <!-- logo -->
<mat-toolbar-row class="os-logo-container" routerLink="/" (click)="toggleSideNav()"></mat-toolbar-row> <a routerLink="/" (click)="toggleSideNav()">
</mat-toolbar> <os-logo class="os-logo-container"
inputAction="logo_web_header"
[footer]="false"></os-logo>
</a>
</div>
<!-- User Menu --> <!-- User Menu -->
<mat-expansion-panel class="user-menu mat-elevation-z0"> <mat-expansion-panel class="user-menu mat-elevation-z0">
@ -118,6 +122,11 @@
> >
<span><small>© Copyright by OpenSlides</small></span> <span><small>© Copyright by OpenSlides</small></span>
</a> </a>
<div class="os-footer-logo-container">
<os-logo inputAction="logo_web_header"
footer="true">
</os-logo>
</div>
</mat-nav-list> </mat-nav-list>
</mat-sidenav> </mat-sidenav>
<mat-sidenav-content> <mat-sidenav-content>

View File

@ -32,19 +32,35 @@ mat-sidenav-container {
} }
} }
/* Logo container */ .nav-toolbar {
.os-logo-container { display: flex;
width: 200px; margin: auto;
margin-left: 10px; width: 250px;
background-image: url(/assets/img/openslides-logo-h.svg); height: 80px;
background-size: contain; align-items: center;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
} }
/* The top logo container can contain any logo with any size.
It needs to always fit.*/
.os-logo-container {
margin: auto;
width: 250px !important;
max-height: 80px;
display: flex;
}
/* The footer container only appears when custom logo is
specified. It can only contain the standard logo */
.os-footer-logo-container {
width: 150px;
margin-left: 10px;
}
.os-logo-container:focus, .os-logo-container:focus,
.os-logo-container:active, .os-logo-container:active,
.os-logo-container:hover { .os-logo-container:hover,
.os-footer-logo-container:focus,
.os-footer-logo-container:active,
.os-footer-logo-container:hover {
border: none; border: none;
outline: none; outline: none;
} }