diff --git a/client/src/app/shared/components/projector-button/projector-button.component.ts b/client/src/app/shared/components/projector-button/projector-button.component.ts index 877b5b825..1fa528d3c 100644 --- a/client/src/app/shared/components/projector-button/projector-button.component.ts +++ b/client/src/app/shared/components/projector-button/projector-button.component.ts @@ -50,7 +50,7 @@ export class ProjectorButtonComponent implements OnInit { * Pre-define projection target */ @Input() - public projector: Projector; + public projector: Projector | null; /** * The constructor @@ -100,6 +100,9 @@ export class ProjectorButtonComponent implements OnInit { if (!this.object) { return false; } - return this.projectorService.isProjected(this.object); + + return this.projector + ? this.projectorService.isProjectedOn(this.object, this.projector) + : this.projectorService.isProjected(this.object); } } diff --git a/client/src/app/site/projector/components/countdown-controls/countdown-controls.component.scss b/client/src/app/site/projector/components/countdown-controls/countdown-controls.component.scss index 963060064..af1015596 100644 --- a/client/src/app/site/projector/components/countdown-controls/countdown-controls.component.scss +++ b/client/src/app/site/projector/components/countdown-controls/countdown-controls.component.scss @@ -8,6 +8,7 @@ grid-template-columns: min-content auto auto; } +// could be in a shared scss .projector-button { grid-area: project; margin: auto 10px auto 0; @@ -21,6 +22,7 @@ white-space: nowrap; } +// could be in a shared scss .action-buttons { grid-area: buttons; text-align: right; diff --git a/client/src/app/site/projector/components/message-controls/message-controls.component.html b/client/src/app/site/projector/components/message-controls/message-controls.component.html new file mode 100644 index 000000000..d9e81ce2e --- /dev/null +++ b/client/src/app/site/projector/components/message-controls/message-controls.component.html @@ -0,0 +1,33 @@ + +
+
+ +
+ +
+ + + +
+ +
+
+
diff --git a/client/src/app/site/projector/components/message-controls/message-controls.component.scss b/client/src/app/site/projector/components/message-controls/message-controls.component.scss new file mode 100644 index 000000000..33710aeba --- /dev/null +++ b/client/src/app/site/projector/components/message-controls/message-controls.component.scss @@ -0,0 +1,45 @@ +.grid-wrapper { + display: grid; + width: 100%; + grid-template-areas: + 'project message buttons' + 'project message buttons'; + grid-gap: 10px; + grid-template-columns: min-content auto auto; +} + +// could be in a shared scss +.projector-button { + grid-area: project; + margin: auto 10px auto 0; +} + +// could be in a shared scss +.action-buttons { + grid-area: buttons; + text-align: right; +} + +// smaller and closer mat icon buttons. +// use on button-tags +// TODO: Somehow does not apply when in style.scss +.small-mat-icon-button { + $size: 20px; + margin: 0 5px; + position: relative; + width: $size; + height: $size; + + ::ng-deep .mat-icon { + position: absolute; + left: 0; + top: 0; + line-height: normal; + width: $size; + height: $size; + } + + .material-icons { + font-size: $size; + } +} diff --git a/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.spec.ts b/client/src/app/site/projector/components/message-controls/message-controls.component.spec.ts similarity index 55% rename from client/src/app/site/projector/components/projector-message-list/projector-message-list.component.spec.ts rename to client/src/app/site/projector/components/message-controls/message-controls.component.spec.ts index 050ff1ff6..d3a03e604 100644 --- a/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.spec.ts +++ b/client/src/app/site/projector/components/message-controls/message-controls.component.spec.ts @@ -1,21 +1,21 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { MessageControlsComponent } from './message-controls.component'; import { E2EImportsModule } from 'e2e-imports.module'; -import { ProjectorMessageListComponent } from './projector-message-list.component'; -describe('ProjectorMessageListComponent', () => { - let component: ProjectorMessageListComponent; - let fixture: ComponentFixture; +describe('MessageControlsComponent', () => { + let component: MessageControlsComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [E2EImportsModule], - declarations: [ProjectorMessageListComponent] + declarations: [MessageControlsComponent] }).compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(ProjectorMessageListComponent); + fixture = TestBed.createComponent(MessageControlsComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/client/src/app/site/projector/components/message-controls/message-controls.component.ts b/client/src/app/site/projector/components/message-controls/message-controls.component.ts new file mode 100644 index 000000000..53b8e0c64 --- /dev/null +++ b/client/src/app/site/projector/components/message-controls/message-controls.component.ts @@ -0,0 +1,90 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; + +import { BaseViewComponent } from 'app/site/base/base-view'; +import { Projector } from 'app/shared/models/core/projector'; +import { ProjectorMessageRepositoryService } from 'app/core/repositories/projector/projector-message-repository.service'; +import { MatSnackBar } from '@angular/material'; +import { ViewProjectorMessage } from '../../models/view-projector-message'; +import { PromptService } from 'app/core/ui-services/prompt.service'; +import { TranslateService } from '@ngx-translate/core'; +import { Title } from '@angular/platform-browser'; +import { ProjectionDialogService } from 'app/core/ui-services/projection-dialog.service'; + +/** + * Small controls component for messages. + * Used in the projector detail view, can could be embedded anywhere else + */ +@Component({ + selector: 'os-message-controls', + templateUrl: './message-controls.component.html', + styleUrls: ['./message-controls.component.scss'] +}) +export class MessageControlsComponent extends BaseViewComponent implements OnInit { + /** + * Input slot for the projector message model + */ + @Input() + public message: ViewProjectorMessage; + + /** + * Output event for the edit button + */ + @Output() + public editEvent = new EventEmitter(); + + /** + * Pre defined projection target (if any) + */ + @Input() + public projector: Projector; + + /** + * Constructor + * + * @param titleService set the title, required by parent + * @param matSnackBar show errors + * @param translate translate properties + * @param repo the projector message repo + * @param promptService delete prompt + */ + public constructor( + titleService: Title, + matSnackBar: MatSnackBar, + protected translate: TranslateService, + private repo: ProjectorMessageRepositoryService, + private promptService: PromptService, + private projectionDialogService: ProjectionDialogService + ) { + super(titleService, translate, matSnackBar); + } + + /** + * Init + */ + public ngOnInit(): void {} + + /** + * Fires an edit event + */ + public onEdit(): void { + this.editEvent.next(this.message); + } + + /** + * Brings the projection dialog + */ + public onBringDialog(): void { + this.projectionDialogService.openProjectDialogFor(this.message); + } + + /** + * On delete button + */ + public async onDelete(): Promise { + const content = + this.translate.instant('Delete message') + ` ${this.translate.instant(this.message.getTitle())}?`; + if (await this.promptService.open('Are you sure?', content)) { + this.repo.delete(this.message).then(() => {}, this.raiseError); + } + } +} diff --git a/client/src/app/site/projector/components/message-dialog/message-dialog.component.html b/client/src/app/site/projector/components/message-dialog/message-dialog.component.html new file mode 100644 index 000000000..5a789fffb --- /dev/null +++ b/client/src/app/site/projector/components/message-dialog/message-dialog.component.html @@ -0,0 +1,27 @@ +

+ Message +

+ +
+
+ + +
+
+ + + + + +
+
diff --git a/client/src/app/site/projector/components/message-dialog/message-dialog.component.scss b/client/src/app/site/projector/components/message-dialog/message-dialog.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/app/site/projector/components/message-dialog/message-dialog.component.spec.ts b/client/src/app/site/projector/components/message-dialog/message-dialog.component.spec.ts new file mode 100644 index 000000000..aae6d5580 --- /dev/null +++ b/client/src/app/site/projector/components/message-dialog/message-dialog.component.spec.ts @@ -0,0 +1,38 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MessageDialogComponent, MessageData } from './message-dialog.component'; +import { E2EImportsModule } from 'e2e-imports.module'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; + +describe('MessageDialogComponent', () => { + let component: MessageDialogComponent; + let fixture: ComponentFixture; + + const dialogData: MessageData = { + text: '' + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [MessageDialogComponent], + imports: [E2EImportsModule], + providers: [ + { provide: MatDialogRef, useValue: {} }, + { + provide: MAT_DIALOG_DATA, + useValue: dialogData + } + ] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MessageDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/site/projector/components/message-dialog/message-dialog.component.ts b/client/src/app/site/projector/components/message-dialog/message-dialog.component.ts new file mode 100644 index 000000000..bc54c939b --- /dev/null +++ b/client/src/app/site/projector/components/message-dialog/message-dialog.component.ts @@ -0,0 +1,58 @@ +import { Component, OnInit, Inject } from '@angular/core'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; +import { MAT_DIALOG_DATA, MatSnackBar } from '@angular/material'; +import { Title } from '@angular/platform-browser'; + +import { TranslateService } from '@ngx-translate/core'; + +import { BaseViewComponent } from 'app/site/base/base-view'; + +/** + * Determine what to send + */ +export interface MessageData { + text: string; +} + +/** + * Dialog component to edit projector messages + */ +@Component({ + selector: 'os-message-dialog', + templateUrl: './message-dialog.component.html', + styleUrls: ['./message-dialog.component.scss'] +}) +export class MessageDialogComponent extends BaseViewComponent implements OnInit { + /** + * The form data + */ + public messageForm: FormGroup; + + /** + * Constrcutor + * + * @param title required by parent + * @param matSnackBar to show errors + * @param translate to translate properties + * @param formBuilder to create the message form + * @param data the injected data, i.e the current text of a message to edit + */ + public constructor( + title: Title, + matSnackBar: MatSnackBar, + translate: TranslateService, + private formBuilder: FormBuilder, + @Inject(MAT_DIALOG_DATA) public data: MessageData + ) { + super(title, translate, matSnackBar); + } + + /** + * Init create the form + */ + public ngOnInit(): void { + this.messageForm = this.formBuilder.group({ + text: [this.data.text, Validators.required] + }); + } +} 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 4becf4ecd..a4b56bb7e 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 @@ -185,11 +185,7 @@ Countdowns - + - + Messages - - - {{ message.getPreview(40) }} + + + - diff --git a/client/src/app/site/projector/components/projector-detail/projector-detail.component.scss b/client/src/app/site/projector/components/projector-detail/projector-detail.component.scss index 86ce82db0..3a618c130 100644 --- a/client/src/app/site/projector/components/projector-detail/projector-detail.component.scss +++ b/client/src/app/site/projector/components/projector-detail/projector-detail.component.scss @@ -123,7 +123,7 @@ } .larger-mat-list-item { - height: 90px; + height: auto; } .larger-mat-list-item + .larger-mat-list-item { diff --git a/client/src/app/site/projector/components/projector-detail/projector-detail.component.spec.ts b/client/src/app/site/projector/components/projector-detail/projector-detail.component.spec.ts index 7730dba37..37e8db920 100644 --- a/client/src/app/site/projector/components/projector-detail/projector-detail.component.spec.ts +++ b/client/src/app/site/projector/components/projector-detail/projector-detail.component.spec.ts @@ -1,8 +1,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { E2EImportsModule } from '../../../../../e2e-imports.module'; import { ProjectorDetailComponent } from './projector-detail.component'; import { ProjectorModule } from '../../projector.module'; +import { E2EImportsModule } from 'e2e-imports.module'; describe('ProjectorDetailComponent', () => { let component: ProjectorDetailComponent; diff --git a/client/src/app/site/projector/components/projector-detail/projector-detail.component.ts b/client/src/app/site/projector/components/projector-detail/projector-detail.component.ts index 1b3aa52e7..a9c4c0627 100644 --- a/client/src/app/site/projector/components/projector-detail/projector-detail.component.ts +++ b/client/src/app/site/projector/components/projector-detail/projector-detail.component.ts @@ -18,13 +18,15 @@ import { CurrentSpeakerChyronSlideService } from '../../services/current-speaker import { DurationService } from 'app/core/ui-services/duration.service'; import { ProjectorService } from 'app/core/core-services/projector.service'; import { moveItemInArray, CdkDragDrop } from '@angular/cdk/drag-drop'; +import { Projectable } from 'app/site/base/projectable'; import { ProjectorElement } from 'app/shared/models/core/projector'; +import { ProjectorMessage } from 'app/shared/models/core/projector-message'; import { SlideManager } from 'app/slides/services/slide-manager.service'; import { CountdownRepositoryService } from 'app/core/repositories/projector/countdown-repository.service'; import { ProjectorMessageRepositoryService } from 'app/core/repositories/projector/projector-message-repository.service'; import { ViewProjectorMessage } from 'app/site/projector/models/view-projector-message'; import { ViewCountdown } from 'app/site/projector/models/view-countdown'; -import { Projectable } from 'app/site/base/projectable'; +import { MessageDialogComponent, MessageData } from '../message-dialog/message-dialog.component'; /** * The projector detail view. @@ -177,7 +179,7 @@ export class ProjectorDetailComponent extends BaseViewComponent implements OnIni } /** - * Opens the countdown dialog + * Opens the countdown dialog* * * @param viewCountdown optional existing countdown to edit */ @@ -212,6 +214,37 @@ export class ProjectorDetailComponent extends BaseViewComponent implements OnIni }); } + /** + * opens the "edit/create" dialog for messages + * + * @param viewMessage an optional ViewProjectorMessage to edit. If empty, a new one was created + */ + public openMessagesDialog(viewMessage?: ViewProjectorMessage): void { + let messageData: MessageData = { + text: '' + }; + + if (viewMessage) { + messageData = { + text: viewMessage.message + }; + } + + const dialogRef = this.dialog.open(MessageDialogComponent, { + data: messageData, + maxHeight: '90vh', + width: '800px', + maxWidth: '90vw', + disableClose: true + }); + + dialogRef.afterClosed().subscribe(result => { + if (result) { + this.submitMessage(result, viewMessage); + } + }); + } + /** * Function to send a countdown * @@ -234,4 +267,22 @@ export class ProjectorDetailComponent extends BaseViewComponent implements OnIni this.countdownRepo.create(sendData).then(() => {}, this.raiseError); } } + + /** + * Submit altered messages to the message repository + * + * @param data: The message to post + * @param viewMessage optional, set viewMessage to update an existing message + */ + public submitMessage(data: MessageData, viewMessage?: ViewProjectorMessage): void { + const sendData = new ProjectorMessage({ + message: data.text + }); + + if (viewMessage) { + this.messageRepo.update(sendData, viewMessage).then(() => {}, this.raiseError); + } else { + this.messageRepo.create(sendData).then(() => {}, 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 9057399fc..0b679f64d 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 @@ -3,15 +3,6 @@

Projectors

- - - @@ -163,11 +154,4 @@ - - - - - + \ No newline at end of file diff --git a/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.html b/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.html deleted file mode 100644 index c9b665dcb..000000000 --- a/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.html +++ /dev/null @@ -1,83 +0,0 @@ - - -
-

Messages

-
-
- -
- - New message - -
-

- -

-
-
- - - - -
- - - - - - - -
-
- -
-
- {{ message.getPreview() }} -
-
- -
-
-
-
Edit message
-

- -

-
- -
-
No messages
-
- - - - - - -
-
- - - -
No messages
-
-
diff --git a/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.scss b/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.scss deleted file mode 100644 index 6aaff8f85..000000000 --- a/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.scss +++ /dev/null @@ -1,42 +0,0 @@ -.head-spacer { - width: 100%; - height: 60px; - line-height: 60px; - text-align: right; - background: white; /* TODO: remove this and replace with theme */ - border-bottom: 1px solid rgba(0, 0, 0, 0.12); -} - -mat-card { - margin-bottom: 20px; -} - -.header-container { - display: grid; - grid-template-rows: auto; - grid-template-columns: 40px 1fr; - width: 100%; - - > div { - grid-row-start: 1; - grid-row-end: span 1; - grid-column-end: span 2; - } - - .header-projector-button { - grid-column-start: 1; - } - - .header-name { - grid-column-start: 2; - padding: 10px; - } -} - -.message { - text-align: center; - - ::ng-deep p { - margin: 0 0 10px; - } -} diff --git a/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.ts b/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.ts deleted file mode 100644 index 043b895ac..000000000 --- a/client/src/app/site/projector/components/projector-message-list/projector-message-list.component.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { Title, SafeHtml, DomSanitizer } from '@angular/platform-browser'; -import { MatSnackBar } from '@angular/material'; -import { FormGroup, FormBuilder } from '@angular/forms'; - -import { TranslateService } from '@ngx-translate/core'; - -import { BaseViewComponent } from '../../../base/base-view'; -import { ProjectorMessage } from 'app/shared/models/core/projector-message'; -import { ViewProjectorMessage } from '../../models/view-projector-message'; -import { ProjectorMessageRepositoryService } from 'app/core/repositories/projector/projector-message-repository.service'; -import { PromptService } from 'app/core/ui-services/prompt.service'; - -/** - * List view for the projector messages. - */ -@Component({ - selector: 'os-projector-message-list', - templateUrl: './projector-message-list.component.html', - styleUrls: ['./projector-message-list.component.scss'] -}) -export class ProjectorMessageListComponent extends BaseViewComponent implements OnInit { - public messageToCreate: ProjectorMessage | null; - - /** - * Source of the Data - */ - public messages: ViewProjectorMessage[] = []; - - /** - * The current focussed formgroup - */ - public updateForm: FormGroup; - - public createForm: FormGroup; - - public openId: number | null; - public editId: number | null; - - /** - */ - public constructor( - titleService: Title, - protected translate: TranslateService, // protected required for ng-translate-extract - matSnackBar: MatSnackBar, - private repo: ProjectorMessageRepositoryService, - private formBuilder: FormBuilder, - private promptService: PromptService, - private santinizer: DomSanitizer - ) { - super(titleService, translate, matSnackBar); - - const form = { - message: [''] - }; - this.createForm = this.formBuilder.group(form); - this.updateForm = this.formBuilder.group(form); - } - - /** - * Init function. - * - * Sets the title and gets/observes messages from DataStore - */ - public ngOnInit(): void { - super.setTitle('Messages'); - this.messages = this.repo.getSortedViewModelList(); - this.repo.getViewModelListObservable().subscribe(messages => (this.messages = messages)); - } - - public getSafeMessage(message: ViewProjectorMessage): SafeHtml { - return this.santinizer.bypassSecurityTrustHtml(message.message); - } - - /** - * Add a new message. - */ - public onPlusButton(): void { - if (!this.messageToCreate) { - this.createForm.reset(); - this.createForm.setValue({ - message: '' - }); - this.messageToCreate = new ProjectorMessage(); - } - } - - /** - * Handler when clicking on create to create a new statute paragraph - */ - public create(): void { - if (this.createForm.valid) { - this.messageToCreate.patchValues(this.createForm.value as ProjectorMessage); - this.repo.create(this.messageToCreate).then(() => { - this.messageToCreate = null; - }, this.raiseError); - } - } - - /** - * Executed on edit button - * @param message - */ - public onEditButton(message: ViewProjectorMessage): void { - this.editId = message.id; - - this.updateForm.setValue({ - message: message.message - }); - } - - /** - * Saves the message - * @param message The message to save - */ - public onSaveButton(message: ViewProjectorMessage): void { - if (this.updateForm.valid) { - this.repo.update(this.updateForm.value as Partial, message).then(() => { - this.openId = this.editId = null; - }, this.raiseError); - } - } - - /** - * Is executed, when the delete button is pressed - * - * @param message The message to delete - */ - public async onDeleteButton(message: ViewProjectorMessage): Promise { - const title = this.translate.instant('Are you sure you want to delete the selected message?'); - if (await this.promptService.open(title, null)) { - this.repo.delete(message).then(() => (this.openId = this.editId = null), this.raiseError); - } - } - - /** - * Is executed when a mat-extension-panel is closed - * - * @param message the message in the panel - */ - public panelClosed(message: ViewProjectorMessage): void { - this.openId = null; - if (this.editId) { - this.onSaveButton(message); - } - } - - /** - * clicking Shift and Enter will save automatically - * clicking Escape will cancel the process - * - * @param event has the code - */ - public onKeyDownCreate(event: KeyboardEvent): void { - if (event.key === 'Enter' && event.shiftKey) { - this.create(); - } - if (event.key === 'Escape') { - this.onCancelCreate(); - } - } - - /** - * Cancels the current form action - */ - public onCancelCreate(): void { - this.messageToCreate = null; - } - - /** - * clicking Shift and Enter will save automatically - * clicking Escape will cancel the process - * - * @param event has the code - */ - public onKeyDownUpdate(event: KeyboardEvent): void { - if (event.key === 'Enter' && event.shiftKey) { - const message = this.messages.find(x => x.id === this.editId); - this.onSaveButton(message); - } - if (event.key === 'Escape') { - this.onCancelUpdate(); - } - } - - /** - * Cancels the current form action - */ - public onCancelUpdate(): void { - this.editId = null; - } -} diff --git a/client/src/app/site/projector/projector-routing.module.ts b/client/src/app/site/projector/projector-routing.module.ts index 1bd66de4c..3f40f9e89 100644 --- a/client/src/app/site/projector/projector-routing.module.ts +++ b/client/src/app/site/projector/projector-routing.module.ts @@ -2,7 +2,6 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { ProjectorListComponent } from './components/projector-list/projector-list.component'; import { ProjectorDetailComponent } from './components/projector-detail/projector-detail.component'; -import { ProjectorMessageListComponent } from './components/projector-message-list/projector-message-list.component'; const routes: Routes = [ { @@ -13,10 +12,6 @@ const routes: Routes = [ { path: 'detail/:id', component: ProjectorDetailComponent - }, - { - path: 'messages', - component: ProjectorMessageListComponent } ]; diff --git a/client/src/app/site/projector/projector.module.ts b/client/src/app/site/projector/projector.module.ts index 3c884c8d2..6a0192c67 100644 --- a/client/src/app/site/projector/projector.module.ts +++ b/client/src/app/site/projector/projector.module.ts @@ -5,19 +5,21 @@ 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 { ProjectorMessageListComponent } from './components/projector-message-list/projector-message-list.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'; @NgModule({ imports: [CommonModule, ProjectorRoutingModule, SharedModule], declarations: [ ProjectorListComponent, ProjectorDetailComponent, - ProjectorMessageListComponent, CountdownControlsComponent, - CountdownDialogComponent + CountdownDialogComponent, + MessageControlsComponent, + MessageDialogComponent ], - entryComponents: [CountdownDialogComponent] + entryComponents: [CountdownDialogComponent, MessageDialogComponent] }) export class ProjectorModule {}