Skip to content
Snippets Groups Projects
dynamic-section-helper-grid.component.ts 4.88 KiB
Newer Older
import { CdkDragDrop } from '@angular/cdk/drag-drop';
import {
  Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges
} from '@angular/core';
import { UIElement, UIElementType } from 'common/models/elements/element';
import { Section } from 'common/models/section';
rhenck's avatar
rhenck committed
import { UnitService } from '../../services/unit.service';

@Component({
  selector: '[app-dynamic-section-helper-grid]',
  template: `
    <ng-container *ngFor="let column of columnCountArray; let x = index">
      <ng-container *ngFor="let row of rowCountArray; let y = index">
        <div class="grid-placeholder"
             [style.grid-column-start]="x + 1"
             [style.grid-column-end]="x + 1"
             [style.grid-row-start]="y + 1"
             [style.grid-row-end]="y + 1"
             cdkDropList [cdkDropListData]="{ sectionIndex: sectionIndex, gridCoordinates: [x + 1, y + 1] }"
             (cdkDropListDropped)="drop($event)"
             id="list-{{sectionIndex}}-{{x+1}}-{{y+1}}"
             (dragover)="$event.preventDefault()"
             (drop)="newElementDropped( $event, x + 1, y + 1)">
          {{x + 1}} / {{y + 1}}
        </div>
      </ng-container>
    </ng-container>

    <ng-content></ng-content>
  `,
  styles: [
  '.grid-placeholder {border: 5px solid aliceblue; color: lightblue; text-align: center;}'
export class DynamicSectionHelperGridComponent implements OnInit, OnChanges {
  @Input() autoColumnSize!: boolean;
  @Input() autoRowSize!: boolean;
  @Input() gridColumnSizes!: { value: number; unit: string }[];
  @Input() gridRowSizes!: { value: number; unit: string }[];
  @Input() section!: Section;
  @Input() sectionIndex!: number;
  @Output() transferElement = new EventEmitter<{ previousSectionIndex: number, newSectionIndex: number }>();

  columnCountArray: unknown[] = [];
  rowCountArray: unknown[] = [];

rhenck's avatar
rhenck committed
  constructor(public unitService: UnitService) {}

  ngOnInit(): void {
    this.calculateColumnCount();
    this.calculateRowCount();
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.autoColumnSize || changes.gridColumnSizes || changes.gridRowSizes) {
      this.calculateColumnCount();
      this.calculateRowCount();
    }
  }

  refresh(): void {
    this.calculateColumnCount();
    this.calculateRowCount();
  }

  private calculateColumnCount(): void {
    let numberOfColumns;
    if (this.autoColumnSize) {
      numberOfColumns = this.section.elements
        .reduce((accumulator, currentValue) => (
          currentValue.position.gridColumn ?
            Math.max(accumulator, currentValue.position.gridColumn + currentValue.position.gridColumnRange) :
            accumulator
        ),
        0) - 1;
    } else {
      numberOfColumns = this.gridColumnSizes.length;
    }
    this.columnCountArray = Array(Math.max(numberOfColumns, 1));
  }

  private calculateRowCount(): void {
    let numberOfRows;
    if (this.autoRowSize) {
      numberOfRows = this.section.elements
        .reduce((accumulator, currentValue) => (
          currentValue.position.gridRow ?
            Math.max(accumulator, currentValue.position.gridRow + currentValue.position.gridRowRange) :
            accumulator
        ),
        0) - 1;
    } else {
      numberOfRows = this.gridRowSizes.length;
    }
    this.rowCountArray = Array(Math.max(numberOfRows, 1));
  }

  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).
    if (event.previousContainer.data.sectionIndex !== event.container.data.sectionIndex) {
      this.transferElement.emit({
        previousSectionIndex: event.previousContainer.data.sectionIndex,
        newSectionIndex: event.container.data.sectionIndex
      });
    }
    if (dragItemData.dragType === 'move') {
      this.unitService.updateElementsPositionProperty(
        [event.item.data.element],
        event.container.data.gridCoordinates[0]
      this.unitService.updateElementsPositionProperty(
        [dragItemData.element],
        event.container.data.gridCoordinates[1]
      );
    } else if (event.item.data.dragType === 'resize') {
      this.unitService.updateElementsPositionProperty(
        [dragItemData.element],
        'gridColumnEnd',
        event.container.data.gridCoordinates[0] + 1
      this.unitService.updateElementsPositionProperty(
        [dragItemData.element],
        'gridRowEnd',
        event.container.data.gridCoordinates[1] + 1
      );
    } else {
      throw new Error('Unknown drop event');
    }
  }

  newElementDropped(event: DragEvent, gridX: number, gridY: number): void {
    event.preventDefault();
    this.unitService.addElementToSection(
      event.dataTransfer?.getData('elementType') as UIElementType,
      this.section,
      { x: gridX, y: gridY }
    );
  }
}