From f44590b5195fbef1653890d3b2c962f06b80c796 Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Tue, 26 Mar 2019 13:50:39 +0100 Subject: [PATCH] Put projector cards in own components in the listview --- .../projector-list-entry.component.html | 113 +++++++++ .../projector-list-entry.component.scss | 19 ++ .../projector-list-entry.component.spec.ts | 26 ++ .../projector-list-entry.component.ts | 229 ++++++++++++++++++ .../projector-list.component.html | 119 +-------- .../projector-list.component.scss | 20 -- .../projector-list.component.ts | 165 +------------ .../app/site/projector/projector.module.ts | 2 + 8 files changed, 398 insertions(+), 295 deletions(-) create mode 100644 client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.html create mode 100644 client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.scss create mode 100644 client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.spec.ts create mode 100644 client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.ts diff --git a/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.html b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.html new file mode 100644 index 000000000..465214323 --- /dev/null +++ b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.html @@ -0,0 +1,113 @@ + + + {{ projector.getTitle() | translate }} + + + + + + + + + +
+ +
+
+ +
+ + + + + Required + + + +

Resolution and size

+ + + + {{ ratio }} + + + + {{ updateForm.value.width }} + + +

Projection defaults

+ + + {{ pd.getTitle() | translate }} + + + + + + Background color + + + Required + + + + Header background color + + + Required + + + + Header font color + + + Required + + + + Headline color + + + Required + + + + +
+ + Show header and footer + +
+
+ + Show title + +
+
+ + Show logo + +
+
+ + Show clock + +
+
+
+
+
diff --git a/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.scss b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.scss new file mode 100644 index 000000000..a7f624446 --- /dev/null +++ b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.scss @@ -0,0 +1,19 @@ +.projector { + width: 320px; + color: black; + border: 1px solid lightgrey; +} + +form { + margin-top: 10px; +} + +::ng-deep mat-card { + margin: 0; +} + +.no-markup { + /* Do not let the a tag ruin the projector */ + color: inherit; + text-decoration: inherit; +} diff --git a/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.spec.ts b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.spec.ts new file mode 100644 index 000000000..9223f6cb1 --- /dev/null +++ b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { E2EImportsModule } from '../../../../../e2e-imports.module'; +import { ProjectorModule } from '../../projector.module'; +import { ProjectorListEntryComponent } from './projector-list-entry.component'; + +describe('ProjectorListEntryComponent', () => { + let component: ProjectorListEntryComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [E2EImportsModule, ProjectorModule] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ProjectorListEntryComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.ts b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.ts new file mode 100644 index 000000000..21ed72490 --- /dev/null +++ b/client/src/app/site/projector/components/projector-list-entry/projector-list-entry.component.ts @@ -0,0 +1,229 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { Title } from '@angular/platform-browser'; +import { MatSnackBar, MatSliderChange } from '@angular/material'; + +import { TranslateService } from '@ngx-translate/core'; + +import { ProjectorRepositoryService } from 'app/core/repositories/projector/projector-repository.service'; +import { ViewProjector } from '../../models/view-projector'; +import { Projector } from 'app/shared/models/core/projector'; +import { BaseViewComponent } from 'app/site/base/base-view'; +import { PromptService } from 'app/core/ui-services/prompt.service'; +import { ClockSlideService } from '../../services/clock-slide.service'; +import { OperatorService } from 'app/core/core-services/operator.service'; +import { ViewProjectionDefault } from '../../models/view-projection-default'; +import { ProjectionDefaultRepositoryService } from 'app/core/repositories/projector/projection-default-repository.service'; + +/** + * All supported aspect rations for projectors. + */ +const aspectRatios: { [ratio: string]: number } = { + '4:3': 4 / 3, + '16:9': 16 / 9, + '16:10': 16 / 10 +}; + +/** + * List for all projectors. + */ +@Component({ + selector: 'os-projector-list-entry', + templateUrl: './projector-list-entry.component.html', + styleUrls: ['./projector-list-entry.component.scss'] +}) +export class ProjectorListEntryComponent extends BaseViewComponent implements OnInit { + /** + * The update form. Will be refreahed for each projector. Just one update + * form can be shown per time. + */ + public updateForm: FormGroup; + + /** + * Saves, if this projector currently is edited. + */ + public isEditing = false; + + /** + * All ProjectionDefaults to select from. + */ + public projectionDefaults: ViewProjectionDefault[]; + + /** + * All aspect ratio keys/strings for the UI. + */ + public aspectRatiosKeys: string[]; + + /** + * The projector shown by this entry. + */ + @Input() + public projector: ViewProjector; + + /** + * Helper to check manage permissions + * + * @returns true if the user can manage projectors + */ + public get canManage(): boolean { + return this.operator.hasPerms('core.can_manage_projector'); + } + + /** + * Constructor. Initializes the update form. + * + * @param titleService + * @param translate + * @param matSnackBar + * @param repo + * @param formBuilder + * @param promptService + * @param clockSlideService + * @param operator OperatorService + */ + public constructor( + titleService: Title, + protected translate: TranslateService, // protected required for ng-translate-extract + matSnackBar: MatSnackBar, + private repo: ProjectorRepositoryService, + private formBuilder: FormBuilder, + private promptService: PromptService, + private clockSlideService: ClockSlideService, + private operator: OperatorService, + private projectionDefaultRepo: ProjectionDefaultRepositoryService + ) { + super(titleService, translate, matSnackBar); + + this.aspectRatiosKeys = Object.keys(aspectRatios); + + this.updateForm = this.formBuilder.group({ + name: ['', Validators.required], + aspectRatio: ['', Validators.required], + width: [0, Validators.required], + projectiondefaults_id: [[]], + clock: [true], + background_color: ['', Validators.required], + header_background_color: ['', Validators.required], + header_font_color: ['', Validators.required], + header_h1_color: ['', Validators.required], + show_header_footer: [], + show_title: [], + show_logo: [] + }); + } + + /** + * Watches all projectiondefaults. + */ + public ngOnInit(): void { + this.projectionDefaults = this.projectionDefaultRepo.getViewModelList(); + this.subscriptions.push( + this.projectionDefaultRepo.getViewModelListObservable().subscribe(pds => (this.projectionDefaults = pds)) + ); + } + + /** + * Event on Key Down in update form. + * + * @param event the keyboard event + * @param the current view in scope + */ + public keyDownFunction(event: KeyboardEvent): void { + if (event.key === 'Enter') { + this.onSaveButton(); + } + if (event.key === 'Escape') { + this.onCancelButton(); + } + } + + /** + * Calculates the aspect ratio of the given projector. + * If no matching ratio is found, the first ratio is returned. + * + * @param projector The projector to check + * @returns the found ratio key. + */ + public getAspectRatioKey(): string { + const ratio = this.projector.width / this.projector.height; + const RATIO_ENVIRONMENT = 0.05; + const foundRatioKey = Object.keys(aspectRatios).find(key => { + const value = aspectRatios[key]; + return value >= ratio - RATIO_ENVIRONMENT && value <= ratio + RATIO_ENVIRONMENT; + }); + if (!foundRatioKey) { + return Object.keys(aspectRatios)[0]; + } else { + return foundRatioKey; + } + } + + /** + * Starts editing for the given projector. + */ + public onEditButton(): void { + if (this.isEditing) { + return; + } + this.isEditing = true; + this.updateForm.reset(); + + this.updateForm.patchValue(this.projector.projector); + this.updateForm.patchValue({ + name: this.translate.instant(this.projector.name), + aspectRatio: this.getAspectRatioKey(), + clock: this.clockSlideService.isProjectedOn(this.projector) + }); + } + + /** + * Cancels the current editing. + */ + public onCancelButton(): void { + this.isEditing = false; + } + + /** + * Saves the projector + * + * @param projector The projector to save. + */ + public async onSaveButton(): Promise { + const updateProjector: Partial = this.updateForm.value; + updateProjector.height = Math.round( + this.updateForm.value.width / aspectRatios[this.updateForm.value.aspectRatio] + ); + + try { + await this.clockSlideService.setProjectedOn(this.projector, this.updateForm.value.clock); + await this.repo.update(updateProjector, this.projector); + this.isEditing = false; + } catch (e) { + this.raiseError(e); + } + } + + /** + * Delete the projector. + */ + public async onDeleteButton(): Promise { + const title = this.translate.instant('Are you sure you want to delete this projector?'); + if (await this.promptService.open(title, this.projector.name)) { + this.repo.delete(this.projector).then(null, this.raiseError); + } + } + + /** + * Eventhandler for slider changes. Directly saves the new aspect ratio. + * + * @param event The slider value + */ + public widthSliderValueChanged(event: MatSliderChange): void { + const aspectRatio = this.getAspectRatioKey(); + const updateProjector: Partial = { + width: event.value + }; + updateProjector.height = Math.round(event.value / aspectRatios[aspectRatio]); + this.repo.update(updateProjector, this.projector).then(null, this.raiseError); + } +} diff --git a/client/src/app/site/projector/components/projector-list/projector-list.component.html b/client/src/app/site/projector/components/projector-list/projector-list.component.html index 4b1d932f2..3c92c882e 100644 --- a/client/src/app/site/projector/components/projector-list/projector-list.component.html +++ b/client/src/app/site/projector/components/projector-list/projector-list.component.html @@ -45,120 +45,7 @@
-
- - - {{ projector.name | translate }} - - - - - - - - - -
- -
-
- -
- - - - - Required - - - -

Resolution and size

- - - - {{ ratio }} - - - - {{ updateForm.value.width }} - - -

Projection defaults

- - - {{ pd.getTitle() | translate }} - - - - - - Background color - - - Required - - - - Header background color - - - Required - - - - Header font color - - - Required - - - - Headline color - - - Required - - - - -
- - Show header and footer - -
-
- - Show title - -
-
- - Show logo - -
-
- - Show clock - -
-
-
-
-
+
+
-
\ No newline at end of file +
diff --git a/client/src/app/site/projector/components/projector-list/projector-list.component.scss b/client/src/app/site/projector/components/projector-list/projector-list.component.scss index 7501de850..5b3fb4aa9 100644 --- a/client/src/app/site/projector/components/projector-list/projector-list.component.scss +++ b/client/src/app/site/projector/components/projector-list/projector-list.component.scss @@ -6,25 +6,5 @@ width: 350px; margin: 10px; float: left; - - .projector { - width: 320px; - color: black; - border: 1px solid lightgrey; - } - - form { - margin-top: 10px; - } - - ::ng-deep mat-card { - margin: 0; - } - - .no-markup { - /* Do not let the a tag ruin the projector */ - color: inherit; - text-decoration: inherit; - } } } diff --git a/client/src/app/site/projector/components/projector-list/projector-list.component.ts b/client/src/app/site/projector/components/projector-list/projector-list.component.ts index 8709400af..f25481337 100644 --- a/client/src/app/site/projector/components/projector-list/projector-list.component.ts +++ b/client/src/app/site/projector/components/projector-list/projector-list.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { Title } from '@angular/platform-browser'; -import { MatSnackBar, MatSelectChange, MatSliderChange } from '@angular/material'; +import { MatSnackBar, MatSelectChange } from '@angular/material'; import { TranslateService } from '@ngx-translate/core'; @@ -9,20 +9,7 @@ import { ProjectorRepositoryService } from 'app/core/repositories/projector/proj import { ViewProjector } from '../../models/view-projector'; import { Projector } from 'app/shared/models/core/projector'; import { BaseViewComponent } from 'app/site/base/base-view'; -import { PromptService } from 'app/core/ui-services/prompt.service'; -import { ClockSlideService } from '../../services/clock-slide.service'; import { OperatorService } from 'app/core/core-services/operator.service'; -import { ProjectionDefaultRepositoryService } from 'app/core/repositories/projector/projection-default-repository.service'; -import { ViewProjectionDefault } from '../../models/view-projection-default'; - -/** - * All supported aspect rations for projectors. - */ -const aspectRatios: { [ratio: string]: number } = { - '4:3': 4 / 3, - '16:9': 16 / 9, - '16:10': 16 / 10 -}; /** * List for all projectors. @@ -43,17 +30,6 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit */ public createForm: FormGroup; - /** - * The update form. Will be refreahed for each projector. Just one update - * form can be shown per time. - */ - public updateForm: FormGroup; - - /** - * The id of the currently edited projector. - */ - public editId: number | null = null; - /** * All aspect ratio keys/strings for the UI. */ @@ -64,8 +40,6 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit */ public projectors: ViewProjector[]; - public projectionDefaults: ViewProjectionDefault[]; - /** * Helper to check manage permissions * @@ -93,32 +67,13 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit matSnackBar: MatSnackBar, private repo: ProjectorRepositoryService, private formBuilder: FormBuilder, - private promptService: PromptService, - private clockSlideService: ClockSlideService, - private operator: OperatorService, - private projectionDefaultRepo: ProjectionDefaultRepositoryService + private operator: OperatorService ) { super(titleService, translate, matSnackBar); - this.aspectRatiosKeys = Object.keys(aspectRatios); - this.createForm = this.formBuilder.group({ name: ['', Validators.required] }); - this.updateForm = this.formBuilder.group({ - name: ['', Validators.required], - aspectRatio: ['', Validators.required], - width: [0, Validators.required], - projectiondefaults_id: [[]], - clock: [true], - background_color: ['', Validators.required], - header_background_color: ['', Validators.required], - header_font_color: ['', Validators.required], - header_h1_color: ['', Validators.required], - show_header_footer: [], - show_title: [], - show_logo: [] - }); } /** @@ -128,8 +83,6 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit super.setTitle('Projectors'); this.projectors = this.repo.getViewModelList(); this.repo.getViewModelListObservable().subscribe(projectors => (this.projectors = projectors)); - this.projectionDefaults = this.projectionDefaultRepo.getViewModelList(); - this.projectionDefaultRepo.getViewModelListObservable().subscribe(pds => (this.projectionDefaults = pds)); } /** @@ -159,110 +112,13 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit * Event on Key Down in update or create form. * * @param event the keyboard event - * @param the current view in scope */ - public keyDownFunction(event: KeyboardEvent, projector?: ViewProjector): void { - if (event.key === 'Enter' && event.shiftKey) { - if (projector) { - this.onSaveButton(projector); - } else { - this.create(); - } + public keyDownFunction(event: KeyboardEvent): void { + if (event.key === 'Enter') { + this.create(); } if (event.key === 'Escape') { - if (projector) { - this.onCancelButton(projector); - } else { - this.projectorToCreate = null; - } - } - } - - /** - * Calculates the aspect ratio of the given projector. - * If no matching ratio is found, the first ratio is returned. - * - * @param projector The projector to check - * @returns the found ratio key. - */ - public getAspectRatioKey(projector: ViewProjector): string { - const ratio = projector.width / projector.height; - const RATIO_ENVIRONMENT = 0.05; - const foundRatioKey = Object.keys(aspectRatios).find(key => { - const value = aspectRatios[key]; - return value >= ratio - RATIO_ENVIRONMENT && value <= ratio + RATIO_ENVIRONMENT; - }); - if (!foundRatioKey) { - return Object.keys(aspectRatios)[0]; - } else { - return foundRatioKey; - } - } - - /** - * Starts editing for the given projector. - * - * @param projector The projector to edit - */ - public onEditButton(projector: ViewProjector): void { - if (this.editId !== null) { - return; - } - this.editId = projector.id; - this.updateForm.reset(); - - this.updateForm.patchValue(projector.projector); - this.updateForm.patchValue({ - name: this.translate.instant(projector.name), - aspectRatio: this.getAspectRatioKey(projector), - clock: this.clockSlideService.isProjectedOn(projector) - }); - } - - /** - * Cancels the current editing. - * @param projector the projector - */ - public onCancelButton(projector: ViewProjector): void { - if (projector.id !== this.editId) { - return; - } - this.editId = null; - } - - /** - * Saves the projector - * - * @param projector The projector to save. - */ - public async onSaveButton(projector: ViewProjector): Promise { - if (projector.id !== this.editId || !this.updateForm.valid) { - return; - } - const updateProjector: Partial = this.updateForm.value; - updateProjector.height = Math.round( - this.updateForm.value.width / aspectRatios[this.updateForm.value.aspectRatio] - ); - - try { - await this.clockSlideService.setProjectedOn(projector, this.updateForm.value.clock); - await this.repo.update(updateProjector, projector); - this.editId = null; - } catch (e) { - this.raiseError(e); - } - } - - /** - * Delete the projector. - * - * @param projector The projector to delete - */ - public async onDeleteButton(projector: ViewProjector): Promise { - const title = this.translate.instant('Are you sure you want to delete this projector?'); - const content = projector.name; - if (await this.promptService.open(title, content)) { - this.repo.delete(projector).then(null, this.raiseError); + this.projectorToCreate = null; } } @@ -275,13 +131,4 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit }); Promise.all(promises).then(null, this.raiseError); } - - public widthSliderValueChanged(projector: ViewProjector, event: MatSliderChange): void { - const aspectRatio = this.getAspectRatioKey(projector); - const updateProjector: Partial = { - width: event.value - }; - updateProjector.height = Math.round(event.value / aspectRatios[aspectRatio]); - this.repo.update(updateProjector, projector).then(null, this.raiseError); - } } diff --git a/client/src/app/site/projector/projector.module.ts b/client/src/app/site/projector/projector.module.ts index 6a0192c67..5ce0a9a13 100644 --- a/client/src/app/site/projector/projector.module.ts +++ b/client/src/app/site/projector/projector.module.ts @@ -9,11 +9,13 @@ 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 { ProjectorListEntryComponent } from './components/projector-list-entry/projector-list-entry.component'; @NgModule({ imports: [CommonModule, ProjectorRoutingModule, SharedModule], declarations: [ ProjectorListComponent, + ProjectorListEntryComponent, ProjectorDetailComponent, CountdownControlsComponent, CountdownDialogComponent,