Skip to content
Snippets Groups Projects
Commit aa6583bf authored by jojohoch's avatar jojohoch
Browse files

[player] Implement UnitStateElementMapperService

- Map value between unit state and element model
- Takes over methods that were previously present in element container
- Gets and holds a list for mapping drop list elements
parent 241a44c8
No related branches found
No related tags found
No related merge requests found
...@@ -5,6 +5,7 @@ Player ...@@ -5,6 +5,7 @@ Player
- Use fixed size property for video and spelling components - Use fixed size property for video and spelling components
- Color the disabled progress bar of the media player green - Color the disabled progress bar of the media player green
- Fix the section from being placed in front of elements with negative z-index - Fix the section from being placed in front of elements with negative z-index
- Fix saving of drop list elements
1.12.0 1.12.0
- Use fixed size property for dynamic button, drop-list and text-field components - Use fixed size property for dynamic button, drop-list and text-field components
......
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { MatDialog } from '@angular/material/dialog';
import { registerLocaleData } from '@angular/common'; import { registerLocaleData } from '@angular/common';
import localeDe from '@angular/common/locales/de'; import localeDe from '@angular/common/locales/de';
import { import { MatDialog } from '@angular/material/dialog';
Unit import { TranslateService } from '@ngx-translate/core';
} from '../../../common/models/unit'; import { Unit } from '../../../common/models/unit';
import { PlayerConfig, VopStartCommand } from './models/verona';
import { UnitStateElementMapperService } from './services/unit-state-element-mapper.service';
import { VeronaSubscriptionService } from './services/verona-subscription.service'; import { VeronaSubscriptionService } from './services/verona-subscription.service';
import { VeronaPostService } from './services/verona-post.service'; import { VeronaPostService } from './services/verona-post.service';
import { NativeEventService } from './services/native-event.service'; import { NativeEventService } from './services/native-event.service';
import { MetaDataService } from './services/meta-data.service'; import { MetaDataService } from './services/meta-data.service';
import { PlayerConfig, VopStartCommand } from './models/verona';
import { AlertDialogComponent } from './components/alert-dialog/alert-dialog.component';
import { UnitStateService } from './services/unit-state.service'; import { UnitStateService } from './services/unit-state.service';
import { MediaPlayerService } from './services/media-player.service'; import { MediaPlayerService } from './services/media-player.service';
import { AlertDialogComponent } from './components/alert-dialog/alert-dialog.component';
import { Page } from '../../../common/models/page'; import { Page } from '../../../common/models/page';
@Component({ @Component({
...@@ -36,6 +35,7 @@ export class AppComponent implements OnInit { ...@@ -36,6 +35,7 @@ export class AppComponent implements OnInit {
private nativeEventService: NativeEventService, private nativeEventService: NativeEventService,
private unitStateService: UnitStateService, private unitStateService: UnitStateService,
private mediaPlayerService: MediaPlayerService, private mediaPlayerService: MediaPlayerService,
private unitStateElementMapperService: UnitStateElementMapperService,
private dialog: MatDialog) { private dialog: MatDialog) {
} }
...@@ -61,6 +61,7 @@ export class AppComponent implements OnInit { ...@@ -61,6 +61,7 @@ export class AppComponent implements OnInit {
console.log('player: onStart', message); console.log('player: onStart', message);
if (message.unitDefinition) { if (message.unitDefinition) {
const unitDefinition: Unit = new Unit(JSON.parse(message.unitDefinition)); const unitDefinition: Unit = new Unit(JSON.parse(message.unitDefinition));
this.unitStateElementMapperService.registerDropListValueIds(unitDefinition);
if (this.metaDataService.verifyUnitDefinitionVersion(unitDefinition.veronaModuleVersion)) { if (this.metaDataService.verifyUnitDefinitionVersion(unitDefinition.veronaModuleVersion)) {
this.playerConfig = message.playerConfig || {}; this.playerConfig = message.playerConfig || {};
this.veronaPostService.sessionId = message.sessionId; this.veronaPostService.sessionId = message.sessionId;
...@@ -99,5 +100,6 @@ export class AppComponent implements OnInit { ...@@ -99,5 +100,6 @@ export class AppComponent implements OnInit {
this.playerConfig = {}; this.playerConfig = {};
this.unitStateService.reset(); this.unitStateService.reset();
this.mediaPlayerService.reset(); this.mediaPlayerService.reset();
this.unitStateElementMapperService.reset();
} }
} }
...@@ -6,30 +6,28 @@ import { ...@@ -6,30 +6,28 @@ import {
} from '@angular/forms'; } from '@angular/forms';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { KeyboardService } from '../../services/keyboard.service';
import { FormService } from '../../services/form.service';
import { UnitStateService } from '../../services/unit-state.service';
import { MarkingService } from '../../services/marking.service';
import { import {
InputElement, InputElementValue, UIElement, ValueChangeElement InputElement, UIElement, ValueChangeElement
} from '../../../../../common/models/uI-element'; } from '../../../../../common/models/uI-element';
import { FormElementComponent } from '../../../../../common/directives/form-element-component.directive'; import { FormElementComponent } from '../../../../../common/directives/form-element-component.directive';
import { CompoundElementComponent } import { CompoundElementComponent }
from '../../../../../common/directives/compound-element.directive'; from '../../../../../common/directives/compound-element.directive';
import { VideoElement } from '../../../../../common/ui-elements/video/video-element';
import { AudioElement } from '../../../../../common/ui-elements/audio/audio-element';
import { ImageElement } from '../../../../../common/ui-elements/image/image-element';
import { VeronaPostService } from '../../services/verona-post.service';
import { MediaPlayerElementComponent } from '../../../../../common/directives/media-player-element-component.directive'; import { MediaPlayerElementComponent } from '../../../../../common/directives/media-player-element-component.directive';
import { MediaPlayerService } from '../../services/media-player.service';
import { TextComponent } from '../../../../../common/ui-elements/text/text.component'; import { TextComponent } from '../../../../../common/ui-elements/text/text.component';
import { TextFieldElement } from '../../../../../common/ui-elements/text-field/text-field-element'; import { TextFieldElement } from '../../../../../common/ui-elements/text-field/text-field-element';
import { ElementComponent } from '../../../../../common/directives/element-component.directive'; import { ElementComponent } from '../../../../../common/directives/element-component.directive';
import { ElementFactory } from '../../../../../common/util/element.factory';
import { ImageComponent } from '../../../../../common/ui-elements/image/image.component'; import { ImageComponent } from '../../../../../common/ui-elements/image/image.component';
import { ButtonComponent } from '../../../../../common/ui-elements/button/button.component'; import { ButtonComponent } from '../../../../../common/ui-elements/button/button.component';
import { TextFieldComponent } from '../../../../../common/ui-elements/text-field/text-field.component'; import { TextFieldComponent } from '../../../../../common/ui-elements/text-field/text-field.component';
import { TextAreaComponent } from '../../../../../common/ui-elements/text-area/text-area.component'; import { TextAreaComponent } from '../../../../../common/ui-elements/text-area/text-area.component';
import { ElementFactory } from '../../../../../common/util/element.factory';
import { KeyboardService } from '../../services/keyboard.service';
import { FormService } from '../../services/form.service';
import { UnitStateService } from '../../services/unit-state.service';
import { MarkingService } from '../../services/marking.service';
import { MediaPlayerService } from '../../services/media-player.service';
import { UnitStateElementMapperService } from '../../services/unit-state-element-mapper.service';
import { VeronaPostService } from '../../services/verona-post.service';
@Component({ @Component({
selector: 'app-element-container', selector: 'app-element-container',
...@@ -58,6 +56,7 @@ export class ElementContainerComponent implements OnInit { ...@@ -58,6 +56,7 @@ export class ElementContainerComponent implements OnInit {
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private veronaPostService: VeronaPostService, private veronaPostService: VeronaPostService,
private mediaPlayerService: MediaPlayerService, private mediaPlayerService: MediaPlayerService,
private unitStateElementMapperService: UnitStateElementMapperService,
private markingService: MarkingService) { private markingService: MarkingService) {
} }
...@@ -92,7 +91,12 @@ export class ElementContainerComponent implements OnInit { ...@@ -92,7 +91,12 @@ export class ElementContainerComponent implements OnInit {
const elementComponentFactory = const elementComponentFactory =
ElementFactory.getComponentFactory(this.elementModel.type, this.componentFactoryResolver); ElementFactory.getComponentFactory(this.elementModel.type, this.componentFactoryResolver);
const elementComponent = this.elementComponentContainer.createComponent(elementComponentFactory).instance; const elementComponent = this.elementComponentContainer.createComponent(elementComponentFactory).instance;
elementComponent.elementModel = this.restoreUnitStateValue(this.elementModel); elementComponent.elementModel = this.unitStateElementMapperService
.mapToElementValue(
this.elementModel,
this.unitStateService.getUnitStateElement(this.elementModel.id),
this.markingService
);
return elementComponent; return elementComponent;
} }
...@@ -126,7 +130,10 @@ export class ElementContainerComponent implements OnInit { ...@@ -126,7 +130,10 @@ export class ElementContainerComponent implements OnInit {
private registerAtUnitStateService(elementComponent: ElementComponent): void { private registerAtUnitStateService(elementComponent: ElementComponent): void {
if (!(elementComponent instanceof CompoundElementComponent)) { if (!(elementComponent instanceof CompoundElementComponent)) {
this.unitStateService.registerElement( this.unitStateService.registerElement(
this.initUnitStateValue(elementComponent.elementModel), this.unitStateElementMapperService.mapToUnitStateValue(
elementComponent.elementModel,
this.unitStateService.getUnitStateElement(elementComponent.elementModel.id)
),
elementComponent.domElement, elementComponent.domElement,
this.pageIndex this.pageIndex
); );
...@@ -142,9 +149,17 @@ export class ElementContainerComponent implements OnInit { ...@@ -142,9 +149,17 @@ export class ElementContainerComponent implements OnInit {
.subscribe((children: QueryList<ElementComponent>) => { .subscribe((children: QueryList<ElementComponent>) => {
children.forEach((child, index) => { children.forEach((child, index) => {
const childModel = compoundChildren[index]; const childModel = compoundChildren[index];
child.elementModel = this.restoreUnitStateValue(childModel); child.elementModel = this.unitStateElementMapperService
.mapToElementValue(
childModel,
this.unitStateService.getUnitStateElement(child.elementModel.id),
this.markingService
);
this.unitStateService.registerElement( this.unitStateService.registerElement(
this.initUnitStateValue(child.elementModel), this.unitStateElementMapperService.mapToUnitStateValue(
child.elementModel,
this.unitStateService.getUnitStateElement(child.elementModel.id)
),
child.domElement, child.domElement,
this.pageIndex this.pageIndex
); );
...@@ -171,7 +186,8 @@ export class ElementContainerComponent implements OnInit { ...@@ -171,7 +186,8 @@ export class ElementContainerComponent implements OnInit {
elementComponent.applySelection elementComponent.applySelection
.pipe(takeUntil(this.ngUnsubscribe)) .pipe(takeUntil(this.ngUnsubscribe))
.subscribe((selection: .subscribe((selection:
{ mode: 'mark' | 'underline' | 'delete', {
mode: 'mark' | 'underline' | 'delete',
color: string; color: string;
element: HTMLElement; element: HTMLElement;
}) => { }) => {
...@@ -255,45 +271,6 @@ export class ElementContainerComponent implements OnInit { ...@@ -255,45 +271,6 @@ export class ElementContainerComponent implements OnInit {
} }
} }
private restoreUnitStateValue(elementModel: UIElement): UIElement {
const unitStateElementCode = this.unitStateService.getUnitStateElement(elementModel.id);
if (unitStateElementCode && unitStateElementCode.value !== undefined) {
switch (elementModel.type) {
case 'text':
elementModel.text = this.markingService
.restoreMarkings(unitStateElementCode.value as string[], this.elementModel.text);
break;
case 'image':
elementModel.magnifierUsed = unitStateElementCode.value;
break;
case 'video':
case 'audio':
if (elementModel && elementModel.playerProps) {
elementModel.playerProps.playbackTime = unitStateElementCode.value as number;
}
break;
default:
elementModel.value = unitStateElementCode.value;
}
}
return elementModel;
}
private initUnitStateValue = (elementModel: UIElement): { id: string, value: InputElementValue } => {
switch (elementModel.type) {
case 'text':
return { id: elementModel.id, value: [] };
case 'image':
return { id: elementModel.id, value: (elementModel as ImageElement).magnifierUsed };
case 'video':
return { id: elementModel.id, value: (elementModel as VideoElement).playerProps.playbackTime };
case 'audio':
return { id: elementModel.id, value: (elementModel as AudioElement).playerProps.playbackTime };
default:
return { id: elementModel.id, value: (elementModel as InputElement).value };
}
};
private registerFormGroup(elementForm: FormGroup): void { private registerFormGroup(elementForm: FormGroup): void {
this.formService.registerFormGroup({ this.formService.registerFormGroup({
formGroup: elementForm, formGroup: elementForm,
......
import { Injectable } from '@angular/core';
import { Unit } from '../../../../common/models/unit';
import {
DragNDropValueObject, InputElement, InputElementValue, UIElement
} from '../../../../common/models/uI-element';
import { Section } from '../../../../common/models/section';
import { ImageElement } from '../../../../common/ui-elements/image/image-element';
import { VideoElement } from '../../../../common/ui-elements/video/video-element';
import { AudioElement } from '../../../../common/ui-elements/audio/audio-element';
import { DropListElement } from '../../../../common/ui-elements/drop-list/drop-list';
import { UnitStateElementCode } from '../models/verona';
import { MarkingService } from './marking.service';
@Injectable({
providedIn: 'root'
})
export class UnitStateElementMapperService {
dropListValueIds!: DragNDropValueObject[];
registerDropListValueIds(unitDefinition: Unit): void {
this.dropListValueIds = unitDefinition.pages.reduce(
(accumulator: Section[], currentValue) => accumulator.concat(currentValue.sections), []
).reduce(
(accumulator: UIElement[], currentValue) => accumulator.concat(currentValue.elements), []
).filter(element => element.type === 'drop-list').reduce(
(accumulator: DragNDropValueObject[], currentValue: UIElement) => (
(currentValue.value && currentValue.value.length) ? accumulator.concat(currentValue.value) : accumulator), []
);
}
mapToElementValue(
elementModel: UIElement,
unitStateElement: UnitStateElementCode | undefined,
markingService: MarkingService
): UIElement {
if (unitStateElement && unitStateElement.value !== undefined) {
switch (elementModel.type) {
case 'text':
elementModel.text = markingService
.restoreMarkings(unitStateElement.value as string[], elementModel.text);
break;
case 'image':
elementModel.magnifierUsed = unitStateElement.value;
break;
case 'video':
case 'audio':
if (elementModel && elementModel.playerProps) {
elementModel.playerProps.playbackTime = unitStateElement.value as number;
}
break;
case 'drop-list':
elementModel.value = (unitStateElement.value as string[])
.map(id => this.getDropListValueById(id));
break;
default:
elementModel.value = unitStateElement.value;
}
}
return elementModel;
}
mapToUnitStateValue = (elementModel: UIElement, unitStateElement: UnitStateElementCode | undefined):
{ id: string, value: InputElementValue } => {
switch (elementModel.type) {
case 'text':
return { id: elementModel.id, value: unitStateElement?.value || [] };
case 'image':
return { id: elementModel.id, value: (elementModel as ImageElement).magnifierUsed };
case 'video':
return { id: elementModel.id, value: (elementModel as VideoElement).playerProps.playbackTime };
case 'audio':
return { id: elementModel.id, value: (elementModel as AudioElement).playerProps.playbackTime };
case 'drop-list':
return {
id: elementModel.id,
value: ((elementModel as DropListElement).value as DragNDropValueObject[])
.map(element => element.id)
};
default:
return { id: elementModel.id, value: (elementModel as InputElement).value };
}
};
reset(): void {
this.dropListValueIds = [];
}
private getDropListValueById(id: string): DragNDropValueObject | undefined {
return this.dropListValueIds.find(dropListValue => dropListValue.id === id);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment