diff --git a/projects/common/classes/audioElement.ts b/projects/common/classes/audioElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..2f6d3be9ed6149b53a164ec56c20e8522e46e013 --- /dev/null +++ b/projects/common/classes/audioElement.ts @@ -0,0 +1,9 @@ +import { UIElement } from './uIElement'; + +export class AudioElement extends UIElement { + src: string = ''; + constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + Object.assign(this, serializedElement); + } +} diff --git a/projects/common/classes/buttonElement.ts b/projects/common/classes/buttonElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..0adf39554593a630a5d4752f46e11a8fa1cdd7a6 --- /dev/null +++ b/projects/common/classes/buttonElement.ts @@ -0,0 +1,25 @@ +import { FontElement, SurfaceUIElement } from '../interfaces/UIElementInterfaces'; +import { initSurfaceElement, initFontElement, UIElement } from './uIElement'; + +export class ButtonElement extends UIElement implements FontElement, SurfaceUIElement { + label: string = 'Knopf'; + imageSrc: string = ''; + borderRadius: number = 0; + action: undefined | 'previous' | 'next' | 'end'; + + fontColor: string = 'black'; + font: string = 'Roboto'; + fontSize: number = 18; + bold: boolean = false; + italic: boolean = false; + underline: boolean = false; + + backgroundColor: string = 'transparent'; + + constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + Object.assign(this, serializedElement); + Object.assign(this, initFontElement()); + Object.assign(this, initSurfaceElement()); + } +} diff --git a/projects/common/classes/checkboxElement.ts b/projects/common/classes/checkboxElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..fbb1853322a0e1c4bb99ee1dcbe32bcb3b48cfc4 --- /dev/null +++ b/projects/common/classes/checkboxElement.ts @@ -0,0 +1,22 @@ +import { initSurfaceElement, initFontElement, InputElement, UIElement } from './uIElement'; +import { FontElement, SurfaceUIElement } from '../interfaces/UIElementInterfaces'; + +export class CheckboxElement extends InputElement implements FontElement, SurfaceUIElement { + fontColor: string = 'black'; + font: string = 'Roboto'; + fontSize: number = 18; + bold: boolean = false; + italic: boolean = false; + underline: boolean = false; + + backgroundColor: string = 'transparent'; + + constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + Object.assign(this, serializedElement); + Object.assign(this, initFontElement()); + Object.assign(this, initSurfaceElement()); + + this.backgroundColor = 'transparent'; + } +} diff --git a/projects/common/classes/dropdownElement.ts b/projects/common/classes/dropdownElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..368e5cbd3f4b55eb151daea5f670508922c2f5b2 --- /dev/null +++ b/projects/common/classes/dropdownElement.ts @@ -0,0 +1,25 @@ +import { initSurfaceElement, initFontElement, InputElement, UIElement } from './uIElement'; +import { FontElement, SurfaceUIElement } from '../interfaces/UIElementInterfaces'; + +export class DropdownElement extends InputElement implements FontElement, SurfaceUIElement { + options: string[] = []; + allowUnset: boolean = false; + + fontColor: string = 'black'; + font: string = 'Roboto'; + fontSize: number = 18; + bold: boolean = false; + italic: boolean = false; + underline: boolean = false; + + backgroundColor: string = 'transparent'; + + constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + Object.assign(this, serializedElement); + Object.assign(this, initFontElement()); + Object.assign(this, initSurfaceElement()); + + this.height = 83; + } +} diff --git a/projects/common/classes/imageElement.ts b/projects/common/classes/imageElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..a7a61456835af3e96eb9ce49fc388f5ed024180c --- /dev/null +++ b/projects/common/classes/imageElement.ts @@ -0,0 +1,10 @@ +import { UIElement } from './uIElement'; + +export class ImageElement extends UIElement { + src: string = ''; + constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + Object.assign(this, serializedElement); + this.height = 100; + } +} diff --git a/projects/common/classes/page.ts b/projects/common/classes/page.ts new file mode 100644 index 0000000000000000000000000000000000000000..182e2609f64aa8c7224d26be674d6edb0675d7e3 --- /dev/null +++ b/projects/common/classes/page.ts @@ -0,0 +1,50 @@ +import { Section } from './section'; +import { moveArrayItem } from '../util/array'; + +export class Page { + [index: string]: string | number | boolean | Section[] | undefined | ((...args: any) => any); + sections: Section[] = []; + hasMaxWidth: boolean = false; + maxWidth: number = 900; + margin: number = 0; + backgroundColor: string = 'white'; + alwaysVisible: boolean = false; + alwaysVisiblePagePosition: 'left' | 'right' | 'top' | 'bottom' = 'left'; + alwaysVisibleAspectRatio: number = 50; + + constructor(serializedPage: Page = {} as Page) { + Object.assign(this, serializedPage); + this.sections = []; + if (serializedPage.sections && serializedPage.sections.length > 0) { + serializedPage?.sections.forEach((section: Section) => { + this.sections.push(new Section(section)); + }); + } else { + this.sections.push(new Section()); + } + } + + appendSection(section: Section): void { + this.sections.push(section); + } + + addSection(): void { + this.sections.push(new Section()); + } + + deleteSection(section: Section): void { + this.sections.splice( + this.sections.indexOf(section), + 1 + ); + } + + duplicateSection(section: Section, sectionIndex: number): void { + const newSection = new Section(section); + this.sections.splice(sectionIndex + 1, 0, newSection); + } + + moveSection(section: Section, direction: 'up' | 'down'): void { + moveArrayItem(section, this.sections, direction); + } +} diff --git a/projects/common/classes/radioButtonGroupElement.ts b/projects/common/classes/radioButtonGroupElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..8fa4ae4ce580bd09ecea41c463b27d2dde22a628 --- /dev/null +++ b/projects/common/classes/radioButtonGroupElement.ts @@ -0,0 +1,26 @@ +import { initSurfaceElement, initFontElement, InputElement, UIElement } from './uIElement'; +import { FontElement, SurfaceUIElement } from '../interfaces/UIElementInterfaces'; + +export class RadioButtonGroupElement extends InputElement implements FontElement, SurfaceUIElement { + options: string[] = []; + alignment: 'row' | 'column' = 'column'; + + fontColor: string = 'black'; + font: string = 'Roboto'; + fontSize: number = 18; + bold: boolean = false; + italic: boolean = false; + underline: boolean = false; + + backgroundColor: string = 'transparent'; + + constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + Object.assign(this, serializedElement); + Object.assign(this, initFontElement()); + Object.assign(this, initSurfaceElement()); + + this.height = 85; + this.backgroundColor = 'transparent'; + } +} diff --git a/projects/common/classes/section.ts b/projects/common/classes/section.ts new file mode 100644 index 0000000000000000000000000000000000000000..edf79cda88a2fe670cd00ecc5deae8b531972322 --- /dev/null +++ b/projects/common/classes/section.ts @@ -0,0 +1,90 @@ +import { + UIElement +} from './uIElement'; +import * as ElementFactory from '../util/element.factory'; + +export class Section { + [index: string]: string | number | boolean | UIElement[] | ((...args: any) => any); + elements: UIElement[] = []; + height: number = 400; + backgroundColor: string = 'white'; + dynamicPositioning: boolean = false; + gridColumnSizes: string = '1fr 1fr'; + gridRowSizes: string = '1fr'; + + constructor(serializedSection?: Section) { + Object.assign(this, serializedSection); + this.elements = []; + if (serializedSection) { + serializedSection?.elements.forEach((element: UIElement) => { + this.elements.push(ElementFactory.createElement(element)); + }); + } + } + + async addElement(elementType: string, coordinates: { x: number; y: number } | undefined): Promise<void> { + this.elements.push(ElementFactory.createElement({ type: elementType } as UIElement, coordinates)); + } + + deleteElements(elements: UIElement[]): void { + this.elements = this.elements.filter(element => !elements.includes(element)); + } + + updateProperty(property: string, value: string | number | boolean): void { + if (property === 'dynamicPositioning') { + this.setDynamicPositioning(value as boolean); + } else { + this[property] = value; + } + } + + private setDynamicPositioning(value: boolean): void { + this.dynamicPositioning = value; + this.elements.forEach((element: UIElement) => { + element.dynamicPositioning = value; + }); + } + + duplicateElements(elements: UIElement[]): void { + elements.forEach((element: UIElement) => { + const newElementConfig: Record<string, string | number | boolean | string[]> = { ...element } as + Record<string, string | number | boolean | string[]>; + delete newElementConfig.id; // remove ID from object, so a new one is created + const newElement: UIElement = ElementFactory.createElement(newElementConfig as UIElement); + newElement.xPosition += 10; + newElement.yPosition += 10; + this.elements.push(newElement); + }); + } + + static alignElements(elements: UIElement[], alignmentDirection: 'left' | 'right' | 'top' | 'bottom'): void { + let newValue: number; + switch (alignmentDirection) { + case 'left': + newValue = Math.min(...elements.map(element => element.xPosition)); + elements.forEach((element: UIElement) => { + element.xPosition = newValue; + }); + break; + case 'right': + newValue = Math.max(...elements.map(element => element.xPosition + element.width)); + elements.forEach((element: UIElement) => { + element.xPosition = newValue - element.width; + }); + break; + case 'top': + newValue = Math.min(...elements.map(element => element.yPosition)); + elements.forEach((element: UIElement) => { + element.yPosition = newValue; + }); + break; + case 'bottom': + newValue = Math.max(...elements.map(element => element.yPosition + element.height)); + elements.forEach((element: UIElement) => { + element.yPosition = newValue - element.height; + }); + break; + // no default + } + } +} diff --git a/projects/common/classes/textAreaElement.ts b/projects/common/classes/textAreaElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..a3694c7f73d34fbc9e5513e373c01a3e8c8df048 --- /dev/null +++ b/projects/common/classes/textAreaElement.ts @@ -0,0 +1,26 @@ +import { FontElement, SurfaceUIElement } from '../interfaces/UIElementInterfaces'; +import { initSurfaceElement, initFontElement, InputElement, UIElement } from './uIElement'; + +export class TextAreaElement extends InputElement implements FontElement, SurfaceUIElement { + appearance: 'standard' | 'legacy' | 'fill' | 'outline' = 'outline'; + resizeEnabled: boolean = false; + + fontColor: string = 'black'; + font: string = 'Roboto'; + fontSize: number = 18; + bold: boolean = false; + italic: boolean = false; + underline: boolean = false; + + backgroundColor: string = 'transparent'; + + constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + Object.assign(this, serializedElement); + Object.assign(this, initFontElement()); + Object.assign(this, initSurfaceElement()); + + this.backgroundColor = 'transparent'; + this.height = 12; + } +} diff --git a/projects/common/classes/textElement.ts b/projects/common/classes/textElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..fa499ada4d69af7713d44fa2a137d16472d9ebc1 --- /dev/null +++ b/projects/common/classes/textElement.ts @@ -0,0 +1,26 @@ +import { initSurfaceElement, initFontElement, UIElement } from './uIElement'; +import { FontElement, SurfaceUIElement } from '../interfaces/UIElementInterfaces'; + +export class TextElement extends UIElement implements FontElement, SurfaceUIElement { + text: string = '<p>Lorem ipsum dolor sit amet</p>'; + highlightable: boolean = false; + + fontColor: string = 'black'; + font: string = 'Roboto'; + fontSize: number = 18; + bold: boolean = false; + italic: boolean = false; + underline: boolean = false; + + backgroundColor: string = 'transparent'; + + constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + Object.assign(this, serializedElement); + Object.assign(this, initFontElement()); + Object.assign(this, initSurfaceElement()); + + this.height = 78; + this.backgroundColor = 'transparent'; + } +} diff --git a/projects/common/classes/textFieldElement.ts b/projects/common/classes/textFieldElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..66aa6d56b8f53cd91eba46ea3fc8aa81f9159a94 --- /dev/null +++ b/projects/common/classes/textFieldElement.ts @@ -0,0 +1,31 @@ +import { initSurfaceElement, initFontElement, InputElement, UIElement } from './uIElement'; +import { FontElement, SurfaceUIElement } from '../interfaces/UIElementInterfaces'; + +export class TextFieldElement extends InputElement implements FontElement, SurfaceUIElement { + appearance: 'standard' | 'legacy' | 'fill' | 'outline' = 'outline'; + minLength: number | undefined; + minLengthWarnMessage: string = 'Eingabe zu kurz'; + maxLength: number | undefined; + maxLengthWarnMessage: string = 'Eingabe zu lang'; + pattern: string = ''; + patternWarnMessage: string = 'Eingabe entspricht nicht der Vorgabe'; + + fontColor: string = 'black'; + font: string = 'Roboto'; + fontSize: number = 18; + bold: boolean = false; + italic: boolean = false; + underline: boolean = false; + + backgroundColor: string = 'transparent'; + + constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + Object.assign(this, serializedElement); + Object.assign(this, initFontElement()); + Object.assign(this, initSurfaceElement()); + + this.height = 100; + this.backgroundColor = 'transparent'; + } +} diff --git a/projects/common/classes/uIElement.ts b/projects/common/classes/uIElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..020663546de4e48dcaedc095764f35aec36625c1 --- /dev/null +++ b/projects/common/classes/uIElement.ts @@ -0,0 +1,73 @@ +// eslint-disable-next-line max-classes-per-file +import { FontElement, SurfaceUIElement } from '../interfaces/UIElementInterfaces'; +import { IdService } from '../id.service'; + +export abstract class UIElement { + [index: string]: string | number | boolean | string[] | undefined | ((...args: any) => any); + type!: 'text' | 'button' | 'text-field' | 'text-area' | 'checkbox' + | 'dropdown' | 'radio' | 'image' | 'audio' | 'video'; + + id: string = 'id_placeholder'; + zIndex: number = 0; + width: number = 180; + height: number = 60; + dynamicPositioning: boolean = false; + xPosition: number = 0; + yPosition: number = 0; + gridColumnStart: number = 1; + gridColumnEnd: number = 2; + gridRowStart: number = 1; + gridRowEnd: number = 2; + marginLeft: number = 0; + marginRight: number = 0; + marginTop: number = 0; + marginBottom: number = 0; + + protected constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + Object.assign(this, serializedElement); + if (!serializedElement.id) { + this.id = IdService.getInstance().getNewID(serializedElement.type); + } + if (coordinates && this.dynamicPositioning) { + this.gridColumnStart = coordinates.x; + this.gridColumnEnd = coordinates.x + 1; + this.gridRowStart = coordinates.y; + this.gridRowEnd = coordinates.y + 1; + } else if (coordinates && !this.dynamicPositioning) { + this.xPosition = coordinates.x; + this.yPosition = coordinates.y; + } + } +} + +export abstract class InputElement extends UIElement { + label: string; + value: string | number | boolean | undefined; + required: boolean; + requiredWarnMessage: string; + + protected constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + this.label = serializedElement.label as string || 'Dummylabel'; + this.value = serializedElement.value as string | number | boolean | undefined || undefined; + this.required = serializedElement.required as boolean || false; + this.requiredWarnMessage = serializedElement.requiredWarnMessage as string || 'Eingabe erforderlich'; + } +} + +// ================================================ + +export function initFontElement(): FontElement { + return { + fontColor: 'black', + font: 'Roboto', + fontSize: 18, + bold: false, + italic: false, + underline: false + }; +} + +export function initSurfaceElement(): SurfaceUIElement { + return { backgroundColor: 'lightgrey' }; +} diff --git a/projects/common/classes/unit.ts b/projects/common/classes/unit.ts new file mode 100644 index 0000000000000000000000000000000000000000..c37094dfda765f0a1871d6b0bbef1c280a226ffa --- /dev/null +++ b/projects/common/classes/unit.ts @@ -0,0 +1,44 @@ +import { Page } from './page'; +import { moveArrayItem } from '../util/array'; + +const EXPORTED_MODULE_VERSION = 'iqb-aspect-module@0.1.1'; + +export class Unit { + veronaModuleVersion: string; + pages: Page[] = []; + + constructor(serializedUnit?: Unit) { + console.log('newUNIT', serializedUnit); + this.veronaModuleVersion = EXPORTED_MODULE_VERSION; + if (serializedUnit && serializedUnit.pages.length > 0) { + serializedUnit?.pages.forEach((page: Page) => { + this.pages.push(new Page(page)); + }); + } else { + this.pages.push(new Page()); + } + } + + addPage(page?: Page): void { + page ? this.pages.push(page) : this.pages.push(new Page()); + } + + deletePage(page: Page): void { + this.pages.splice(this.pages.indexOf(page), 1); + } + + movePage(selectedPage: Page, direction: 'up' | 'down'): void { + if (direction === 'up' && + this.pages.indexOf(selectedPage) === 1 && + this.pages[0].alwaysVisible) { + return; + } + moveArrayItem(selectedPage, this.pages, direction); + } + + // Make page first element in page array + movePageToTop(pageIndex: number, page: Page): void { + this.pages.splice(pageIndex, 1); + this.pages.splice(0, 0, page); + } +} diff --git a/projects/common/classes/videoElement.ts b/projects/common/classes/videoElement.ts new file mode 100644 index 0000000000000000000000000000000000000000..650ba49f08352bfa5ac8ba8bc37b25b8382afdf8 --- /dev/null +++ b/projects/common/classes/videoElement.ts @@ -0,0 +1,12 @@ +import { UIElement } from './uIElement'; + +export class VideoElement extends UIElement { + src: string = ''; + + constructor(serializedElement: UIElement, coordinates?: { x: number; y: number }) { + super(serializedElement, coordinates); + Object.assign(this, serializedElement); + + this.height = 100; + } +} diff --git a/projects/common/element-component.directive.ts b/projects/common/element-component.directive.ts index 1d723608453c62578d43f1f4977511563f2ad5dd..26e0931d27ae312d824ae11c99cf42f156fd8827 100644 --- a/projects/common/element-component.directive.ts +++ b/projects/common/element-component.directive.ts @@ -1,9 +1,9 @@ import { Directive } from '@angular/core'; -import { UnitUIElement } from './unit'; +import { UIElement } from './classes/uIElement'; @Directive() export abstract class ElementComponent { - abstract elementModel: UnitUIElement; + abstract elementModel: UIElement; } diff --git a/projects/common/element-components/audio.component.ts b/projects/common/element-components/audio.component.ts index 7494d0ff48675435ae7d0e82b5314d7fb8bca4e1..77bef3a509eb4b2b700b1684f6514d38b70d57da 100644 --- a/projects/common/element-components/audio.component.ts +++ b/projects/common/element-components/audio.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; -import { AudioElement } from '../unit'; import { ElementComponent } from '../element-component.directive'; +import { AudioElement } from '../classes/audioElement'; @Component({ selector: 'app-audio', diff --git a/projects/common/element-components/button.component.ts b/projects/common/element-components/button.component.ts index ab72d54ceab03b287e9944ddbb59c00268e2196c..b940318476eccc9e5e700a43b30f5694ce517621 100644 --- a/projects/common/element-components/button.component.ts +++ b/projects/common/element-components/button.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Output } from '@angular/core'; import { ElementComponent } from '../element-component.directive'; -import { ButtonElement } from '../unit'; +import { ButtonElement } from '../classes/buttonElement'; @Component({ selector: 'app-button', diff --git a/projects/common/element-components/checkbox.component.ts b/projects/common/element-components/checkbox.component.ts index aac74faab0ddc0dac904db64f4b7ad4282e9bac9..750826b7e4b98da246fbdf941b90c7150d7a81d8 100644 --- a/projects/common/element-components/checkbox.component.ts +++ b/projects/common/element-components/checkbox.component.ts @@ -1,7 +1,7 @@ import { Component, EventEmitter, Output } from '@angular/core'; import { ValidatorFn, Validators } from '@angular/forms'; -import { CheckboxElement } from '../unit'; import { FormElementComponent } from '../form-element-component.directive'; +import { CheckboxElement } from '../classes/checkboxElement'; @Component({ selector: 'app-checkbox', diff --git a/projects/common/element-components/dropdown.component.ts b/projects/common/element-components/dropdown.component.ts index 51dee9a03b919586e068928d25c9d119f8082dbb..2ecf91a14d6fe2f05f65c251302c693f92359bc6 100644 --- a/projects/common/element-components/dropdown.component.ts +++ b/projects/common/element-components/dropdown.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Output } from '@angular/core'; -import { DropdownElement } from '../unit'; import { FormElementComponent } from '../form-element-component.directive'; +import { DropdownElement } from '../classes/dropdownElement'; @Component({ selector: 'app-dropdown', diff --git a/projects/common/element-components/image.component.ts b/projects/common/element-components/image.component.ts index c63919811efd3697e38c07d543a7c46621fdb66c..a49b9a5083ddc9fb3249eb4dd44e718604c19a31 100644 --- a/projects/common/element-components/image.component.ts +++ b/projects/common/element-components/image.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; -import { ImageElement } from '../unit'; import { ElementComponent } from '../element-component.directive'; +import { ImageElement } from '../classes/imageElement'; @Component({ selector: 'app-image', diff --git a/projects/common/element-components/pipes/error-transform.pipe.ts b/projects/common/element-components/pipes/error-transform.pipe.ts index 14bb4d29040c9f4bd3ef6ccc490451bd4c10a1e3..0521d6fd0299524a1d20058d27b0a5b4865c176c 100644 --- a/projects/common/element-components/pipes/error-transform.pipe.ts +++ b/projects/common/element-components/pipes/error-transform.pipe.ts @@ -1,9 +1,7 @@ import { Pipe, PipeTransform } from '@angular/core'; import { ValidationErrors } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; -import { - CheckboxElement, InputUIElement, TextFieldElement, UnitUIElement -} from '../../unit'; +import { UIElement } from '../../classes/uIElement'; @Pipe({ name: 'errorTransform' @@ -11,7 +9,7 @@ import { export class ErrorTransformPipe implements PipeTransform { constructor(private translateService: TranslateService) {} - transform(validationErrors: ValidationErrors, elementModel: UnitUIElement): string { + transform(validationErrors: ValidationErrors, elementModel: UIElement): string { const validationMessages = this.getValidationMessages(elementModel); let returnMessage = ''; @@ -25,21 +23,17 @@ export class ErrorTransformPipe implements PipeTransform { return returnMessage; } - private getValidationMessages(elementModel: UnitUIElement): Record<string, string> { + private getValidationMessages(elementModel: UIElement): Record<string, string> { return { - required: (elementModel as InputUIElement).requiredWarnMessage || + required: elementModel.requiredWarnMessage || this.translateService.instant('validators.inputRequired'), - - requiredTrue: (elementModel as CheckboxElement).requiredWarnMessage || + requiredTrue: elementModel.requiredWarnMessage || this.translateService.instant('validators.inputRequiredTrue'), - - minlength: (elementModel as TextFieldElement).minWarnMessage || + minlength: elementModel.minWarnMessage || this.translateService.instant('validators.inputTooShort'), - - maxlength: (elementModel as TextFieldElement).maxWarnMessage || + maxlength: elementModel.maxWarnMessage || this.translateService.instant('validators.inputTooLong'), - - pattern: (elementModel as TextFieldElement).patternWarnMessage || + pattern: elementModel.patternWarnMessage || this.translateService.instant('validators.wrongPattern') }; } diff --git a/projects/common/element-components/radio-button-group.component.ts b/projects/common/element-components/radio-button-group.component.ts index 950566e2f6ce15e01fd3ef1f691fd8b9ce39bbb5..e1914310417cb72b1651a061af893c53c2d27c3a 100644 --- a/projects/common/element-components/radio-button-group.component.ts +++ b/projects/common/element-components/radio-button-group.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Output } from '@angular/core'; -import { RadioButtonGroupElement } from '../unit'; import { FormElementComponent } from '../form-element-component.directive'; +import { RadioButtonGroupElement } from '../classes/radioButtonGroupElement'; @Component({ selector: 'app-radio-button-group', diff --git a/projects/common/element-components/text-area.component.ts b/projects/common/element-components/text-area.component.ts index 2ab468a3e9efc0957e915a115fb8661698f03f02..fb23425d35e83f820107246acc53770ebbd40145 100644 --- a/projects/common/element-components/text-area.component.ts +++ b/projects/common/element-components/text-area.component.ts @@ -1,6 +1,6 @@ import { Component, Output, EventEmitter } from '@angular/core'; -import { TextAreaElement } from '../unit'; import { FormElementComponent } from '../form-element-component.directive'; +import { TextAreaElement } from '../classes/textAreaElement'; @Component({ selector: 'app-text-area', diff --git a/projects/common/element-components/text-field.component.ts b/projects/common/element-components/text-field.component.ts index b28397c7b3515172dffe33acf9053547511d1fe9..452211b95cfb83fcc36fcaa628955c93ae290d8e 100644 --- a/projects/common/element-components/text-field.component.ts +++ b/projects/common/element-components/text-field.component.ts @@ -1,7 +1,7 @@ import { Component, EventEmitter, Output } from '@angular/core'; import { ValidatorFn, Validators } from '@angular/forms'; -import { TextFieldElement } from '../unit'; import { FormElementComponent } from '../form-element-component.directive'; +import { TextFieldElement } from '../classes/textFieldElement'; @Component({ selector: 'app-text-field', diff --git a/projects/common/element-components/text.component.ts b/projects/common/element-components/text.component.ts index f59b879c5b6f33972885affad568732c8d205d81..f61ac1ceab5e1fa7743257e3d8f1e90d2f05ada5 100644 --- a/projects/common/element-components/text.component.ts +++ b/projects/common/element-components/text.component.ts @@ -1,7 +1,7 @@ import { Component, ElementRef, ViewChild } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; -import { TextElement } from '../unit'; import { ElementComponent } from '../element-component.directive'; +import { TextElement } from '../classes/textElement'; @Component({ selector: 'app-text', diff --git a/projects/common/element-components/video.component.ts b/projects/common/element-components/video.component.ts index f0e27bdd92ca9e443e6e84a0381449d12eaca9ea..8ec946d33c3ffd6133a500d286f0cdaa414c7f43 100644 --- a/projects/common/element-components/video.component.ts +++ b/projects/common/element-components/video.component.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; -import { VideoElement } from '../unit'; import { ElementComponent } from '../element-component.directive'; +import { VideoElement } from '../classes/videoElement'; @Component({ selector: 'app-video', diff --git a/projects/common/interfaces/UIElementInterfaces.ts b/projects/common/interfaces/UIElementInterfaces.ts new file mode 100644 index 0000000000000000000000000000000000000000..f315783b2ab04ab52b97d64f08682e9369561987 --- /dev/null +++ b/projects/common/interfaces/UIElementInterfaces.ts @@ -0,0 +1,12 @@ +export interface FontElement { + fontColor: string; + font: string; + fontSize: number; + bold: boolean; + italic: boolean; + underline: boolean; +} + +export interface SurfaceUIElement { + backgroundColor: string; +} diff --git a/projects/common/unit.ts b/projects/common/unit.ts deleted file mode 100644 index 219b9a270d5fbb92671bb4effc8d605e6fa4a3f8..0000000000000000000000000000000000000000 --- a/projects/common/unit.ts +++ /dev/null @@ -1,132 +0,0 @@ -export interface Unit { - veronaModuleVersion: string; - pages: UnitPage[]; -} - -export interface UnitPage { - [index: string]: string | number | boolean | undefined | UnitPageSection[]; - id: string; - sections: UnitPageSection[]; - hasMaxWidth: boolean; - maxWidth: number; - margin: number; - backgroundColor: string; - alwaysVisible: boolean; - alwaysVisiblePagePosition: 'left' | 'right' | 'top' | 'bottom'; - alwaysVisibleAspectRatio: number; -} - -export interface UnitPageSection { - [index: string]: string | number | boolean | undefined | UnitUIElement[]; - elements: UnitUIElement[]; - height: number; - backgroundColor: string; - dynamicPositioning: boolean; - gridColumnSizes: string; - gridRowSizes: string; -} - -export interface UnitUIElement { - [index: string]: string | number | boolean | string[] | undefined; - type: 'text' | 'button' | 'text-field' | 'text-area' | 'checkbox' - | 'dropdown' | 'radio' | 'image' | 'audio' | 'video'; - id: string; - zIndex: number - width: number; - height: number; - dynamicPositioning: boolean; - xPosition: number; - yPosition: number; - gridColumnStart: number; - gridColumnEnd: number; - gridRowStart: number; - gridRowEnd: number; - marginLeft: number; - marginRight: number; - marginTop: number; - marginBottom: number; -} - -export interface TextUIElement extends UnitUIElement { - fontColor: string; - font: string; - fontSize: number; - bold: boolean; - italic: boolean; - underline: boolean; -} - -export interface InputUIElement extends UnitUIElement { - label: string; - value: string | number | boolean | undefined; - required: boolean; - requiredWarnMessage: string; -} - -export interface SurfaceUIElement extends UnitUIElement { - backgroundColor: string; -} - -export interface TextElement extends SurfaceUIElement { - text: string; - fontColor: string; - font: string; - bold: boolean; - italic: boolean; - underline: boolean; - highlightable: boolean -} - -export interface ButtonElement extends TextUIElement, SurfaceUIElement { - label: string; - imageSrc?: string; - borderRadius?: number; - action: undefined | 'previous' | 'next' | 'end'; -} - -export interface TextFieldElement extends InputUIElement, TextUIElement, SurfaceUIElement { - value: string; - appearance: 'standard' | 'legacy' | 'fill' | 'outline'; - minLength: number | undefined; - minLengthWarnMessage: string; - maxLength: number | undefined; - maxLengthWarnMessage: string; - pattern: string; - patternWarnMessage: string; -} - -export interface TextAreaElement extends InputUIElement, TextUIElement, SurfaceUIElement { - value: string; - appearance: 'standard' | 'legacy' | 'fill' | 'outline'; - resizeEnabled: boolean; -} - -export interface CheckboxElement extends InputUIElement, TextUIElement, SurfaceUIElement { - value: boolean; -} - -export interface DropdownElement extends InputUIElement, TextUIElement, SurfaceUIElement { - label: string; - options: string[]; - value: string | undefined; - allowUnset: boolean; -} - -export interface RadioButtonGroupElement extends InputUIElement, TextUIElement, SurfaceUIElement { - label: string; - options: string[]; - alignment: 'row' | 'column'; - value: string | undefined; -} - -export interface ImageElement extends UnitUIElement { - src: string; -} - -export interface AudioElement extends UnitUIElement { - src: string; -} - -export interface VideoElement extends UnitUIElement { - src: string; -} diff --git a/projects/editor/src/app/UnitFactory.ts b/projects/editor/src/app/UnitFactory.ts deleted file mode 100644 index 9f9c3a404d972ed729e1ac2027f66c4a2f0c98ff..0000000000000000000000000000000000000000 --- a/projects/editor/src/app/UnitFactory.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { - AudioElement, ButtonElement, - CheckboxElement, CompoundElementCorrection, DropdownElement, - ImageElement, TextElement, RadioButtonGroupElement, - TextFieldElement, Unit, UnitPage, UnitPageSection, UnitUIElement, - VideoElement, TextAreaElement -} from '../../../common/unit'; - -const EXPORTED_MODULE_VERSION = 'iqb-aspect-module@0.1.1'; - -export function createUnit(): Unit { - return { - veronaModuleVersion: EXPORTED_MODULE_VERSION, - pages: [] - }; -} - -export function createUnitPage(pageIndex: number): UnitPage { - return { - id: `page${pageIndex}`, - sections: [], - hasMaxWidth: false, - maxWidth: 900, - margin: 8, - backgroundColor: 'white', - alwaysVisible: false, - alwaysVisiblePagePosition: 'left', - alwaysVisibleAspectRatio: 50 - }; -} - -export function createUnitPageSection(): UnitPageSection { - return { - elements: [], - height: 400, - backgroundColor: 'white', - dynamicPositioning: false, - gridColumnSizes: '1fr 1fr', - gridRowSizes: '1fr' - }; -} - -export function createUnitUIElement(type: 'text' | 'button' | 'text-field' | 'text-area' | 'checkbox' -| 'dropdown' | 'radio' | 'image' | 'audio' | 'video'): UnitUIElement { - return { - type, - id: 'id_placeholder', - zIndex: 0, - width: 180, - height: 60, - dynamicPositioning: false, - xPosition: 0, - yPosition: 0, - gridColumnStart: 1, - gridColumnEnd: 2, - gridRowStart: 1, - gridRowEnd: 2, - marginLeft: 0, - marginRight: 0, - marginTop: 0, - marginBottom: 0 - }; -} - -export function createTextUIElement(): Record<string, unknown> { - return { - fontColor: 'black', - font: 'Roboto', - fontSize: 18, - bold: false, - italic: false, - underline: false - }; -} - -export function createInputUIElement( - label: string, value: string | number | boolean | undefined -): Record<string, unknown> { - return { - label: label, - value: value, - required: false, - requiredWarnMessage: 'Eingabe erforderlich' - }; -} - -export function createSurfaceUIElement(): Record<string, unknown> { - return { - backgroundColor: 'lightgrey' - }; -} - -export function createTextElement(): TextElement { - return <TextElement>{ - text: '<p>Lorem ipsum dolor sit amet</p>', - fontColor: 'black', - font: 'Roboto', - bold: false, - italic: false, - underline: false, - highlightable: false, - ...createUnitUIElement('text'), - ...createSurfaceUIElement(), - backgroundColor: 'transparent', - height: 78 - }; -} - -export function createButtonElement(): ButtonElement { - return <ButtonElement>{ - label: 'Knopf Beschriftung', - action: undefined, - ...createUnitUIElement('button'), - ...createTextUIElement(), - ...createSurfaceUIElement() - }; -} - -export function createTextfieldElement(): TextFieldElement { - return <TextFieldElement>{ - appearance: 'outline', - minLength: undefined, - minLengthWarnMessage: 'Eingabe zu kurz', - maxLength: undefined, - maxLengthWarnMessage: 'Eingabe zu lang', - pattern: '', - patternWarnMessage: 'Eingabe entspricht nicht der Vorgabe', - ...createUnitUIElement('text-field'), - ...createInputUIElement('Beispiel Beschriftung', ''), - ...createTextUIElement(), - ...createSurfaceUIElement(), - backgroundColor: 'transparent', - height: 100 - }; -} - -export function createTextareaElement(): TextAreaElement { - return <TextAreaElement>{ - resizeEnabled: false, - appearance: 'outline', - ...createUnitUIElement('text-area'), - ...createInputUIElement('Beispiel Beschriftung', ''), - ...createTextUIElement(), - ...createSurfaceUIElement(), - backgroundColor: 'transparent', - height: 120 - }; -} - -export function createCheckboxElement(): CheckboxElement { - return <CheckboxElement>{ - ...createUnitUIElement('checkbox'), - ...createInputUIElement('Beschriftung', false), - ...createTextUIElement(), - ...createSurfaceUIElement(), - backgroundColor: 'transparent' - }; -} - -export function createDropdownElement(): DropdownElement { - return <DropdownElement><unknown>{ - options: [], - allowUnset: false, - ...createUnitUIElement('dropdown'), - ...createInputUIElement('Beschriftung', undefined), - ...createTextUIElement(), - ...createSurfaceUIElement(), - height: 83 - }; -} - -export function createRadioButtonGroupElement(): RadioButtonGroupElement { - return <RadioButtonGroupElement><unknown>{ - options: [], - alignment: 'column', - ...createUnitUIElement('radio'), - ...createInputUIElement('Beschriftung Optionsfeld', undefined), - ...createTextUIElement(), - ...createSurfaceUIElement(), - height: 85, - backgroundColor: 'transparent' - }; -} - -export function createImageElement(imageSrc: string): ImageElement { - return { - src: imageSrc, - ...createUnitUIElement('image'), - height: 100 - }; -} - -export function createAudioElement(audioSrc: string): AudioElement { - return { - src: audioSrc, - ...createUnitUIElement('audio') - }; -} - -export function createVideoElement(videoSrc: string): VideoElement { - return { - src: videoSrc, - ...createUnitUIElement('video'), - height: 100 - }; -}