Skip to content
Snippets Groups Projects
Commit 4dda125e authored by rhenck's avatar rhenck
Browse files

Add new element DropList

This element has a list of string as editable options. Those strings 
form draggable elements which may be reordered or moved between 
different DropList elements.

Also refactor option change logic to allow any property not just the 
text property.
parent 7c37aed0
No related branches found
No related tags found
No related merge requests found
Showing
with 128 additions and 10 deletions
import { Component } from '@angular/core';
import { CdkDragDrop } from '@angular/cdk/drag-drop/drag-events';
import { moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
import { DropListElement } from '../../models/compound-elements/drop-list';
import { FormElementComponent } from '../../form-element-component.directive';
@Component({
selector: 'app-drop-list',
template: `
<div class="list" cdkDropList
[id]="elementModel.id"
[cdkDropListData]="this"
[cdkDropListConnectedTo]="elementModel.connectedTo"
(cdkDropListDropped)="drop($event)">
<div class="item" *ngFor="let option of elementModel.options" cdkDrag>
{{option}}
</div>
</div>
`,
styles: [
'.list {border: 1px solid; border-radius: 3px}',
'.item {padding: 10px;}',
'.item:not(:last-child) {border-bottom: 1px solid;}'
]
})
export class DropListComponent extends FormElementComponent {
elementModel!: DropListElement;
drop(event: CdkDragDrop<DropListComponent>): void {
if (event.previousContainer === event.container) {
moveItemInArray(event.container.data.elementModel.options, event.previousIndex, event.currentIndex);
} else {
transferArrayItem(
event.previousContainer.data.elementModel.options,
event.container.data.elementModel.options,
event.previousIndex,
event.currentIndex
);
event.previousContainer.data.elementFormControl.setValue(event.previousContainer.data.elementModel.options);
}
this.elementFormControl.setValue(event.container.data.elementModel.options);
}
}
......@@ -16,7 +16,8 @@ export class IdService {
video: 0,
likert: 0,
likert_row: 0,
'radio-group-images': 0
'radio-group-images': 0,
'drop-list': 0
};
static getInstance(): IdService {
......
import { InputElement, UIElement } from '../uI-element';
import { FontElement, SurfaceUIElement } from '../../interfaces/UIElementInterfaces';
import { initFontElement, initSurfaceElement } from '../../util/unit-interface-initializer';
export class DropListElement extends InputElement implements FontElement, SurfaceUIElement {
options: string[] = [];
connectedTo: string[] = [];
fontColor: string = 'black';
font: string = 'Roboto';
fontSize: number = 18;
lineHeight: number = 120;
bold: boolean = false;
italic: boolean = false;
underline: boolean = false;
backgroundColor: string = 'transparent';
constructor(serializedElement: UIElement) {
super(serializedElement);
Object.assign(this, serializedElement);
Object.assign(this, initFontElement(serializedElement));
Object.assign(this, initSurfaceElement(serializedElement));
this.height = serializedElement.height || 100;
this.backgroundColor = serializedElement.backgroundColor as string || 'transparent';
}
}
......@@ -3,7 +3,7 @@ import { IdService } from '../id.service';
import { LikertColumn, LikertRow } from '../interfaces/UIElementInterfaces';
export type UIElementType = 'text' | 'button' | 'text-field' | 'text-area' | 'checkbox'
| 'dropdown' | 'radio' | 'image' | 'audio' | 'video' | 'likert' | 'likert_row' | 'radio-group-images';
| 'dropdown' | 'radio' | 'image' | 'audio' | 'video' | 'likert' | 'likert_row' | 'radio-group-images' | 'drop-list';
export type InputElementValue = string | number | boolean | null;
export interface ValueChangeElement {
......
......@@ -42,6 +42,7 @@ import { LikertComponent } from './element-components/compound-elements/likert.c
import { LikertRadioButtonGroupComponent } from './element-components/compound-elements/likert-radio-button-group.component';
import { Magnifier } from './element-components/magnifier.component';
import { RadioGroupImagesComponent } from './element-components/compound-elements/radio-group-images.component';
import { DropListComponent } from './element-components/compound-elements/drop-list.component';
@NgModule({
imports: [
......@@ -81,7 +82,8 @@ import { RadioGroupImagesComponent } from './element-components/compound-element
LikertComponent,
LikertRadioButtonGroupComponent,
Magnifier,
RadioGroupImagesComponent
RadioGroupImagesComponent,
DropListComponent
],
exports: [
CommonModule,
......
......@@ -25,6 +25,8 @@ import { LikertElement } from '../models/compound-elements/likert-element';
import { LikertComponent } from '../element-components/compound-elements/likert.component';
import { RadioGroupImagesComponent } from '../element-components/compound-elements/radio-group-images.component';
import { RadioGroupImagesElement } from '../models/compound-elements/radio-group-images';
import { DropListComponent } from '../element-components/compound-elements/drop-list.component';
import { DropListElement } from '../models/compound-elements/drop-list';
export function createElement(elementModel: UIElement): UIElement {
let newElement: UIElement;
......@@ -65,6 +67,9 @@ export function createElement(elementModel: UIElement): UIElement {
case 'radio-group-images':
newElement = new RadioGroupImagesElement(elementModel);
break;
case 'drop-list':
newElement = new DropListElement(elementModel);
break;
default:
throw new Error(`ElementType ${elementModel.type} not found!`);
}
......@@ -101,6 +106,8 @@ export function getComponentFactory(
return componentFactoryResolver.resolveComponentFactory(LikertComponent);
case 'radio-group-images':
return componentFactoryResolver.resolveComponentFactory(RadioGroupImagesComponent);
case 'drop-list':
return componentFactoryResolver.resolveComponentFactory(DropListComponent);
default:
throw new Error('unknown element');
}
......
......@@ -44,6 +44,11 @@
<mat-icon>radio_button_checked</mat-icon>
Optionsfelder (Bild)
</button>
<button mat-raised-button (click)="addUIElement('drop-list')"
draggable="true" (dragstart)="$event.dataTransfer?.setData('elementType','drop-list')">
<mat-icon>drag_indicator</mat-icon>
Ablegeliste
</button>
<button mat-raised-button (click)="addUIElement('image')"
draggable="true" (dragstart)="$event.dataTransfer?.setData('elementType','image')">
<mat-icon>image</mat-icon>
......
......@@ -84,7 +84,7 @@
{{option}}
</div>
<button mat-icon-button color="primary"
(click)="editTextOption(i)">
(click)="editTextOption('options', i)">
<mat-icon>build</mat-icon>
</button>
<button mat-icon-button color="primary"
......@@ -148,7 +148,7 @@
[width]="200">
</ng-container>
<mat-form-field *ngIf="combinedProperties.options !== undefined"
<mat-form-field *ngIf="combinedProperties.options !== undefined && !combinedProperties.connectedTo"
appearance="fill">
<mat-label>{{'propertiesPanel.preset' | translate }}</mat-label>
<mat-select [value]="combinedProperties.value"
......@@ -374,6 +374,37 @@
{{combinedProperties.magnifierZoom}}
</div>
<mat-form-field disabled="true" *ngIf="combinedProperties.connectedTo !== undefined">
<ng-container>
<mat-label>{{'propertiesPanel.connectedDropList' | translate }}</mat-label>
<div class="drop-list" cdkDropList [cdkDropListData]="combinedProperties.connectedTo"
(cdkDropListDropped)="reorderOptions('connectedTo', $any($event))">
<div *ngFor="let connectedTo of $any(combinedProperties.connectedTo); let i = index" cdkDrag
class="list-items" fxLayout="row" fxLayoutAlign="end center">
<div fxFlex="70">
{{connectedTo}}
</div>
<button mat-icon-button color="primary"
(click)="editTextOption('connectedTo', i)">
<mat-icon>build</mat-icon>
</button>
<button mat-icon-button color="primary"
(click)="removeOption('connectedTo', connectedTo)">
<mat-icon>clear</mat-icon>
</button>
</div>
</div>
</ng-container>
<div fxLayout="row" fxLayoutAlign="center center">
<button mat-icon-button matPrefix
(click)="addOption('connectedTo', newconnectedTo.value); newconnectedTo.select()">
<mat-icon>add</mat-icon>
</button>
<input #newconnectedTo matInput type="text"
(keyup.enter)="addOption('connectedTo', newconnectedTo.value); newconnectedTo.select()">
</div>
</mat-form-field>
<mat-divider></mat-divider>
<button mat-raised-button class="element-button"
......
......@@ -145,8 +145,8 @@ export class ElementPropertiesComponent implements OnInit, OnDestroy {
this.updateModel('rows', this.combinedProperties.rows as LikertElementRow[]);
}
async editTextOption(optionIndex: number): Promise<void> {
await this.unitService.editTextOption(optionIndex);
async editTextOption(property: string, optionIndex: number): Promise<void> {
await this.unitService.editTextOption(property, optionIndex);
}
async editColumnOption(optionIndex: number): Promise<void> {
......
......@@ -220,8 +220,8 @@ export class UnitService {
return true;
}
async editTextOption(optionIndex: number): Promise<void> {
const oldOptions = this.selectionService.getSelectedElements()[0].options as string[];
async editTextOption(property: string, optionIndex: number): Promise<void> {
const oldOptions = this.selectionService.getSelectedElements()[0][property] as string[];
await this.dialogService.showTextEditDialog(oldOptions[optionIndex])
.subscribe((result: string) => {
if (result) {
......
......@@ -103,7 +103,8 @@
"lineColoringColor": "Zeilenfarbe",
"magnifier": "Lupe",
"magnifierSize": "Größe der Lupe",
"magnifierZoom": "Vergrößerung der Lupe",
"magnifierZoom": "Vergrößerungsfaktor",
"connectedDropList": "Verbundene Ablegelisten",
"duplicateElement": "Element duplizieren",
"deleteElement": "Element löschen",
"noElementSelected": "Kein Element ausgewählt"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment