Newer
Older
Component, OnDestroy, Input, Output, EventEmitter, ViewChild, ElementRef
} from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Clipboard } from '@angular/cdk/clipboard';
import { MessageService } from 'common/services/message.service';
import { UIElement } from 'common/models/elements/element';
import { Section } from 'common/models/section';
import { DropListElement } from 'common/models/elements/input-elements/drop-list';
import { IDService } from 'editor/src/app/services/id.service';
import { VisibilityRule } from 'common/models/visibility-rule';
import { UnitService } from '../../services/unit.service';
import { DialogService } from '../../services/dialog.service';
import { SelectionService } from '../../services/selection.service';
selector: 'aspect-section-menu',
<button mat-mini-fab [matMenuTriggerFor]="elementListMenu"
[matTooltip]="'Elementliste'"
[matTooltipPosition]="'left'">
<mat-icon>list</mat-icon>
</button>
<mat-menu #elementListMenu="matMenu" class="layoutMenu" xPosition="before">
<mat-action-list>
<ng-container *ngIf="section.elements.length === 0">
<mat-list-item *ngFor="let element of section.elements"
{{element.id}}
</mat-list-item>
</mat-action-list>
</mat-menu>
<button mat-mini-fab [matTooltip]="'Hintergrundfarbe'" [matTooltipPosition]="'left'"
(click)="openColorPicker()">
<mat-icon>palette</mat-icon>
</button>
<input #colorPicker type="color" [style.display]="'none'"
[value]="$any(section.backgroundColor)"
(change)="updateModel('backgroundColor', $any($event.target).value)">
<button mat-mini-fab
(click)="showVisibilityRulesDialog()"
[matTooltip]="'Sichtbarkeit'" [matTooltipPosition]="'left'">
<mat-icon>disabled_visible</mat-icon>
</button>
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<!-- <mat-menu #activeAfterIDMenu="matMenu"-->
<!-- class="activeAfterID-menu" xPosition="before">-->
<!-- <aspect-rules [elementIds]="elementIds"-->
<!-- [rules]="section.rules"-->
<!-- (click)="$event.stopPropagation()">-->
<!-- </aspect-rules>-->
<!-- <mat-form-field appearance="outline">-->
<!-- <mat-label>{{'section-menu.activeAfterID' | translate }}</mat-label>-->
<!-- <input matInput-->
<!-- [value]="$any(section.activeAfterID)"-->
<!-- (click)="$any($event).stopPropagation()"-->
<!-- (change)="updateModel('activeAfterID', $any($event.target).value)">-->
<!-- </mat-form-field>-->
<!-- <mat-form-field appearance="outline">-->
<!-- <mat-label>{{'section-menu.activeAfterIdDelay' | translate }}</mat-label>-->
<!-- <input matInput type="number" step="1000" min="0"-->
<!-- [disabled]="!section.activeAfterID"-->
<!-- [value]="$any(section.activeAfterIdDelay)"-->
<!-- (click)="$any($event).stopPropagation()"-->
<!-- (change)="updateModel('activeAfterIdDelay', $any($event.target).value)">-->
<!-- </mat-form-field>-->
<!-- <button mat-icon-button-->
<!-- matSuffix-->
<!-- color="primary"-->
<!-- (click)="addRule($event)">-->
<!-- <mat-icon>add</mat-icon>-->
<!-- </button>-->
<!-- <ng-container *ngFor="let rule of section.rules; let i = index">-->
<!-- <aspect-rule [elementIds]="elementIds"-->
<!-- [rule]="rule"-->
<!-- (ruleChange)="updateRule(i, $event)"-->
<!-- (click)="$event.stopPropagation()">-->
<!-- </aspect-rule>-->
<!-- <button mat-icon-button-->
<!-- matSuffix-->
<!-- color="primary"-->
<!-- (click)="deleteRule(i)">-->
<!-- <mat-icon>delete</mat-icon>-->
<!-- </button>-->
<!-- </ng-container>-->
<!-- </mat-menu>-->
<button mat-mini-fab [matMenuTriggerFor]="layoutMenu"
[matTooltip]="'Layout'" [matTooltipPosition]="'left'">
<mat-icon>space_dashboard</mat-icon>
</button>
<mat-menu #layoutMenu="matMenu" class="layoutMenu" xPosition="before">
<div (click)="$event.stopPropagation()">
<mat-checkbox class="menuItem" [checked]="section.dynamicPositioning"
(click)="$any($event).stopPropagation()"
(change)="updateModel('dynamicPositioning', $event.checked)">
{{'section-menu.dynamic-positioning' | translate }}
</mat-checkbox>
<ng-container *ngIf="!section.dynamicPositioning">
<mat-form-field class="section-height-input" appearance="outline">
<mat-label>{{'section-menu.height' | translate }}</mat-label>
(change)="updateModel('height', $any($event.target).value)">
</mat-form-field>
</ng-container>
<div *ngIf="section.dynamicPositioning">
<fieldset>
<legend>{{'section-menu.columns' | translate }}</legend>
<mat-checkbox class="menuItem" [checked]="section.autoColumnSize"
(click)="$any($event).stopPropagation()"
(change)="updateModel('autoColumnSize', $event.checked)">
{{'section-menu.autoColumnSize' | translate }}
</mat-checkbox>
<ng-container *ngIf="!section.autoColumnSize">
<mat-form-field appearance="outline">
<mat-label>{{'section-menu.columnCount' | translate }}</mat-label>
<input matInput type="number"
[value]="$any(section.gridColumnSizes.length)"
(click)="$any($event).stopPropagation()"
(change)="modifySizeArray('gridColumnSizes', $any($event).target.value)">
</mat-form-field>
<ng-container *ngFor="let size of section.gridColumnSizes; let i = index">
<aspect-size-input-panel [label]="('section-menu.width' | translate) + ' ' + (i + 1)"
[value]="size.value"
[unit]="size.unit"
[allowedUnits]="['px', 'fr']"
(valueUpdated)="changeGridSize('gridColumnSizes', i, $event)">
</aspect-size-input-panel>
</ng-container>
</fieldset>
<fieldset>
<legend>{{'section-menu.rows' | translate }}</legend>
<mat-checkbox class="menuItem" [checked]="section.autoRowSize"
(click)="$any($event).stopPropagation()"
(change)="updateModel('autoRowSize', $event.checked)">
{{'section-menu.autoRowSize' | translate }}
</mat-checkbox>
<ng-container *ngIf="!section.autoRowSize">
<mat-form-field appearance="outline">
<mat-label>{{'section-menu.height' | translate }}</mat-label>
<input matInput type="number"
[value]="$any(section.height)"
(click)="$any($event).stopPropagation()"
(change)="updateModel('height', $any($event.target).value)">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>{{'section-menu.rowCount' | translate }}</mat-label>
<input matInput type="number"
[value]="$any(section.gridRowSizes.length)"
(click)="$any($event).stopPropagation()"
(change)="modifySizeArray('gridRowSizes', $any($event).target.value)">
</mat-form-field>
<ng-container *ngFor="let size of section.gridRowSizes ; let i = index">
<aspect-size-input-panel [label]="('section-menu.height' | translate) + ' ' + (i + 1)"
[value]="size.value"
[unit]="size.unit"
[allowedUnits]="['px', 'fr']"
(valueUpdated)="changeGridSize('gridRowSizes', i, $event)">
</aspect-size-input-panel>
</ng-container>
<button mat-mini-fab [matTooltip]="'Abschnitt kopieren'" [matTooltipPosition]="'left'"
(click)="copySectionToClipboard()">
<mat-icon>content_copy</mat-icon>
</button>
<button mat-mini-fab
[matTooltip]="'Abschnitt einfügen'" [matTooltipPosition]="'left'"
(click)="showSectionInsertDialog()">
<mat-icon>content_paste</mat-icon>
</button>
<button *ngIf="allowMoveUp" mat-mini-fab
[matTooltip]="'Nach oben verschieben'" [matTooltipPosition]="'left'"
(click)="this.moveSection.emit('up')">
<mat-icon>north</mat-icon>
</button>
<button *ngIf="allowMoveDown" mat-mini-fab
[matTooltip]="'Nach unten verschieben'" [matTooltipPosition]="'left'"
(click)="this.moveSection.emit('down')">
<mat-icon>south</mat-icon>
</button>
<button mat-mini-fab [matTooltip]="'Duplizieren'" [matTooltipPosition]="'left'"
<mat-icon>control_point_duplicate</mat-icon>
<button *ngIf="allowDelete" mat-mini-fab
[matTooltip]="'Löschen'" [matTooltipPosition]="'left'"
(click)="deleteSection()">
<mat-icon>clear</mat-icon>
styles: [
'::ng-deep .layoutMenu {padding: 0 15px; width: 250px;}',
'::ng-deep .layoutMenu fieldset {margin: 10px 0; display: flex; flex-direction: column; align-items: flex-start;}',
'::ng-deep .layoutMenu .section-height-input {margin-top: 10px;}',
'.menuItem {margin-bottom: 5px;}',
'::ng-deep .activeAfterID-menu .mat-mdc-form-field {width:90%; margin-left: 10px;}'
export class SectionMenuComponent implements OnDestroy {
@Input() section!: Section;
@Input() allowMoveUp!: boolean;
@Input() allowMoveDown!: boolean;
@Output() moveSection = new EventEmitter<'up' | 'down'>();
@Output() duplicateSection = new EventEmitter();
@Output() selectElementComponent = new EventEmitter<UIElement>();
@ViewChild('colorPicker') colorPicker!: ElementRef;
private ngUnsubscribe = new Subject<void>();
constructor(public unitService: UnitService,
private dialogService: DialogService,
private messageService: MessageService,
updateModel(
property: string, value: string | number | boolean | VisibilityRule[] | { value: number; unit: string }[]
): void {
this.unitService.updateSectionProperty(this.section, property, value);
}
selectElement(element: UIElement): void {
this.selectElementComponent.emit(element);
}
this.dialogService.showConfirmDialog('Abschnitt löschen?')
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe((result: boolean) => {
if (result) {
this.unitService.deleteSection(this.section);
if (this.sectionIndex === this.selectionService.selectedPageSectionIndex &&
this.selectionService.selectedPageSectionIndex > 0) {
this.selectionService.selectedPageSectionIndex -= 1;
}
/* Add or remove elements to size array. Default value 1fr. */
modifySizeArray(property: 'gridColumnSizes' | 'gridRowSizes', newLength: number): void {
const sizeArray: { value: number; unit: string }[] = property === 'gridColumnSizes' ?
this.section.gridColumnSizes : this.section.gridRowSizes;
if (newLength < sizeArray.length) {
newArray = sizeArray.slice(0, newLength);
...sizeArray,
...Array(newLength - sizeArray.length).fill({ value: 1, unit: 'fr' })
this.updateModel(property, newArray);
changeGridSize(property: string, index: number, newValue: { value: number; unit: string }): void {
const sizeArray: { value: number; unit: string }[] = property === 'gridColumnSizes' ?
this.section.gridColumnSizes : this.section.gridRowSizes;
sizeArray[index] = newValue;
this.updateModel(property, [...sizeArray]);
this.colorPicker.nativeElement.click();
}
ngOnDestroy(): void {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
copySectionToClipboard() {
this.clipboard.copy(JSON.stringify(this.section));
this.messageService.showSuccess('Abschnitt in Zwischenablage kopiert');
showSectionInsertDialog(): void {
this.dialogService.showSectionInsertDialog(this.section)
.pipe(takeUntil(this.ngUnsubscribe))
.subscribe((newSection: Section) => {
if (newSection) {
newSection.getAllElements().filter(element => !this.idService.isIdAvailable(element.id)).forEach(element => {
element.id = this.idService.getAndRegisterNewID(element.type);
if (['drop-list', 'drop-list-simple'].includes((element as UIElement).type as string)) {
(element as DropListElement).value
.filter(valueElement => !this.idService.isIdAvailable(valueElement.id))
.forEach(valueElement => {
valueElement.id = this.idService.getAndRegisterNewID('value');
});
}
});
this.unitService.replaceSection(this.selectionService.selectedPageIndex, this.sectionIndex, newSection);
}
});
showVisibilityRulesDialog(): void {
this.dialogService
.showVisibilityRulesDialog(this.section.visibilityRules, this.getControlIds(), this.section.visibilityDelay)
.subscribe(rulesWithDelay => {
if (rulesWithDelay) {
this.updateModel('visibilityRules', rulesWithDelay.visibilityRules);
this.updateModel('visibilityDelay', rulesWithDelay.visibilityDelay);
}
});
}
private getControlIds(): string[] {
return this.unitService.unit.getAllElements()
.map(element => element.id)
.concat(this.unitService.unit.stateVariables
.map(element => element.id));
}