use placeholder area for d&d

pull/6834/head
Jens Ulferts 6 years ago
parent c95dc496c6
commit a8a91eda05
No known key found for this signature in database
GPG Key ID: 3CAA4B1182CF5308
  1. 33
      frontend/src/app/modules/grids/grid.component.html
  2. 179
      frontend/src/app/modules/grids/grid.component.ts

@ -25,12 +25,13 @@
cdkDropList
[id]="gridAreaId(area) + '-widgeted-' + area.guid"
[cdkDropListData]="area"
[cdkDropListConnectedTo]="gridAreaDropIdsWithoutSelf(area)">
[cdkDropListConnectedTo]="gridAreaDropIds">
<div class="widget-box"
cdkDrag
(cdkDragStarted)="dragStart(area)"
(cdkDragEnded)="dragStop()"
(cdkDragEnded)="dragStop(area, $event)"
style="height: 100%">
<div *cdkDragPlaceholder></div>
<div class="grid--widget-remove"
(click)="removeWidget(area)">
</div>
@ -48,7 +49,7 @@
<!-- One grid area per cell (row x columns) -->
<div *ngFor="let area of gridAreas; trackBy: identifyGridArea;"
class="grid--area"
[ngClass] = "{'-drop-target': currentlyDragging && gridAreaDropIds.indexOf(gridAreaId(area)) >= 0,
[ngClass] = "{'-drop-target': currentlyDragging,
'-resize-target': isResizeTarget(area),
'-addable': isAddable(area) }"
[style.grid-row-start]="area.startRow"
@ -61,6 +62,7 @@
[cdkDropListData]="area"
(cdkDropListDropped)="drop($event)"
(cdkDropListEntered)="dragEntered($event)"
(cdkDropListExited)="dragExited($event)"
[cdkDropListConnectedTo]="gridAreaDropIds">
<div class="grid--widget-add"
*ngIf="isAddable(area)"
@ -70,10 +72,25 @@
<!-- Grid area to visualize resizing -->
<div class="grid--area -resizing"
*ngIf="resizeArea"
[style.grid-row-start]="resizeArea.startRow"
[style.grid-row-end]="resizeArea.endRow"
[style.grid-column-start]="resizeArea.startColumn"
[style.grid-column-end]="resizeArea.endColumn">
*ngIf="resizePlaceholderArea"
[style.grid-row-start]="resizePlaceholderArea.startRow"
[style.grid-row-end]="resizePlaceholderArea.endRow"
[style.grid-column-start]="resizePlaceholderArea.startColumn"
[style.grid-column-end]="resizePlaceholderArea.endColumn">
</div>
<!-- Grid area used as a placeholder while dragging -->
<div *ngIf="dragPlaceholderArea"
class="grid--area -widgeted"
[style.grid-row-start]="dragPlaceholderArea.startRow"
[style.grid-row-end]="dragPlaceholderArea.endRow"
[style.grid-column-start]="dragPlaceholderArea.startColumn"
[style.grid-column-end]="dragPlaceholderArea.endColumn">
<div class="widget-box"
style="height: 100%">
<ndc-dynamic [ndcDynamicComponent]="widgetComponent(dragPlaceholderArea.widget)"
[ndcDynamicOutputs]="{}">
</ndc-dynamic>
</div>
</div>
</div>

@ -9,7 +9,7 @@ import {GridWidgetResource} from "app/modules/hal/resources/grid-widget-resource
import {HookService} from "app/modules/plugins/hook-service";
import {debugLog} from "app/helpers/debug_output";
import {DomSanitizer} from "@angular/platform-browser";
import {CdkDragDrop, CdkDragEnter} from "@angular/cdk/drag-drop";
import {CdkDragDrop, CdkDragEnter, CdkDragExit, CdkDragEnd} from "@angular/cdk/drag-drop";
import {ResizeDelta} from "../common/resizer/resizer.component";
import {GridWidgetsService} from "core-app/modules/grids/widgets/widgets.service";
import {AddGridWidgetService} from "core-app/modules/grids/widgets/add/add.service";
@ -37,11 +37,13 @@ export class GridComponent implements OnDestroy, OnInit {
public gridWidgetAreas:GridWidgetArea[];
public gridAreaDropIds:string[];
public draggedArea:GridWidgetArea|null;
public dragPlaceholderArea:GridWidgetArea|null;
public GRID_AREA_HEIGHT = 100;
private schema:SchemaResource;
public resizeArea:GridArea|null;
public resizePlaceholderArea:GridWidgetArea|null;
private resizedArea:GridWidgetArea|null;
public resizeAreaTargetIds:string[];
private mousedOverArea:GridArea|null;
@ -104,74 +106,110 @@ export class GridComponent implements OnDestroy, OnInit {
public dragStart(area:GridWidgetArea) {
this.draggedArea = area;
this.dragPlaceholderArea = new GridWidgetArea(area.widget);
}
public dragStop() {
public dragStop(area:GridWidgetArea, event:CdkDragEnd) {
if (!this.draggedArea) {
return;
}
let dropArea = event.source.dropContainer.data;
// Handle special case of user starting to move the widget but then deciding to
// move it back to the original area.
if (this.draggedArea.startColumn === dropArea.startColumn &&
this.draggedArea.startRow === dropArea.startRow) {
this.resetAreasOnDragging();
}
this.draggedArea = null;
this.dragPlaceholderArea = null;
}
public drop(event:CdkDragDrop<GridArea>) {
// this.draggedArea is already reset to null at this point
if (event.previousContainer !== event.container) {
let dropArea = event.container.data;
let draggedArea = event.previousContainer.data as GridWidgetArea;
// Set the draggedArea's startRow/startColumn properties
// to the drop zone ones.
// The dragged Area should keep it's height and width normally but will
// shrink if the area would otherwise end outside the grid.
draggedArea.startRow = dropArea.startRow;
if (dropArea.startRow + draggedArea.widget.height > this.numRows + 1) {
draggedArea.endRow = this.numRows + 1;
} else {
draggedArea.endRow = dropArea.startRow + draggedArea.widget.height;
}
let dropArea = event.container.data;
let draggedArea = event.previousContainer.data as GridWidgetArea;
// Set the draggedArea's startRow/startColumn properties
// to the drop zone ones.
// The dragged Area should keep it's height and width normally but will
// shrink if the area would otherwise end outside the grid.
draggedArea.startRow = dropArea.startRow;
if (dropArea.startRow + draggedArea.widget.height > this.numRows + 1) {
draggedArea.endRow = this.numRows + 1;
} else {
draggedArea.endRow = dropArea.startRow + draggedArea.widget.height;
}
draggedArea.startColumn = dropArea.startColumn;
if (dropArea.startColumn + draggedArea.widget.width > this.numColumns + 1) {
draggedArea.endColumn = this.numColumns + 1;
} else {
draggedArea.endColumn = dropArea.startColumn + draggedArea.widget.width;
}
draggedArea.startColumn = dropArea.startColumn;
if (dropArea.startColumn + draggedArea.widget.width > this.numColumns + 1) {
draggedArea.endColumn = this.numColumns + 1;
} else {
draggedArea.endColumn = dropArea.startColumn + draggedArea.widget.width;
}
// persist all changes to the areas caused by dragging
// to the widget
this.gridWidgetAreas.forEach((area) => {
area.widget.startRow = area.startRow;
area.widget.endRow = area.endRow;
area.widget.startColumn = area.startColumn;
area.widget.endColumn = area.endColumn;
});
this.writeAreaChangesToWidgets();
this.buildAreas();
}
this.buildAreas();
}
// persist all changes to the areas caused by dragging/resizing
// to the widget
private writeAreaChangesToWidgets() {
this.gridWidgetAreas.forEach((area) => {
area.widget.startRow = area.startRow;
area.widget.endRow = area.endRow;
area.widget.startColumn = area.startColumn;
area.widget.endColumn = area.endColumn;
});
}
public dragEntered(event:CdkDragEnter<GridArea>) {
if (this.draggedArea) {
let dropArea = event.container.data;
this.resetAreasOnDragging();
this.resetAreasOnDragging(this.draggedArea);
this.moveAreasOnDragging(dropArea);
}
}
public dragExited(event:CdkDragExit<GridArea>) {
// prevent flickering when dragging within the area spanned
// by the dragged element. Otherwise, cdk drag fire an entered event on every
// move.
if (this.draggedArea) {
this.draggedArea.endRow = this.draggedArea.startRow + 1;
this.draggedArea.endColumn = this.draggedArea.startColumn + 1;
}
}
private moveAreasOnDragging(dropArea:GridArea) {
if (!this.dragPlaceholderArea) {
return;
}
let widgetArea = this.draggedArea!;
// we cannot use the widget's original area as moving it while dragging confuses cdkDrag
let widget = widgetArea.widget;
let placeholderArea = new GridWidgetArea(widget);
this.dragPlaceholderArea.startRow = dropArea.startRow;
if (this.dragPlaceholderArea.startRow + this.dragPlaceholderArea.widget.height > this.numRows + 1) {
this.dragPlaceholderArea.endRow = this.numRows + 1;
} else {
this.dragPlaceholderArea.endRow = dropArea.startRow + this.dragPlaceholderArea.widget.height;
}
placeholderArea.startRow = dropArea.startRow;
placeholderArea.endRow = placeholderArea.startRow + widget.height;
placeholderArea.startColumn = dropArea.startColumn;
placeholderArea.endColumn = placeholderArea.startColumn + widget.width;
this.dragPlaceholderArea.startColumn = dropArea.startColumn;
if (this.dragPlaceholderArea.startColumn + this.dragPlaceholderArea.widget.height > this.numColumns + 1) {
this.dragPlaceholderArea.endColumn = this.numColumns + 1;
} else {
this.dragPlaceholderArea.endColumn = dropArea.startColumn + this.dragPlaceholderArea.widget.height;
}
this.moveAreasDown(placeholderArea, widgetArea);
this.moveAreasDown(this.dragPlaceholderArea, widgetArea);
}
private resetAreasOnDragging() {
this.gridWidgetAreas.forEach((area) => {
private resetAreasOnDragging(ignoredArea:GridWidgetArea|null = null) {
this.gridWidgetAreas.filter((area) => {
return !ignoredArea || area.guid !== ignoredArea.guid;
}).forEach((area) => {
area.startRow = area.widget.startRow;
area.endRow = area.widget.endRow;
area.startColumn = area.widget.startColumn;
@ -183,39 +221,28 @@ export class GridComponent implements OnDestroy, OnInit {
}
public resize(area:GridWidgetArea, deltas:ResizeDelta) {
if (!this.resizeArea) {
if (!this.resizePlaceholderArea ||
!this.resizedArea) {
return;
}
let widget = area.widget;
widget.endRow = this.resizeArea.endRow;
widget.endColumn = this.resizeArea.endColumn;
this.resizedArea.endRow = this.resizePlaceholderArea.endRow;
this.resizedArea.endColumn = this.resizePlaceholderArea.endColumn;
this.writeAreaChangesToWidgets();
this.buildAreas();
return this.resizeArea = null;
this.resizedArea = null;
this.resizePlaceholderArea = null;
}
public resizeStart(resizedArea:GridWidgetArea) {
this.resizeArea = new GridArea(resizedArea.startRow,
resizedArea.endRow,
resizedArea.startColumn,
resizedArea.endColumn);
let blockableWidgetAreas = this.gridWidgetAreas.filter((widgetArea) => {
return resizedArea.guid !== widgetArea.guid &&
widgetArea.startRow >= resizedArea.startRow &&
widgetArea.startColumn >= resizedArea.startColumn;
}) as GridWidgetArea[];
this.resizePlaceholderArea = new GridWidgetArea(resizedArea.widget);
this.resizedArea = resizedArea;
let resizeTargets = this.gridAreas.filter((area) => {
return area.startRow >= this.resizeArea!.startRow &&
area.startColumn >= this.resizeArea!.startColumn &&
!blockableWidgetAreas.some((widgetArea) => {
return area.startRow >= widgetArea.startRow &&
area.startColumn >= widgetArea.startColumn;
});
return area.startRow >= this.resizePlaceholderArea!.startRow &&
area.startColumn >= this.resizePlaceholderArea!.startColumn; //&&
});
this.resizeAreaTargetIds = resizeTargets.map((area) => {
@ -224,20 +251,24 @@ export class GridComponent implements OnDestroy, OnInit {
}
public resizeMove(deltas:ResizeDelta) {
if (!this.resizeArea ||
if (!this.resizePlaceholderArea ||
!this.mousedOverArea ||
!this.resizeAreaTargetIds.includes(this.gridAreaId(this.mousedOverArea))) {
return;
}
this.resizeArea.endRow = this.mousedOverArea.endRow;
this.resizeArea.endColumn = this.mousedOverArea.endColumn;
this.resetAreasOnDragging();
this.resizePlaceholderArea.endRow = this.mousedOverArea.endRow;
this.resizePlaceholderArea.endColumn = this.mousedOverArea.endColumn;
this.moveAreasDown(this.resizePlaceholderArea, this.resizedArea);
}
public isResizeTarget(area:GridArea) {
let areaId = this.gridAreaId(area);
return this.resizeArea && this.resizeAreaTargetIds.includes(areaId);
return this.resizePlaceholderArea && this.resizeAreaTargetIds.includes(areaId);
}
public isAddable(area:GridArea) {
@ -248,7 +279,7 @@ export class GridComponent implements OnDestroy, OnInit {
}
public get currentlyResizing() {
return this.resizeArea;
return this.resizePlaceholderArea;
}
public setMousedOverArea(area:GridArea) {
@ -438,14 +469,6 @@ export class GridComponent implements OnDestroy, OnInit {
return `gridArea ${cell.guid}`;
}
private gridAreaDropIdsWithoutSelf(area:GridArea) {
let selfId = this.gridAreaId(area);
return this.gridAreaDropIds.filter((areaId) => {
return selfId !== areaId;
});
}
private buildGridAreaDropIds() {
let ids:string[] = [];

Loading…
Cancel
Save