Merge pull request #4389 from FinnStutzenstein/chyron
current speaker chyron
This commit is contained in:
commit
23c1857fa6
@ -1,10 +1,10 @@
|
|||||||
<div id="container" [osResized]="resizeSubject" [ngStyle]="containerStyle" #container>
|
<div id="container" [osResized]="resizeSubject" [ngStyle]="containerStyle" #container>
|
||||||
<div id="projector" [ngStyle]="projectorStyle">
|
<div id="projector" [ngStyle]="projectorStyle">
|
||||||
<div id="header" [ngStyle]="headerFooterStyle" *ngIf="enableHeaderAndFooter">
|
<div id="header" [ngStyle]="headerFooterStyle" *ngIf="projector && projector.show_header_footer">
|
||||||
<!-- projector logo -->
|
<!-- projector logo -->
|
||||||
<img *ngIf="enableLogo && projectorLogo" src="{{ projectorLogo }}" class="projector-logo-main" />
|
<img *ngIf="enableLogo && projectorLogo" src="{{ projectorLogo }}" class="projector-logo-main" />
|
||||||
|
|
||||||
<div *ngIf="enableTitle" id="eventdata">
|
<div *ngIf="projector.show_title" id="eventdata">
|
||||||
<div
|
<div
|
||||||
*ngIf="eventName"
|
*ngIf="eventName"
|
||||||
class="event-name"
|
class="event-name"
|
||||||
@ -19,7 +19,7 @@
|
|||||||
<os-slide-container [slideData]="slide" [scroll]="scroll" [scale]="scale"></os-slide-container>
|
<os-slide-container [slideData]="slide" [scroll]="scroll" [scale]="scale"></os-slide-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="footer" [ngStyle]="headerFooterStyle" *ngIf="enableHeaderAndFooter">
|
<div id="footer" [ngStyle]="headerFooterStyle" *ngIf="projector && projector.show_header_footer">
|
||||||
<div class="footertext">
|
<div class="footertext">
|
||||||
<span *ngIf="eventDate"> {{ eventDate }} </span>
|
<span *ngIf="eventDate"> {{ eventDate }} </span>
|
||||||
<span *ngIf="eventDate && eventLocation"> | </span>
|
<span *ngIf="eventDate && eventLocation"> | </span>
|
||||||
|
@ -52,6 +52,9 @@ export class ProjectorComponent extends BaseComponent implements OnDestroy {
|
|||||||
) {
|
) {
|
||||||
this.updateScaling();
|
this.updateScaling();
|
||||||
}
|
}
|
||||||
|
this.projectorStyle['background-color'] = projector.background_color;
|
||||||
|
this.headerFooterStyle.color = projector.header_font_color;
|
||||||
|
this.headerFooterStyle['background-color'] = projector.header_background_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +97,8 @@ export class ProjectorComponent extends BaseComponent implements OnDestroy {
|
|||||||
/**
|
/**
|
||||||
* Dynamic style attributes for the header and footer.
|
* Dynamic style attributes for the header and footer.
|
||||||
*/
|
*/
|
||||||
public headerFooterStyle: { 'background-color': string; color: string } = {
|
public headerFooterStyle: { 'background-image': string; 'background-color': string; color: string } = {
|
||||||
|
'background-image': 'none',
|
||||||
'background-color': 'blue',
|
'background-color': 'blue',
|
||||||
color: 'white'
|
color: 'white'
|
||||||
};
|
};
|
||||||
@ -156,26 +160,6 @@ export class ProjectorComponent extends BaseComponent implements OnDestroy {
|
|||||||
private configService: ConfigService
|
private configService: ConfigService
|
||||||
) {
|
) {
|
||||||
super(titleService, translate);
|
super(titleService, translate);
|
||||||
|
|
||||||
// Get all important config variables.
|
|
||||||
|
|
||||||
// enable header/footer
|
|
||||||
this.configService
|
|
||||||
.get<boolean>('projector_enable_header_footer')
|
|
||||||
.subscribe(val => (this.enableHeaderAndFooter = val));
|
|
||||||
this.configService.get<boolean>('projector_enable_title').subscribe(val => (this.enableTitle = val));
|
|
||||||
|
|
||||||
// projector colors
|
|
||||||
this.configService
|
|
||||||
.get<string>('projector_header_fontcolor')
|
|
||||||
.subscribe(val => (this.headerFooterStyle.color = val));
|
|
||||||
this.configService
|
|
||||||
.get<string>('projector_header_backgroundcolor')
|
|
||||||
.subscribe(val => (this.headerFooterStyle['background-color'] = val));
|
|
||||||
this.configService
|
|
||||||
.get<string>('projector_background_color')
|
|
||||||
.subscribe(val => (this.projectorStyle['background-color'] = val));
|
|
||||||
|
|
||||||
// projector logo / background-image
|
// projector logo / background-image
|
||||||
this.configService.get<boolean>('projector_enable_logo').subscribe(val => (this.enableLogo = val));
|
this.configService.get<boolean>('projector_enable_logo').subscribe(val => (this.enableLogo = val));
|
||||||
this.configService.get<{ path?: string }>('logo_projector_main').subscribe(val => {
|
this.configService.get<{ path?: string }>('logo_projector_main').subscribe(val => {
|
||||||
@ -186,6 +170,8 @@ export class ProjectorComponent extends BaseComponent implements OnDestroy {
|
|||||||
this.configService.get<{ path?: string }>('logo_projector_header').subscribe(val => {
|
this.configService.get<{ path?: string }>('logo_projector_header').subscribe(val => {
|
||||||
if (val && val.path) {
|
if (val && val.path) {
|
||||||
this.headerFooterStyle['background-image'] = "url('" + val.path + "')";
|
this.headerFooterStyle['background-image'] = "url('" + val.path + "')";
|
||||||
|
} else {
|
||||||
|
this.headerFooterStyle['background-image'] = 'none';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -65,6 +65,13 @@ export class Projector extends BaseModel<Projector> {
|
|||||||
public height: number;
|
public height: number;
|
||||||
public reference_projector_id: number;
|
public reference_projector_id: number;
|
||||||
public projectiondefaults: ProjectionDefault[];
|
public projectiondefaults: ProjectionDefault[];
|
||||||
|
public background_color: string;
|
||||||
|
public header_background_color: string;
|
||||||
|
public header_font_color: string;
|
||||||
|
public header_h1_color: string;
|
||||||
|
public show_header_footer: boolean;
|
||||||
|
public show_title: boolean;
|
||||||
|
public show_logo: boolean;
|
||||||
|
|
||||||
public constructor(input?: any) {
|
public constructor(input?: any) {
|
||||||
super(Projector.COLLECTIONSTRING, input);
|
super(Projector.COLLECTIONSTRING, input);
|
||||||
|
@ -9,7 +9,6 @@ import { BehaviorSubject, Subscription } from 'rxjs';
|
|||||||
|
|
||||||
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
import { ItemRepositoryService } from 'app/core/repositories/agenda/item-repository.service';
|
||||||
import { BaseViewComponent } from 'app/site/base/base-view';
|
import { BaseViewComponent } from 'app/site/base/base-view';
|
||||||
import { CurrentListOfSpeakersSlideService } from 'app/site/projector/services/current-list-of-of-speakers-slide.service';
|
|
||||||
import { OperatorService } from 'app/core/core-services/operator.service';
|
import { OperatorService } from 'app/core/core-services/operator.service';
|
||||||
import { ProjectorRepositoryService } from 'app/core/repositories/projector/projector-repository.service';
|
import { ProjectorRepositoryService } from 'app/core/repositories/projector/projector-repository.service';
|
||||||
import { PromptService } from 'app/core/ui-services/prompt.service';
|
import { PromptService } from 'app/core/ui-services/prompt.service';
|
||||||
@ -20,6 +19,7 @@ import { ViewProjector } from 'app/site/projector/models/view-projector';
|
|||||||
import { ViewUser } from 'app/site/users/models/view-user';
|
import { ViewUser } from 'app/site/users/models/view-user';
|
||||||
import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service';
|
import { UserRepositoryService } from 'app/core/repositories/users/user-repository.service';
|
||||||
import { DurationService } from 'app/core/ui-services/duration.service';
|
import { DurationService } from 'app/core/ui-services/duration.service';
|
||||||
|
import { CurrentAgendaItemService } from 'app/site/projector/services/current-agenda-item.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of speakers for agenda items.
|
* The list of speakers for agenda items.
|
||||||
@ -104,7 +104,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
|||||||
* @param itemRepo Repository fpr agenda items
|
* @param itemRepo Repository fpr agenda items
|
||||||
* @param op the current operator
|
* @param op the current operator
|
||||||
* @param promptService
|
* @param promptService
|
||||||
* @param currentListOfSpeakersService
|
* @param currentAgendaItemService
|
||||||
* @param durationService helper for speech duration display
|
* @param durationService helper for speech duration display
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
@ -116,7 +116,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
|||||||
private itemRepo: ItemRepositoryService,
|
private itemRepo: ItemRepositoryService,
|
||||||
private op: OperatorService,
|
private op: OperatorService,
|
||||||
private promptService: PromptService,
|
private promptService: PromptService,
|
||||||
private currentListOfSpeakersService: CurrentListOfSpeakersSlideService,
|
private currentAgendaItemService: CurrentAgendaItemService,
|
||||||
private durationService: DurationService,
|
private durationService: DurationService,
|
||||||
private userRepository: UserRepositoryService
|
private userRepository: UserRepositoryService
|
||||||
) {
|
) {
|
||||||
@ -185,7 +185,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
|
|||||||
this.viewItem = null;
|
this.viewItem = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.projectorSubscription = this.currentListOfSpeakersService
|
this.projectorSubscription = this.currentAgendaItemService
|
||||||
.getAgendaItemObservable(projector)
|
.getAgendaItemObservable(projector)
|
||||||
.subscribe(item => {
|
.subscribe(item => {
|
||||||
if (item) {
|
if (item) {
|
||||||
|
@ -131,6 +131,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4>Current speaker chyron</h4>
|
||||||
|
<mat-list>
|
||||||
|
<mat-list-item [ngClass]="{'projected': isChyronProjected()}">
|
||||||
|
<button type="button" mat-icon-button (click)="toggleChyron()">
|
||||||
|
<mat-icon>videocam</mat-icon>
|
||||||
|
</button>
|
||||||
|
<span translate>Current speaker chyron</span>
|
||||||
|
</mat-list-item>
|
||||||
|
</mat-list>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="queue">
|
<div class="queue">
|
||||||
<h5 translate>Queue</h5>
|
<h5 translate>Queue</h5>
|
||||||
<div cdkDropList class="drop-list" (cdkDropListDropped)="onSortingChange($event)">
|
<div cdkDropList class="drop-list" (cdkDropListDropped)="onSortingChange($event)">
|
||||||
|
@ -21,6 +21,7 @@ import { ViewProjectorMessage } from 'app/site/projector/models/view-projector-m
|
|||||||
import { ViewCountdown } from 'app/site/projector/models/view-countdown';
|
import { ViewCountdown } from 'app/site/projector/models/view-countdown';
|
||||||
import { Projectable } from 'app/site/base/projectable';
|
import { Projectable } from 'app/site/base/projectable';
|
||||||
import { CurrentListOfSpeakersSlideService } from '../../services/current-list-of-of-speakers-slide.service';
|
import { CurrentListOfSpeakersSlideService } from '../../services/current-list-of-of-speakers-slide.service';
|
||||||
|
import { CurrentSpeakerChyronSlideService } from '../../services/current-speaker-chyron-slide.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The projector detail view.
|
* The projector detail view.
|
||||||
@ -59,7 +60,8 @@ export class ProjectorDetailComponent extends BaseViewComponent implements OnIni
|
|||||||
private slideManager: SlideManager,
|
private slideManager: SlideManager,
|
||||||
private countdownRepo: CountdownRepositoryService,
|
private countdownRepo: CountdownRepositoryService,
|
||||||
private messageRepo: ProjectorMessageRepositoryService,
|
private messageRepo: ProjectorMessageRepositoryService,
|
||||||
private currentListOfSpeakersSlideService: CurrentListOfSpeakersSlideService
|
private currentListOfSpeakersSlideService: CurrentListOfSpeakersSlideService,
|
||||||
|
private currentSpeakerChyronService: CurrentSpeakerChyronSlideService
|
||||||
) {
|
) {
|
||||||
super(titleService, translate, matSnackBar);
|
super(titleService, translate, matSnackBar);
|
||||||
|
|
||||||
@ -148,4 +150,12 @@ export class ProjectorDetailComponent extends BaseViewComponent implements OnIni
|
|||||||
public toggleClos(stable: boolean): void {
|
public toggleClos(stable: boolean): void {
|
||||||
this.currentListOfSpeakersSlideService.toggleOn(this.projector, stable);
|
this.currentListOfSpeakersSlideService.toggleOn(this.projector, stable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isChyronProjected(): boolean {
|
||||||
|
return this.currentSpeakerChyronService.isProjectedOn(this.projector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleChyron(): void {
|
||||||
|
this.currentSpeakerChyronService.toggleOn(this.projector);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,52 @@
|
|||||||
<mat-slider [thumbLabel]="true" formControlName="width" min="800" max="3840" step="10"></mat-slider>
|
<mat-slider [thumbLabel]="true" formControlName="width" min="800" max="3840" step="10"></mat-slider>
|
||||||
{{ updateForm.value.width }}
|
{{ updateForm.value.width }}
|
||||||
|
|
||||||
<!-- Clock -->
|
<!-- colors -->
|
||||||
|
<mat-form-field>
|
||||||
|
<span translate>Background color</span>
|
||||||
|
<input matInput formControlName="background_color" type="color" />
|
||||||
|
<mat-hint *ngIf="!updateForm.controls.background_color.valid">
|
||||||
|
<span translate>Required</span>
|
||||||
|
</mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field>
|
||||||
|
<span translate>Header background color</span>
|
||||||
|
<input matInput formControlName="header_background_color" type="color" />
|
||||||
|
<mat-hint *ngIf="!updateForm.controls.header_background_color.valid">
|
||||||
|
<span translate>Required</span>
|
||||||
|
</mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field>
|
||||||
|
<span translate>Header font color</span>
|
||||||
|
<input matInput formControlName="header_font_color" type="color" />
|
||||||
|
<mat-hint *ngIf="!updateForm.controls.header_font_color.valid">
|
||||||
|
<span translate>Required</span>
|
||||||
|
</mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field>
|
||||||
|
<span translate>Header headline color</span>
|
||||||
|
<input matInput formControlName="header_h1_color" type="color" />
|
||||||
|
<mat-hint *ngIf="!updateForm.controls.header_h1_color.valid">
|
||||||
|
<span translate>Required</span>
|
||||||
|
</mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<!-- checkboxes -->
|
||||||
|
<div>
|
||||||
|
<mat-checkbox formControlName="show_header_footer">
|
||||||
|
<span translate>Show header and footer</span>
|
||||||
|
</mat-checkbox>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<mat-checkbox formControlName="show_title">
|
||||||
|
<span translate>Show title</span>
|
||||||
|
</mat-checkbox>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<mat-checkbox formControlName="show_logo">
|
||||||
|
<span translate>Show logo</span>
|
||||||
|
</mat-checkbox>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<mat-checkbox formControlName="clock">
|
<mat-checkbox formControlName="clock">
|
||||||
<span translate>Show clock</span>
|
<span translate>Show clock</span>
|
||||||
|
@ -105,7 +105,14 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit
|
|||||||
aspectRatio: ['', Validators.required],
|
aspectRatio: ['', Validators.required],
|
||||||
width: [0, Validators.required],
|
width: [0, Validators.required],
|
||||||
clock: [true],
|
clock: [true],
|
||||||
reference_projector_id: []
|
reference_projector_id: [],
|
||||||
|
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: []
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,11 +209,21 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit
|
|||||||
const reference_projector_id = projector.reference_projector_id
|
const reference_projector_id = projector.reference_projector_id
|
||||||
? projector.reference_projector_id
|
? projector.reference_projector_id
|
||||||
: projector.id;
|
: projector.id;
|
||||||
this.updateForm.patchValue({
|
/*this.updateForm.patchValue({
|
||||||
name: projector.name,
|
name: projector.name,
|
||||||
aspectRatio: this.getAspectRatioKey(projector),
|
aspectRatio: this.getAspectRatioKey(projector),
|
||||||
width: projector.width,
|
width: projector.width,
|
||||||
clock: this.clockSlideService.isProjectedOn(projector),
|
clock: this.clockSlideService.isProjectedOn(projector),
|
||||||
|
reference_projector_id: reference_projector_id,
|
||||||
|
background_color: projector.background_color,
|
||||||
|
show_header_footer: projector.show_header_footer,
|
||||||
|
show_title: projector.show_title,
|
||||||
|
show_logo: projector.show_logo
|
||||||
|
});*/
|
||||||
|
this.updateForm.patchValue(projector.projector);
|
||||||
|
this.updateForm.patchValue({
|
||||||
|
aspectRatio: this.getAspectRatioKey(projector),
|
||||||
|
clock: this.clockSlideService.isProjectedOn(projector),
|
||||||
reference_projector_id: reference_projector_id
|
reference_projector_id: reference_projector_id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -231,12 +248,21 @@ export class ProjectorListComponent extends BaseViewComponent implements OnInit
|
|||||||
if (projector.id !== this.editId || !this.updateForm.valid) {
|
if (projector.id !== this.editId || !this.updateForm.valid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const updateProjector: Partial<Projector> = {
|
const updateProjector: Partial<Projector> = this.updateForm.value;
|
||||||
|
/*const updateProjector: Partial<Projector> = {
|
||||||
name: this.updateForm.value.name,
|
name: this.updateForm.value.name,
|
||||||
width: this.updateForm.value.width,
|
width: this.updateForm.value.width,
|
||||||
height: Math.round(this.updateForm.value.width / aspectRatios[this.updateForm.value.aspectRatio]),
|
height: Math.round(this.updateForm.value.width / aspectRatios[this.updateForm.value.aspectRatio]),
|
||||||
reference_projector_id: this.updateForm.value.reference_projector_id
|
reference_projector_id: this.updateForm.value.reference_projector_id,
|
||||||
};
|
background_color: this.updateForm.value.background_color,
|
||||||
|
show_header_footer: this.updateForm.value.show_header_footer,
|
||||||
|
show_title: this.updateForm.value.show_title,
|
||||||
|
show_logo: this.updateForm.value.show_logo
|
||||||
|
};*/
|
||||||
|
updateProjector.height = Math.round(
|
||||||
|
this.updateForm.value.width / aspectRatios[this.updateForm.value.aspectRatio]
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.clockSlideService.setProjectedOn(projector, this.updateForm.value.clock);
|
await this.clockSlideService.setProjectedOn(projector, this.updateForm.value.clock);
|
||||||
await this.repo.update(updateProjector, projector);
|
await this.repo.update(updateProjector, projector);
|
||||||
|
@ -54,6 +54,34 @@ export class ViewProjector extends BaseViewModel {
|
|||||||
return this.projector.reference_projector_id;
|
return this.projector.reference_projector_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get background_color(): string {
|
||||||
|
return this.projector.background_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get header_background_color(): string {
|
||||||
|
return this.projector.header_background_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get header_font_color(): string {
|
||||||
|
return this.projector.header_font_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get header_h1_color(): string {
|
||||||
|
return this.projector.header_h1_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get show_header_footer(): boolean {
|
||||||
|
return this.projector.show_header_footer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get show_title(): boolean {
|
||||||
|
return this.projector.show_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get show_logo(): boolean {
|
||||||
|
return this.projector.show_logo;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is set by the repository
|
* This is set by the repository
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { ProjectorService } from 'app/core/core-services/projector.service';
|
||||||
|
import { ViewProjector } from '../models/view-projector';
|
||||||
|
import { ProjectorRepositoryService } from 'app/core/repositories/projector/projector-repository.service';
|
||||||
|
import { SlideManager } from 'app/slides/services/slide-manager.service';
|
||||||
|
import { BaseAgendaViewModel } from 'app/site/base/base-agenda-view-model';
|
||||||
|
import { ViewItem } from 'app/site/agenda/models/view-item';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Observes the projector config for a given projector and returns a observable of the
|
||||||
|
* current view item displayed at on the projector.
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class CurrentAgendaItemService {
|
||||||
|
private currentItemIds: { [projectorId: number]: BehaviorSubject<ViewItem | null> } = {};
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private projectorService: ProjectorService,
|
||||||
|
private projectorRepo: ProjectorRepositoryService,
|
||||||
|
private slideManager: SlideManager
|
||||||
|
) {
|
||||||
|
this.projectorRepo.getGeneralViewModelObservable().subscribe(projector => {
|
||||||
|
if (projector && this.currentItemIds[projector.id]) {
|
||||||
|
const item = this.getCurrentAgendaItemIdForProjector(projector);
|
||||||
|
this.currentItemIds[projector.id].next(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an observable for the agenda item id of the currently projected element on the
|
||||||
|
* given projector.
|
||||||
|
*
|
||||||
|
* @param projector The projector to observe.
|
||||||
|
* @returns An observalbe for the agenda item id. Null, if no element with an agenda item is shown.
|
||||||
|
*/
|
||||||
|
public getAgendaItemObservable(projector: ViewProjector): Observable<ViewItem | null> {
|
||||||
|
if (!this.currentItemIds[projector.id]) {
|
||||||
|
const item = this.getCurrentAgendaItemIdForProjector(projector);
|
||||||
|
this.currentItemIds[projector.id] = new BehaviorSubject<ViewItem | null>(item);
|
||||||
|
}
|
||||||
|
return this.currentItemIds[projector.id].asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to get the agenda item id for one non stable element on the projector.
|
||||||
|
*
|
||||||
|
* @param projector The projector
|
||||||
|
* @returns The agenda item id or null, if there is no such projector element.
|
||||||
|
*/
|
||||||
|
private getCurrentAgendaItemIdForProjector(projector: ViewProjector): ViewItem | null {
|
||||||
|
const nonStableElements = projector.elements.filter(element => !element.stable);
|
||||||
|
if (nonStableElements.length > 0) {
|
||||||
|
const nonStableElement = this.slideManager.getIdentifialbeProjectorElement(nonStableElements[0]); // The normal case is just one non stable slide
|
||||||
|
try {
|
||||||
|
const viewModel = this.projectorService.getViewModelFromProjectorElement(nonStableElement);
|
||||||
|
if (viewModel instanceof BaseAgendaViewModel) {
|
||||||
|
return viewModel.getAgendaItem();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// make TypeScript silent.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,33 +1,18 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { ProjectorService } from 'app/core/core-services/projector.service';
|
import { ProjectorService } from 'app/core/core-services/projector.service';
|
||||||
import { ViewProjector } from '../models/view-projector';
|
import { ViewProjector } from '../models/view-projector';
|
||||||
import { IdentifiableProjectorElement } from 'app/shared/models/core/projector';
|
import { IdentifiableProjectorElement } from 'app/shared/models/core/projector';
|
||||||
import { ProjectorRepositoryService } from 'app/core/repositories/projector/projector-repository.service';
|
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
|
||||||
import { SlideManager } from 'app/slides/services/slide-manager.service';
|
|
||||||
import { BaseAgendaViewModel } from 'app/site/base/base-agenda-view-model';
|
|
||||||
import { ViewItem } from 'app/site/agenda/models/view-item';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Handles the curent list of speakers slide. Manages the projection and provides
|
||||||
|
* function to check, if it is projected. Handles the overlay and slide.
|
||||||
*/
|
*/
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class CurrentListOfSpeakersSlideService {
|
export class CurrentListOfSpeakersSlideService {
|
||||||
private currentItemIds: { [projectorId: number]: BehaviorSubject<ViewItem | null> } = {};
|
public constructor(private projectorService: ProjectorService) {}
|
||||||
|
|
||||||
public constructor(
|
|
||||||
private projectorService: ProjectorService,
|
|
||||||
private projectorRepo: ProjectorRepositoryService,
|
|
||||||
private slideManager: SlideManager
|
|
||||||
) {
|
|
||||||
this.projectorRepo.getGeneralViewModelObservable().subscribe(projector => {
|
|
||||||
if (projector && this.currentItemIds[projector.id]) {
|
|
||||||
const item = this.getCurrentAgendaItemIdForProjector(projector);
|
|
||||||
this.currentItemIds[projector.id].next(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the basic projector element for the CLOS slide. If overlay=True, the projector element
|
* Returns the basic projector element for the CLOS slide. If overlay=True, the projector element
|
||||||
@ -44,43 +29,6 @@ export class CurrentListOfSpeakersSlideService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an observable for the agenda item id of the currently projected element on the
|
|
||||||
* given projector.
|
|
||||||
*
|
|
||||||
* @param projector The projector to observe.
|
|
||||||
* @returns An observalbe for the agenda item id. Null, if no element with an agenda item is shown.
|
|
||||||
*/
|
|
||||||
public getAgendaItemObservable(projector: ViewProjector): Observable<ViewItem | null> {
|
|
||||||
if (!this.currentItemIds[projector.id]) {
|
|
||||||
const item = this.getCurrentAgendaItemIdForProjector(projector);
|
|
||||||
this.currentItemIds[projector.id] = new BehaviorSubject<ViewItem | null>(item);
|
|
||||||
}
|
|
||||||
return this.currentItemIds[projector.id].asObservable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tries to get the agenda item id for one non stable element on the projector.
|
|
||||||
*
|
|
||||||
* @param projector The projector
|
|
||||||
* @returns The agenda item id or null, if there is no such projector element.
|
|
||||||
*/
|
|
||||||
private getCurrentAgendaItemIdForProjector(projector: ViewProjector): ViewItem | null {
|
|
||||||
const nonStableElements = projector.elements.filter(element => !element.stable);
|
|
||||||
if (nonStableElements.length > 0) {
|
|
||||||
const nonStableElement = this.slideManager.getIdentifialbeProjectorElement(nonStableElements[0]); // The normal case is just one non stable slide
|
|
||||||
try {
|
|
||||||
const viewModel = this.projectorService.getViewModelFromProjectorElement(nonStableElement);
|
|
||||||
if (viewModel instanceof BaseAgendaViewModel) {
|
|
||||||
return viewModel.getAgendaItem();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// make TypeScript silent.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queries, if the slide/overlay is projected on the given projector.
|
* Queries, if the slide/overlay is projected on the given projector.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { ProjectorService } from 'app/core/core-services/projector.service';
|
||||||
|
import { ViewProjector } from '../models/view-projector';
|
||||||
|
import { IdentifiableProjectorElement } from 'app/shared/models/core/projector';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class CurrentSpeakerChyronSlideService {
|
||||||
|
public constructor(private projectorService: ProjectorService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the basic projector element for the chyron slide
|
||||||
|
*
|
||||||
|
* @returns the identifiable chyron projector element.
|
||||||
|
*/
|
||||||
|
private getCurrentSpeakerChyronProjectorElement(): IdentifiableProjectorElement {
|
||||||
|
return {
|
||||||
|
name: 'agenda/current-speaker-chyron',
|
||||||
|
stable: true,
|
||||||
|
getIdentifiers: () => ['name']
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries, if the slide is projected on the given projector.
|
||||||
|
*
|
||||||
|
* @param projector The projector
|
||||||
|
* @returns if the slide is projected on the projector
|
||||||
|
*/
|
||||||
|
public isProjectedOn(projector: ViewProjector): boolean {
|
||||||
|
return this.projectorService.isProjectedOn(this.getCurrentSpeakerChyronProjectorElement(), projector.projector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle the projection state of the slide on the given projector
|
||||||
|
*
|
||||||
|
* @param projector The projector
|
||||||
|
*/
|
||||||
|
public async toggleOn(projector: ViewProjector): Promise<void> {
|
||||||
|
const isClosProjected = this.isProjectedOn(projector);
|
||||||
|
if (isClosProjected) {
|
||||||
|
await this.projectorService.removeFrom(projector.projector, this.getCurrentSpeakerChyronProjectorElement());
|
||||||
|
} else {
|
||||||
|
await this.projectorService.projectOn(projector.projector, this.getCurrentSpeakerChyronProjectorElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@
|
|||||||
<div *ngIf="data.data.current" class="currentSpeaker">
|
<div *ngIf="data.data.current" class="currentSpeaker">
|
||||||
<mat-icon>mic</mat-icon>
|
<mat-icon>mic</mat-icon>
|
||||||
<span>{{ data.data.current.user }}</span>
|
<span>{{ data.data.current.user }}</span>
|
||||||
|
<mat-icon *ngIf="data.data.current.marked">star</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Next speakers -->
|
<!-- Next speakers -->
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
export interface CurrentSpeakerChyronSlideData {
|
||||||
|
current_speaker?: string;
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<div id="chyron" *ngIf="data">
|
||||||
|
<span id="inner">
|
||||||
|
{{ data.data.current_speaker }}
|
||||||
|
</span>
|
||||||
|
</div>
|
@ -0,0 +1,19 @@
|
|||||||
|
#chyron {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 10;
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
font-size: 32px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.1;
|
||||||
|
display: table;
|
||||||
|
|
||||||
|
#inner {
|
||||||
|
display: table-cell;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CurrentSpeakerChyronSlideComponent } from './current-speaker-chyron-slide.component';
|
||||||
|
import { E2EImportsModule } from '../../../../e2e-imports.module';
|
||||||
|
|
||||||
|
describe('CurrentSpeakerChyronSlideComponent', () => {
|
||||||
|
let component: CurrentSpeakerChyronSlideComponent;
|
||||||
|
let fixture: ComponentFixture<CurrentSpeakerChyronSlideComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [E2EImportsModule],
|
||||||
|
declarations: [CurrentSpeakerChyronSlideComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(CurrentSpeakerChyronSlideComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
import { BaseSlideComponent } from 'app/slides/base-slide-component';
|
||||||
|
import { CurrentSpeakerChyronSlideData } from './current-speaker-chyron-slide-data';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'os-current-speaker-chyron-speakers-slide',
|
||||||
|
templateUrl: './current-speaker-chyron-slide.component.html',
|
||||||
|
styleUrls: ['./current-speaker-chyron-slide.component.scss']
|
||||||
|
})
|
||||||
|
export class CurrentSpeakerChyronSlideComponent extends BaseSlideComponent<CurrentSpeakerChyronSlideData> {
|
||||||
|
public constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
import { CurrentSpeakerChyronSlideModule } from './current-speaker-chyron-slide.module';
|
||||||
|
|
||||||
|
describe('CurrentSpeakerChyronSlideModule', () => {
|
||||||
|
let currentSpeakerChyronSlideModule: CurrentSpeakerChyronSlideModule;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
currentSpeakerChyronSlideModule = new CurrentSpeakerChyronSlideModule();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create an instance', () => {
|
||||||
|
expect(currentSpeakerChyronSlideModule).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,7 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
import { makeSlideModule } from 'app/slides/base-slide-module';
|
||||||
|
import { CurrentSpeakerChyronSlideComponent } from './current-speaker-chyron-slide.component';
|
||||||
|
|
||||||
|
@NgModule(makeSlideModule(CurrentSpeakerChyronSlideComponent))
|
||||||
|
export class CurrentSpeakerChyronSlideModule {}
|
@ -72,6 +72,11 @@ export const allSlidesDynamicConfiguration: (SlideDynamicConfiguration & Slide)[
|
|||||||
scaleable: false,
|
scaleable: false,
|
||||||
scrollable: false
|
scrollable: false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
slide: 'agenda/current-speaker-chyron',
|
||||||
|
scaleable: false,
|
||||||
|
scrollable: false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
slide: 'assignments/assignment',
|
slide: 'assignments/assignment',
|
||||||
scaleable: true,
|
scaleable: true,
|
||||||
|
@ -78,7 +78,7 @@ export const allSlides: SlideManifest[] = [
|
|||||||
loadChildren:
|
loadChildren:
|
||||||
'./slides/agenda/current-list-of-speakers/current-list-of-speakers-slide.module#CurrentListOfSpeakersSlideModule',
|
'./slides/agenda/current-list-of-speakers/current-list-of-speakers-slide.module#CurrentListOfSpeakersSlideModule',
|
||||||
verboseName: 'Current list of speakers',
|
verboseName: 'Current list of speakers',
|
||||||
elementIdentifiers: ['name', 'id'],
|
elementIdentifiers: ['name'],
|
||||||
canBeMappedToModel: false
|
canBeMappedToModel: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -87,7 +87,16 @@ export const allSlides: SlideManifest[] = [
|
|||||||
loadChildren:
|
loadChildren:
|
||||||
'./slides/agenda/current-list-of-speakers-overlay/current-list-of-speakers-overlay-slide.module#CurrentListOfSpeakersOverlaySlideModule',
|
'./slides/agenda/current-list-of-speakers-overlay/current-list-of-speakers-overlay-slide.module#CurrentListOfSpeakersOverlaySlideModule',
|
||||||
verboseName: 'Current list of speakers overlay',
|
verboseName: 'Current list of speakers overlay',
|
||||||
elementIdentifiers: ['name', 'id'],
|
elementIdentifiers: ['name'],
|
||||||
|
canBeMappedToModel: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slide: 'agenda/current-speaker-chyron',
|
||||||
|
path: 'agenda/current-speaker-chyron',
|
||||||
|
loadChildren:
|
||||||
|
'./slides/agenda/current-speaker-chyron/current-speaker-chyron-slide.module#CurrentSpeakerChyronSlideModule',
|
||||||
|
verboseName: 'Current speaker chyron',
|
||||||
|
elementIdentifiers: ['name'],
|
||||||
canBeMappedToModel: false
|
canBeMappedToModel: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -65,8 +65,14 @@
|
|||||||
background-color: mat-color($background, app-bar);
|
background-color: mat-color($background, app-bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
// drag & drop view
|
/* drag & drop views */
|
||||||
.node-content-wrapper {
|
.node-content-wrapper {
|
||||||
background-color: mat-color($background, app-bar);
|
background-color: mat-color($background, app-bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* projector components */
|
||||||
|
#chyron {
|
||||||
|
background-color: mat-color($primary);
|
||||||
|
color: white; // TODO
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
* {
|
* {
|
||||||
font-family: customProjectorFont;
|
font-family: customProjectorFont;
|
||||||
}
|
}
|
||||||
|
.material-icons {
|
||||||
|
font-family: 'Material Icons';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List, Union
|
||||||
|
|
||||||
from ..users.projector import get_user_name
|
from ..users.projector import get_user_name
|
||||||
from ..utils.projector import (
|
from ..utils.projector import (
|
||||||
@ -149,31 +149,16 @@ def get_list_of_speakers_slide_data(all_data: AllData, item_id: int) -> Dict[str
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def current_list_of_speakers_slide(
|
def get_current_item_id_for_projector(
|
||||||
all_data: AllData, element: Dict[str, Any], projector_id: int
|
all_data: AllData, projector: Dict[str, Any]
|
||||||
) -> Dict[str, Any]:
|
) -> Union[int, None]:
|
||||||
"""
|
"""
|
||||||
The current list of speakers slide. Creates the data for the given projector.
|
Search for elements, that do have an agenda item:
|
||||||
|
Try to get a model by the collection and id in the element. This
|
||||||
|
model needs to have a 'agenda_item_id'. This item must exist. The first
|
||||||
|
matching element is taken.
|
||||||
"""
|
"""
|
||||||
try:
|
elements = projector["elements"]
|
||||||
this_projector = all_data["core/projector"][projector_id]
|
|
||||||
except KeyError:
|
|
||||||
raise ProjectorElementException(f"Projector {projector_id} does not exist")
|
|
||||||
|
|
||||||
reference_projector_id = this_projector["reference_projector_id"] or projector_id
|
|
||||||
try:
|
|
||||||
reference_projector = all_data["core/projector"][reference_projector_id]
|
|
||||||
except KeyError:
|
|
||||||
raise ProjectorElementException(
|
|
||||||
f"Projector {reference_projector_id} does not exist"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Search for elements, that do have an agenda item:
|
|
||||||
# Try to get a model by the collection and id in the element. This
|
|
||||||
# model needs to have a 'agenda_item_id'. This item must exist. The first
|
|
||||||
# matching element is taken.
|
|
||||||
|
|
||||||
elements = reference_projector["elements"]
|
|
||||||
item_id = None
|
item_id = None
|
||||||
for element in elements:
|
for element in elements:
|
||||||
if "id" not in element:
|
if "id" not in element:
|
||||||
@ -193,12 +178,69 @@ def current_list_of_speakers_slide(
|
|||||||
item_id = model["agenda_item_id"]
|
item_id = model["agenda_item_id"]
|
||||||
break
|
break
|
||||||
|
|
||||||
|
return item_id
|
||||||
|
|
||||||
|
|
||||||
|
def get_reference_projector(all_data: AllData, projector_id: int) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Returns the reference projector to the given projector (by id)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
this_projector = all_data["core/projector"][projector_id]
|
||||||
|
except KeyError:
|
||||||
|
raise ProjectorElementException(f"Projector {projector_id} does not exist")
|
||||||
|
|
||||||
|
reference_projector_id = this_projector["reference_projector_id"] or projector_id
|
||||||
|
try:
|
||||||
|
reference_projector = all_data["core/projector"][reference_projector_id]
|
||||||
|
except KeyError:
|
||||||
|
raise ProjectorElementException(
|
||||||
|
f"Projector {reference_projector_id} does not exist"
|
||||||
|
)
|
||||||
|
|
||||||
|
return reference_projector
|
||||||
|
|
||||||
|
|
||||||
|
def current_list_of_speakers_slide(
|
||||||
|
all_data: AllData, element: Dict[str, Any], projector_id: int
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
The current list of speakers slide. Creates the data for the given projector.
|
||||||
|
"""
|
||||||
|
reference_projector = get_reference_projector(all_data, projector_id)
|
||||||
|
item_id = get_current_item_id_for_projector(all_data, reference_projector)
|
||||||
if item_id is None: # no element found
|
if item_id is None: # no element found
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
return get_list_of_speakers_slide_data(all_data, item_id)
|
return get_list_of_speakers_slide_data(all_data, item_id)
|
||||||
|
|
||||||
|
|
||||||
|
def current_speaker_chyron_slide(
|
||||||
|
all_data: AllData, element: Dict[str, Any], projector_id: int
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Returns the username for the current speaker.
|
||||||
|
"""
|
||||||
|
reference_projector = get_reference_projector(all_data, projector_id)
|
||||||
|
item_id = get_current_item_id_for_projector(all_data, reference_projector)
|
||||||
|
if item_id is None: # no element found
|
||||||
|
return {}
|
||||||
|
|
||||||
|
# get item
|
||||||
|
try:
|
||||||
|
item = all_data["agenda/item"][item_id]
|
||||||
|
except KeyError:
|
||||||
|
raise ProjectorElementException(f"Item {item_id} does not exist")
|
||||||
|
|
||||||
|
# find current speaker
|
||||||
|
current_speaker = None
|
||||||
|
for speaker in item["speakers"]:
|
||||||
|
if speaker["begin_time"] is not None and speaker["end_time"] is None:
|
||||||
|
current_speaker = get_user_name(all_data, speaker["user_id"])
|
||||||
|
|
||||||
|
return {"current_speaker": current_speaker}
|
||||||
|
|
||||||
|
|
||||||
def register_projector_slides() -> None:
|
def register_projector_slides() -> None:
|
||||||
register_projector_slide("agenda/item-list", item_list_slide)
|
register_projector_slide("agenda/item-list", item_list_slide)
|
||||||
register_projector_slide("agenda/list-of-speakers", list_of_speakers_slide)
|
register_projector_slide("agenda/list-of-speakers", list_of_speakers_slide)
|
||||||
@ -208,3 +250,6 @@ def register_projector_slides() -> None:
|
|||||||
register_projector_slide(
|
register_projector_slide(
|
||||||
"agenda/current-list-of-speakers-overlay", current_list_of_speakers_slide
|
"agenda/current-list-of-speakers-overlay", current_list_of_speakers_slide
|
||||||
)
|
)
|
||||||
|
register_projector_slide(
|
||||||
|
"agenda/current-speaker-chyron", current_speaker_chyron_slide
|
||||||
|
)
|
||||||
|
@ -203,62 +203,6 @@ def get_config_variables():
|
|||||||
group="Projector",
|
group="Projector",
|
||||||
)
|
)
|
||||||
|
|
||||||
yield ConfigVariable(
|
|
||||||
name="projector_enable_logo",
|
|
||||||
default_value=True,
|
|
||||||
input_type="boolean",
|
|
||||||
label="Show logo on projector",
|
|
||||||
help_text="You can replace the logo by uploading an image and set it as "
|
|
||||||
'the "Projector logo" in "files".',
|
|
||||||
weight=152,
|
|
||||||
group="Projector",
|
|
||||||
)
|
|
||||||
|
|
||||||
yield ConfigVariable(
|
|
||||||
name="projector_enable_title",
|
|
||||||
default_value=True,
|
|
||||||
input_type="boolean",
|
|
||||||
label="Show title and description of event on projector",
|
|
||||||
weight=155,
|
|
||||||
group="Projector",
|
|
||||||
)
|
|
||||||
|
|
||||||
yield ConfigVariable(
|
|
||||||
name="projector_enable_header_footer",
|
|
||||||
default_value=True,
|
|
||||||
input_type="boolean",
|
|
||||||
label="Display header and footer",
|
|
||||||
weight=157,
|
|
||||||
group="Projector",
|
|
||||||
)
|
|
||||||
|
|
||||||
yield ConfigVariable(
|
|
||||||
name="projector_header_backgroundcolor",
|
|
||||||
default_value="#317796",
|
|
||||||
input_type="colorpicker",
|
|
||||||
label="Background color of projector header and footer",
|
|
||||||
weight=160,
|
|
||||||
group="Projector",
|
|
||||||
)
|
|
||||||
|
|
||||||
yield ConfigVariable(
|
|
||||||
name="projector_header_fontcolor",
|
|
||||||
default_value="#F5F5F5",
|
|
||||||
input_type="colorpicker",
|
|
||||||
label="Font color of projector header and footer",
|
|
||||||
weight=165,
|
|
||||||
group="Projector",
|
|
||||||
)
|
|
||||||
|
|
||||||
yield ConfigVariable(
|
|
||||||
name="projector_h1_fontcolor",
|
|
||||||
default_value="#317796",
|
|
||||||
input_type="colorpicker",
|
|
||||||
label="Font color of projector headline",
|
|
||||||
weight=170,
|
|
||||||
group="Projector",
|
|
||||||
)
|
|
||||||
|
|
||||||
yield ConfigVariable(
|
yield ConfigVariable(
|
||||||
name="projector_default_countdown",
|
name="projector_default_countdown",
|
||||||
default_value=60,
|
default_value=60,
|
||||||
@ -268,15 +212,6 @@ def get_config_variables():
|
|||||||
group="Projector",
|
group="Projector",
|
||||||
)
|
)
|
||||||
|
|
||||||
yield ConfigVariable(
|
|
||||||
name="projector_background_color",
|
|
||||||
default_value="#FFFFFF",
|
|
||||||
input_type="colorpicker",
|
|
||||||
label="Backgroundolor of the projector",
|
|
||||||
weight=190,
|
|
||||||
group="Projector",
|
|
||||||
)
|
|
||||||
|
|
||||||
yield ConfigVariable(
|
yield ConfigVariable(
|
||||||
name="projector_currentListOfSpeakers_reference",
|
name="projector_currentListOfSpeakers_reference",
|
||||||
default_value=1,
|
default_value=1,
|
||||||
|
46
openslides/core/migrations/0018_auto_20190222_1209.py
Normal file
46
openslides/core/migrations/0018_auto_20190222_1209.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Generated by Django 2.1.5 on 2019-02-22 11:09
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [("core", "0017_auto_20190219_2015")]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="projector",
|
||||||
|
name="background_color",
|
||||||
|
field=models.CharField(default="#ffffff", max_length=7),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="projector",
|
||||||
|
name="header_background_color",
|
||||||
|
field=models.CharField(default="#317796", max_length=7),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="projector",
|
||||||
|
name="header_font_color",
|
||||||
|
field=models.CharField(default="#f5f5f5", max_length=7),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="projector",
|
||||||
|
name="header_h1_color",
|
||||||
|
field=models.CharField(default="#317796", max_length=7),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="projector",
|
||||||
|
name="show_header_footer",
|
||||||
|
field=models.BooleanField(default=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="projector",
|
||||||
|
name="show_logo",
|
||||||
|
field=models.BooleanField(default=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="projector",
|
||||||
|
name="show_title",
|
||||||
|
field=models.BooleanField(default=True),
|
||||||
|
),
|
||||||
|
]
|
@ -82,6 +82,14 @@ class Projector(RESTModelMixin, models.Model):
|
|||||||
width = models.PositiveIntegerField(default=1024)
|
width = models.PositiveIntegerField(default=1024)
|
||||||
height = models.PositiveIntegerField(default=768)
|
height = models.PositiveIntegerField(default=768)
|
||||||
|
|
||||||
|
background_color = models.CharField(max_length=7, default="#ffffff")
|
||||||
|
header_background_color = models.CharField(max_length=7, default="#317796")
|
||||||
|
header_font_color = models.CharField(max_length=7, default="#f5f5f5")
|
||||||
|
header_h1_color = models.CharField(max_length=7, default="#317796")
|
||||||
|
show_header_footer = models.BooleanField(default=True)
|
||||||
|
show_title = models.BooleanField(default=True)
|
||||||
|
show_logo = models.BooleanField(default=True)
|
||||||
|
|
||||||
name = models.CharField(max_length=255, unique=True, blank=True)
|
name = models.CharField(max_length=255, unique=True, blank=True)
|
||||||
|
|
||||||
reference_projector = models.ForeignKey(
|
reference_projector = models.ForeignKey(
|
||||||
|
@ -99,6 +99,13 @@ class ProjectorSerializer(ModelSerializer):
|
|||||||
"height",
|
"height",
|
||||||
"reference_projector",
|
"reference_projector",
|
||||||
"projectiondefaults",
|
"projectiondefaults",
|
||||||
|
"background_color",
|
||||||
|
"header_background_color",
|
||||||
|
"header_font_color",
|
||||||
|
"header_h1_color",
|
||||||
|
"show_header_footer",
|
||||||
|
"show_title",
|
||||||
|
"show_logo",
|
||||||
)
|
)
|
||||||
read_only_fields = ("scale", "scroll")
|
read_only_fields = ("scale", "scroll")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user