Merge pull request #5380 from FinnStutzenstein/closService

Fix the CLOS service to trigger on CLOS updates
This commit is contained in:
Sean 2020-05-20 18:29:11 +02:00 committed by GitHub
commit 4ac7b1eb4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 157 additions and 104 deletions

View File

@ -255,7 +255,7 @@ export class ProjectorService {
projectorData.forEach(entry => { projectorData.forEach(entry => {
if (entry.data.error && entry.element.stable) { if (entry.data.error && entry.element.stable) {
// Remove this element // Remove this element
const idElementToRemove = this.slideManager.getIdentifialbeProjectorElement(entry.element); const idElementToRemove = this.slideManager.getIdentifiableProjectorElement(entry.element);
elements = elements.filter(element => { elements = elements.filter(element => {
return !elementIdentifies(idElementToRemove, element); return !elementIdentifies(idElementToRemove, element);
}); });
@ -332,7 +332,7 @@ export class ProjectorService {
*/ */
public getSlideTitle(element: ProjectorElement): ProjectorTitle { public getSlideTitle(element: ProjectorElement): ProjectorTitle {
if (this.slideManager.canSlideBeMappedToModel(element.name)) { if (this.slideManager.canSlideBeMappedToModel(element.name)) {
const idElement = this.slideManager.getIdentifialbeProjectorElement(element); const idElement = this.slideManager.getIdentifiableProjectorElement(element);
const viewModel = this.getViewModelFromProjectorElement(idElement); const viewModel = this.getViewModelFromProjectorElement(idElement);
if (viewModel) { if (viewModel) {
return viewModel.getProjectorTitle(); return viewModel.getProjectorTitle();

View File

@ -21,8 +21,8 @@ import { SortingListComponent } from 'app/shared/components/sorting-list/sorting
import { BaseViewComponent } from 'app/site/base/base-view'; import { BaseViewComponent } from 'app/site/base/base-view';
import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable'; import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable';
import { ViewProjector } from 'app/site/projector/models/view-projector'; import { ViewProjector } from 'app/site/projector/models/view-projector';
import { CurrentListOfSpeakersService } from 'app/site/projector/services/current-agenda-item.service'; import { CurrentListOfSpeakersSlideService } from 'app/site/projector/services/current-list-of-speakers-slide.service';
import { CurrentListOfSpeakersSlideService } from 'app/site/projector/services/current-list-of-of-speakers-slide.service'; import { CurrentListOfSpeakersService } from 'app/site/projector/services/current-list-of-speakers.service';
import { ViewUser } from 'app/site/users/models/view-user'; import { ViewUser } from 'app/site/users/models/view-user';
import { ViewListOfSpeakers } from '../../models/view-list-of-speakers'; import { ViewListOfSpeakers } from '../../models/view-list-of-speakers';
import { SpeakerState, ViewSpeaker } from '../../models/view-speaker'; import { SpeakerState, ViewSpeaker } from '../../models/view-speaker';
@ -254,7 +254,7 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
.getListOfSpeakersObservable(referenceProjector) .getListOfSpeakersObservable(referenceProjector)
.subscribe(listOfSpeakers => { .subscribe(listOfSpeakers => {
if (listOfSpeakers) { if (listOfSpeakers) {
this.setListOfSpeakersId(listOfSpeakers.id); this.setListOfSpeakers(listOfSpeakers);
} }
}); });
this.subscriptions.push(this.projectorSubscription); this.subscriptions.push(this.projectorSubscription);
@ -279,6 +279,12 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
this.closSubscription = this.listOfSpeakersRepo.getViewModelObservable(id).subscribe(listOfSpeakers => { this.closSubscription = this.listOfSpeakersRepo.getViewModelObservable(id).subscribe(listOfSpeakers => {
if (listOfSpeakers) { if (listOfSpeakers) {
this.setListOfSpeakers(listOfSpeakers);
}
});
}
private setListOfSpeakers(listOfSpeakers: ViewListOfSpeakers): void {
const title = this.isCurrentListOfSpeakers const title = this.isCurrentListOfSpeakers
? 'Current list of speakers' ? 'Current list of speakers'
: listOfSpeakers.getTitle() + ` - ${this.translate.instant('List of speakers')}`; : listOfSpeakers.getTitle() + ` - ${this.translate.instant('List of speakers')}`;
@ -300,8 +306,6 @@ export class ListOfSpeakersComponent extends BaseViewComponent implements OnInit
this.activeSpeaker = allSpeakers.find(speaker => speaker.state === SpeakerState.CURRENT); this.activeSpeaker = allSpeakers.find(speaker => speaker.state === SpeakerState.CURRENT);
} }
});
}
/** /**
* @returns the verbose name of the model of the content object from viewItem. * @returns the verbose name of the model of the content object from viewItem.

View File

@ -138,7 +138,7 @@ export class PresentationControlComponent extends BaseViewComponent {
} }
private updateElement(element: MediafileProjectorElement): void { private updateElement(element: MediafileProjectorElement): void {
const idElement = this.slideManager.getIdentifialbeProjectorElement(element); const idElement = this.slideManager.getIdentifiableProjectorElement(element);
this.projectorService.updateElement(this.projector.projector, idElement).catch(this.raiseError); this.projectorService.updateElement(this.projector.projector, idElement).catch(this.raiseError);
} }
} }

View File

@ -29,7 +29,7 @@ import { ViewCountdown } from 'app/site/projector/models/view-countdown';
import { ViewProjectorMessage } from 'app/site/projector/models/view-projector-message'; import { ViewProjectorMessage } from 'app/site/projector/models/view-projector-message';
import { SlideManager } from 'app/slides/services/slide-manager.service'; import { SlideManager } from 'app/slides/services/slide-manager.service';
import { CountdownData, CountdownDialogComponent } from '../countdown-dialog/countdown-dialog.component'; import { CountdownData, CountdownDialogComponent } from '../countdown-dialog/countdown-dialog.component';
import { CurrentListOfSpeakersSlideService } from '../../services/current-list-of-of-speakers-slide.service'; import { CurrentListOfSpeakersSlideService } from '../../services/current-list-of-speakers-slide.service';
import { CurrentSpeakerChyronSlideService } from '../../services/current-speaker-chyron-slide.service'; import { CurrentSpeakerChyronSlideService } from '../../services/current-speaker-chyron-slide.service';
import { MessageData, MessageDialogComponent } from '../message-dialog/message-dialog.component'; import { MessageData, MessageDialogComponent } from '../message-dialog/message-dialog.component';
import { ProjectorEditDialogComponent } from '../projector-edit-dialog/projector-edit-dialog.component'; import { ProjectorEditDialogComponent } from '../projector-edit-dialog/projector-edit-dialog.component';
@ -232,7 +232,7 @@ export class ProjectorDetailComponent extends BaseViewComponent implements OnIni
} }
public unprojectCurrent(element: ProjectorElement): void { public unprojectCurrent(element: ProjectorElement): void {
const idElement = this.slideManager.getIdentifialbeProjectorElement(element); const idElement = this.slideManager.getIdentifiableProjectorElement(element);
this.projectorService.removeFrom(this.projector.projector, idElement).catch(this.raiseError); this.projectorService.removeFrom(this.projector.projector, idElement).catch(this.raiseError);
} }

View File

@ -1,75 +0,0 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { ProjectorService } from 'app/core/core-services/projector.service';
import { ProjectorRepositoryService } from 'app/core/repositories/projector/projector-repository.service';
import { ViewListOfSpeakers } from 'app/site/agenda/models/view-list-of-speakers';
import { isBaseViewModelWithListOfSpeakers } from 'app/site/base/base-view-model-with-list-of-speakers';
import { SlideManager } from 'app/slides/services/slide-manager.service';
import { ViewProjector } from '../models/view-projector';
/**
* Observes the projector config for a given projector and returns a observable of the
* current view list of speakers displayed on the projector.
*/
@Injectable({
providedIn: 'root'
})
export class CurrentListOfSpeakersService {
private currentListOfSpeakersIds: { [projectorId: number]: BehaviorSubject<ViewListOfSpeakers | null> } = {};
public constructor(
private projectorService: ProjectorService,
private projectorRepo: ProjectorRepositoryService,
private slideManager: SlideManager
) {
// Watch for changes and update the current list of speakers for every projector.
this.projectorRepo.getGeneralViewModelObservable().subscribe(projector => {
if (projector && this.currentListOfSpeakersIds[projector.id]) {
const listOfSpeakers = this.getCurrentListOfSpeakersForProjector(projector);
this.currentListOfSpeakersIds[projector.id].next(listOfSpeakers);
}
});
}
/**
* Returns an observable for the view list of speakers of the currently projected element on the
* given projector.
*
* @param projector The projector to observe.
* @returns An observalbe for the list of speakers. Null, if no element with an list of speakers is shown.
*/
public getListOfSpeakersObservable(projector: ViewProjector): Observable<ViewListOfSpeakers | null> {
if (!this.currentListOfSpeakersIds[projector.id]) {
const listOfSpeakers = this.getCurrentListOfSpeakersForProjector(projector);
this.currentListOfSpeakersIds[projector.id] = new BehaviorSubject<ViewListOfSpeakers | null>(
listOfSpeakers
);
}
return this.currentListOfSpeakersIds[projector.id].asObservable();
}
/**
* Tries to get the view list of speakers for one non stable element on the projector.
*
* @param projector The projector
* @returns The view list of speakers or null, if there is no such projector element.
*/
private getCurrentListOfSpeakersForProjector(projector: ViewProjector): ViewListOfSpeakers | null {
const nonStableElements = projector.elements.filter(element => !element.stable);
if (nonStableElements.length > 0) {
// The normal case is just one non stable slide
const nonStableElement = this.slideManager.getIdentifialbeProjectorElement(nonStableElements[0]);
try {
const viewModel = this.projectorService.getViewModelFromProjectorElement(nonStableElement);
if (isBaseViewModelWithListOfSpeakers(viewModel)) {
return viewModel.listOfSpeakers;
}
} catch (e) {
// make TypeScript silent.
}
}
return null;
}
}

View File

@ -0,0 +1,124 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { ProjectorService } from 'app/core/core-services/projector.service';
import { ListOfSpeakersRepositoryService } from 'app/core/repositories/agenda/list-of-speakers-repository.service';
import { ProjectorRepositoryService } from 'app/core/repositories/projector/projector-repository.service';
import { ViewListOfSpeakers } from 'app/site/agenda/models/view-list-of-speakers';
import { isBaseViewModelWithListOfSpeakers } from 'app/site/base/base-view-model-with-list-of-speakers';
import { SlideManager } from 'app/slides/services/slide-manager.service';
import { ViewProjector } from '../models/view-projector';
/**
* Observes the projector config for a given projector and returns a observable of the
* current view list of speakers displayed on the projector.
*/
@Injectable({
providedIn: 'root'
})
export class CurrentListOfSpeakersService {
/**
* This map holds the current (number or null) los-id for the the projector.
* It is used to check, if the reference has changed (this clos id changed for one projector).
*/
private currentListOfSpeakersIds: { [projectorId: number]: number | null } = {};
/**
* Active subscriptions for the clos of each projector.
*/
private currentListOfSpeakersSubscriptions: { [projectorId: number]: Subscription } = {};
/**
* All subjects for all clos of each projector.
*/
private currentListOfSpeakers: { [projectorId: number]: BehaviorSubject<ViewListOfSpeakers | null> } = {};
public constructor(
private projectorService: ProjectorService,
private projectorRepo: ProjectorRepositoryService,
private listOfSpeakersRepo: ListOfSpeakersRepositoryService,
private slideManager: SlideManager
) {
// Watch for changes and update the current list of speakers for every projector.
this.projectorRepo.getGeneralViewModelObservable().subscribe(projector => {
if (projector) {
this.setListOfSpeakersForProjector(projector);
}
});
}
/**
* Returns an observable for the view list of speakers of the currently projected element on the
* given projector.
*
* @param projector The projector to observe.
* @returns An observalbe for the list of speakers. Null, if no element with an list of speakers is shown.
*/
public getListOfSpeakersObservable(projector: ViewProjector): Observable<ViewListOfSpeakers | null> {
if (!this.currentListOfSpeakers[projector.id]) {
this.setListOfSpeakersForProjector(projector);
}
return this.currentListOfSpeakers[projector.id].asObservable();
}
/**
* calld on startup and on every projector update.
* If the reference didn't changed the clos for the projector just gets pushed.
*
* If it was the first call to this function for a projector or the id changed,
* there will be a subscription to the LOS-repo to stay informed when the clos
* of the projector is updated (if there is a current CLOS).
*/
private setListOfSpeakersForProjector(projector: ViewProjector): void {
const listOfSpeakers = this.getCurrentListOfSpeakersForProjector(projector);
const listOfSpeakersId = listOfSpeakers ? listOfSpeakers.id : null;
if (this.currentListOfSpeakersIds[projector.id] === listOfSpeakersId) {
this.currentListOfSpeakers[projector.id].next(listOfSpeakers);
} else {
this.currentListOfSpeakersIds[projector.id] = listOfSpeakersId;
if (!this.currentListOfSpeakers[projector.id]) {
this.currentListOfSpeakers[projector.id] = new BehaviorSubject(listOfSpeakers);
}
// Do not send the listOfSpeakers through currentListOfSpeakers, because this will be
// toggled by the listOfSpeakersRepo subscription below.
if (this.currentListOfSpeakersSubscriptions[projector.id]) {
this.currentListOfSpeakersSubscriptions[projector.id].unsubscribe();
this.currentListOfSpeakersSubscriptions[projector.id] = null;
}
if (listOfSpeakersId !== null) {
this.currentListOfSpeakersSubscriptions[projector.id] = this.listOfSpeakersRepo
.getViewModelObservable(listOfSpeakers.id)
.subscribe(los => {
if (los && this.currentListOfSpeakers[projector.id]) {
this.currentListOfSpeakers[projector.id].next(los);
}
});
}
}
}
/**
* Tries to get the view list of speakers for one non stable element on the projector.
*
* @param projector The projector
* @returns The view list of speakers or null, if there is no such projector element.
*/
private getCurrentListOfSpeakersForProjector(projector: ViewProjector): ViewListOfSpeakers | null {
const nonStableElements = projector.elements.filter(element => !element.stable);
for (const nonStableElement of nonStableElements) {
const identifiableNonStableElement = this.slideManager.getIdentifiableProjectorElement(nonStableElement);
try {
const viewModel = this.projectorService.getViewModelFromProjectorElement(identifiableNonStableElement);
if (isBaseViewModelWithListOfSpeakers(viewModel)) {
return viewModel.listOfSpeakers;
}
} catch (e) {
// make TypeScript silent.
}
}
return null;
}
}

View File

@ -54,7 +54,7 @@ export class SlideManager {
return this.loadedSlideConfigurations[slideName]; return this.loadedSlideConfigurations[slideName];
} }
public getIdentifialbeProjectorElement<P extends ProjectorElement>(element: P): IdentifiableProjectorElement & P { public getIdentifiableProjectorElement<P extends ProjectorElement>(element: P): IdentifiableProjectorElement & P {
const identifiableElement: IdentifiableProjectorElement & P = element as IdentifiableProjectorElement & P; const identifiableElement: IdentifiableProjectorElement & P = element as IdentifiableProjectorElement & P;
const identifiers = this.getManifest(element.name).elementIdentifiers.map(x => x); // map to copy. const identifiers = this.getManifest(element.name).elementIdentifiers.map(x => x); // map to copy.
identifiableElement.getIdentifiers = () => identifiers; identifiableElement.getIdentifiers = () => identifiers;