Skip to content

Commit

Permalink
feat: support fs,ss,sf,ff dnd to create line (#195)
Browse files Browse the repository at this point in the history
  • Loading branch information
walkerkay authored Mar 10, 2022
1 parent 175508c commit e91ce5b
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 66 deletions.
2 changes: 2 additions & 0 deletions packages/gantt/src/class/event.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { QueryList } from '@angular/core';
import { NgxGanttTableColumnComponent } from '../table/gantt-column.component';
import { GanttItem } from './item';
import { GanttLinkType } from './link';

export class GanttDragEvent<T = unknown> {
item: GanttItem<T>;
Expand All @@ -13,6 +14,7 @@ export class GanttTableEvent {
export class GanttLinkDragEvent<T = unknown> {
source: GanttItem<T>;
target?: GanttItem<T>;
type?: GanttLinkType;
}

export class GanttLoadOnScrollEvent {
Expand Down
5 changes: 3 additions & 2 deletions packages/gantt/src/class/item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,9 @@ export class GanttItemInternal {
this.origin.expanded = expanded;
}

addLink(linkId: string) {
this.links = [...this.links, { type: GanttLinkType.fs, link: linkId }];
addLink(link: GanttLink) {
console.log(link);
this.links = [...this.links, link];
this.origin.links = this.links;
}
}
6 changes: 5 additions & 1 deletion packages/gantt/src/class/test/item.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { GanttLinkType } from 'ngx-gantt';
import { GanttDate } from '../../utils/date';
import { GanttItem, GanttItemInternal } from '../item';
import { GanttViewType } from '../view-type';
Expand Down Expand Up @@ -96,7 +97,10 @@ describe('GanttItemInternal', () => {
});

it(`should add link`, () => {
ganttItemInternal.addLink('0102');
ganttItemInternal.addLink({
link: '0102',
type: GanttLinkType.fs
});
// expect(ganttItemInternal.links).toContain('0102');
});
});
54 changes: 42 additions & 12 deletions packages/gantt/src/components/bar/bar-drag.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { Injectable, ElementRef, OnDestroy, NgZone } from '@angular/core';
import { Injectable, ElementRef, OnDestroy } from '@angular/core';
import { DragRef, DragDrop } from '@angular/cdk/drag-drop';
import { GanttDomService } from '../../gantt-dom.service';
import { GanttDragContainer } from '../../gantt-drag-container';
import { GanttDragContainer, InBarPosition } from '../../gantt-drag-container';
import { GanttItemInternal } from '../../class/item';
import { GanttDate, differenceInCalendarDays } from '../../utils/date';
import { fromEvent, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { GanttUpper } from '../../gantt-upper';
import { GanttLinkType } from '../../class/link';

const dragMinWidth = 10;
const activeClass = 'gantt-bar-active';
const linkDropClass = 'gantt-bar-link-drop';
const dropActiveClass = 'gantt-bar-drop-active';
const singleDropActiveClass = 'gantt-bar-single-drop-active';

function createSvgElement(qualifiedName: string, className: string) {
const element = document.createElementNS('http://www.w3.org/2000/svg', qualifiedName);
Expand Down Expand Up @@ -45,13 +47,22 @@ export class GanttBarDrag implements OnDestroy {
constructor(private dragDrop: DragDrop, private dom: GanttDomService, private dragContainer: GanttDragContainer) {}

private createMouseEvents() {
const dropClass =
this.ganttUpper.config.linkOptions?.dependencyTypes?.length === 0 &&
this.ganttUpper.config.linkOptions?.dependencyTypes[0] === GanttLinkType.fs
? singleDropActiveClass
: dropActiveClass;

fromEvent(this.barElement, 'mouseenter')
.pipe(takeUntil(this.destroy$))
.subscribe(() => {
.subscribe((event: MouseEvent) => {
if (this.dragContainer.linkDraggingId && this.dragContainer.linkDraggingId !== this.item.id) {
if (this.item.linkable) {
this.barElement.classList.add(linkDropClass);
this.dragContainer.emitLinkDragEntered(this.item);
this.barElement.classList.add(dropClass);
this.dragContainer.emitLinkDragEntered({
item: this.item,
element: this.barElement
});
}
} else {
this.barElement.classList.add(activeClass);
Expand All @@ -64,9 +75,11 @@ export class GanttBarDrag implements OnDestroy {
if (!this.dragContainer.linkDraggingId) {
this.barElement.classList.remove(activeClass);
} else {
if (this.dragContainer.linkDraggingId !== this.item.id) {
this.barElement.classList.remove(dropClass);
}
this.dragContainer.emitLinkDragLeaved();
}
this.barElement.classList.remove(linkDropClass);
});
}

Expand Down Expand Up @@ -179,7 +192,7 @@ export class GanttBarDrag implements OnDestroy {
const dragRefs = [];
const handles = this.barElement.querySelectorAll<HTMLElement>('.link-handles .handle');
handles.forEach((handle, index) => {
const isBefore = index === 0;
const isBegin = index === 0;
const dragRef = this.dragDrop.createDrag(handle);
dragRef.withBoundaryElement(this.dom.root as HTMLElement);
dragRef.beforeStarted.subscribe(() => {
Expand All @@ -188,26 +201,43 @@ export class GanttBarDrag implements OnDestroy {
this.barDragRef.disabled = true;
}
this.createLinkDraggingLine();
this.dragContainer.emitLinkDragStarted(isBefore ? 'target' : 'source', this.item);
this.dragContainer.emitLinkDragStarted({
element: this.barElement,
item: this.item,
pos: isBegin ? InBarPosition.start : InBarPosition.finish
});
});

dragRef.moved.subscribe(() => {
const positions = this.calcLinkLinePositions(handle, isBefore);
const positions = this.calcLinkLinePositions(handle, isBegin);
this.linkDraggingLine.setAttribute('x1', positions.x1.toString());
this.linkDraggingLine.setAttribute('y1', positions.y1.toString());
this.linkDraggingLine.setAttribute('x2', positions.x2.toString());
this.linkDraggingLine.setAttribute('y2', positions.y2.toString());
});

dragRef.ended.subscribe((event) => {
event.source.reset();
handle.style.pointerEvents = '';
if (this.barDragRef) {
this.barDragRef.disabled = false;
}
// 计算line拖动的落点位于目标Bar的值,如果值大于Bar宽度的一半,说明是拖动到Begin位置,否则则为拖动到End位置
if (this.dragContainer.linkDragPath.to) {
const placePointX =
event.source.getRootElement().getBoundingClientRect().x -
this.dragContainer.linkDragPath.to.element.getBoundingClientRect().x;

this.dragContainer.emitLinkDragEnded({
...this.dragContainer.linkDragPath.to,
pos:
placePointX < this.dragContainer.linkDragPath.to.item.refs.width / 2
? InBarPosition.start
: InBarPosition.finish
});
}
event.source.reset();
this.barElement.classList.remove(activeClass);
this.destroyLinkDraggingLine();
this.dragContainer.emitLinkDragEnded();
});

dragRefs.push(dragRef);
Expand Down
25 changes: 24 additions & 1 deletion packages/gantt/src/components/bar/bar.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ $gantt-bar-link-drop-border: 5px;
background: $gantt-bar-background-color;
overflow: hidden;
box-sizing: border-box;

.gantt-bar-content-progress {
position: absolute;
left: 0;
Expand All @@ -157,7 +158,7 @@ $gantt-bar-link-drop-border: 5px;
@include active-bar();
}

&-link-drop {
&-single-drop-active- {
.gantt-bar-border {
display: block;
}
Expand All @@ -166,4 +167,26 @@ $gantt-bar-link-drop-border: 5px;
box-shadow: none;
}
}

&-drop-active {
@include active-bar();

.gantt-bar-layer {
.link-handles {
.handle {
&:first-child {
left: -$gantt-bar-link-height;
top: 50%;
padding-bottom: $gantt-bar-link-height;
}

&:last-child {
right: -$gantt-bar-link-height;
top: 50%;
padding-bottom: $gantt-bar-link-height;
}
}
}
}
}
}
2 changes: 0 additions & 2 deletions packages/gantt/src/components/bar/bar.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {
Component,
OnInit,
Input,
TemplateRef,
HostBinding,
ElementRef,
OnChanges,
Expand Down
95 changes: 56 additions & 39 deletions packages/gantt/src/gantt-drag-container.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,37 @@
import { Injectable, EventEmitter } from '@angular/core';
import { Injectable, EventEmitter, Inject } from '@angular/core';
import { GanttLinkType } from './class';
import { GanttDragEvent, GanttLinkDragEvent } from './class/event';
import { GanttItemInternal } from './class/item';
import { GanttUpper, GANTT_UPPER_TOKEN } from './gantt-upper';

export type LinkDragFrom = 'source' | 'target';
function getDependencyType(path: LinkDragPath, dependencyTypes: GanttLinkType[]): GanttLinkType {
if (dependencyTypes.includes(GanttLinkType.ss) && path.from.pos === InBarPosition.start && path.to.pos === InBarPosition.start) {
return GanttLinkType.ss;
}
if (dependencyTypes.includes(GanttLinkType.ff) && path.from.pos === InBarPosition.finish && path.to.pos === InBarPosition.finish) {
return GanttLinkType.ff;
}
if (dependencyTypes.includes(GanttLinkType.sf) && path.from.pos === InBarPosition.start && path.to.pos === InBarPosition.finish) {
return GanttLinkType.sf;
}
return GanttLinkType.fs;
}

export enum InBarPosition {
start = 'start',
finish = 'finish'
}

export type LinkDragPosition = {
element: HTMLElement;
item: GanttItemInternal;
pos?: InBarPosition;
};

export interface LinkDragPath {
from?: LinkDragPosition;
to?: LinkDragPosition;
}

@Injectable()
export class GanttDragContainer {
Expand All @@ -20,56 +49,44 @@ export class GanttDragContainer {

linkDraggingId: string;

private linkDragSource: GanttItemInternal;

private linkDragTarget: GanttItemInternal;
linkDragPath: LinkDragPath = { from: null, to: null };

private linkDragFrom: LinkDragFrom;
constructor(@Inject(GANTT_UPPER_TOKEN) public ganttUpper: GanttUpper) {}

constructor() {}

emitLinkDragStarted(from: LinkDragFrom, item: GanttItemInternal) {
this.linkDraggingId = item.id;
this.linkDragFrom = from;
this.linkDragSource = this.linkDragFrom === 'source' ? item : null;
this.linkDragTarget = this.linkDragFrom === 'target' ? item : null;
emitLinkDragStarted(from: LinkDragPosition) {
this.linkDraggingId = from.item.id;
this.linkDragPath.from = from;
this.linkDragStarted.emit({
source: this.linkDragSource && this.linkDragSource.origin,
target: this.linkDragTarget && this.linkDragTarget.origin
source: from.item.origin,
target: null
});
}

emitLinkDragEntered(item: GanttItemInternal) {
if (this.linkDragFrom === 'source') {
this.linkDragTarget = item;
} else {
this.linkDragSource = item;
}
emitLinkDragEntered(to: LinkDragPosition) {
this.linkDragPath.to = to;
this.linkDragEntered.emit({
source: this.linkDragSource.origin,
target: this.linkDragTarget.origin
source: this.linkDragPath.from.item.origin,
target: to.item.origin
});
}

emitLinkDragLeaved() {
if (this.linkDragFrom === 'source') {
this.linkDragTarget = null;
} else {
this.linkDragSource = null;
}
this.linkDragPath.to = null;
}

emitLinkDragEnded() {
emitLinkDragEnded(to: LinkDragPosition) {
this.linkDragPath.to = to;
const dependencyType = getDependencyType(this.linkDragPath, this.ganttUpper.linkOptions?.dependencyTypes);
this.linkDragPath.from.item.addLink({
link: this.linkDragPath.to.item.id,
type: dependencyType
});
this.linkDragEnded.emit({
source: this.linkDragPath.from.item.origin,
target: this.linkDragPath.to.item.origin,
type: dependencyType
});
this.linkDraggingId = null;
if (this.linkDragSource && this.linkDragTarget) {
this.linkDragSource.addLink(this.linkDragTarget.id);

this.linkDragEnded.emit({
source: this.linkDragSource.origin,
target: this.linkDragTarget.origin
});
}
this.linkDragSource = null;
this.linkDragTarget = null;
this.linkDragPath = { from: null, to: null };
}
}
14 changes: 11 additions & 3 deletions packages/gantt/src/gantt-upper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ export abstract class GanttUpper {

@Input() viewOptions: GanttViewOptions = {};

@Input() set linkOptions(options: GanttLinkOptions) {
this._linkOptions = Object.assign(options, this.config.linkOptions);
}

get linkOptions() {
return this._linkOptions;
}

@Input() disabledLoadOnScroll: boolean;

@Input()
Expand Down Expand Up @@ -107,8 +115,6 @@ export abstract class GanttUpper {

public linkable: boolean;

public linkOptions: GanttLinkOptions;

public linkDragEnded = new EventEmitter<GanttLinkDragEvent>();

public view: GanttView;
Expand Down Expand Up @@ -139,13 +145,15 @@ export abstract class GanttUpper {

private _multiple = false;

private _linkOptions: GanttLinkOptions;

@HostBinding('class.gantt') ganttClass = true;

constructor(
protected elementRef: ElementRef<HTMLElement>,
protected cdr: ChangeDetectorRef,
protected ngZone: NgZone,
@Inject(GANTT_GLOBAL_CONFIG) protected config: GanttGlobalConfig
@Inject(GANTT_GLOBAL_CONFIG) public config: GanttGlobalConfig
) {}

private createView() {
Expand Down
Loading

0 comments on commit e91ce5b

Please sign in to comment.