diff --git a/projects/common/models/elements/button/button.ts b/projects/common/models/elements/button/button.ts index 595b107c50dad4771d6a220d7486af809cc16a6f..2596637f7fa243431635763f8a522bc7449065fb 100644 --- a/projects/common/models/elements/button/button.ts +++ b/projects/common/models/elements/button/button.ts @@ -1,7 +1,7 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, PositionedUIElement, PositionProperties, UIElement } from 'common/models/elements/element'; import { ButtonComponent } from 'common/components/button/button.component'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; export class ButtonElement extends UIElement implements PositionedUIElement { diff --git a/projects/common/models/elements/compound-elements/likert/likert-row.ts b/projects/common/models/elements/compound-elements/likert/likert-row.ts index e4ae7a398aa0e3a692779462d19a6908d02909a8..715d0f6c1d4e660799d5b8a87df18e9134cce50f 100644 --- a/projects/common/models/elements/compound-elements/likert/likert-row.ts +++ b/projects/common/models/elements/compound-elements/likert/likert-row.ts @@ -1,5 +1,5 @@ -import { InputElement, TextImageLabel } from 'common/models/elements/element'; import { Type } from '@angular/core'; +import { InputElement, TextImageLabel } from 'common/models/elements/element'; import { ElementComponent } from 'common/directives/element-component.directive'; import { LikertRadioButtonGroupComponent diff --git a/projects/common/models/elements/compound-elements/likert/likert.ts b/projects/common/models/elements/compound-elements/likert/likert.ts index 261fac49930713d04fb7269b8db7f01e24743b1b..076ad6d8c76cad39d8d4ccafada6d971944196f7 100644 --- a/projects/common/models/elements/compound-elements/likert/likert.ts +++ b/projects/common/models/elements/compound-elements/likert/likert.ts @@ -1,13 +1,10 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { - BasicStyles, CompoundElement, - PositionedUIElement, - PositionProperties, - TextImageLabel, - UIElement + BasicStyles, CompoundElement, UIElement, + PositionedUIElement, PositionProperties, TextImageLabel } from 'common/models/elements/element'; import { LikertRowElement } from 'common/models/elements/compound-elements/likert/likert-row'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { LikertComponent } from 'common/components/compound-elements/likert/likert.component'; diff --git a/projects/common/models/elements/element.ts b/projects/common/models/elements/element.ts index a8ef1c4f4324dee5f62feaa82d018fb865d09c4d..5d332a82b6d1ca578dda5308d7a853eee3a860dc 100644 --- a/projects/common/models/elements/element.ts +++ b/projects/common/models/elements/element.ts @@ -16,7 +16,7 @@ export type InputAssistancePreset = null | 'french' | 'numbers' | 'numbersAndOpe | 'comparisonOperators' | 'squareDashDot' | 'placeValue'; export abstract class UIElement { - [index: string]: any; + [index: string]: unknown; id: string = 'id_placeholder'; type: UIElementType; width: number = 180; @@ -55,15 +55,15 @@ export abstract class UIElement { } setStyleProperty(property: string, value: UIElementValue): void { - (this.styling as { [key: string]: any })[property] = value; + (this.styling as BasicStyles & ExtendedStyles)[property] = value; } setPositionProperty(property: string, value: UIElementValue): void { - (this.position as { [key: string]: any })[property] = value; + (this.position as PositionProperties)[property] = value; } setPlayerProperty(property: string, value: UIElementValue): void { - (this.player as { [key: string]: any })[property] = value; + (this.player as PlayerProperties)[property] = value; } getChildElements(): UIElement[] { @@ -110,7 +110,7 @@ export interface PositionedUIElement extends UIElement { } export interface PositionProperties { - [index: string]: string | number | boolean | null; + [index: string]: unknown; fixedSize: boolean; dynamicPositioning: boolean; xPosition: number; @@ -128,6 +128,7 @@ export interface PositionProperties { } export interface BasicStyles { + [index: string]: unknown; fontColor: string; font: string; fontSize: number; @@ -138,6 +139,7 @@ export interface BasicStyles { } export interface ExtendedStyles { + [index: string]: unknown; lineHeight?: number; borderRadius?: number; itemBackgroundColor?: string; @@ -154,7 +156,7 @@ export interface PlayerElement { } export interface PlayerProperties { - [index: string]: string | number | boolean | null; + [index: string]: unknown; autostart: boolean; autostartDelay: number; loop: boolean; diff --git a/projects/common/models/elements/frame/frame.ts b/projects/common/models/elements/frame/frame.ts index 409933c0ecd64ee4526ec27df9e75639cbfa07a0..5a63eafeff14fbb031b76753d97b77cfdb196190 100644 --- a/projects/common/models/elements/frame/frame.ts +++ b/projects/common/models/elements/frame/frame.ts @@ -1,8 +1,8 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, PositionedUIElement, PositionProperties, UIElement } from 'common/models/elements/element'; import { FrameComponent } from 'common/components/frame/frame.component'; import { ElementComponent } from 'common/directives/element-component.directive'; -import { Type } from '@angular/core'; export class FrameElement extends UIElement implements PositionedUIElement { position: PositionProperties; diff --git a/projects/common/models/elements/input-elements/checkbox.ts b/projects/common/models/elements/input-elements/checkbox.ts index 00f448bd8448f85d45a1f1180c18b2f1dee6259c..a7d8b77c4b22299fdbcec70a78311547219805de 100644 --- a/projects/common/models/elements/input-elements/checkbox.ts +++ b/projects/common/models/elements/input-elements/checkbox.ts @@ -1,6 +1,6 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, InputElement, PositionedUIElement, PositionProperties } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { CheckboxComponent } from 'common/components/input-elements/checkbox.component'; diff --git a/projects/common/models/elements/input-elements/drop-list.ts b/projects/common/models/elements/input-elements/drop-list.ts index e392fb3d7c5ffe85dc6896e998bc39cee75c29de..a0a5727d290759112f75845fe4783bda456d6c2a 100644 --- a/projects/common/models/elements/input-elements/drop-list.ts +++ b/projects/common/models/elements/input-elements/drop-list.ts @@ -1,6 +1,6 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, InputElement, PositionedUIElement, PositionProperties } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { DropListComponent } from 'common/components/input-elements/drop-list.component'; @@ -24,7 +24,8 @@ export class DropListElement extends InputElement implements PositionedUIElement if (element.copyOnDrop) this.copyOnDrop = element.copyOnDrop; if (element.orientation) this.orientation = element.orientation; if (element.highlightReceivingDropList) this.highlightReceivingDropList = element.highlightReceivingDropList; - if (element.highlightReceivingDropListColor) this.highlightReceivingDropListColor = element.highlightReceivingDropListColor; + if (element.highlightReceivingDropListColor) this.highlightReceivingDropListColor = + element.highlightReceivingDropListColor; this.position = ElementFactory.initPositionProps({ useMinHeight: true, ...element.position }); this.styling = { ...ElementFactory.initStylingProps({ diff --git a/projects/common/models/elements/input-elements/dropdown.ts b/projects/common/models/elements/input-elements/dropdown.ts index 2f25dedcae6bb0c1c23a4e014bfca6e098abe181..0a20295878469804ae045825a4490c90fc53e8b7 100644 --- a/projects/common/models/elements/input-elements/dropdown.ts +++ b/projects/common/models/elements/input-elements/dropdown.ts @@ -1,6 +1,6 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, InputElement, PositionedUIElement, PositionProperties } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { DropdownComponent } from 'common/components/input-elements/dropdown.component'; diff --git a/projects/common/models/elements/input-elements/radio-button-group-complex.ts b/projects/common/models/elements/input-elements/radio-button-group-complex.ts index b0bd11853bd129099177bd0b5231f73d577c8ae8..18a5c1be43ba60010841bcde2d596d53abd4fb16 100644 --- a/projects/common/models/elements/input-elements/radio-button-group-complex.ts +++ b/projects/common/models/elements/input-elements/radio-button-group-complex.ts @@ -1,3 +1,4 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, @@ -6,7 +7,6 @@ import { PositionProperties, TextImageLabel } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { RadioGroupImagesComponent } from 'common/components/input-elements/radio-group-images.component'; diff --git a/projects/common/models/elements/input-elements/radio-button-group.ts b/projects/common/models/elements/input-elements/radio-button-group.ts index 1549dec75eb5e944b7e6bcf401261bcf0691588d..b6f4403c7fc526c65300deca18f4fddd6d58626a 100644 --- a/projects/common/models/elements/input-elements/radio-button-group.ts +++ b/projects/common/models/elements/input-elements/radio-button-group.ts @@ -1,6 +1,6 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, InputElement, PositionedUIElement, PositionProperties } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { RadioButtonGroupComponent } from 'common/components/input-elements/radio-button-group.component'; diff --git a/projects/common/models/elements/input-elements/slider.ts b/projects/common/models/elements/input-elements/slider.ts index f71a9cfb1307e4e2caebe0f02f57b190950d0506..fdd6c6556f3a3c631b21d4c7418a45054bf3e10a 100644 --- a/projects/common/models/elements/input-elements/slider.ts +++ b/projects/common/models/elements/input-elements/slider.ts @@ -1,6 +1,6 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, InputElement, PositionedUIElement, PositionProperties } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { SliderComponent } from 'common/components/input-elements/slider.component'; diff --git a/projects/common/models/elements/input-elements/spell-correct.ts b/projects/common/models/elements/input-elements/spell-correct.ts index bbaa278a7dee4639176d436d68a5691761ceb171..67856149300a58c183c5757c1c41f64eee6cf78b 100644 --- a/projects/common/models/elements/input-elements/spell-correct.ts +++ b/projects/common/models/elements/input-elements/spell-correct.ts @@ -1,3 +1,4 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, @@ -6,7 +7,6 @@ import { PositionedUIElement, PositionProperties } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { SpellCorrectComponent } from 'common/components/input-elements/spell-correct.component'; diff --git a/projects/common/models/elements/input-elements/text-area.ts b/projects/common/models/elements/input-elements/text-area.ts index df2645318e2e18a6cc1a7f81af79b516acd94d95..ef6eb0d9722711c5d0fcdcdd6f6deccb6f0f1e0d 100644 --- a/projects/common/models/elements/input-elements/text-area.ts +++ b/projects/common/models/elements/input-elements/text-area.ts @@ -1,3 +1,4 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, @@ -6,7 +7,6 @@ import { PositionedUIElement, PositionProperties } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { TextAreaComponent } from 'common/components/input-elements/text-area.component'; diff --git a/projects/common/models/elements/input-elements/text-field.ts b/projects/common/models/elements/input-elements/text-field.ts index aec57c7dd5791f3d5992a13b3b68051fe1c67043..584ee9980664845af1a70bf3d156eb534bda94e8 100644 --- a/projects/common/models/elements/input-elements/text-field.ts +++ b/projects/common/models/elements/input-elements/text-field.ts @@ -1,9 +1,9 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { BasicStyles, InputAssistancePreset, InputElement, PositionedUIElement, PositionProperties } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { TextFieldComponent } from 'common/components/input-elements/text-field.component'; diff --git a/projects/common/models/elements/media-elements/audio.ts b/projects/common/models/elements/media-elements/audio.ts index ca2c2712d2d4b9ca53f23e380eab9b04b8fc5551..388ac28b0c37f72d709b77e63f04cd14fb9e284b 100644 --- a/projects/common/models/elements/media-elements/audio.ts +++ b/projects/common/models/elements/media-elements/audio.ts @@ -1,6 +1,6 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { PlayerElement, PositionedUIElement, PositionProperties } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { AudioComponent } from 'common/components/media-elements/audio.component'; diff --git a/projects/common/models/elements/media-elements/image.ts b/projects/common/models/elements/media-elements/image.ts index 4ce17a75be8081d386d13f7546fce80abdcc6c47..f189af3e1b76ef119e16098a283e923b55c675e2 100644 --- a/projects/common/models/elements/media-elements/image.ts +++ b/projects/common/models/elements/media-elements/image.ts @@ -1,6 +1,6 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { PositionedUIElement, PositionProperties, UIElement } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { ImageComponent } from 'common/components/media-elements/image.component'; diff --git a/projects/common/models/elements/media-elements/video.ts b/projects/common/models/elements/media-elements/video.ts index 99e285f588b930ab96bfdc0805c5a9e87f99b007..89ff862e1664ea3f8bf9793b51aafbfd3eaad7d8 100644 --- a/projects/common/models/elements/media-elements/video.ts +++ b/projects/common/models/elements/media-elements/video.ts @@ -1,6 +1,6 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { PlayerElement, PositionedUIElement, PositionProperties } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { VideoComponent } from 'common/components/media-elements/video.component'; diff --git a/projects/common/models/elements/text/text.ts b/projects/common/models/elements/text/text.ts index 8186aedd77c9e62efc93c764fbd786bad6771270..7474633bb0e66ca26ceaad369ef08423a3af578a 100644 --- a/projects/common/models/elements/text/text.ts +++ b/projects/common/models/elements/text/text.ts @@ -1,11 +1,9 @@ +import { Type } from '@angular/core'; import { ElementFactory } from 'common/util/element.factory'; import { - BasicStyles, - PositionedUIElement, - PositionProperties, - UIElement + BasicStyles, PositionedUIElement, + PositionProperties, UIElement } from 'common/models/elements/element'; -import { Type } from '@angular/core'; import { ElementComponent } from 'common/directives/element-component.directive'; import { TextComponent } from 'common/components/text/text.component'; diff --git a/projects/common/models/page.ts b/projects/common/models/page.ts index f63488b37765d002987427925eaadfd3d05c9688..df8fcda487911a3c9cc9a4709684d1d8d8e874f9 100644 --- a/projects/common/models/page.ts +++ b/projects/common/models/page.ts @@ -3,7 +3,7 @@ import { IDManager } from 'common/util/id-manager'; import { UIElement } from 'common/models/elements/element'; export class Page { - [index: string]: any; + [index: string]: unknown; sections: Section[] = []; hasMaxWidth: boolean = false; maxWidth: number = 900; diff --git a/projects/common/models/section.ts b/projects/common/models/section.ts index 3fbd1d2fd7c43c057eb603ea7136837e760a561d..c7612b91f712c575e6ed55c12b20465f1e0f1796 100644 --- a/projects/common/models/section.ts +++ b/projects/common/models/section.ts @@ -1,4 +1,6 @@ -import { PositionedUIElement, UIElement } from 'common/models/elements/element'; +import { Type } from '@angular/core'; +import { IDManager } from 'common/util/id-manager'; +import { PositionedUIElement, UIElement, UIElementValue } from 'common/models/elements/element'; import { ButtonElement } from 'common/models/elements/button/button'; import { TextElement } from 'common/models/elements/text/text'; import { TextFieldElement } from 'common/models/elements/input-elements/text-field'; @@ -23,10 +25,9 @@ import { SliderElement } from 'common/models/elements/input-elements/slider'; import { SpellCorrectElement } from 'common/models/elements/input-elements/spell-correct'; import { FrameElement } from 'common/models/elements/frame/frame'; import { ToggleButtonElement } from 'common/models/elements/compound-elements/cloze/cloze-child-elements/toggle-button'; -import { IDManager } from 'common/util/id-manager'; export class Section { - [index: string]: any; + [index: string]: unknown; elements: PositionedUIElement[] = []; height: number = 400; backgroundColor: string = '#ffffff'; @@ -37,7 +38,7 @@ export class Section { gridRowSizes: string = '1fr'; activeAfterID: string | null = null; - static ELEMENT_CLASSES: Record<string, any> = { + static ELEMENT_CLASSES: Record<string, Type<UIElement>> = { 'text': TextElement, 'button': ButtonElement, 'text-field': TextFieldElement, @@ -74,11 +75,11 @@ export class Section { []; } - static createElement(element: { type: string } & Partial<UIElement>, idManager?: IDManager) { - return new Section.ELEMENT_CLASSES[element.type](element, idManager); + static createElement(element: { type: string } & Partial<UIElement>, idManager?: IDManager): PositionedUIElement { + return new Section.ELEMENT_CLASSES[element.type](element, idManager) as PositionedUIElement; } - setProperty(property: string, value: any): void { + setProperty(property: string, value: UIElementValue): void { this[property] = value; } diff --git a/projects/common/services/sanitization.service.ts b/projects/common/services/sanitization.service.ts index 32db7840347691e325f920660d66e64c34bdc1bd..bf57a0c950602eedee9021dc8a17ef396a98d676 100644 --- a/projects/common/services/sanitization.service.ts +++ b/projects/common/services/sanitization.service.ts @@ -2,14 +2,15 @@ import { Injectable } from '@angular/core'; import packageJSON from '../../../package.json'; import { Editor } from '@tiptap/core'; import StarterKit from '@tiptap/starter-kit'; -import ToggleButtonExtension from 'common/models/elements/compound-elements/cloze/tiptap-editor-extensions/toggle-button'; +import ToggleButtonExtension from + 'common/models/elements/compound-elements/cloze/tiptap-editor-extensions/toggle-button'; import DropListExtension from 'common/models/elements/compound-elements/cloze/tiptap-editor-extensions/drop-list'; import TextFieldExtension from 'common/models/elements/compound-elements/cloze/tiptap-editor-extensions/text-field'; import { Unit } from 'common/models/unit'; import { BasicStyles, DragNDropValueObject, ExtendedStyles, InputElement, PlayerProperties, - PositionedUIElement, PositionProperties, + PositionedUIElement, PositionProperties, TextImageLabel, UIElement, UIElementValue } from 'common/models/elements/element'; import { LikertElement } from 'common/models/elements/compound-elements/likert/likert'; @@ -82,7 +83,10 @@ export class SanitizationService { return { ...section, elements: section.elements.map((element: UIElement) => ( - this.sanitizeElement(element, section.dynamicPositioning))) as PositionedUIElement[] + this.sanitizeElement( + element as Record<string, UIElementValue>, + section.dynamicPositioning + ))) as PositionedUIElement[] } as Section; } @@ -95,11 +99,11 @@ export class SanitizationService { player: SanitizationService.getPlayerProps(element) }; if (newElement.type === 'text') { - newElement = SanitizationService.handleTextElement(newElement); + newElement = SanitizationService.handleTextElement(newElement as Record<string, UIElementValue>); } if (['text-field', 'text-area', 'text-field-simple', 'spell-correct'] .includes(newElement.type as string)) { - newElement = SanitizationService.sanitizeTextInputElement(newElement); + newElement = SanitizationService.sanitizeTextInputElement(newElement as Record<string, UIElementValue>); } if (newElement.type === 'cloze') { newElement = this.handleClozeElement(newElement as Record<string, UIElementValue>); @@ -121,7 +125,7 @@ export class SanitizationService { newElement = this.handleLikertElement(newElement as LikertElement); } if (['likert-row', 'likert_row'].includes(newElement.type as string)) { - newElement = SanitizationService.handleLikertRowElement(newElement as LikertRowElement); + newElement = SanitizationService.handleLikertRowElement(newElement as Record<string, UIElementValue>); } return newElement as unknown as UIElement; @@ -277,7 +281,7 @@ export class SanitizationService { ...paraPart, attrs: { ...paraPart.attrs, - model: this.sanitizeElement(childElements.shift()!) + model: this.sanitizeElement(childElements.shift() as Record<string, UIElementValue>) } } : { @@ -340,11 +344,12 @@ export class SanitizationService { private handleLikertElement(element: LikertElement): LikertElement { return new LikertElement({ ...element, - rows: element.rows.map((row: LikertRowElement) => this.sanitizeElement(row) as LikertRowElement) + rows: element.rows + .map((row: LikertRowElement) => this.sanitizeElement(row as Record<string, UIElementValue>) as LikertRowElement) }); } - private static handleLikertRowElement(element: LikertRowElement): LikertRowElement { + private static handleLikertRowElement(element: Record<string, UIElementValue>): Partial<LikertRowElement> { if (element.rowLabel) { return element; } @@ -354,7 +359,7 @@ export class SanitizationService { text: element.text, imgSrc: null, position: 'above' - } + } as TextImageLabel }); } diff --git a/projects/common/util/element.factory.ts b/projects/common/util/element.factory.ts index 602d972b56be36426b0742df955a56bdb8a3071d..7573c6f82d674b400bea45fdb2b718171d48b3ef 100644 --- a/projects/common/util/element.factory.ts +++ b/projects/common/util/element.factory.ts @@ -1,10 +1,9 @@ import { - BasicStyles, PlayerProperties, PositionProperties, TextImageLabel, - UIElementValue + BasicStyles, PlayerProperties, PositionProperties, TextImageLabel } from 'common/models/elements/element'; export abstract class ElementFactory { - static initPositionProps(defaults: Record<string, UIElementValue> = {}): PositionProperties { + static initPositionProps(defaults: Partial<PositionProperties> = {}): PositionProperties { return { fixedSize: defaults.fixedSize !== undefined ? defaults.fixedSize as boolean : false, dynamicPositioning: defaults.dynamicPositioning !== undefined ? defaults.dynamicPositioning as boolean : true, @@ -44,7 +43,7 @@ export abstract class ElementFactory { }; } - static initPlayerProps(defaults: Record<string, UIElementValue> = {}): PlayerProperties { + static initPlayerProps(defaults: Partial<PlayerProperties> = {}): PlayerProperties { return { autostart: defaults.autostart !== undefined ? defaults.autostart as boolean : false, autostartDelay: defaults.autostartDelay !== undefined ? defaults.autostartDelay as number : 0, diff --git a/projects/common/util/unit-utils.ts b/projects/common/util/unit-utils.ts index b242c9c2eaafcfdb9f12dd8ac401d1957052a81e..c5989685a249600d2d3a5951d344f7b7c0070531 100644 --- a/projects/common/util/unit-utils.ts +++ b/projects/common/util/unit-utils.ts @@ -1,6 +1,6 @@ import { UIElement, UIElementType } from 'common/models/elements/element'; -export abstract class UnitUtils { +export abstract class UnitUtils { // TODO delete this. replce by unit method static findUIElements(value: any | unknown[], type?: UIElementType): UIElement[] { const elements: UIElement[] = []; if (value && typeof value === 'object') { diff --git a/projects/editor/src/app/components/canvas/canvas.component.html b/projects/editor/src/app/components/canvas/canvas.component.html index d99ef49a9a7c8149f9280bae6a9ab4617a471fbc..8f130d24db7e979cbbdf3673e53e1141b395668f 100644 --- a/projects/editor/src/app/components/canvas/canvas.component.html +++ b/projects/editor/src/app/components/canvas/canvas.component.html @@ -14,7 +14,7 @@ [allowDelete]="page.sections.length > 1" (moveSection)="unitService.moveSection(section, page, $event)" (duplicateSection)="unitService.duplicateSection(section, page, i)" - (selectElementComponent)="selectElementComponent($event)"> + (selectElementComponent)="selectElementOverlay($event)"> </aspect-section-menu> <aspect-section-static *ngIf="!section.dynamicPositioning" #sectionComponent diff --git a/projects/editor/src/app/components/canvas/canvas.component.ts b/projects/editor/src/app/components/canvas/canvas.component.ts index b7346e505cf4671a765f421c259e6f4d9ec76d3a..4fc948d6be6d257dbd081aa5b354b9941f5442b1 100644 --- a/projects/editor/src/app/components/canvas/canvas.component.ts +++ b/projects/editor/src/app/components/canvas/canvas.component.ts @@ -25,7 +25,7 @@ import { Section } from 'common/models/section'; export class CanvasComponent { @Input() page!: Page; @ViewChildren('sectionComponent') - childSectionComponents!: QueryList<SectionStaticComponent | SectionDynamicComponent>; + sectionComponents!: QueryList<SectionStaticComponent | SectionDynamicComponent>; constructor(public selectionService: SelectionService, public unitService: UnitService) { } @@ -75,8 +75,8 @@ export class CanvasComponent { this.selectionService.selectedPageSectionIndex = this.page.sections.length - 1; } - selectElementComponent(element: UIElement): void { - const elementComponent = this.getElementComponent(element); + selectElementOverlay(element: UIElement): void { + const elementComponent = this.getElementOverlay(element); if (elementComponent) { this.selectionService.selectElement({ elementComponent: elementComponent, multiSelect: false }); } else { @@ -84,8 +84,8 @@ export class CanvasComponent { } } - private getElementComponent(element: UIElement): CanvasElementOverlay | null { - for (const sectionComponent of this.childSectionComponents.toArray()) { + private getElementOverlay(element: UIElement): CanvasElementOverlay | null { + for (const sectionComponent of this.sectionComponents.toArray()) { for (const elementComponent of sectionComponent.childElementComponents.toArray()) { if (elementComponent.element.id === element.id) { return elementComponent; diff --git a/projects/editor/src/app/components/canvas/dynamic-section-helper-grid.component.ts b/projects/editor/src/app/components/canvas/dynamic-section-helper-grid.component.ts index 37d00cd234da4d6fbf4097bc9235d633189b68f1..f8c898252a7e5a65c19df8988a3519727aba2084 100644 --- a/projects/editor/src/app/components/canvas/dynamic-section-helper-grid.component.ts +++ b/projects/editor/src/app/components/canvas/dynamic-section-helper-grid.component.ts @@ -17,7 +17,7 @@ import { Section } from 'common/models/section'; [style.grid-row-start]="y + 1" [style.grid-row-end]="y + 1" cdkDropList [cdkDropListData]="{ sectionIndex: sectionIndex, gridCoordinates: [x + 1, y + 1] }" - (cdkDropListDropped)="drop($any($event))" + (cdkDropListDropped)="drop($event)" id="list-{{sectionIndex}}-{{x+1}}-{{y+1}}" (dragover)="$event.preventDefault()" (drop)="newElementDropped( $event, x + 1, y + 1)"> @@ -97,7 +97,7 @@ export class DynamicSectionHelperGridComponent implements OnInit, OnChanges { this.rowCountArray = Array(Math.max(numberOfRows, 1)); } - drop(event: CdkDragDrop<{ sectionIndex: number; gridCoordinates?: number[]; }>): void { + drop(event: CdkDragDrop<{ sectionIndex: number; gridCoordinates: number[]; }>): void { const dragItemData: { dragType: string; element: UIElement; } = event.item.data; // Move element to other section - handled by parent (page-canvas). @@ -111,23 +111,23 @@ export class DynamicSectionHelperGridComponent implements OnInit, OnChanges { this.unitService.updateElementsPositionProperty( [event.item.data.element], 'gridColumn', - event.container.data.gridCoordinates![0] + event.container.data.gridCoordinates[0] ); this.unitService.updateElementsPositionProperty( [dragItemData.element], 'gridRow', - event.container.data.gridCoordinates![1] + event.container.data.gridCoordinates[1] ); } else if (event.item.data.dragType === 'resize') { this.unitService.updateElementsPositionProperty( [dragItemData.element], 'gridColumnEnd', - event.container.data.gridCoordinates![0] + 1 + event.container.data.gridCoordinates[0] + 1 ); this.unitService.updateElementsPositionProperty( [dragItemData.element], 'gridRowEnd', - event.container.data.gridCoordinates![1] + 1 + event.container.data.gridCoordinates[1] + 1 ); } else { throw new Error('Unknown drop event'); diff --git a/projects/editor/src/app/components/canvas/overlays/canvas-element-overlay.ts b/projects/editor/src/app/components/canvas/overlays/canvas-element-overlay.ts index 73ff5e32d38a9813d753dc579521db11d28805ff..1388d7d083fd83c859ec15bce599e5434caac81e 100644 --- a/projects/editor/src/app/components/canvas/overlays/canvas-element-overlay.ts +++ b/projects/editor/src/app/components/canvas/overlays/canvas-element-overlay.ts @@ -10,7 +10,7 @@ import { SelectionService } from '../../../services/selection.service'; import { CompoundElementComponent } from 'common/directives/compound-element.directive'; import { ClozeComponent } from 'common/components/compound-elements/cloze/cloze.component'; import { CompoundChildOverlayComponent } from - 'common/components/compound-elements/cloze/compound-child-overlay.component'; + 'common/components/compound-elements/cloze/compound-child-overlay.component'; import { UIElement } from 'common/models/elements/element'; @Directive() @@ -70,7 +70,7 @@ export abstract class CanvasElementOverlay implements OnInit, OnDestroy { } } - elementClicked(event: MouseEvent): void { + elementClicked(event: MouseEvent): void { //TODO method name if (!this.isSelected) { this.selectElement(event.shiftKey); } diff --git a/projects/editor/src/app/components/properties-panel/element-properties-panel.component.ts b/projects/editor/src/app/components/properties-panel/element-properties-panel.component.ts index b01cb4f93801aadec708a4a1a156bad1565fc360..57b07c20227d20da4676db3a65ce69661aaed734 100644 --- a/projects/editor/src/app/components/properties-panel/element-properties-panel.component.ts +++ b/projects/editor/src/app/components/properties-panel/element-properties-panel.component.ts @@ -8,7 +8,7 @@ import { TranslateService } from '@ngx-translate/core'; import { UnitService } from '../../services/unit.service'; import { SelectionService } from '../../services/selection.service'; import { MessageService } from 'common/services/message.service'; -import { DragNDropValueObject, TextImageLabel, UIElement, UIElementValue } from 'common/models/elements/element'; +import { DragNDropValueObject, TextImageLabel, UIElement } from 'common/models/elements/element'; @Component({ selector: 'aspect-element-properties', @@ -53,8 +53,8 @@ export class ElementPropertiesPanelComponent implements OnInit, OnDestroy { ); } - static createCombinedProperties(elements: Record<string, UIElementValue>[]): Record<string, UIElementValue> { - const combinedProperties: Record<string, UIElementValue> = { ...elements[0], id: [elements[0]?.id as string] }; + static createCombinedProperties(elements: UIElement[]): Partial<UIElement> { + const combinedProperties: Partial<UIElement> & { id: string | string[] } = { ...elements[0], id: elements[0].id }; for (let elementCounter = 1; elementCounter < elements.length; elementCounter++) { const elementToMerge = elements[elementCounter]; @@ -63,11 +63,11 @@ export class ElementPropertiesPanelComponent implements OnInit, OnDestroy { if (typeof combinedProperties[property] === 'object' && !Array.isArray(combinedProperties[property]) && combinedProperties[property] !== null) { - (combinedProperties[property] as Record<string, UIElementValue>) = + (combinedProperties[property] as UIElement) = ElementPropertiesPanelComponent.createCombinedProperties( - [(combinedProperties[property] as Record<string, UIElementValue>), - (elementToMerge[property] as Record<string, UIElementValue>)] - ); + [(combinedProperties[property] as UIElement), + (elementToMerge[property] as UIElement)] + ) as UIElement; } else if (JSON.stringify(combinedProperties[property]) !== JSON.stringify(elementToMerge[property])) { if (property === 'id') { (combinedProperties.id as string[]).push(elementToMerge.id as string); diff --git a/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/button-properties.component.ts b/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/button-properties.component.ts index 1649639e3047d66885bb9066efdc5e18e9374e7d..8db4f5d8a51aa0b2db10488b30e95a7b7826aa3d 100644 --- a/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/button-properties.component.ts +++ b/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/button-properties.component.ts @@ -1,24 +1,27 @@ import { - Component, EventEmitter, Input, Output + Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { UnitService } from '../../../../services/unit.service'; import { SelectionService } from '../../../../services/selection.service'; import { FileService } from 'common/services/file.service'; +import { UIElement } from 'common/models/elements/element'; +import { ButtonElement } from 'common/models/elements/button/button'; @Component({ selector: 'aspect-button-properties', template: ` <fieldset *ngIf="combinedProperties.asLink !== undefined"> <legend>Knopf</legend> + <mat-checkbox *ngIf="combinedProperties.asLink !== undefined" - [checked]="$any(combinedProperties.asLink)" + [checked]="combinedButtonElement.asLink" (change)="updateModel.emit({ property: 'asLink', value: $event.checked })"> {{'propertiesPanel.asLink' | translate }} </mat-checkbox> <mat-form-field *ngIf="combinedProperties.action !== undefined" appearance="fill"> <mat-label>{{'propertiesPanel.action' | translate }}</mat-label> - <mat-select [value]="combinedProperties.action" + <mat-select [value]="combinedButtonElement.action" (selectionChange)="updateModel.emit({ property: 'action', value: $event.value })"> <mat-option [value]="null"> {{ 'propertiesPanel.none' | translate }} @@ -32,13 +35,13 @@ import { FileService } from 'common/services/file.service'; <mat-form-field appearance="fill"> <mat-label>{{'propertiesPanel.actionParam' | translate }}</mat-label> - <mat-select [disabled]="combinedProperties.action === null" - [value]="combinedProperties.actionParam" - [matTooltipDisabled]="combinedProperties.action !== 'pageNav'" + <mat-select [disabled]="combinedButtonElement.action === null" + [value]="combinedButtonElement.actionParam" + [matTooltipDisabled]="combinedButtonElement.action !== 'pageNav'" [matTooltip]="'propertiesPanel.pageNavSelectionHint' | translate" (selectionChange)="updateModel.emit({ property: 'actionParam', value: $event.value })"> - <ng-container *ngIf="combinedProperties.action === 'pageNav'"> + <ng-container *ngIf="combinedButtonElement.action === 'pageNav'"> <ng-container *ngFor="let page of unitService.unit.pages; index as i"> <mat-option *ngIf="!page.alwaysVisible && selectionService.selectedPageIndex !== i" [value]="i"> @@ -47,7 +50,7 @@ import { FileService } from 'common/services/file.service'; </ng-container> </ng-container> - <ng-container *ngIf="combinedProperties.action === 'unitNav'"> + <ng-container *ngIf="combinedButtonElement.action === 'unitNav'"> <mat-option *ngFor="let option of [undefined, 'previous', 'next', 'first', 'last', 'end']" [value]="option"> {{ 'propertiesPanel.' + option | translate }} @@ -57,14 +60,14 @@ import { FileService } from 'common/services/file.service'; </mat-form-field> <div class="image-panel" (mouseenter)="hoveringImage = true" (mouseleave)="hoveringImage = false"> - <button *ngIf="combinedProperties.imageSrc === null || hoveringImage" + <button *ngIf="combinedButtonElement.imageSrc === null || hoveringImage" class="add-image-button" mat-raised-button (click)="loadImage()">{{'loadImage' | translate }}</button> - <button *ngIf="combinedProperties.imageSrc !== null && hoveringImage" + <button *ngIf="combinedButtonElement.imageSrc !== null && hoveringImage" class="remove-image-button" mat-raised-button (click)="removeImage()">{{'removeImage' | translate }}</button> - <img *ngIf="combinedProperties.imageSrc" - [src]="combinedProperties.imageSrc"> + <img *ngIf="combinedButtonElement.imageSrc" + [src]="combinedButtonElement.imageSrc"> </div> </fieldset> `, @@ -77,15 +80,20 @@ import { FileService } from 'common/services/file.service'; '.image-panel img {width:100%; height:100%;}' ] }) -export class ButtonPropertiesComponent { - @Input() combinedProperties!: any; +export class ButtonPropertiesComponent implements OnInit { + @Input() combinedProperties!: UIElement; @Output() updateModel = - new EventEmitter<{ property: string; value: string | number | boolean | null, isInputValid?: boolean | null }>(); + new EventEmitter<{ property: string; value: string | number | boolean | null, isInputValid?: boolean | null }>(); + combinedButtonElement: ButtonElement = {} as ButtonElement; hoveringImage = false; constructor(public unitService: UnitService, public selectionService: SelectionService) { } + ngOnInit(): void { + this.combinedButtonElement = this.combinedProperties as ButtonElement; + } + async loadImage(): Promise<void> { this.updateModel.emit({ property: 'imageSrc', value: await FileService.loadImage() }); } diff --git a/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts b/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts index 83360045f672176c29604b3f9493d595d06a5306..dcf7b37f87d41e71e3e2d40237c3dcc0ffe9ff3e 100644 --- a/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts +++ b/projects/editor/src/app/components/properties-panel/model-properties-tab/input-groups/drop-list-properties.component.ts @@ -1,5 +1,5 @@ import { - Component, ElementRef, EventEmitter, Input, Output, ViewChild + Component, EventEmitter, Input, Output } from '@angular/core'; import { UnitService } from '../../../../services/unit.service'; import { SelectionService } from '../../../../services/selection.service'; diff --git a/projects/editor/src/app/components/unit-view/unit-view.component.html b/projects/editor/src/app/components/unit-view/unit-view.component.html index 2bdeef3e2f780641a5a740d09fc4d6577ed54fb2..d093f740cc7967839d56586f15d551cd195686cc 100644 --- a/projects/editor/src/app/components/unit-view/unit-view.component.html +++ b/projects/editor/src/app/components/unit-view/unit-view.component.html @@ -48,8 +48,8 @@ </button> <mat-divider></mat-divider> <mat-checkbox class="menuItem" [checked]="page.hasMaxWidth" - (click)="$any($event).stopPropagation()" - (change)="updateModel(page, 'hasMaxWidth', $any($event.source).checked)"> + (click)="$event.stopPropagation()" + (change)="updateModel(page, 'hasMaxWidth', $event.source.checked)"> {{'pageProperties.maxWidth' | translate }} </mat-checkbox> <div *ngIf="page.hasMaxWidth" class="menuItem"> @@ -59,33 +59,33 @@ <mat-label>{{'pageProperties.sectionWidth' | translate }}</mat-label> <input matInput type="number" min="0" #maxWidth="ngModel" [ngModel]="page.maxWidth" - (click)="$any($event).stopPropagation()" + (click)="$event.stopPropagation()" (ngModelChange)="updateModel(page,'maxWidth', $event, maxWidth.valid)"> </mat-form-field> <mat-form-field class="menuItem" appearance="fill"> <mat-label>{{'pageProperties.marginWidth' | translate }}</mat-label> <input matInput type="number" min="0" #margin="ngModel" [ngModel]="page.margin" - (click)="$any($event).stopPropagation()" + (click)="$event.stopPropagation()" (ngModelChange)="updateModel(page,'margin', $event, margin.valid)"> </mat-form-field> <mat-form-field class="menuItem" appearance="fill"> <mat-label>{{'pageProperties.backgroundColor' | translate }}</mat-label> <input matInput type="color" - [value]="page.backgroundColor" - (change)="updateModel(page,'backgroundColor', $any($event.target).value)"> + [ngModel]="page.backgroundColor" + (ngModelChange)="updateModel(page,'backgroundColor', $event.target.value)"> </mat-form-field> <mat-checkbox class="menuItem" [disabled]="unitService.unit.pages.length < 2 || unitService.unit.pages[0].alwaysVisible && i != 0" [ngModel]="page.alwaysVisible" - (click)="$any($event).stopPropagation()" - (change)="updateModel(page, 'alwaysVisible', $any($event.source).checked)"> + (click)="$event.stopPropagation()" + (change)="updateModel(page, 'alwaysVisible', $event.source.checked)"> {{'pageProperties.alwaysVisible' | translate }} </mat-checkbox> <mat-form-field *ngIf="page.alwaysVisible" class="menuItem" appearance="fill"> <mat-label>{{'pageProperties.position' | translate }}</mat-label> <mat-select [value]="page.alwaysVisiblePagePosition" - (click)="$any($event).stopPropagation()" + (click)="$event.stopPropagation()" (selectionChange)="updateModel(page, 'alwaysVisiblePagePosition', $event.value)"> <mat-option *ngFor="let option of ['left', 'right', 'top', 'bottom']" [value]="option"> @@ -98,7 +98,7 @@ <mat-label>{{'pageProperties.alwaysVisibleAspectRatio' | translate }}</mat-label> <input matInput type="number" min="0" max="100" [ngModel]="page.alwaysVisibleAspectRatio" - (click)="$any($event).stopPropagation()" + (click)="$event.stopPropagation()" (ngModelChange)="updateModel(page, 'alwaysVisibleAspectRatio', $event)"> </mat-form-field> </div> diff --git a/projects/editor/src/app/services/unit.service.ts b/projects/editor/src/app/services/unit.service.ts index b61d0d22cc8270f38e79b237bd3096b34dcfd117..4632609d70604fabd35aa16c295c226546194ac7 100644 --- a/projects/editor/src/app/services/unit.service.ts +++ b/projects/editor/src/app/services/unit.service.ts @@ -176,13 +176,13 @@ export class UnitService { } if ('value' in newElement && newElement.value instanceof Object) { // replace value Ids with fresh ones (dropList) - newElement.value.forEach((valueObject: { id: string }) => { + (newElement.value as DragNDropValueObject[]).forEach((valueObject: { id: string }) => { valueObject.id = IDManager.getInstance().getNewID('value'); }); } if ('row' in newElement && newElement.rows instanceof Object) { // replace row Ids with fresh ones (likert) - newElement.rows.forEach((rowObject: { id: string }) => { + (newElement.rows as LikertRowElement[]).forEach((rowObject: { id: string }) => { rowObject.id = IDManager.getInstance().getNewID('likert_row'); }); }