Merge pull request #4444 from FinnStutzenstein/stableElementsCleanup
clean up stable projectorelements, if they have an error
This commit is contained in:
commit
40de87c5b4
@ -1,5 +1,5 @@
|
||||
import { TestBed, inject } from '@angular/core/testing';
|
||||
import { E2EImportsModule } from '../../../../e2e-imports.module';
|
||||
import { E2EImportsModule } from '../../../e2e-imports.module';
|
||||
import { ProjectorDataService } from './projector-data.service';
|
||||
|
||||
describe('ProjectorDataService', () => {
|
@ -1,9 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { WebsocketService } from 'app/core/core-services/websocket.service';
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
import { ProjectorElement } from 'app/shared/models/core/projector';
|
||||
|
||||
export interface SlideData<T = object> {
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
|
||||
import { WebsocketService } from 'app/core/core-services/websocket.service';
|
||||
import { ProjectorElement, Projector } from 'app/shared/models/core/projector';
|
||||
|
||||
export interface SlideData<T = { error?: string }> {
|
||||
data: T;
|
||||
element: ProjectorElement;
|
||||
error?: string;
|
||||
@ -40,21 +42,16 @@ export class ProjectorDataService {
|
||||
* @param websocketService
|
||||
*/
|
||||
public constructor(private websocketService: WebsocketService) {
|
||||
// TODO: On reconnect, we do need to re-inform the server about all needed projectors. This also
|
||||
// updates our projector data, which is great!
|
||||
this.websocketService.getOberservable('projector').subscribe((update: AllProjectorData) => {
|
||||
Object.keys(update).forEach(_id => {
|
||||
const id = parseInt(_id, 10);
|
||||
if ((<{ error: string }>update[id]).error !== undefined) {
|
||||
console.log(update, update[_id]);
|
||||
console.log('TODO: Why does the server sends errors on autoupdates?');
|
||||
} else {
|
||||
if (this.currentProjectorData[id]) {
|
||||
this.currentProjectorData[id].next(update[id] as ProjectorData);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.websocketService.reconnectEvent.subscribe(() => this.updateProjectorDataSubscription());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,4 +102,15 @@ export class ProjectorDataService {
|
||||
.filter(id => this.openProjectorInstances[id] > 0);
|
||||
this.websocketService.send('listenToProjectors', { projector_ids: allActiveProjectorIds });
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns the available projectior data for the given projector. Note that the data
|
||||
* might not be there, if there is no subscribtion for this projector. But the
|
||||
* data, if exist, is always the current data.
|
||||
*/
|
||||
public getAvailableProjectorData(projector: Projector): ProjectorData | null {
|
||||
if (this.currentProjectorData[projector.id]) {
|
||||
return this.currentProjectorData[projector.id].getValue();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import {
|
||||
Projectable,
|
||||
ProjectorElementBuildDeskriptor,
|
||||
@ -11,15 +13,16 @@ import {
|
||||
Projector,
|
||||
ProjectorElement,
|
||||
ProjectorElements,
|
||||
IdentifiableProjectorElement
|
||||
IdentifiableProjectorElement,
|
||||
elementIdentifies
|
||||
} from 'app/shared/models/core/projector';
|
||||
import { HttpService } from './http.service';
|
||||
import { SlideManager } from 'app/slides/services/slide-manager.service';
|
||||
import { BaseModel } from 'app/shared/models/base/base-model';
|
||||
import { ViewModelStoreService } from './view-model-store.service';
|
||||
import { BaseProjectableViewModel } from 'app/site/base/base-projectable-view-model';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { ConfigService } from '../ui-services/config.service';
|
||||
import { ProjectorDataService } from './projector-data.service';
|
||||
|
||||
/**
|
||||
* This service cares about Projectables being projected and manage all projection-related
|
||||
@ -43,7 +46,8 @@ export class ProjectorService {
|
||||
private slideManager: SlideManager,
|
||||
private viewModelStore: ViewModelStoreService,
|
||||
private translate: TranslateService,
|
||||
private configService: ConfigService
|
||||
private configService: ConfigService,
|
||||
private projectorDataService: ProjectorDataService
|
||||
) {}
|
||||
|
||||
/**
|
||||
@ -201,7 +205,7 @@ export class ProjectorService {
|
||||
): Promise<void> {
|
||||
const requestData: any = {};
|
||||
if (elements) {
|
||||
requestData.elements = elements;
|
||||
requestData.elements = this.cleanupElements(projector, elements);
|
||||
}
|
||||
if (preview) {
|
||||
requestData.preview = preview;
|
||||
@ -218,6 +222,31 @@ export class ProjectorService {
|
||||
await this.http.post(`/rest/core/projector/${projector.id}/project/`, requestData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up stable elements with errors from the projector
|
||||
*
|
||||
* @param projector The projector
|
||||
* @param elements The elements to clean up
|
||||
* @reutns the cleaned up elements.
|
||||
*/
|
||||
private cleanupElements(projector: Projector, elements: ProjectorElements): ProjectorElements {
|
||||
const projectorData = this.projectorDataService.getAvailableProjectorData(projector);
|
||||
|
||||
if (projectorData) {
|
||||
projectorData.forEach(entry => {
|
||||
if (entry.data.error && entry.element.stable) {
|
||||
// Remove this element
|
||||
const idElementToRemove = this.slideManager.getIdentifialbeProjectorElement(entry.element);
|
||||
elements = elements.filter(element => {
|
||||
return !elementIdentifies(idElementToRemove, element);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a projectiondefault, we want to retrieve the projector, that is assigned
|
||||
* to this default.
|
||||
|
@ -8,7 +8,7 @@ import { BaseComponent } from 'app/base.component';
|
||||
import { ConfigService } from 'app/core/ui-services/config.service';
|
||||
import { ViewProjector } from 'app/site/projector/models/view-projector';
|
||||
import { Size } from 'app/site/projector/size';
|
||||
import { SlideData, ProjectorDataService } from 'app/site/projector/services/projector-data.service';
|
||||
import { SlideData, ProjectorDataService } from 'app/core/core-services/projector-data.service';
|
||||
import { ProjectorRepositoryService } from 'app/core/repositories/projector/projector-repository.service';
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,7 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { BaseComponent } from 'app/base.component';
|
||||
import { SlideManager } from 'app/slides/services/slide-manager.service';
|
||||
import { BaseSlideComponent } from 'app/slides/base-slide-component';
|
||||
import { SlideData } from 'app/site/projector/services/projector-data.service';
|
||||
import { SlideData } from 'app/core/core-services/projector-data.service';
|
||||
import { ProjectorElement } from 'app/shared/models/core/projector';
|
||||
import { ViewProjector } from 'app/site/projector/models/view-projector';
|
||||
|
||||
|
@ -29,6 +29,19 @@ export interface IdentifiableProjectorElement extends ProjectorElement {
|
||||
getIdentifiers(): (keyof IdentifiableProjectorElement)[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares an identifiable element to an element. Every identifier of `a` must match, if
|
||||
* the attribute is given in the element `b`.
|
||||
*
|
||||
* @param a The identifiable element
|
||||
* @param b The non-identifiable element
|
||||
*/
|
||||
export function elementIdentifies(a: IdentifiableProjectorElement, b: ProjectorElement): boolean {
|
||||
return a.getIdentifiers().every(identifier => {
|
||||
return !b[identifier] || b[identifier] === a[identifier];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple elements.
|
||||
*/
|
||||
@ -128,14 +141,24 @@ export class Projector extends BaseModel<Projector> {
|
||||
let removedElements: ProjectorElements;
|
||||
let nonRemovedElements: ProjectorElements;
|
||||
[removedElements, nonRemovedElements] = this.partitionArray(this.elements, elementOnProjector => {
|
||||
return element.getIdentifiers().every(identifier => {
|
||||
return !elementOnProjector[identifier] || elementOnProjector[identifier] === element[identifier];
|
||||
});
|
||||
return elementIdentifies(element, elementOnProjector);
|
||||
});
|
||||
this.elements = nonRemovedElements;
|
||||
return removedElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all elements with the given elements, if these elements can identify to the
|
||||
* given one.
|
||||
*
|
||||
* @param element The element to replace
|
||||
*/
|
||||
public replaceElements(element: IdentifiableProjectorElement): void {
|
||||
this.elements = this.elements.map(elementOnProjector =>
|
||||
elementIdentifies(element, elementOnProjector) ? element : elementOnProjector
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits up the array into two arrays. All elements with a true return value from the callback
|
||||
* will be in the fist array, all others in the second one.
|
||||
|
@ -5,15 +5,11 @@ 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 { ClockSlideService } from './services/clock-slide.service';
|
||||
import { ProjectorDataService } from './services/projector-data.service';
|
||||
import { CurrentListOfSpeakersSlideService } from './services/current-list-of-of-speakers-slide.service';
|
||||
import { CountdownListComponent } from './components/countdown-list/countdown-list.component';
|
||||
import { ProjectorMessageListComponent } from './components/projector-message-list/projector-message-list.component';
|
||||
import { CountdownControlsComponent } from './components/countdown-controls/countdown-controls.component';
|
||||
|
||||
@NgModule({
|
||||
providers: [ClockSlideService, ProjectorDataService, CurrentListOfSpeakersSlideService],
|
||||
imports: [CommonModule, ProjectorRoutingModule, SharedModule],
|
||||
declarations: [
|
||||
ProjectorListComponent,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Input } from '@angular/core';
|
||||
import { SlideData } from 'app/site/projector/services/projector-data.service';
|
||||
|
||||
import { ViewProjector } from 'app/site/projector/models/view-projector';
|
||||
import { SlideData } from 'app/core/core-services/projector-data.service';
|
||||
|
||||
/**
|
||||
* Every slide has to extends this base class. It forces the slides
|
||||
|
@ -8,7 +8,7 @@ import { DiffLinesInParagraph, DiffService, LineRange } from '../../../core/ui-s
|
||||
import { LinenumberingService } from '../../../core/ui-services/linenumbering.service';
|
||||
import { ViewUnifiedChange } from '../../../shared/models/motions/view-unified-change';
|
||||
import { MotionSlideObjChangeReco } from './motion-slide-obj-change-reco';
|
||||
import { SlideData } from '../../../site/projector/services/projector-data.service';
|
||||
import { SlideData } from '../../../core/core-services/projector-data.service';
|
||||
import { MotionSlideObjAmendmentParagraph } from './motion-slide-obj-amendment-paragraph';
|
||||
|
||||
@Component({
|
||||
|
Loading…
Reference in New Issue
Block a user