From b3ff250d3845de71075879e13d11e27112eb42e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20B=C3=B6hlke?= Date: Sat, 23 Feb 2019 16:59:01 +0100 Subject: [PATCH 1/5] WIP: show PDF, PNG and JPEG files in projector --- client/package.json | 1 + .../mediafile/mediafile-slide.component.html | 14 +++++++++++--- .../mediafile/mediafile-slide.component.ts | 12 +++++++++--- .../mediafiles/mediafile/mediafile-slide.module.ts | 8 +++++++- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/client/package.json b/client/package.json index ce2b4ffb8..4ba41e54c 100644 --- a/client/package.json +++ b/client/package.json @@ -51,6 +51,7 @@ "ng-pick-datetime": "^7.0.0", "ngx-file-drop": "^6.0.0", "ngx-mat-select-search": "^1.7.2", + "ng2-pdf-viewer": "^5.2.3", "ngx-papaparse": "^3.0.2", "pdfmake": "^0.1.53", "po2json": "^1.0.0-alpha", diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html index 0aeb50f15..c0b7bb4fe 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html @@ -1,5 +1,13 @@
-

{{ data.data.path }}

-

{{ data.data.type }}

-

{{ data.data.media_url_prefix }}

+
+ +
+
+ +
+
+ +
diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts index cab715e8b..e62a48122 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts @@ -1,7 +1,9 @@ -import { Component } from '@angular/core'; +import {Component} from '@angular/core'; +import {computed} from 'mobx-angular'; -import { BaseSlideComponent } from 'app/slides/base-slide-component'; -import { MediafileSlideData } from './mediafile-slide-data'; + +import {BaseSlideComponent} from 'app/slides/base-slide-component'; +import {MediafileSlideData} from './mediafile-slide-data'; @Component({ selector: 'os-mediafile-slide', @@ -12,4 +14,8 @@ export class MediafileSlideComponent extends BaseSlideComponent Date: Wed, 27 Feb 2019 08:43:51 +0100 Subject: [PATCH 2/5] some controls, integrate the pdfviewer --- .../core/core-services/projector.service.ts | 9 ++ .../mediafile-list.component.html | 2 +- .../site/mediafiles/models/view-mediafile.ts | 8 ++ .../presentation-control.component.html | 34 +++++++ .../presentation-control.component.scss | 0 .../presentation-control.component.spec.ts | 26 +++++ .../presentation-control.component.ts | 97 +++++++++++++++++++ .../app/site/projector/projector.module.ts | 7 +- .../mediafile/mediafile-slide.component.html | 14 ++- .../mediafile-slide.component.spec.ts | 3 +- .../mediafile/mediafile-slide.component.ts | 14 +-- .../mediafile/mediafile-slide.module.ts | 17 ++-- 12 files changed, 210 insertions(+), 21 deletions(-) create mode 100644 client/src/app/site/projector/components/presentation-control/presentation-control.component.html create mode 100644 client/src/app/site/projector/components/presentation-control/presentation-control.component.scss create mode 100644 client/src/app/site/projector/components/presentation-control/presentation-control.component.spec.ts create mode 100644 client/src/app/site/projector/components/presentation-control/presentation-control.component.ts diff --git a/client/src/app/core/core-services/projector.service.ts b/client/src/app/core/core-services/projector.service.ts index 1d36ee3a2..4e958b5b0 100644 --- a/client/src/app/core/core-services/projector.service.ts +++ b/client/src/app/core/core-services/projector.service.ts @@ -186,6 +186,15 @@ export class ProjectorService { } } + public async updateElement( + projector: Projector, + obj: Projectable | ProjectorElementBuildDeskriptor | IdentifiableProjectorElement + ): Promise { + const element = this.getProjectorElement(obj); + projector.replaceElements(element); + await this.projectRequest(projector, projector.elements, projector.elements_preview); + } + /** * Executes the request to change projector elements. * diff --git a/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.html b/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.html index 168e6c4be..87659fb3d 100644 --- a/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.html +++ b/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.html @@ -71,7 +71,7 @@ Projector - + diff --git a/client/src/app/site/mediafiles/models/view-mediafile.ts b/client/src/app/site/mediafiles/models/view-mediafile.ts index dbeb91857..bc4cc4fb0 100644 --- a/client/src/app/site/mediafiles/models/view-mediafile.ts +++ b/client/src/app/site/mediafiles/models/view-mediafile.ts @@ -57,6 +57,10 @@ export class ViewMediafile extends BaseViewModelWithListOfSpeakers return this.mediafile.downloadUrl; } + public get pages(): number | null { + return this.mediafile.mediafile.pages; + } + /** * Determines if the file has the 'hidden' attribute * @returns the hidden attribute, also 'hidden' if there is no file @@ -96,6 +100,10 @@ export class ViewMediafile extends BaseViewModelWithListOfSpeakers }; } + public isProjectable(): boolean { + return this.isImage() || this.isPdf(); + } + /** * Determine if the file is an image * diff --git a/client/src/app/site/projector/components/presentation-control/presentation-control.component.html b/client/src/app/site/projector/components/presentation-control/presentation-control.component.html new file mode 100644 index 000000000..93b737280 --- /dev/null +++ b/client/src/app/site/projector/components/presentation-control/presentation-control.component.html @@ -0,0 +1,34 @@ +
Presentation control
+
+ {{ getMediafile(element).getTitle() }} + + + + + + + + + Page {{ getPage(element) }}/{{ getMediafile(element).pages }} + + + + + +
diff --git a/client/src/app/site/projector/components/presentation-control/presentation-control.component.scss b/client/src/app/site/projector/components/presentation-control/presentation-control.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/app/site/projector/components/presentation-control/presentation-control.component.spec.ts b/client/src/app/site/projector/components/presentation-control/presentation-control.component.spec.ts new file mode 100644 index 000000000..b4cce692c --- /dev/null +++ b/client/src/app/site/projector/components/presentation-control/presentation-control.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { E2EImportsModule } from '../../../../../e2e-imports.module'; +import { PresentationControlComponent } from './presentation-control.component'; +import { ProjectorModule } from '../../projector.module'; + +describe('PresentationControlComponent', () => { + let component: PresentationControlComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [E2EImportsModule, ProjectorModule] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(PresentationControlComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts b/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts new file mode 100644 index 000000000..6c7bf4bb7 --- /dev/null +++ b/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts @@ -0,0 +1,97 @@ +import { Component, Input } from '@angular/core'; +import { Title } from '@angular/platform-browser'; +import { MatSnackBar } from '@angular/material'; + +import { TranslateService } from '@ngx-translate/core'; + +import { BaseViewComponent } from 'app/site/base/base-view'; +import { ViewProjector } from '../../models/view-projector'; +import { ProjectorElements, ProjectorElement } from 'app/shared/models/core/projector'; +import { Mediafile } from 'app/shared/models/mediafiles/mediafile'; +import { MediafileRepositoryService } from 'app/core/repositories/mediafiles/mediafile-repository.service'; +import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile'; +import { SlideManager } from 'app/slides/services/slide-manager.service'; +import { ProjectorService } from 'app/core/core-services/projector.service'; + +/** + * The presentation controls. + */ +@Component({ + selector: 'os-presentation-control', + templateUrl: './presentation-control.component.html', + styleUrls: ['./presentation-control.component.scss'] +}) +export class PresentationControlComponent extends BaseViewComponent { + /** + * The projector. + */ + private _projector: ViewProjector; + + @Input() + public set projector(projector: ViewProjector) { + this._projector = projector; + this.updateElements(); + } + + public get projector(): ViewProjector { + return this._projector; + } + + // All mediafile elements. + public elements: ProjectorElements = []; + + public constructor( + titleService: Title, + translate: TranslateService, + matSnackBar: MatSnackBar, + private mediafileRepo: MediafileRepositoryService, + private slideManager: SlideManager, + private projectorService: ProjectorService + ) { + super(titleService, translate, matSnackBar); + } + + private updateElements(): void { + this.elements = this.projector.elements.filter(element => { + if (element.name !== Mediafile.COLLECTIONSTRING && !element.id) { + return false; + } + const mediafile = this.mediafileRepo.getViewModel(element.id); + return !!mediafile && mediafile.isProjectable(); + }); + } + + public getMediafile(element: ProjectorElement): ViewMediafile { + return this.mediafileRepo.getViewModel(element.id); + } + + public getPage(element: ProjectorElement): number { + return element.page || 1; + } + + public pdfForward(element: ProjectorElement): void { + if (this.getPage(element) < this.getMediafile(element).pages) { + this.pdfSetPage(element, this.getPage(element) + 1); + } + } + + public pdfBackward(element: ProjectorElement): void { + if (this.getPage(element) > 1) { + this.pdfSetPage(element, this.getPage(element) - 1); + } + } + + public pdfSetPage(element: ProjectorElement, page: number): void { + const idElement = this.slideManager.getIdentifialbeProjectorElement(element); + idElement.page = page; + this.projectorService.updateElement(this.projector.projector, idElement).then(null, this.raiseError); + } + + public pdfZoom(element: ProjectorElement, direction: 'in' | 'out' | 'reset'): void {} + + public pdfRotate(element: ProjectorElement): void {} + + public imageFullscreen(element: ProjectorElement): void {} + + public imageRotate(element: ProjectorElement): void {} +} diff --git a/client/src/app/site/projector/projector.module.ts b/client/src/app/site/projector/projector.module.ts index 5ce0a9a13..269f274f7 100644 --- a/client/src/app/site/projector/projector.module.ts +++ b/client/src/app/site/projector/projector.module.ts @@ -9,6 +9,7 @@ import { CountdownControlsComponent } from './components/countdown-controls/coun import { CountdownDialogComponent } from './components/countdown-dialog/countdown-dialog.component'; import { MessageControlsComponent } from './components/message-controls/message-controls.component'; import { MessageDialogComponent } from './components/message-dialog/message-dialog.component'; +import { PresentationControlComponent } from './components/presentation-control/presentation-control.component'; import { ProjectorListEntryComponent } from './components/projector-list-entry/projector-list-entry.component'; @NgModule({ @@ -22,6 +23,10 @@ import { ProjectorListEntryComponent } from './components/projector-list-entry/p MessageControlsComponent, MessageDialogComponent ], - entryComponents: [CountdownDialogComponent, MessageDialogComponent] + entryComponents: [ + CountdownDialogComponent, + MessageDialogComponent, + PresentationControlComponent + ] }) export class ProjectorModule {} diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html index c0b7bb4fe..74d3f4245 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html @@ -2,12 +2,16 @@
-
- -
+
+ +
diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.spec.ts b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.spec.ts index 49b245453..3cd1b9998 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.spec.ts +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.spec.ts @@ -2,6 +2,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { MediafileSlideComponent } from './mediafile-slide.component'; import { E2EImportsModule } from '../../../../e2e-imports.module'; +import { PdfViewerModule } from 'ng2-pdf-viewer'; describe('MediafileSlideComponent', () => { let component: MediafileSlideComponent; @@ -9,7 +10,7 @@ describe('MediafileSlideComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - imports: [E2EImportsModule], + imports: [E2EImportsModule, PdfViewerModule], declarations: [MediafileSlideComponent] }).compileComponents(); })); diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts index e62a48122..ec60bcdcb 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts @@ -1,9 +1,7 @@ -import {Component} from '@angular/core'; -import {computed} from 'mobx-angular'; +import { Component } from '@angular/core'; - -import {BaseSlideComponent} from 'app/slides/base-slide-component'; -import {MediafileSlideData} from './mediafile-slide-data'; +import { BaseSlideComponent } from 'app/slides/base-slide-component'; +import { MediafileSlideData } from './mediafile-slide-data'; @Component({ selector: 'os-mediafile-slide', @@ -15,7 +13,11 @@ export class MediafileSlideComponent extends BaseSlideComponent Date: Fri, 26 Apr 2019 13:56:49 +0200 Subject: [PATCH 3/5] fixes --- .../presentation-control.component.ts | 49 ++++++++++++++++--- .../projector-detail.component.html | 9 ++++ .../app/site/projector/projector.module.ts | 16 +++--- .../mediafile/mediafile-slide.module.ts | 2 +- 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts b/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts index 6c7bf4bb7..695892b2a 100644 --- a/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts +++ b/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts @@ -1,17 +1,17 @@ import { Component, Input } from '@angular/core'; -import { Title } from '@angular/platform-browser'; import { MatSnackBar } from '@angular/material'; +import { Title } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; import { BaseViewComponent } from 'app/site/base/base-view'; -import { ViewProjector } from '../../models/view-projector'; -import { ProjectorElements, ProjectorElement } from 'app/shared/models/core/projector'; import { Mediafile } from 'app/shared/models/mediafiles/mediafile'; import { MediafileRepositoryService } from 'app/core/repositories/mediafiles/mediafile-repository.service'; -import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile'; -import { SlideManager } from 'app/slides/services/slide-manager.service'; +import { ProjectorElements, ProjectorElement } from 'app/shared/models/core/projector'; import { ProjectorService } from 'app/core/core-services/projector.service'; +import { SlideManager } from 'app/slides/services/slide-manager.service'; +import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile'; +import { ViewProjector } from '../../models/view-projector'; /** * The presentation controls. @@ -40,6 +40,16 @@ export class PresentationControlComponent extends BaseViewComponent { // All mediafile elements. public elements: ProjectorElements = []; + /** + * Constructor + * + * @param titleService + * @param translate + * @param matSnackBar + * @param mediafileRepo + * @param slideManager + * @param projectorService + */ public constructor( titleService: Title, translate: TranslateService, @@ -51,6 +61,9 @@ export class PresentationControlComponent extends BaseViewComponent { super(titleService, translate, matSnackBar); } + /** + * Updates incoming elements + */ private updateElements(): void { this.elements = this.projector.elements.filter(element => { if (element.name !== Mediafile.COLLECTIONSTRING && !element.id) { @@ -65,26 +78,48 @@ export class PresentationControlComponent extends BaseViewComponent { return this.mediafileRepo.getViewModel(element.id); } + /** + * @returns the currently used page number (1 in case of unnumbered elements) + */ public getPage(element: ProjectorElement): number { return element.page || 1; } + /** + * moves the projected forward by one page (if not already at end) + * + * @param element + */ public pdfForward(element: ProjectorElement): void { if (this.getPage(element) < this.getMediafile(element).pages) { this.pdfSetPage(element, this.getPage(element) + 1); } } + /** + * moves the projected one page backwards (if not already at beginnning) + * + * @param element + */ public pdfBackward(element: ProjectorElement): void { if (this.getPage(element) > 1) { this.pdfSetPage(element, this.getPage(element) - 1); } } + /** + * Moves the element to a specific given page. If the number given is greater + * than the amount of element pages, it does nothing + * + * @param element + * @param page + */ public pdfSetPage(element: ProjectorElement, page: number): void { const idElement = this.slideManager.getIdentifialbeProjectorElement(element); - idElement.page = page; - this.projectorService.updateElement(this.projector.projector, idElement).then(null, this.raiseError); + if (this.getMediafile(element).pages >= page) { + idElement.page = page; + this.projectorService.updateElement(this.projector.projector, idElement).then(null, this.raiseError); + } } public pdfZoom(element: ProjectorElement, direction: 'in' | 'out' | 'reset'): void {} diff --git a/client/src/app/site/projector/components/projector-detail/projector-detail.component.html b/client/src/app/site/projector/components/projector-detail/projector-detail.component.html index 0395f7afd..7b0b2bfc2 100644 --- a/client/src/app/site/projector/components/projector-detail/projector-detail.component.html +++ b/client/src/app/site/projector/components/projector-detail/projector-detail.component.html @@ -262,6 +262,15 @@ + + + + + Media controls + + + + diff --git a/client/src/app/site/projector/projector.module.ts b/client/src/app/site/projector/projector.module.ts index 269f274f7..7490309a7 100644 --- a/client/src/app/site/projector/projector.module.ts +++ b/client/src/app/site/projector/projector.module.ts @@ -1,16 +1,16 @@ -import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; -import { ProjectorRoutingModule } from './projector-routing.module'; -import { SharedModule } from '../../shared/shared.module'; -import { ProjectorListComponent } from './components/projector-list/projector-list.component'; -import { ProjectorDetailComponent } from './components/projector-detail/projector-detail.component'; import { CountdownControlsComponent } from './components/countdown-controls/countdown-controls.component'; import { CountdownDialogComponent } from './components/countdown-dialog/countdown-dialog.component'; import { MessageControlsComponent } from './components/message-controls/message-controls.component'; import { MessageDialogComponent } from './components/message-dialog/message-dialog.component'; import { PresentationControlComponent } from './components/presentation-control/presentation-control.component'; +import { ProjectorDetailComponent } from './components/projector-detail/projector-detail.component'; +import { ProjectorListComponent } from './components/projector-list/projector-list.component'; import { ProjectorListEntryComponent } from './components/projector-list-entry/projector-list-entry.component'; +import { ProjectorRoutingModule } from './projector-routing.module'; +import { SharedModule } from '../../shared/shared.module'; @NgModule({ imports: [CommonModule, ProjectorRoutingModule, SharedModule], @@ -21,12 +21,14 @@ import { ProjectorListEntryComponent } from './components/projector-list-entry/p CountdownControlsComponent, CountdownDialogComponent, MessageControlsComponent, - MessageDialogComponent + MessageDialogComponent, + PresentationControlComponent ], entryComponents: [ CountdownDialogComponent, MessageDialogComponent, - PresentationControlComponent + PresentationControlComponent, + ProjectorListEntryComponent ] }) export class ProjectorModule {} diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.module.ts b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.module.ts index 39d899293..9ad94d5a5 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.module.ts +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.module.ts @@ -4,8 +4,8 @@ import { CommonModule } from '@angular/common'; import { PdfViewerModule } from 'ng2-pdf-viewer'; import { MediafileSlideComponent } from './mediafile-slide.component'; -import { SLIDE } from 'app/slides/slide-token'; import { SharedModule } from 'app/shared/shared.module'; +import { SLIDE } from 'app/slides/slide-token'; @NgModule({ imports: [CommonModule, SharedModule, PdfViewerModule], From 469084a1b6329e012c0b1718118b514653b09abd Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Mon, 29 Apr 2019 13:39:02 +0200 Subject: [PATCH 4/5] Work on the presentation controls --- .../core-services/projector-data.service.ts | 4 +- .../models/mediafile-projector-element.ts | 13 ++++ .../site/mediafiles/models/view-mediafile.ts | 11 ++- .../presentation-control.component.html | 76 ++++++++++--------- .../presentation-control.component.ts | 58 ++++++++++---- .../projector-detail.component.html | 7 +- client/src/app/slides/base-slide-component.ts | 5 +- .../mediafile/mediafile-slide.component.html | 28 +++---- .../mediafile/mediafile-slide.component.scss | 12 +++ .../mediafile/mediafile-slide.component.ts | 28 ++++--- .../slides/services/slide-manager.service.ts | 4 +- 11 files changed, 164 insertions(+), 82 deletions(-) create mode 100644 client/src/app/site/mediafiles/models/mediafile-projector-element.ts diff --git a/client/src/app/core/core-services/projector-data.service.ts b/client/src/app/core/core-services/projector-data.service.ts index 7b3a2358d..9600e20d2 100644 --- a/client/src/app/core/core-services/projector-data.service.ts +++ b/client/src/app/core/core-services/projector-data.service.ts @@ -5,9 +5,9 @@ import { Observable, BehaviorSubject } from 'rxjs'; import { WebsocketService } from 'app/core/core-services/websocket.service'; import { ProjectorElement, Projector } from 'app/shared/models/core/projector'; -export interface SlideData { +export interface SlideData { data: T; - element: ProjectorElement; + element: P; error?: string; } diff --git a/client/src/app/site/mediafiles/models/mediafile-projector-element.ts b/client/src/app/site/mediafiles/models/mediafile-projector-element.ts new file mode 100644 index 000000000..98670520e --- /dev/null +++ b/client/src/app/site/mediafiles/models/mediafile-projector-element.ts @@ -0,0 +1,13 @@ +import { ProjectorElement } from 'app/shared/models/core/projector'; + +export interface MediafileProjectorElement extends ProjectorElement { + // Images and Pdf + rotation?: 0 | 90 | 180 | 270; + + // Images + fullscreen?: boolean; + + // Pdf + page?: number; + zoom?: number; // 0 is normal, then +-1, +-2, ... +} diff --git a/client/src/app/site/mediafiles/models/view-mediafile.ts b/client/src/app/site/mediafiles/models/view-mediafile.ts index bc4cc4fb0..fa12cac5f 100644 --- a/client/src/app/site/mediafiles/models/view-mediafile.ts +++ b/client/src/app/site/mediafiles/models/view-mediafile.ts @@ -7,12 +7,17 @@ import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable'; import { BaseViewModelWithListOfSpeakers } from 'app/site/base/base-view-model-with-list-of-speakers'; import { ViewListOfSpeakers } from 'app/site/agenda/models/view-list-of-speakers'; +export const IMAGE_MIMETYPES = ['image/png', 'image/jpeg', 'image/gif']; +export const FONT_MIMETYPES = ['font/ttf', 'font/woff', 'application/font-woff', 'application/font-sfnt']; +export const PDF_MIMETYPES = ['application/pdf']; + export interface MediafileTitleInformation { title: string; } export class ViewMediafile extends BaseViewModelWithListOfSpeakers implements MediafileTitleInformation, Searchable { + public static COLLECTIONSTRING = Mediafile.COLLECTIONSTRING; private _uploader: ViewUser; @@ -110,7 +115,7 @@ export class ViewMediafile extends BaseViewModelWithListOfSpeakers * @returns true or false */ public isImage(): boolean { - return ['image/png', 'image/jpeg', 'image/gif'].includes(this.type); + return IMAGE_MIMETYPES.includes(this.type); } /** @@ -119,7 +124,7 @@ export class ViewMediafile extends BaseViewModelWithListOfSpeakers * @returns true or false */ public isFont(): boolean { - return ['font/ttf', 'font/woff', 'application/font-woff', 'application/font-sfnt'].includes(this.type); + return FONT_MIMETYPES.includes(this.type); } /** @@ -128,7 +133,7 @@ export class ViewMediafile extends BaseViewModelWithListOfSpeakers * @returns true or false */ public isPdf(): boolean { - return ['application/pdf'].includes(this.type); + return PDF_MIMETYPES.includes(this.type); } /** diff --git a/client/src/app/site/projector/components/presentation-control/presentation-control.component.html b/client/src/app/site/projector/components/presentation-control/presentation-control.component.html index 93b737280..41e285865 100644 --- a/client/src/app/site/projector/components/presentation-control/presentation-control.component.html +++ b/client/src/app/site/projector/components/presentation-control/presentation-control.component.html @@ -1,34 +1,42 @@ -
Presentation control
-
- {{ getMediafile(element).getTitle() }} - - - - - - - - - Page {{ getPage(element) }}/{{ getMediafile(element).pages }} - - - - - -
+ + + Media controls + +
Presentation control
+
+ {{ getMediafile(element).getTitle() }} + + + + + + + + + + Page {{ getPage(element) }}/{{ getMediafile(element).pages }} + + + + + +
+
diff --git a/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts b/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts index 695892b2a..5618204ff 100644 --- a/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts +++ b/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts @@ -7,11 +7,11 @@ import { TranslateService } from '@ngx-translate/core'; import { BaseViewComponent } from 'app/site/base/base-view'; import { Mediafile } from 'app/shared/models/mediafiles/mediafile'; import { MediafileRepositoryService } from 'app/core/repositories/mediafiles/mediafile-repository.service'; -import { ProjectorElements, ProjectorElement } from 'app/shared/models/core/projector'; import { ProjectorService } from 'app/core/core-services/projector.service'; import { SlideManager } from 'app/slides/services/slide-manager.service'; import { ViewMediafile } from 'app/site/mediafiles/models/view-mediafile'; import { ViewProjector } from '../../models/view-projector'; +import { MediafileProjectorElement } from 'app/site/mediafiles/models/mediafile-projector-element'; /** * The presentation controls. @@ -38,7 +38,7 @@ export class PresentationControlComponent extends BaseViewComponent { } // All mediafile elements. - public elements: ProjectorElements = []; + public elements: MediafileProjectorElement[] = []; /** * Constructor @@ -66,7 +66,7 @@ export class PresentationControlComponent extends BaseViewComponent { */ private updateElements(): void { this.elements = this.projector.elements.filter(element => { - if (element.name !== Mediafile.COLLECTIONSTRING && !element.id) { + if (element.name !== Mediafile.COLLECTIONSTRING || !element.id) { return false; } const mediafile = this.mediafileRepo.getViewModel(element.id); @@ -74,14 +74,14 @@ export class PresentationControlComponent extends BaseViewComponent { }); } - public getMediafile(element: ProjectorElement): ViewMediafile { + public getMediafile(element: MediafileProjectorElement): ViewMediafile { return this.mediafileRepo.getViewModel(element.id); } /** * @returns the currently used page number (1 in case of unnumbered elements) */ - public getPage(element: ProjectorElement): number { + public getPage(element: MediafileProjectorElement): number { return element.page || 1; } @@ -90,7 +90,7 @@ export class PresentationControlComponent extends BaseViewComponent { * * @param element */ - public pdfForward(element: ProjectorElement): void { + public pdfForward(element: MediafileProjectorElement): void { if (this.getPage(element) < this.getMediafile(element).pages) { this.pdfSetPage(element, this.getPage(element) + 1); } @@ -101,7 +101,7 @@ export class PresentationControlComponent extends BaseViewComponent { * * @param element */ - public pdfBackward(element: ProjectorElement): void { + public pdfBackward(element: MediafileProjectorElement): void { if (this.getPage(element) > 1) { this.pdfSetPage(element, this.getPage(element) - 1); } @@ -114,19 +114,47 @@ export class PresentationControlComponent extends BaseViewComponent { * @param element * @param page */ - public pdfSetPage(element: ProjectorElement, page: number): void { - const idElement = this.slideManager.getIdentifialbeProjectorElement(element); + public pdfSetPage(element: MediafileProjectorElement, page: number): void { if (this.getMediafile(element).pages >= page) { - idElement.page = page; - this.projectorService.updateElement(this.projector.projector, idElement).then(null, this.raiseError); + element.page = page; + this.updateElement(element); } } - public pdfZoom(element: ProjectorElement, direction: 'in' | 'out' | 'reset'): void {} + public zoom(element: MediafileProjectorElement, direction: 'in' | 'out' | 'reset'): void { + if (direction === 'reset') { + element.zoom = 0; + } else if (direction === 'in') { + element.zoom = (element.zoom || 0) + 1; + } else if (direction === 'out') { + element.zoom = (element.zoom || 0) - 1; + } + this.updateElement(element); + } - public pdfRotate(element: ProjectorElement): void {} + public fullscreen(element: MediafileProjectorElement): void { + element.fullscreen = !element.fullscreen; + this.updateElement(element); + } - public imageFullscreen(element: ProjectorElement): void {} + public rotate(element: MediafileProjectorElement): void { + let rotation: 0 | 90 | 180 | 270 = element.rotation || 0; + if (rotation === 0) { + rotation = 90; + } else if (rotation === 90) { + rotation = 180; + } else if (rotation === 180) { + rotation = 270; + } else { + // 270 + rotation = 0; + } + element.rotation = rotation; + this.updateElement(element); + } - public imageRotate(element: ProjectorElement): void {} + private updateElement(element: MediafileProjectorElement): void { + const idElement = this.slideManager.getIdentifialbeProjectorElement(element); + this.projectorService.updateElement(this.projector.projector, idElement).then(null, this.raiseError); + } } diff --git a/client/src/app/site/projector/components/projector-detail/projector-detail.component.html b/client/src/app/site/projector/components/projector-detail/projector-detail.component.html index 7b0b2bfc2..1296de599 100644 --- a/client/src/app/site/projector/components/projector-detail/projector-detail.component.html +++ b/client/src/app/site/projector/components/projector-detail/projector-detail.component.html @@ -264,13 +264,16 @@ - + + + + diff --git a/client/src/app/slides/base-slide-component.ts b/client/src/app/slides/base-slide-component.ts index 29d1e2eec..f83515b7f 100644 --- a/client/src/app/slides/base-slide-component.ts +++ b/client/src/app/slides/base-slide-component.ts @@ -2,17 +2,18 @@ import { Input } from '@angular/core'; import { ViewProjector } from 'app/site/projector/models/view-projector'; import { SlideData } from 'app/core/core-services/projector-data.service'; +import { ProjectorElement } from 'app/shared/models/core/projector'; /** * Every slide has to extends this base class. It forces the slides * to have an input for the slidedata. */ -export abstract class BaseSlideComponent { +export abstract class BaseSlideComponent { /** * Each slide must take slide data. */ @Input() - public data: SlideData; + public data: SlideData; /** * The projector where this slide is projected on. diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html index 74d3f4245..225838d5b 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html @@ -1,17 +1,19 @@
-
- +
+ + {{ data.element.fullscreen || false }}
-
- -
-
- +
+ {{ data.element.rotation || 0 }} +
diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.scss b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.scss index e69de29bb..53fc4c228 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.scss +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.scss @@ -0,0 +1,12 @@ +.rotate0 { + transform: rotate(0deg); +} +.rotate90 { + transform: rotate(90deg); +} +.rotate180 { + transform: rotate(180deg); +} +.rotate270 { + transform: rotate(270deg); +} diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts index ec60bcdcb..5a31c04e5 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts @@ -2,22 +2,32 @@ import { Component } from '@angular/core'; import { BaseSlideComponent } from 'app/slides/base-slide-component'; import { MediafileSlideData } from './mediafile-slide-data'; +import { IMAGE_MIMETYPES, PDF_MIMETYPES } from 'app/site/mediafiles/models/view-mediafile'; +import { MediafileProjectorElement } from 'app/site/mediafiles/models/mediafile-projector-element'; @Component({ selector: 'os-mediafile-slide', templateUrl: './mediafile-slide.component.html', styleUrls: ['./mediafile-slide.component.scss'] }) -export class MediafileSlideComponent extends BaseSlideComponent { - public constructor() { - super(); - } - - public get page(): string { - return this.data.element.page; - } - +export class MediafileSlideComponent extends BaseSlideComponent { public get url(): string { return `${this.data.data.media_url_prefix}/${this.data.data.path}`; } + + public get zoom(): number { + return Math.pow(1.1, this.data.element.zoom || 0); + } + + public get isImage(): boolean { + return IMAGE_MIMETYPES.includes(this.data.data.type); + } + + public get isPdf(): boolean { + return PDF_MIMETYPES.includes(this.data.data.type); + } + + public constructor() { + super(); + } } diff --git a/client/src/app/slides/services/slide-manager.service.ts b/client/src/app/slides/services/slide-manager.service.ts index f2ef6a768..5ed340c1b 100644 --- a/client/src/app/slides/services/slide-manager.service.ts +++ b/client/src/app/slides/services/slide-manager.service.ts @@ -54,8 +54,8 @@ export class SlideManager { return this.loadedSlideConfigurations[slideName]; } - public getIdentifialbeProjectorElement(element: ProjectorElement): IdentifiableProjectorElement { - const identifiableElement: IdentifiableProjectorElement = element as IdentifiableProjectorElement; + public getIdentifialbeProjectorElement

(element: P): IdentifiableProjectorElement & P { + const identifiableElement: IdentifiableProjectorElement & P = element as IdentifiableProjectorElement & P; const identifiers = this.getManifest(element.name).elementIdentifiers.map(x => x); // map to copy. identifiableElement.getIdentifiers = () => identifiers; return identifiableElement; From 2cfff9e1b9640332d671e055a06d8814c5f6f6b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emanuel=20Sch=C3=BCtze?= Date: Fri, 17 May 2019 08:56:18 +0200 Subject: [PATCH 5/5] Template rework and fullscreen mode --- .../slide-container.component.scss | 4 +-- .../site/mediafiles/models/view-mediafile.ts | 1 - .../presentation-control.component.html | 27 ++++++-------- .../presentation-control.component.ts | 16 --------- ...urrent-speaker-chyron-slide.component.html | 2 +- .../mediafile/mediafile-slide.component.html | 9 ++--- .../mediafile/mediafile-slide.component.scss | 36 ++++++++++++++----- 7 files changed, 43 insertions(+), 52 deletions(-) diff --git a/client/src/app/shared/components/slide-container/slide-container.component.scss b/client/src/app/shared/components/slide-container/slide-container.component.scss index cb29e038e..ad8395fe0 100644 --- a/client/src/app/shared/components/slide-container/slide-container.component.scss +++ b/client/src/app/shared/components/slide-container/slide-container.component.scss @@ -10,8 +10,6 @@ line-height: 1.5em; } } - -::ng-deep #slide { - z-index: 5; +#slide { height: 100%; } diff --git a/client/src/app/site/mediafiles/models/view-mediafile.ts b/client/src/app/site/mediafiles/models/view-mediafile.ts index fa12cac5f..51a9cf5ae 100644 --- a/client/src/app/site/mediafiles/models/view-mediafile.ts +++ b/client/src/app/site/mediafiles/models/view-mediafile.ts @@ -17,7 +17,6 @@ export interface MediafileTitleInformation { export class ViewMediafile extends BaseViewModelWithListOfSpeakers implements MediafileTitleInformation, Searchable { - public static COLLECTIONSTRING = Mediafile.COLLECTIONSTRING; private _uploader: ViewUser; diff --git a/client/src/app/site/projector/components/presentation-control/presentation-control.component.html b/client/src/app/site/projector/components/presentation-control/presentation-control.component.html index 41e285865..a3b01a6e6 100644 --- a/client/src/app/site/projector/components/presentation-control/presentation-control.component.html +++ b/client/src/app/site/projector/components/presentation-control/presentation-control.component.html @@ -1,22 +1,19 @@ - Media controls + Media file -

Presentation control
- {{ getMediafile(element).getTitle() }} - + {{ getMediafile(element).getTitle() }} +
- - - + fullscreen +
+
@@ -24,10 +21,8 @@ arrow_forward - Page {{ getPage(element) }}/{{ getMediafile(element).pages }} - + Page {{ getPage(element) }}/{{ getMediafile(element).pages }} +
@@ -37,6 +32,6 @@ - +
diff --git a/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts b/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts index 5618204ff..5eafcf77b 100644 --- a/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts +++ b/client/src/app/site/projector/components/presentation-control/presentation-control.component.ts @@ -137,22 +137,6 @@ export class PresentationControlComponent extends BaseViewComponent { this.updateElement(element); } - public rotate(element: MediafileProjectorElement): void { - let rotation: 0 | 90 | 180 | 270 = element.rotation || 0; - if (rotation === 0) { - rotation = 90; - } else if (rotation === 90) { - rotation = 180; - } else if (rotation === 180) { - rotation = 270; - } else { - // 270 - rotation = 0; - } - element.rotation = rotation; - this.updateElement(element); - } - private updateElement(element: MediafileProjectorElement): void { const idElement = this.slideManager.getIdentifialbeProjectorElement(element); this.projectorService.updateElement(this.projector.projector, idElement).then(null, this.raiseError); diff --git a/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.html b/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.html index eba96bae0..81ff50cb8 100644 --- a/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.html +++ b/client/src/app/slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.component.html @@ -1,4 +1,4 @@ -
diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html index 225838d5b..618db8aa4 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html @@ -1,10 +1,8 @@
-
- - {{ data.element.fullscreen || false }} +
+
-
- {{ data.element.rotation || 0 }} +
diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.scss b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.scss index 53fc4c228..0ff1a9b0f 100644 --- a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.scss +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.scss @@ -1,12 +1,30 @@ -.rotate0 { - transform: rotate(0deg); +.fullscreen img, +.nofullscreen img { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; } -.rotate90 { - transform: rotate(90deg); +.fullscreen { + z-index: 100; /* TODO: find solution to overlap header/footer */ + width: 100%; + height: 100%; + background-color: white; + position: fixed; + top: 0; + left: 0; + + img { + width: 100%; + height: auto; /* TODO: use dynamic auto width/height for landscape/portrait format */ + } } -.rotate180 { - transform: rotate(180deg); -} -.rotate270 { - transform: rotate(270deg); + +.nofullscreen { + max-width: 100%; + max-height: 100%; + width: auto; + height: auto; }