From f8cfb418f66ae2858dc1d036cad4d779a3830e77 Mon Sep 17 00:00:00 2001 From: Jochen Saalfeld Date: Wed, 16 Jan 2019 15:54:34 +0100 Subject: [PATCH] adding and implementing logo component --- .../components/logo/logo.component.html | 3 + .../components/logo/logo.component.scss | 10 ++ .../components/logo/logo.component.spec.ts | 25 +++ .../shared/components/logo/logo.component.ts | 155 ++++++++++++++++++ client/src/app/shared/shared.module.ts | 7 +- .../services/media-manage.service.ts | 12 ++ client/src/app/site/site.component.html | 15 +- client/src/app/site/site.component.scss | 36 ++-- 8 files changed, 248 insertions(+), 15 deletions(-) create mode 100644 client/src/app/shared/components/logo/logo.component.html create mode 100644 client/src/app/shared/components/logo/logo.component.scss create mode 100644 client/src/app/shared/components/logo/logo.component.spec.ts create mode 100644 client/src/app/shared/components/logo/logo.component.ts diff --git a/client/src/app/shared/components/logo/logo.component.html b/client/src/app/shared/components/logo/logo.component.html new file mode 100644 index 000000000..cfdf83f4d --- /dev/null +++ b/client/src/app/shared/components/logo/logo.component.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/client/src/app/shared/components/logo/logo.component.scss b/client/src/app/shared/components/logo/logo.component.scss new file mode 100644 index 000000000..5d3fec5f5 --- /dev/null +++ b/client/src/app/shared/components/logo/logo.component.scss @@ -0,0 +1,10 @@ +img { + max-width: 100%; + height: auto; + max-height: 100%; +} + +.logo-container { + width: 100%; + text-align: center; +} diff --git a/client/src/app/shared/components/logo/logo.component.spec.ts b/client/src/app/shared/components/logo/logo.component.spec.ts new file mode 100644 index 000000000..acb109ee0 --- /dev/null +++ b/client/src/app/shared/components/logo/logo.component.spec.ts @@ -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; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [E2EImportsModule] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(LogoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/shared/components/logo/logo.component.ts b/client/src/app/shared/components/logo/logo.component.ts new file mode 100644 index 000000000..92285586d --- /dev/null +++ b/client/src/app/shared/components/logo/logo.component.ts @@ -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 + * + * + * ``` + * + * 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; + 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; + } + } +} diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index f22025705..71c17ac88 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -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 { 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 { LogoComponent } from './components/logo/logo.component'; /** * Share Module for all "dumb" components and pipes. @@ -171,7 +172,8 @@ import { FilterMenuComponent } from './components/os-sort-filter-bar/filter-menu EditorModule, SortingTreeComponent, TreeModule, - OsSortFilterBarComponent + OsSortFilterBarComponent, + LogoComponent ], declarations: [ PermsDirective, @@ -188,7 +190,8 @@ import { FilterMenuComponent } from './components/os-sort-filter-bar/filter-menu ChoiceDialogComponent, OsSortFilterBarComponent, OsSortBottomSheetComponent, - FilterMenuComponent + FilterMenuComponent, + LogoComponent ], providers: [ { provide: DateAdapter, useClass: OpenSlidesDateAdapter }, diff --git a/client/src/app/site/mediafiles/services/media-manage.service.ts b/client/src/app/site/mediafiles/services/media-manage.service.ts index 7072db41e..cd5cad3ff 100644 --- a/client/src/app/site/mediafiles/services/media-manage.service.ts +++ b/client/src/app/site/mediafiles/services/media-manage.service.ts @@ -79,6 +79,18 @@ export class MediaManageService { return this.httpService.put(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 (object).path !== undefined; + } + } + /** * Get all actions that can be executed on images * diff --git a/client/src/app/site/site.component.html b/client/src/app/site/site.component.html index 956dda489..46f051577 100644 --- a/client/src/app/site/site.component.html +++ b/client/src/app/site/site.component.html @@ -10,10 +10,14 @@ disableClose="!vp.isMobile" class="side-panel" > - + @@ -118,6 +122,11 @@ > © Copyright by OpenSlides + diff --git a/client/src/app/site/site.component.scss b/client/src/app/site/site.component.scss index 65b678f39..e73b3b2fc 100644 --- a/client/src/app/site/site.component.scss +++ b/client/src/app/site/site.component.scss @@ -32,19 +32,35 @@ mat-sidenav-container { } } -/* Logo container */ -.os-logo-container { - width: 200px; - margin-left: 10px; - background-image: url(/assets/img/openslides-logo-h.svg); - background-size: contain; - background-repeat: no-repeat; - background-position: center; - cursor: pointer; +.nav-toolbar { + display: flex; + margin: auto; + width: 250px; + height: 80px; + align-items: center; } +/* 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: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; outline: none; }