diff --git a/projects/common/classes/buttonElement.ts b/projects/common/classes/buttonElement.ts index 0adf39554593a630a5d4752f46e11a8fa1cdd7a6..7b8410e43caf555af551a56cc10bac19cf3ff7e2 100644 --- a/projects/common/classes/buttonElement.ts +++ b/projects/common/classes/buttonElement.ts @@ -3,7 +3,7 @@ import { initSurfaceElement, initFontElement, UIElement } from './uIElement'; export class ButtonElement extends UIElement implements FontElement, SurfaceUIElement { label: string = 'Knopf'; - imageSrc: string = ''; + imageSrc: string | undefined; borderRadius: number = 0; action: undefined | 'previous' | 'next' | 'end'; diff --git a/projects/editor/src/app/components/unit-view/page-view/properties/element-properties.component.html b/projects/editor/src/app/components/unit-view/page-view/properties/element-properties.component.html index 52c15c332fb5da63f60243164b7a53364c7c4dce..c8302ee77e99d201acc9e2da2723860a2c279f3d 100644 --- a/projects/editor/src/app/components/unit-view/page-view/properties/element-properties.component.html +++ b/projects/editor/src/app/components/unit-view/page-view/properties/element-properties.component.html @@ -5,14 +5,14 @@ <mat-icon class="example-tab-icon">build</mat-icon> </ng-template> <div fxLayout="column"> - <mat-form-field *ngIf="combinedProperties.id" appearance="fill"> + <mat-form-field appearance="fill"> <mat-label>ID</mat-label> <input matInput type="text" *ngIf="selectedElements.length === 1" [value]="combinedProperties.id" (input)="updateModel('id', $any($event.target).value)"> <input matInput type="text" disabled *ngIf="selectedElements.length > 1" [value]="'Muss eindeutig sein'"> </mat-form-field> - <mat-form-field *ngIf="combinedProperties.label" appearance="fill"> + <mat-form-field *ngIf="combinedProperties.label !== null" appearance="fill"> <mat-label>Label</mat-label> <input matInput type="text" [value]="combinedProperties.label" (input)="updateModel('label', $any($event.target).value)"> @@ -25,35 +25,83 @@ </div> </ng-container> - <div *ngIf="combinedProperties.type === 'button'"> - <input #imageUpload type="file" hidden (click)="loadImage()"> - <button mat-raised-button (click)="imageUpload.click()">Bild laden</button> - <button mat-raised-button (click)="removeImage()">Bild entfernen</button> - <img [src]="combinedProperties.imageSrc" - [style.object-fit]="'scale-down'" - [width]="200"> - <mat-form-field appearance="fill"> - <mat-label>Kantenradius</mat-label> - <input matInput type="number" [value]="combinedProperties.borderRadius" - (input)="updateModel('borderRadius', $any($event.target).value)"> - </mat-form-field> - </div> - - <mat-form-field *ngIf="combinedProperties.appearance" appearance="fill"> - <mat-label>Aussehen</mat-label> - <mat-select [value]="combinedProperties.appearance" - (selectionChange)="updateModel('appearance', $event.value)"> - <mat-option *ngFor="let option of [{displayValue: 'standard', value: 'standard'}, - {displayValue: 'legacy', value: 'legacy'}, - {displayValue: 'fill', value: 'fill'}, - {displayValue: 'outline', value: 'outline'}]" + <mat-form-field *ngIf="combinedProperties.borderRadius != null" appearance="fill"> + <mat-label>Kantenradius</mat-label> + <input matInput type="number" [value]="combinedProperties.borderRadius" + (input)="updateModel('borderRadius', $any($event.target).value)"> + </mat-form-field> + + <mat-checkbox *ngIf="combinedProperties.highlightable != null" + [checked]="$any(combinedProperties.highlightable)" + (change)="updateModel('highlightable', $event.checked)"> + Farbmarkierungen erlauben + </mat-checkbox> + + <mat-checkbox *ngIf="combinedProperties.allowUnset != null" + [checked]="$any(combinedProperties.allowUnset)" + (change)="updateModel('allowUnset', $event.checked)"> + Deselektion erlauben + </mat-checkbox> + + <mat-checkbox *ngIf="combinedProperties.required != null" + [checked]="$any(combinedProperties.required)" + (change)="updateModel('required', $event.checked)"> + Pflichtfeld + </mat-checkbox> + <mat-form-field *ngIf="combinedProperties.required" + appearance="fill"> + <mat-label>Warnmeldung</mat-label> + <input matInput type="text" [value]="combinedProperties.requiredWarnMessage" + (input)="updateModel('requiredWarnMessage', $any($event.target).value)"> + </mat-form-field> + + <mat-form-field disabled="true" *ngIf="combinedProperties.options != null"> + <ng-container> + <mat-label>Optionen</mat-label> + <div class="drop-list" cdkDropList [cdkDropListData]="combinedProperties.options" + (cdkDropListDropped)="reorderOptions('options', $any($event))"> + <div *ngFor="let option of $any(combinedProperties.options)" cdkDrag + class="list-items"> + {{option}} + <button mat-icon-button color="warn" + (click)="removeOption('options', option)"> + <mat-icon>clear</mat-icon> + </button> + </div> + </div> + </ng-container> + <div class="newOptionElement" fxLayout="row" fxLayoutAlign="center center"> + <button mat-icon-button matPrefix + (click)="addOption('options', newOption.value); newOption.select()"> + <mat-icon>add</mat-icon> + </button> + <input #newOption matInput type="text" placeholder="Optionstext" + (keyup.enter)="addOption('options', newOption.value); newOption.select()"> + </div> + </mat-form-field> + + <mat-form-field *ngIf="combinedProperties.alignment" appearance="fill"> + <mat-label>Ausrichtung</mat-label> + <mat-select [value]="combinedProperties.alignment" + (selectionChange)="updateModel('alignment', $event.value)"> + <mat-option *ngFor="let option of [{displayValue: 'horizontal', value: 'row'}, + {displayValue: 'vertikal', value: 'column'}]" [value]="option.value"> {{option.displayValue}} </mat-option> </mat-select> </mat-form-field> - <mat-form-field *ngIf="combinedProperties.action" appearance="fill"> + <mat-checkbox *ngIf="combinedProperties.resizeEnabled != null" + [checked]="$any(combinedProperties.resizeEnabled)" + (change)="updateModel('resizeEnabled', $event.checked)"> + größenverstellbar + </mat-checkbox> + </div> + + <!-- Some type specific fields which may be undefined but need to show up regardless --> + <ng-container *ngIf="combinedProperties.type == 'button'"> + <mat-form-field appearance="fill"> <mat-label>Aktion</mat-label> <mat-select [value]="combinedProperties.action" (selectionChange)="updateModel('action', $event.value)"> @@ -67,57 +115,56 @@ </mat-select> </mat-form-field> - <mat-checkbox *ngIf="combinedProperties.highlightable" - [checked]="$any(combinedProperties.highlightable)" - (change)="updateModel('highlightable', $event.checked)"> - Farbmarkierungen erlauben - </mat-checkbox> - - <mat-form-field *ngIf="combinedProperties.type === 'text-field'" appearance="fill"> + <input #imageUpload type="file" hidden (click)="loadImage()"> + <button mat-raised-button (click)="imageUpload.click()">Bild laden</button> + <button mat-raised-button (click)="removeImage()">Bild entfernen</button> + <img [src]="combinedProperties.imageSrc" + [style.object-fit]="'scale-down'" + [width]="200"> + </ng-container> + + <ng-container *ngIf="combinedProperties.type === 'checkbox'"> + Vorbelegung + <mat-button-toggle-group [value]="combinedProperties.value" + (change)="updateModel('value', $event.value)"> + <mat-button-toggle [value]="true">wahr</mat-button-toggle> + <mat-button-toggle [value]="false">falsch</mat-button-toggle> + </mat-button-toggle-group> + </ng-container> + + <mat-form-field *ngIf="combinedProperties.type === 'dropdown' || combinedProperties.type === 'radio'" + appearance="fill"> + <mat-label>Vorbelegung</mat-label> + <mat-select [value]="combinedProperties.value" + (selectionChange)="updateModel('value', $event.value)"> + <mat-option>undefiniert</mat-option> + <mat-option *ngFor="let option of $any(combinedProperties).options" [value]="option"> + {{option}} + </mat-option> + </mat-select> + </mat-form-field> + + <ng-container *ngIf="combinedProperties.type === 'text-field' || combinedProperties.type === 'text-area'"> + <mat-form-field appearance="fill"> <mat-label>Vorbelegung</mat-label> <input matInput type="text" [value]="combinedProperties.value" (input)="updateModel('value', $any($event.target).value)"> </mat-form-field> - <section *ngIf="combinedProperties.type === 'checkbox'"> - Vorbelegung - <mat-button-toggle-group [value]="combinedProperties.value" - (change)="updateModel('value', $event.value)"> - <mat-button-toggle [value]="true">wahr</mat-button-toggle> - <mat-button-toggle [value]="false">falsch</mat-button-toggle> - </mat-button-toggle-group> - </section> - <mat-form-field *ngIf="combinedProperties.type === 'dropdown' || combinedProperties.type === 'radio'" - appearance="fill"> - <mat-label>Vorbelegung</mat-label> - <mat-select [value]="combinedProperties.value" - (selectionChange)="updateModel('value', $event.value)"> - <mat-option>undefiniert</mat-option> - <mat-option *ngFor="let option of $any(combinedProperties).options" [value]="option"> - {{option}} + <mat-form-field appearance="fill"> + <mat-label>Aussehen</mat-label> + <mat-select [value]="combinedProperties.appearance" + (selectionChange)="updateModel('appearance', $event.value)"> + <mat-option *ngFor="let option of [{displayValue: 'standard', value: 'standard'}, + {displayValue: 'legacy', value: 'legacy'}, + {displayValue: 'fill', value: 'fill'}, + {displayValue: 'outline', value: 'outline'}]" + [value]="option.value"> + {{option.displayValue}} </mat-option> </mat-select> </mat-form-field> - - <mat-checkbox *ngIf="combinedProperties.allowUnset" - [checked]="$any(combinedProperties.allowUnset)" - (change)="updateModel('allowUnset', $event.checked)"> - Deselektion erlauben - </mat-checkbox> - - <mat-checkbox *ngIf="combinedProperties.required" - [checked]="$any(combinedProperties.required)" - (change)="updateModel('required', $event.checked)"> - Pflichtfeld - </mat-checkbox> - <mat-form-field *ngIf="combinedProperties.required && combinedProperties.required" - appearance="fill"> - <mat-label>Warnmeldung</mat-label> - <input matInput type="text" [value]="combinedProperties.requiredWarnMessage" - (input)="updateModel('requiredWarnMessage', $any($event.target).value)"> - </mat-form-field> - - <mat-form-field *ngIf="combinedProperties.minLength" appearance="fill"> + <mat-form-field appearance="fill"> <mat-label>Minimallänge</mat-label> <input matInput type="number" #minLength="ngModel" min="0" [ngModel]="combinedProperties.minLength" @@ -130,7 +177,7 @@ <input matInput type="text" [value]="combinedProperties.minLengthWarnMessage" (input)="updateModel('minLengthWarnMessage', $any($event.target).value)"> </mat-form-field> - <mat-form-field *ngIf="combinedProperties.maxLength" appearance="fill"> + <mat-form-field appearance="fill"> <mat-label>Maximalwert</mat-label> <input matInput type="number" #maxLength="ngModel" min="0" [ngModel]="combinedProperties.maxLength" @@ -144,7 +191,7 @@ (input)="updateModel('maxLengthWarnMessage', $any($event.target).value)"> </mat-form-field> - <mat-form-field *ngIf="combinedProperties.pattern" appearance="fill"> + <mat-form-field appearance="fill"> <mat-label>Muster</mat-label> <input matInput [value]="combinedProperties.pattern" (input)="updateModel('pattern', $any($event.target).value)"> @@ -157,50 +204,7 @@ <input matInput type="text" [value]="combinedProperties.patternWarnMessage" (input)="updateModel('patternWarnMessage', $any($event.target).value)"> </mat-form-field> - - <mat-form-field disabled="true" *ngIf="combinedProperties.options"> - <ng-container *ngIf="combinedProperties.options !== undefined"> - <mat-label>Optionen</mat-label> - <div class="drop-list" cdkDropList [cdkDropListData]="combinedProperties.options" - (cdkDropListDropped)="reorderOptions('options', $any($event))"> - <div *ngFor="let option of $any(combinedProperties.options)" cdkDrag - class="list-items"> - {{option}} - <button mat-icon-button color="warn" - (click)="removeOption('options', option)"> - <mat-icon>clear</mat-icon> - </button> - </div> - </div> - </ng-container> - <div class="newOptionElement" fxLayout="row" fxLayoutAlign="center center"> - <button mat-icon-button matPrefix - (click)="addOption('options', newOption.value); newOption.select()"> - <mat-icon>add</mat-icon> - </button> - <input #newOption matInput type="text" placeholder="Optionstext" - (keyup.enter)="addOption('options', newOption.value); newOption.select()"> - </div> - </mat-form-field> - - <mat-form-field *ngIf="combinedProperties.alignment" appearance="fill"> - <mat-label>Ausrichtung</mat-label> - <mat-select [value]="combinedProperties.alignment" - (selectionChange)="updateModel('alignment', $event.value)"> - <mat-option *ngFor="let option of [{displayValue: 'horizontal', value: 'row'}, - {displayValue: 'vertikal', value: 'column'}]" - [value]="option.value"> - {{option.displayValue}} - </mat-option> - </mat-select> - </mat-form-field> - - <mat-checkbox *ngIf="combinedProperties.resizeEnabled" - [checked]="$any(combinedProperties.resizeEnabled)" - (change)="updateModel('resizeEnabled', $event.checked)"> - größenverstellbar - </mat-checkbox> - </div> + </ng-container> <mat-divider></mat-divider> diff --git a/projects/editor/src/app/components/unit-view/page-view/properties/element-properties.component.ts b/projects/editor/src/app/components/unit-view/page-view/properties/element-properties.component.ts index 9d737cda9d9a14d379dc9752841445451047953c..b28278c4b91e93afda4e45478281c8db640122f5 100644 --- a/projects/editor/src/app/components/unit-view/page-view/properties/element-properties.component.ts +++ b/projects/editor/src/app/components/unit-view/page-view/properties/element-properties.component.ts @@ -6,11 +6,11 @@ import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { CdkDragDrop } from '@angular/cdk/drag-drop/drag-events'; import { moveItemInArray } from '@angular/cdk/drag-drop'; -import { UnitUIElement } from '../../../../../../../common/unit'; import { UnitService } from '../../../../unit.service'; import { SelectionService } from '../../../../selection.service'; import { MessageService } from '../../../../../../../common/message.service'; import { FileService } from '../../../../../../../common/file.service'; +import { UIElement } from '../../../../../../../common/classes/uIElement'; @Component({ selector: 'app-element-properties', @@ -19,7 +19,8 @@ import { FileService } from '../../../../../../../common/file.service'; }) export class ElementPropertiesComponent implements OnInit, OnDestroy { selectedElements!: UIElement[]; - combinedProperties: Record<string, string | number | boolean | string[] | undefined> = {}; + // combinedProperties: Record<string, string | number | boolean | string[] | undefined> = {}; + combinedProperties: UIElement = {} as UIElement; private ngUnsubscribe = new Subject<void>(); constructor(private selectionService: SelectionService, public unitService: UnitService, @@ -47,13 +48,18 @@ export class ElementPropertiesComponent implements OnInit, OnDestroy { /* Create new object with properties of all selected elements. When values differ set prop to undefined. */ createCombinedProperties(): void { if (this.selectedElements.length === 0) { - this.combinedProperties = {}; + this.combinedProperties = {} as UIElement; } else { - this.combinedProperties = { ...this.selectedElements[0] }; + this.combinedProperties = { ...this.selectedElements[0] } as UIElement; for (let i = 1; i < this.selectedElements.length; i++) { - Object.keys(this.combinedProperties).forEach((property: keyof UnitUIElement) => { + Object.keys(this.combinedProperties).forEach((property: keyof UIElement) => { if (Object.prototype.hasOwnProperty.call(this.selectedElements[i], property)) { + if (Array.isArray(this.selectedElements[i][property])) { + if (this.selectedElements[i][property]!.toString() === this.combinedProperties[property]!.toString()) { + this.combinedProperties[property] = this.selectedElements[i][property]; + } + } if (this.selectedElements[i][property] !== this.combinedProperties[property]) { this.combinedProperties[property] = undefined; } @@ -63,6 +69,7 @@ export class ElementPropertiesComponent implements OnInit, OnDestroy { }); } } + console.log('combined:', this.combinedProperties); } updateModel(property: string, @@ -98,7 +105,7 @@ export class ElementPropertiesComponent implements OnInit, OnDestroy { addOption(property: string, value: string): void { (this.combinedProperties[property] as string[]).push(value); - this.updateModel(property, this.combinedProperties[property]); + this.updateModel(property, this.combinedProperties[property] as string[]); } reorderOptions(property: string, event: CdkDragDrop<string[]>): void { @@ -107,7 +114,7 @@ export class ElementPropertiesComponent implements OnInit, OnDestroy { } removeOption(property: string, option: string): void { - const valueList: string[] = this.combinedProperties[property] as []; + const valueList: string[] = this.combinedProperties[property] as string[]; valueList.splice(valueList.indexOf(option), 1); this.updateModel(property, valueList); } diff --git a/projects/editor/src/app/components/unit-view/page-view/properties/element-sizing-properties.component.ts b/projects/editor/src/app/components/unit-view/page-view/properties/element-sizing-properties.component.ts index 739037f3cb358d7eb6774954b4385d43cf94f95f..298ea6b70c445a16fac3a7d439e8d3e59593c401 100644 --- a/projects/editor/src/app/components/unit-view/page-view/properties/element-sizing-properties.component.ts +++ b/projects/editor/src/app/components/unit-view/page-view/properties/element-sizing-properties.component.ts @@ -3,6 +3,7 @@ import { } from '@angular/core'; import { UnitService } from '../../../../unit.service'; import { SelectionService } from '../../../../selection.service'; +import { UIElement } from '../../../../../../../common/classes/uIElement'; @Component({ selector: 'app-element-sizing-properties', @@ -149,7 +150,7 @@ import { SelectionService } from '../../../../selection.service'; ] }) export class ElementSizingPropertiesComponent { - @Input() combinedProperties: Record<string, string | number | boolean | string[] | undefined> = {}; + @Input() combinedProperties: UIElement = {} as UIElement; @Output() updateModel = new EventEmitter<{ property: string; value: string | boolean, isInputValid?: boolean | null }>(); diff --git a/projects/editor/src/app/components/unit-view/page-view/properties/element-style-properties.component.ts b/projects/editor/src/app/components/unit-view/page-view/properties/element-style-properties.component.ts index 4cafcdd9d4dac80c0eb67add8907ca2a7a9ce371..d47a8e0849fbfb3ea8fd70435e600edd4282a8af 100644 --- a/projects/editor/src/app/components/unit-view/page-view/properties/element-style-properties.component.ts +++ b/projects/editor/src/app/components/unit-view/page-view/properties/element-style-properties.component.ts @@ -1,18 +1,19 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { UIElement } from '../../../../../../../common/classes/uIElement'; @Component({ selector: 'app-element-style-properties', template: ` <div fxLayout="column"> - <mat-form-field *ngIf="combinedProperties.backgroundColor != null" + <mat-form-field *ngIf="combinedProperties.backgroundColor" appearance="fill" class="mdInput textsingleline"> <mat-label>Hintergrundfarbe</mat-label> <input matInput type="color" [value]="combinedProperties.backgroundColor" (input)="updateModel.emit({ property: 'backgroundColor', value: $any($event.target).value })"> </mat-form-field> - <mat-form-field *ngIf="combinedProperties.fontColor != null" + <mat-form-field *ngIf="combinedProperties.fontColor" appearance="fill" class="mdInput textsingleline"> <mat-label>Schriftfarbe</mat-label> <input matInput type="color" [value]="combinedProperties.fontColor" @@ -50,6 +51,6 @@ import { ` }) export class ElementStylePropertiesComponent { - @Input() combinedProperties: Record<string, string | number | boolean | string[] | undefined> = {}; + @Input() combinedProperties: UIElement = {} as UIElement; @Output() updateModel = new EventEmitter<{ property: string; value: string | boolean }>(); }