diff --git a/projects/common/id.service.ts b/projects/common/id.service.ts index e45dca5a69879085ca56838a601b54bae8754edd..0b927d1c30be2cbc333d02abf8395498f60b8f49 100644 --- a/projects/common/id.service.ts +++ b/projects/common/id.service.ts @@ -22,6 +22,7 @@ export class IdService { 'drop-list': 0, cloze: 0, frame: 0, + 'toggle-button': 0, value: 0 }; diff --git a/projects/common/models/uI-element.ts b/projects/common/models/uI-element.ts index d875b7f1f525b5a0b58706ae8dcffc0cf4434657..302257af0a299f430a29d97fe33c223871c77cd3 100644 --- a/projects/common/models/uI-element.ts +++ b/projects/common/models/uI-element.ts @@ -3,7 +3,7 @@ import { IdService } from '../id.service'; export type UIElementType = 'text' | 'button' | 'text-field' | 'text-area' | 'checkbox' | 'dropdown' | 'radio' | 'image' | 'audio' | 'video' | 'likert' | 'likert_row' | 'radio-group-images' -| 'drop-list' | 'cloze' | 'spell-correct' | 'slider' | 'frame'; +| 'drop-list' | 'cloze' | 'spell-correct' | 'slider' | 'frame' | 'toggle-button'; export type InputElementValue = string[] | string | number | boolean | DragNDropValueObject[] | null; export type DragNDropValueObject = { id: string; diff --git a/projects/common/shared.module.ts b/projects/common/shared.module.ts index 199ea52dede95e034e18e2a3b50dff9b549f08af..0c0b9b991ff46eec192bd820177854fa50b8859b 100644 --- a/projects/common/shared.module.ts +++ b/projects/common/shared.module.ts @@ -14,6 +14,7 @@ import { MatTabsModule } from '@angular/material/tabs'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatSnackBarModule } from '@angular/material/snack-bar'; import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatButtonToggleModule } from '@angular/material/button-toggle'; import { TranslateModule } from '@ngx-translate/core'; import { MatDialogModule } from '@angular/material/dialog'; @@ -47,6 +48,7 @@ import { SliderComponent } from './ui-elements/slider/slider.component'; import { SpellCorrectComponent } from './ui-elements/spell-correct/spell-correct.component'; import { DropListSimpleComponent } from './ui-elements/drop-list-simple/drop-list-simple.component'; import { FrameComponent } from './ui-elements/frame/frame.component'; +import { ToggleButtonComponent } from './ui-elements/toggle-button/toggle-button.component'; @NgModule({ imports: [ @@ -65,7 +67,8 @@ import { FrameComponent } from './ui-elements/frame/frame.component'; MatDialogModule, MatButtonModule, TranslateModule, - MatSliderModule + MatSliderModule, + MatButtonToggleModule ], declarations: [ ButtonComponent, @@ -95,7 +98,8 @@ import { FrameComponent } from './ui-elements/frame/frame.component'; SliderComponent, SpellCorrectComponent, TextFieldSimpleComponent, - FrameComponent + FrameComponent, + ToggleButtonComponent ], exports: [ CommonModule, diff --git a/projects/common/ui-elements/cloze/cloze-element.ts b/projects/common/ui-elements/cloze/cloze-element.ts index f97afdda091e3534a8921e86a4d09317937a655c..c005d215555e790545fc27e288bfc4a6fec8ccf2 100644 --- a/projects/common/ui-elements/cloze/cloze-element.ts +++ b/projects/common/ui-elements/cloze/cloze-element.ts @@ -16,6 +16,7 @@ import { DropdownElement } from '../dropdown/dropdown-element'; import { initFontElement, initPositionedElement } from '../../util/unit-interface-initializer'; import { TextFieldSimpleElement } from '../textfield-simple/text-field-simple-element'; import { DropListSimpleElement } from '../drop-list-simple/drop-list-simple'; +import { ToggleButtonElement } from '../toggle-button/toggle-button'; // TODO styles like em dont continue after inserted components @@ -26,7 +27,7 @@ export type ClozePart = { }; export class ClozeElement extends CompoundElement implements PositionedElement, FontElement { - text: string = '<p>Lorem ipsum dolor \\z sdfsdf \\i sdfsdf</p>'; + text: string = '<p>Lorem ipsum dolor \\r sdfsdf \\i sdfsdf</p>'; parts: ClozePart[][] = []; positionProps: PositionProperties; @@ -114,6 +115,9 @@ export class ClozeElement extends CompoundElement implements PositionedElement, if (p.indexOf('\\z') > 0) { x.push(p.indexOf('\\z')); } + if (p.indexOf('\\r') > 0) { + x.push(p.indexOf('\\r')); + } const y = Math.min(...x); let nextElementType = ''; @@ -121,6 +125,7 @@ export class ClozeElement extends CompoundElement implements PositionedElement, case 'd': nextElementType = 'dropdown'; break; case 'i': nextElementType = 'text-field'; break; case 'z': nextElementType = 'drop-list'; break; + case 'r': nextElementType = 'toggle-button'; break; default: return [-1, 'unknown']; } return [y, nextElementType]; @@ -147,6 +152,9 @@ export class ClozeElement extends CompoundElement implements PositionedElement, newElement.height = 25; newElement.width = 100; break; + case 'toggle-button': + newElement = new ToggleButtonElement(elementModel); + break; default: throw new Error(`ElementType ${elementModel.type} not found!`); } diff --git a/projects/common/ui-elements/cloze/cloze.component.ts b/projects/common/ui-elements/cloze/cloze.component.ts index 79f49dca9b3b3171a5228f9a00756290329634f9..6268dbdd0aeb55717886aa498314555534ccff3f 100644 --- a/projects/common/ui-elements/cloze/cloze.component.ts +++ b/projects/common/ui-elements/cloze/cloze.component.ts @@ -60,6 +60,15 @@ import { FormElementComponent } from '../../directives/form-element-component.di [elementModel]="$any(part.value)" (elementValueChanged)="elementValueChanged.emit($event)"> </app-text-field-simple> + + <app-toggle-button *ngIf="part.type === 'toggle-button'" #radioComponent + [parentForm]="parentForm" + [style.display]="'inline-block'" + [style.pointerEvents]="allowClickThrough ? 'auto' : 'none'" + [elementModel]="$any(part.value)" + (elementValueChanged)="elementValueChanged.emit($event)"> + </app-toggle-button> + <div *ngIf="part.type === 'drop-list'" [style.display]="'inline-block'" [style.pointerEvents]="allowClickThrough ? 'auto' : 'none'" @@ -88,7 +97,7 @@ import { FormElementComponent } from '../../directives/form-element-component.di export class ClozeComponent extends CompoundElementComponent { elementModel!: ClozeElement; @Output() elementSelected = new EventEmitter<{ element: ClozeElement, event: MouseEvent }>(); - @ViewChildren('drowdownComponent, textfieldComponent, droplistComponent') + @ViewChildren('drowdownComponent, textfieldComponent, droplistComponent, radioComponent') compoundChildren!: QueryList<FormElementComponent>; getFormElementModelChildren(): InputElement[] { diff --git a/projects/common/ui-elements/toggle-button/toggle-button.component.ts b/projects/common/ui-elements/toggle-button/toggle-button.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..3c7424e341736a12735e1430be928754f8616543 --- /dev/null +++ b/projects/common/ui-elements/toggle-button/toggle-button.component.ts @@ -0,0 +1,38 @@ +import { Component, Input } from '@angular/core'; +import { ToggleButtonElement } from './toggle-button'; +import { FormElementComponent } from '../../directives/form-element-component.directive'; + +@Component({ + selector: 'app-toggle-button', + template: ` + <div class="mat-form-field"> + <mat-button-toggle-group [formControl]="elementFormControl" + [style.height.px]="elementModel.height" + [style.background-color]="elementModel.surfaceProps.backgroundColor" + [style.color]="elementModel.fontProps.fontColor" + [style.font-family]="elementModel.fontProps.font" + [style.font-size.px]="elementModel.fontProps.fontSize" + [style.font-weight]="elementModel.fontProps.bold ? 'bold' : ''" + [style.font-style]="elementModel.fontProps.italic ? 'italic' : ''" + [style.text-decoration]="elementModel.fontProps.underline ? 'underline' : ''" + [style.line-height.%]="elementModel.fontProps.lineHeight"> + <mat-button-toggle *ngFor="let option of elementModel.options; let i = index" + [value]="i" + [ngClass]="{ 'strike' : elementModel.strikeOtherOptions && + elementFormControl.value !== null && + elementFormControl.value !== i }"> + {{option}} + </mat-button-toggle> + </mat-button-toggle-group> + </div> + `, + styles: [ + 'mat-button-toggle-group {min-width: 70px; min-height: 20px}', + ':host ::ng-deep .mat-button-toggle-button {height: 100%}', + ':host ::ng-deep .mat-button-toggle-label-content {height: 100%; line-height: unset}', + ':host ::ng-deep .strike .mat-button-toggle-label-content {text-decoration: line-through}', + ] +}) +export class ToggleButtonComponent extends FormElementComponent { + @Input() elementModel!: ToggleButtonElement; +} diff --git a/projects/common/ui-elements/toggle-button/toggle-button.ts b/projects/common/ui-elements/toggle-button/toggle-button.ts new file mode 100644 index 0000000000000000000000000000000000000000..506f51eef04604b275977149bdfaf3d1b53757c8 --- /dev/null +++ b/projects/common/ui-elements/toggle-button/toggle-button.ts @@ -0,0 +1,25 @@ +import { + UIElement, + InputElement, + FontElement, + SurfaceElement, + FontProperties, SurfaceProperties +} from '../../models/uI-element'; +import { initFontElement, initSurfaceElement } from '../../util/unit-interface-initializer'; + +export class ToggleButtonElement extends InputElement implements FontElement, SurfaceElement { + options: string[] = ['abc', 'def']; + strikeOtherOptions: boolean = false; + + fontProps: FontProperties; + surfaceProps: SurfaceProperties; + + constructor(serializedElement: Partial<UIElement>) { + super(serializedElement); + Object.assign(this, serializedElement); + this.fontProps = initFontElement(serializedElement); + this.surfaceProps = initSurfaceElement(serializedElement); + + this.height = serializedElement.height as number || 25; + } +}