diff --git a/projects/player/src/app/app.module.ts b/projects/player/src/app/app.module.ts index 22e42b70c0e722d403560c8ee9518ef09f46c983..cf24bc4f6ac02669a513aab8270ee913d3fa1ee9 100644 --- a/projects/player/src/app/app.module.ts +++ b/projects/player/src/app/app.module.ts @@ -15,6 +15,7 @@ import { HasReturnKeyPipe } from 'player/src/app/pipes/has-return-key.pipe'; import { PageNavButtonComponent } from 'player/src/app/components/page-nav-button/page-nav-button.component'; import { HasPreviousPagePipe } from 'player/src/app/pipes/has-previous-page.pipe'; import { MeasurePipe } from 'common/pipes/measure.pipe'; +import { TableComponent } from 'common/components/compound-elements/table/table.component'; import { AppComponent } from './app.component'; import { PageComponent } from './components/page/page.component'; import { SectionComponent } from './components/section/section.component'; @@ -110,7 +111,8 @@ import { IsValidPagePipe } from './pipes/is-valid-page.pipe'; OverlayModule, ScrollingModule, UnitMenuModule, - MeasurePipe + MeasurePipe, + TableComponent ], providers: [ { provide: APIService, useExisting: MetaDataService } diff --git a/projects/player/src/app/components/elements/compound-group-element/compound-group-element.component.html b/projects/player/src/app/components/elements/compound-group-element/compound-group-element.component.html index 7a553cebcdac56fc342d06f06a3e4b6e1561c00e..f7940da450e825d98cf8f943ac16889135db81fa 100644 --- a/projects/player/src/app/components/elements/compound-group-element/compound-group-element.component.html +++ b/projects/player/src/app/components/elements/compound-group-element/compound-group-element.component.html @@ -14,6 +14,13 @@ [elementModel]="elementModel | cast: LikertElement" (childrenAdded)="registerCompoundChildren($event)"> </aspect-likert> + <aspect-table + *ngIf="elementModel.type === 'table'" + #elementComponent + [parentForm]="form" + [elementModel]="elementModel | cast: TableElement" + (childrenAdded)="registerCompoundChildren($event)"> + </aspect-table> </form> <aspect-floating-keypad diff --git a/projects/player/src/app/components/elements/compound-group-element/compound-group-element.component.ts b/projects/player/src/app/components/elements/compound-group-element/compound-group-element.component.ts index 819e2ad1bea9393ca4d71469f1077167d8ae9ec4..4c3cac7bdc3a57adfd4705ddb817d022eefc361d 100644 --- a/projects/player/src/app/components/elements/compound-group-element/compound-group-element.component.ts +++ b/projects/player/src/app/components/elements/compound-group-element/compound-group-element.component.ts @@ -9,7 +9,7 @@ import { } from 'common/components/compound-elements/cloze/cloze-child-elements/text-field-simple.component'; import { ClozeElement } from 'common/models/elements/compound-elements/cloze/cloze'; import { LikertElement } from 'common/models/elements/compound-elements/likert/likert'; -import { CompoundElement, InputElement } from 'common/models/elements/element'; +import { CompoundElement, InputElement, UIElement } from 'common/models/elements/element'; import { ButtonComponent } from 'common/components/button/button.component'; import { VeronaPostService } from 'player/modules/verona/services/verona-post.service'; import { NavigationService } from 'player/src/app/services/navigation.service'; @@ -19,6 +19,11 @@ import { StateVariableStateService } from 'player/src/app/services/state-variabl import { Subscription } from 'rxjs'; import { TextInputGroupDirective } from 'player/src/app/directives/text-input-group.directive'; import { ResponseValueType } from '@iqb/responses'; +import { TableElement } from 'common/models/elements/compound-elements/table/table'; +import { ImageElement } from 'common/models/elements/media-elements/image'; +import { TextElement } from 'common/models/elements/text/text'; +import { TextFieldComponent } from 'common/components/input-elements/text-field.component'; +import { ImageComponent } from 'common/components/media-elements/image.component'; import { UnitStateService } from '../../../services/unit-state.service'; import { ElementModelElementCodeMappingService } from '../../../services/element-model-element-code-mapping.service'; import { ValidationService } from '../../../services/validation.service'; @@ -35,6 +40,8 @@ export class CompoundGroupElementComponent extends TextInputGroupDirective imple @ViewChild('elementComponent') elementComponent!: ElementComponent; ClozeElement!: ClozeElement; LikertElement!: LikertElement; + TableElement!: TableElement; + ImageElement!: ImageElement; isKeypadOpen: boolean = false; inputElement!: HTMLTextAreaElement | HTMLInputElement; @@ -73,23 +80,58 @@ export class CompoundGroupElementComponent extends TextInputGroupDirective imple registerCompoundChildren(children: ElementComponent[]): void { children.forEach(child => { - const childModel = child.elementModel as InputElement; - const initialValue: ResponseValueType = childModel.type === 'button' ? - null : - ElementModelElementCodeMappingService.mapToElementCodeValue(childModel.value, childModel.type); - this.registerAtUnitStateService(childModel.id, initialValue, child, this.pageIndex); - if (childModel.type === 'text-field-simple') { - this.manageKeyInputToggling(child as TextFieldSimpleComponent); - this.manageOnKeyDown(child as TextFieldSimpleComponent, childModel); - } - if (childModel.type === 'button') { - this.addButtonActionEventListener(child as ButtonComponent); + const childModel = child.elementModel; + let initialValue: ResponseValueType; + switch (childModel.type) { + case 'image': + initialValue = ElementModelElementCodeMappingService.mapToElementCodeValue( + (this.elementModel as ImageElement).magnifierUsed, this.elementModel.type); + break; + case 'button': + initialValue = null; + break; + case 'text': + initialValue = ElementModelElementCodeMappingService + .mapToElementCodeValue((childModel as TextElement).text, childModel.type); + break; + default: + initialValue = ElementModelElementCodeMappingService + .mapToElementCodeValue((childModel as InputElement).value, childModel.type); } + this.registerAtUnitStateService(childModel.id, initialValue, child, this.pageIndex); + this.registerChildEvents(child, childModel); }); } - private manageOnKeyDown(textFieldSimpleComponent: TextFieldSimpleComponent, elementModel: InputElement): void { - (textFieldSimpleComponent) + private registerChildEvents(child: ElementComponent, childModel: UIElement): void { + if (childModel.type === 'text-field-simple') { + this.manageKeyInputToggling(child as TextFieldSimpleComponent); + this.manageOnKeyDown(child as TextFieldSimpleComponent, childModel as InputElement); + } + if (childModel.type === 'text-field') { + this.manageKeyInputToggling(child as TextFieldComponent); + this.manageOnKeyDown(child as TextFieldComponent, childModel as InputElement); + } + if (childModel.type === 'button') { + this.addButtonActionEventListener(child as ButtonComponent); + } + if (childModel.type === 'image') { + (child as ImageComponent).elementValueChanged + .pipe(takeUntil(this.ngUnsubscribe)) + .subscribe(value => { + this.unitStateService.changeElementCodeValue({ + id: value.id, + value: ElementModelElementCodeMappingService + .mapToElementCodeValue(value.value, this.elementModel.type) + }); + }); + } + } + + private manageOnKeyDown( + textInputComponent: TextFieldSimpleComponent | TextFieldComponent, + elementModel: InputElement): void { + textInputComponent .onKeyDown .pipe(takeUntil(this.ngUnsubscribe)) .subscribe(event => { @@ -97,12 +139,12 @@ export class CompoundGroupElementComponent extends TextInputGroupDirective imple }); } - private manageKeyInputToggling(textFieldSimpleComponent: TextFieldSimpleComponent): void { - (textFieldSimpleComponent) + private manageKeyInputToggling(textInputComponent: TextFieldSimpleComponent | TextFieldComponent): void { + textInputComponent .focusChanged .pipe(takeUntil(this.ngUnsubscribe)) .subscribe(focusedTextInput => { - this.toggleKeyInput(focusedTextInput, textFieldSimpleComponent); + this.toggleKeyInput(focusedTextInput, textInputComponent); }); } diff --git a/projects/player/src/app/components/elements/element-group-selection/element-group-selection.component.ts b/projects/player/src/app/components/elements/element-group-selection/element-group-selection.component.ts index 45f615daf257ac195b48732d808195fc7be4310e..1919896e8dfd7affb2a2b205ce5608e6d91089d3 100644 --- a/projects/player/src/app/components/elements/element-group-selection/element-group-selection.component.ts +++ b/projects/player/src/app/components/elements/element-group-selection/element-group-selection.component.ts @@ -21,7 +21,7 @@ export class ElementGroupSelectionComponent implements OnInit { 'dropdown', 'hotspot-image', 'math-field', 'text-area-math' ] }, - { name: 'compoundGroup', types: ['cloze', 'likert'] }, + { name: 'compoundGroup', types: ['cloze', 'likert', 'table'] }, { name: 'textGroup', types: ['text'] }, { name: 'interactiveGroup', types: ['button', 'image', 'math-table', 'trigger'] }, { name: 'externalAppGroup', types: ['geometry'] }