From f70c48345096d3301078b8755f5c2f474d95a49c Mon Sep 17 00:00:00 2001 From: jojohoch <joachim.hoch@iqb.hu-berlin.de> Date: Fri, 4 Nov 2022 13:08:02 +0100 Subject: [PATCH] Implement custom option for input assistant --- docs/release-notes-editor.txt | 3 +++ docs/release-notes-player.txt | 2 ++ docs/unit_definition_changelog.txt | 2 ++ .../cloze-child-elements/text-field-simple.ts | 4 ++++ projects/common/models/elements/element.ts | 2 +- .../elements/input-elements/spell-correct.ts | 4 ++++ .../elements/input-elements/text-area.ts | 4 ++++ .../elements/input-elements/text-field.ts | 4 ++++ ...text-field-element-properties.component.ts | 11 ++++++++- projects/editor/src/assets/i18n/de.json | 2 ++ .../keypad-layout/keypad-layout.component.css | 4 ++++ .../keypad-layout.component.html | 3 ++- .../keypad-layout/keypad-layout.component.ts | 9 ++++---- .../components/keypad/keypad.component.html | 1 + .../components/keypad/keypad.component.ts | 11 +++++++-- .../modules/key-input/configs/key-layout.ts | 23 ++++++++++++++----- .../floating-keypad.component.html | 1 + .../player-layout.component.html | 1 + .../player/src/app/services/keypad.service.ts | 2 +- 19 files changed, 77 insertions(+), 16 deletions(-) diff --git a/docs/release-notes-editor.txt b/docs/release-notes-editor.txt index 6a8d41bc9..0226e5131 100644 --- a/docs/release-notes-editor.txt +++ b/docs/release-notes-editor.txt @@ -13,6 +13,9 @@ Editor - Ermöglicht die Darstellung eines optionalen Tastatursymbols bei Eingabefeldern und -bereichen - Erlaubt Validierungen ohne Warnmeldungen Warnmeldungen können nun ohne Zeichenketten abgespeichert werden. +- Ermöglicht die Definition eigener Zeichen für die Eingabehilfe + Durch Auswahl der Option "Eigene Zeichen" öffnet sich ein Textfeld, + in das die gewünschten Zeichen als ein Wort eingegeben werden. 1.34.0 - Implement GeoGebra applet element diff --git a/docs/release-notes-player.txt b/docs/release-notes-player.txt index e83b58e06..2f2819f6c 100644 --- a/docs/release-notes-player.txt +++ b/docs/release-notes-player.txt @@ -10,6 +10,8 @@ Player werden nach erster Benutzung der Elemente ausgeblendet - Verbessert die Performanz von GeoGebra-Elementen - Zeigt Validierungsfehler ohne angegebene Warnmeldungen nur mit rotem Rahmen an +- Die Eingabehilfe "Eigene Zeichen" nutzt weitestgehend das Layout + der Eingabehilfe "Französische Sonderzeichen" 1.27.0 - Add new input assistance presets ('Space' and 'Comma'). diff --git a/docs/unit_definition_changelog.txt b/docs/unit_definition_changelog.txt index 17f3a3777..c7320369c 100644 --- a/docs/unit_definition_changelog.txt +++ b/docs/unit_definition_changelog.txt @@ -52,3 +52,5 @@ iqb-aspect-definition@1.0.0 +expectedCharactersCount: number; +hasKeyboardIcon: boolean; - TextFieldElement: +hasKeyboardIcon: boolean; +- TextFieldElement/TextFieldSimpleElement/SpellCorrectElement/TextAreaElement: InputAssistancePreset +'custom' + +inputAssistanceCustomKeys: string; diff --git a/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple.ts b/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple.ts index a24b51a7f..7d5ff0069 100644 --- a/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple.ts +++ b/projects/common/models/elements/compound-elements/cloze/cloze-child-elements/text-field-simple.ts @@ -15,6 +15,7 @@ export class TextFieldSimpleElement extends InputElement { pattern: string | null = null; patternWarnMessage: string = 'Eingabe entspricht nicht der Vorgabe'; inputAssistancePreset: InputAssistancePreset = null; + inputAssistanceCustomKeys: string = ''; inputAssistancePosition: 'floating' | 'right' = 'floating'; restrictedToInputAssistanceChars: boolean = true; hasArrowKeys: boolean = false; @@ -34,6 +35,9 @@ export class TextFieldSimpleElement extends InputElement { if (element.pattern) this.pattern = element.pattern; if (element.patternWarnMessage !== undefined) this.patternWarnMessage = element.patternWarnMessage; if (element.inputAssistancePreset) this.inputAssistancePreset = element.inputAssistancePreset; + if (element.inputAssistanceCustomKeys !== undefined) { + this.inputAssistanceCustomKeys = element.inputAssistanceCustomKeys; + } if (element.inputAssistancePosition) this.inputAssistancePosition = element.inputAssistancePosition; if (element.restrictedToInputAssistanceChars !== undefined) { this.restrictedToInputAssistanceChars = element.restrictedToInputAssistanceChars; diff --git a/projects/common/models/elements/element.ts b/projects/common/models/elements/element.ts index d883aca9b..35f195952 100644 --- a/projects/common/models/elements/element.ts +++ b/projects/common/models/elements/element.ts @@ -13,7 +13,7 @@ TextLabel | TextLabel[] | ClozeDocument | LikertRowElement[] | Hotspot[] | PositionProperties | PlayerProperties | BasicStyles; export type InputAssistancePreset = null | 'french' | 'numbers' | 'numbersAndOperators' | 'numbersAndBasicOperators' -| 'comparisonOperators' | 'squareDashDot' | 'placeValue' | 'space' | 'comma'; +| 'comparisonOperators' | 'squareDashDot' | 'placeValue' | 'space' | 'comma' | 'custom'; export abstract class UIElement { [index: string]: unknown; diff --git a/projects/common/models/elements/input-elements/spell-correct.ts b/projects/common/models/elements/input-elements/spell-correct.ts index 9f687bb99..e635cb995 100644 --- a/projects/common/models/elements/input-elements/spell-correct.ts +++ b/projects/common/models/elements/input-elements/spell-correct.ts @@ -11,6 +11,7 @@ import { SpellCorrectComponent } from 'common/components/input-elements/spell-co export class SpellCorrectElement extends InputElement implements PositionedUIElement { inputAssistancePreset: InputAssistancePreset = null; + inputAssistanceCustomKeys: string = ''; inputAssistancePosition: 'floating' | 'right' = 'floating'; restrictedToInputAssistanceChars: boolean = true; hasArrowKeys: boolean = false; @@ -22,6 +23,9 @@ export class SpellCorrectElement extends InputElement implements PositionedUIEle constructor(element: Partial<SpellCorrectElement>) { super({ width: 230, height: 80, ...element }); if (element.inputAssistancePreset) this.inputAssistancePreset = element.inputAssistancePreset; + if (element.inputAssistanceCustomKeys !== undefined) { + this.inputAssistanceCustomKeys = element.inputAssistanceCustomKeys; + } if (element.inputAssistancePosition) this.inputAssistancePosition = element.inputAssistancePosition; if (element.restrictedToInputAssistanceChars !== undefined) { this.restrictedToInputAssistanceChars = element.restrictedToInputAssistanceChars; diff --git a/projects/common/models/elements/input-elements/text-area.ts b/projects/common/models/elements/input-elements/text-area.ts index c29c0f382..dc74f4198 100644 --- a/projects/common/models/elements/input-elements/text-area.ts +++ b/projects/common/models/elements/input-elements/text-area.ts @@ -16,6 +16,7 @@ export class TextAreaElement extends InputElement implements PositionedUIElement rowCount: number = 3; expectedCharactersCount: number = 300; inputAssistancePreset: InputAssistancePreset = null; + inputAssistanceCustomKeys: string = ''; inputAssistancePosition: 'floating' | 'right' = 'floating'; hasArrowKeys: boolean = false; hasReturnKey: boolean = false; @@ -36,6 +37,9 @@ export class TextAreaElement extends InputElement implements PositionedUIElement if (element.hasDynamicRowCount) this.hasDynamicRowCount = element.hasDynamicRowCount; if (element.expectedCharactersCount) this.expectedCharactersCount = element.expectedCharactersCount; if (element.inputAssistancePreset) this.inputAssistancePreset = element.inputAssistancePreset; + if (element.inputAssistanceCustomKeys !== undefined) { + this.inputAssistanceCustomKeys = element.inputAssistanceCustomKeys; + } if (element.inputAssistancePosition) this.inputAssistancePosition = element.inputAssistancePosition; if (element.restrictedToInputAssistanceChars !== undefined) { this.restrictedToInputAssistanceChars = element.restrictedToInputAssistanceChars; diff --git a/projects/common/models/elements/input-elements/text-field.ts b/projects/common/models/elements/input-elements/text-field.ts index c6e1750c0..e9ed44c08 100644 --- a/projects/common/models/elements/input-elements/text-field.ts +++ b/projects/common/models/elements/input-elements/text-field.ts @@ -15,6 +15,7 @@ export class TextFieldElement extends InputElement implements PositionedUIElemen pattern: string | null = null; patternWarnMessage: string = 'Eingabe entspricht nicht der Vorgabe'; inputAssistancePreset: InputAssistancePreset = null; + inputAssistanceCustomKeys: string = ''; inputAssistancePosition: 'floating' | 'right' = 'floating'; restrictedToInputAssistanceChars: boolean = true; hasArrowKeys: boolean = false; @@ -37,6 +38,9 @@ export class TextFieldElement extends InputElement implements PositionedUIElemen if (element.pattern !== undefined) this.pattern = element.pattern; if (element.patternWarnMessage !== undefined) this.patternWarnMessage = element.patternWarnMessage; if (element.inputAssistancePreset) this.inputAssistancePreset = element.inputAssistancePreset; + if (element.inputAssistanceCustomKeys !== undefined) { + this.inputAssistanceCustomKeys = element.inputAssistanceCustomKeys; + } if (element.inputAssistancePosition) this.inputAssistancePosition = element.inputAssistancePosition; if (element.restrictedToInputAssistanceChars !== undefined) { this.restrictedToInputAssistanceChars = element.restrictedToInputAssistanceChars; diff --git a/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/text-field-element-properties.component.ts b/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/text-field-element-properties.component.ts index 28cdb0a99..018a26163 100644 --- a/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/text-field-element-properties.component.ts +++ b/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/text-field-element-properties.component.ts @@ -102,12 +102,21 @@ import { CombinedProperties } from 'editor/src/app/components/properties-panel/e <mat-select [value]="combinedProperties.inputAssistancePreset" (selectionChange)="updateModel.emit({ property: 'inputAssistancePreset', value: $event.value })"> <mat-option *ngFor="let option of [null, 'french', 'numbers', 'numbersAndOperators', 'numbersAndBasicOperators', - 'comparisonOperators', 'squareDashDot', 'placeValue', 'space', 'comma']" + 'comparisonOperators', 'squareDashDot', 'placeValue', 'space', 'comma', 'custom']" [value]="option"> {{ option === null ? ('propertiesPanel.none' | translate) : ('propertiesPanel.' + option | translate) }} </mat-option> </mat-select> </mat-form-field> + + <mat-form-field *ngIf="combinedProperties.inputAssistancePreset === 'custom'" + class="wide-form-field" appearance="fill"> + <mat-label>{{'propertiesPanel.inputAssistanceCustomKeys' | translate }}</mat-label> + <input matInput type="text" + [value]="$any(combinedProperties.inputAssistanceCustomKeys)" + (input)="updateModel.emit({ property: 'inputAssistanceCustomKeys', value: $any($event.target).value })"> + </mat-form-field> + <mat-form-field *ngIf="combinedProperties.inputAssistancePreset !== null && combinedProperties.inputAssistancePosition !== undefined" appearance="fill"> diff --git a/projects/editor/src/assets/i18n/de.json b/projects/editor/src/assets/i18n/de.json index bd37edc0c..387202ddf 100644 --- a/projects/editor/src/assets/i18n/de.json +++ b/projects/editor/src/assets/i18n/de.json @@ -133,6 +133,8 @@ "squareDashDot": "Quadrat Strich Punkt", "placeValue": "Stellenwert", "comparisonOperators": "Vergleichsoperatoren", + "custom": "Eigene Zeichen", + "inputAssistanceCustomKeys": "Zeichenkette", "inputAssistancePosition": "Eingabehilfeposition", "floating": "schwebend", "showSoftwareKeyboard": "Tastatur einblenden", diff --git a/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.css b/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.css index ae36ce968..9953287e4 100644 --- a/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.css +++ b/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.css @@ -3,6 +3,10 @@ margin: auto; } +.floating-row-container { + max-width: 354px; +} + .grid-layout { justify-content: center; margin-top: 15px; diff --git a/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.html b/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.html index ac09adb36..3698e6a63 100644 --- a/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.html +++ b/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.html @@ -1,4 +1,5 @@ -<div [class.fixed-row-container]="position === 'right' && preset === 'french'"> +<div [class.fixed-row-container]="position === 'right' && ( preset === 'french' || preset === 'custom' )" + [class.floating-row-container]="position === 'floating'"> <div *ngFor="let row of rows; let last = last"> <ng-container *ngFor="let key of row; let index = index; let lastRowKey = last"> <aspect-keypad-key diff --git a/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.ts b/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.ts index c9e9f569c..87f3fb53b 100644 --- a/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.ts +++ b/projects/player/modules/key-input/components/keypad-layout/keypad-layout.component.ts @@ -3,7 +3,7 @@ import { } from '@angular/core'; import { InputAssistancePreset } from 'common/models/elements/element'; import { KeyInputRestrictionDirective } from '../../directives/key-input-restriction.directive'; -import { KeyLayout } from '../../configs/key-layout'; +import { KeyInputLayout } from '../../configs/key-layout'; @Component({ selector: 'aspect-keypad-layout', @@ -12,6 +12,7 @@ import { KeyLayout } from '../../configs/key-layout'; }) export class KeypadLayoutComponent extends KeyInputRestrictionDirective implements OnInit { @Input() preset!: InputAssistancePreset; + @Input() layout!: KeyInputLayout; @Input() position!: 'floating' | 'right'; @Output() keyClicked = new EventEmitter<string>(); @@ -21,8 +22,8 @@ export class KeypadLayoutComponent extends KeyInputRestrictionDirective implemen shift: boolean = false; ngOnInit(): void { - this.rows = KeyLayout.get(this.preset).default; - this.additionalRows = KeyLayout.get(this.preset).additional; + this.rows = this.layout.default; + this.additionalRows = this.layout.additional; this.allowedKeys = [ ...this.rows.flat().filter(key => key.length === 1), ...this.additionalRows.flat().filter(key => key.length === 1) @@ -45,6 +46,6 @@ export class KeypadLayoutComponent extends KeyInputRestrictionDirective implemen toggleShift(): void { this.shift = !this.shift; - this.rows = this.shift ? KeyLayout.get(this.preset).shift : KeyLayout.get(this.preset).default; + this.rows = this.shift ? this.layout.shift : this.layout.default; } } diff --git a/projects/player/modules/key-input/components/keypad/keypad.component.html b/projects/player/modules/key-input/components/keypad/keypad.component.html index c8bb4b239..17febc138 100644 --- a/projects/player/modules/key-input/components/keypad/keypad.component.html +++ b/projects/player/modules/key-input/components/keypad/keypad.component.html @@ -10,6 +10,7 @@ <aspect-keypad-layout [inputElement]="inputElement" [preset]="preset" + [layout]="layout" [position]="position" [restrictToAllowedKeys]="restrictToAllowedKeys" [hasArrowKeys]="hasArrowKeys" diff --git a/projects/player/modules/key-input/components/keypad/keypad.component.ts b/projects/player/modules/key-input/components/keypad/keypad.component.ts index c9d62b232..09b7677ef 100644 --- a/projects/player/modules/key-input/components/keypad/keypad.component.ts +++ b/projects/player/modules/key-input/components/keypad/keypad.component.ts @@ -1,15 +1,17 @@ import { - Component, EventEmitter, Input, Output + Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { InputAssistancePreset } from 'common/models/elements/element'; +import { KeyInputLayout, KeyLayout } from 'player/modules/key-input/configs/key-layout'; @Component({ selector: 'aspect-keypad', templateUrl: './keypad.component.html', styleUrls: ['./keypad.component.css'] }) -export class KeypadComponent { +export class KeypadComponent implements OnInit { @Input() preset!: InputAssistancePreset; + @Input() customKeys!: string; @Input() position!: 'floating' | 'right'; @Input() inputElement!: HTMLTextAreaElement | HTMLInputElement; @Input() positionOffset!: number; @@ -21,6 +23,11 @@ export class KeypadComponent { @Output() keyClicked = new EventEmitter<string>(); arrows: string[] = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; + layout: KeyInputLayout = { default: [], shift: [], additional: [] }; + + ngOnInit(): void { + this.layout = KeyLayout.get(this.preset, this.customKeys); + } evaluateClickedKeyValue(key: string): void { if (this.arrows.includes(key)) { diff --git a/projects/player/modules/key-input/configs/key-layout.ts b/projects/player/modules/key-input/configs/key-layout.ts index b26e660b9..06430e0fb 100644 --- a/projects/player/modules/key-input/configs/key-layout.ts +++ b/projects/player/modules/key-input/configs/key-layout.ts @@ -1,11 +1,13 @@ import { InputAssistancePreset } from 'common/models/elements/element'; +export interface KeyInputLayout { + default: string[][], + shift: string[][], + additional: string[][] +} + export class KeyLayout { - static get = (preset: InputAssistancePreset | 'keyboard'): { - default: string[][], - shift: string[][], - additional: string[][] - } => { + static get = (preset: InputAssistancePreset | 'keyboard', customKeys: string = ''): KeyInputLayout => { switch (preset) { case 'french': { return { @@ -112,7 +114,7 @@ export class KeyLayout { additional: [[]] }; } - default: { // keyboard + case 'keyboard': { return { default: [ ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'ß', 'Backspace'], @@ -131,6 +133,15 @@ export class KeyLayout { additional: [[]] }; } + default: { // custom + return { + default: [ + customKeys.split('') + ], + shift: [[]], + additional: [[]] + }; + } } }; } diff --git a/projects/player/src/app/components/floating-keypad/floating-keypad.component.html b/projects/player/src/app/components/floating-keypad/floating-keypad.component.html index a41123ccd..842e27cfa 100644 --- a/projects/player/src/app/components/floating-keypad/floating-keypad.component.html +++ b/projects/player/src/app/components/floating-keypad/floating-keypad.component.html @@ -9,6 +9,7 @@ [inputElement]="keypadService.inputElement" [position]="keypadService.position" [preset]="keypadService.preset" + [customKeys]="keypadService.elementComponent.elementModel.inputAssistanceCustomKeys" [restrictToAllowedKeys]="keypadService.elementComponent.elementModel.restrictedToInputAssistanceChars" [hasArrowKeys]="keypadService.elementComponent.elementModel.hasArrowKeys" [hasReturnKey]="!!keypadService.elementComponent.elementModel.hasReturnKey" diff --git a/projects/player/src/app/components/layouts/player-layout/player-layout.component.html b/projects/player/src/app/components/layouts/player-layout/player-layout.component.html index 3ec577af7..8473b75da 100644 --- a/projects/player/src/app/components/layouts/player-layout/player-layout.component.html +++ b/projects/player/src/app/components/layouts/player-layout/player-layout.component.html @@ -12,6 +12,7 @@ [inputElement]="keypadService.inputElement" [position]="keypadService.position" [preset]="keypadService.preset" + [customKeys]="keypadService.elementComponent.elementModel.inputAssistanceCustomKeys" [restrictToAllowedKeys]="keypadService.elementComponent.elementModel.restrictedToInputAssistanceChars" [hasArrowKeys]="keypadService.elementComponent.elementModel.hasArrowKeys" [hasReturnKey]="!!keypadService.elementComponent.elementModel.hasReturnKey" diff --git a/projects/player/src/app/services/keypad.service.ts b/projects/player/src/app/services/keypad.service.ts index af0af2b98..f9f529e4c 100644 --- a/projects/player/src/app/services/keypad.service.ts +++ b/projects/player/src/app/services/keypad.service.ts @@ -1,12 +1,12 @@ import { Injectable } from '@angular/core'; import { TextFieldComponent } from 'common/components/input-elements/text-field.component'; import { TextAreaComponent } from 'common/components/input-elements/text-area.component'; -import { InputService } from '../classes/input-service'; import { SpellCorrectComponent } from 'common/components/input-elements/spell-correct.component'; import { TextFieldSimpleComponent } from 'common/components/compound-elements/cloze/cloze-child-elements/text-field-simple.component'; import { InputAssistancePreset } from 'common/models/elements/element'; +import { InputService } from '../classes/input-service'; @Injectable({ providedIn: 'root' -- GitLab