|
|
@ -27,7 +27,7 @@ |
|
|
|
// ++
|
|
|
|
// ++
|
|
|
|
|
|
|
|
|
|
|
|
import {States} from "../../states.service"; |
|
|
|
import {States} from "../../states.service"; |
|
|
|
import {WorkPackageTimelineService, TimelineViewParameters} from "./wp-timeline.service"; |
|
|
|
import {WorkPackageTimelineService, RenderInfo, calculatePositionValueForDayCount} from "./wp-timeline.service"; |
|
|
|
import {WorkPackageResource} from "../../api/api-v3/hal-resources/work-package-resource.service"; |
|
|
|
import {WorkPackageResource} from "../../api/api-v3/hal-resources/work-package-resource.service"; |
|
|
|
import {State} from "../../../helpers/reactive-fassade"; |
|
|
|
import {State} from "../../../helpers/reactive-fassade"; |
|
|
|
import {scopedObservable} from "../../../helpers/angular-rx-utils"; |
|
|
|
import {scopedObservable} from "../../../helpers/angular-rx-utils"; |
|
|
@ -36,15 +36,6 @@ import WorkPackage = op.WorkPackage; |
|
|
|
import Observable = Rx.Observable; |
|
|
|
import Observable = Rx.Observable; |
|
|
|
import IDisposable = Rx.IDisposable; |
|
|
|
import IDisposable = Rx.IDisposable; |
|
|
|
|
|
|
|
|
|
|
|
function calculatePositionValueForDayCount(viewParams: TimelineViewParameters, days: number): string { |
|
|
|
|
|
|
|
const daysInPx = days * viewParams.pixelPerDay; |
|
|
|
|
|
|
|
if (viewParams.showDurationInPx) { |
|
|
|
|
|
|
|
return daysInPx + "px"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return (daysInPx / viewParams.maxWidthInPx * 100) + "%"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export class WorkPackageTimelineCell { |
|
|
|
export class WorkPackageTimelineCell { |
|
|
|
|
|
|
|
|
|
|
|
private wpState: State<WorkPackageResource>; |
|
|
|
private wpState: State<WorkPackageResource>; |
|
|
@ -53,7 +44,7 @@ export class WorkPackageTimelineCell { |
|
|
|
|
|
|
|
|
|
|
|
private bar: HTMLDivElement = null; |
|
|
|
private bar: HTMLDivElement = null; |
|
|
|
|
|
|
|
|
|
|
|
private today: HTMLDivElement; |
|
|
|
private globalElements: {[type: string]: HTMLDivElement} = {}; |
|
|
|
|
|
|
|
|
|
|
|
constructor(private workPackageTimelineService: WorkPackageTimelineService, |
|
|
|
constructor(private workPackageTimelineService: WorkPackageTimelineService, |
|
|
|
private scope: IScope, |
|
|
|
private scope: IScope, |
|
|
@ -69,52 +60,41 @@ export class WorkPackageTimelineCell { |
|
|
|
this.scope, |
|
|
|
this.scope, |
|
|
|
this.workPackageTimelineService.addWorkPackage(this.workPackageId)) |
|
|
|
this.workPackageTimelineService.addWorkPackage(this.workPackageId)) |
|
|
|
.subscribe(renderInfo => { |
|
|
|
.subscribe(renderInfo => { |
|
|
|
this.updateView(renderInfo.viewParams, renderInfo.workPackage); |
|
|
|
this.updateView(renderInfo); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO never called
|
|
|
|
deactivate() { |
|
|
|
deactivate() { |
|
|
|
this.timelineCell.innerHTML = ""; |
|
|
|
this.timelineCell.innerHTML = ""; |
|
|
|
this.disposable && this.disposable.dispose(); |
|
|
|
this.disposable && this.disposable.dispose(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private lazyInit() { |
|
|
|
private lazyInit() { |
|
|
|
if (this.bar === null) { |
|
|
|
|
|
|
|
this.today = document.createElement("div"); |
|
|
|
|
|
|
|
this.timelineCell.appendChild(this.today); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.bar === null) { |
|
|
|
if (this.bar === null) { |
|
|
|
this.bar = document.createElement("div"); |
|
|
|
this.bar = document.createElement("div"); |
|
|
|
this.timelineCell.appendChild(this.bar); |
|
|
|
this.timelineCell.appendChild(this.bar); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private updateView(viewParams: TimelineViewParameters, wp: WorkPackage) { |
|
|
|
private updateView(renderInfo: RenderInfo) { |
|
|
|
|
|
|
|
// display bar
|
|
|
|
this.lazyInit(); |
|
|
|
this.lazyInit(); |
|
|
|
|
|
|
|
const viewParams = renderInfo.viewParams; |
|
|
|
|
|
|
|
const wp = renderInfo.workPackage; |
|
|
|
|
|
|
|
|
|
|
|
const cellHeight = jQuery(this.timelineCell).outerHeight(); |
|
|
|
// const cellHeight = jQuery(this.timelineCell).outerHeight();
|
|
|
|
const start = moment(wp.startDate as any); |
|
|
|
const start = moment(wp.startDate as any); |
|
|
|
const due = moment(wp.dueDate as any); |
|
|
|
const due = moment(wp.dueDate as any); |
|
|
|
|
|
|
|
|
|
|
|
// general settings - today
|
|
|
|
// update global elements
|
|
|
|
this.today.style.position = "absolute"; |
|
|
|
this.updateGlobalElements(renderInfo); |
|
|
|
this.today.style.width = "2px"; |
|
|
|
|
|
|
|
this.today.style.borderLeft = "2px dotted red"; |
|
|
|
|
|
|
|
this.today.style.zIndex = "10"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.today.style.top = "-" + cellHeight + "px"; |
|
|
|
|
|
|
|
this.today.style.height = (cellHeight * 4) + "px"; |
|
|
|
|
|
|
|
const offsetToday = viewParams.now.diff(viewParams.dateDisplayStart, "days"); |
|
|
|
|
|
|
|
this.today.style.left = calculatePositionValueForDayCount(viewParams, offsetToday); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// abort if no start or due date
|
|
|
|
// abort if no start or due date
|
|
|
|
if (!wp.startDate || !wp.dueDate) { |
|
|
|
if (!wp.startDate || !wp.dueDate) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// general settings - bar
|
|
|
|
// general settings - bar
|
|
|
|
this.bar.style.position = "relative"; |
|
|
|
this.bar.style.position = "relative"; |
|
|
|
this.bar.style.height = "1em"; |
|
|
|
this.bar.style.height = "1em"; |
|
|
@ -129,6 +109,36 @@ export class WorkPackageTimelineCell { |
|
|
|
// duration
|
|
|
|
// duration
|
|
|
|
const duration = due.diff(start, "days"); |
|
|
|
const duration = due.diff(start, "days"); |
|
|
|
this.bar.style.width = calculatePositionValueForDayCount(viewParams, duration); |
|
|
|
this.bar.style.width = calculatePositionValueForDayCount(viewParams, duration); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private updateGlobalElements(renderInfo: RenderInfo) { |
|
|
|
|
|
|
|
const activeGlobalElementTypes = _.keys(renderInfo.globalElements); |
|
|
|
|
|
|
|
const knownGlobalElementTypes = _.keys(this.globalElements); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const newGlobalElementTypes = _.difference(activeGlobalElementTypes, knownGlobalElementTypes); |
|
|
|
|
|
|
|
const removedGlobalElementTypes = _.difference(knownGlobalElementTypes, activeGlobalElementTypes); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// new elements
|
|
|
|
|
|
|
|
for (const newElem of newGlobalElementTypes) { |
|
|
|
|
|
|
|
const elem = document.createElement("div"); |
|
|
|
|
|
|
|
this.timelineCell.appendChild(elem); |
|
|
|
|
|
|
|
this.globalElements[newElem] = elem; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// removed elements
|
|
|
|
|
|
|
|
for (const removedElem of removedGlobalElementTypes) { |
|
|
|
|
|
|
|
this.globalElements[removedElem].remove(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// update elements
|
|
|
|
|
|
|
|
for (const elemType of _.keys(renderInfo.globalElements)) { |
|
|
|
|
|
|
|
const elem = this.globalElements[elemType]; |
|
|
|
|
|
|
|
const cellHeight = jQuery(this.timelineCell).outerHeight(); |
|
|
|
|
|
|
|
elem.style.top = "-" + cellHeight + "px"; |
|
|
|
|
|
|
|
elem.style.height = (cellHeight * 4) + "px"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
renderInfo.globalElements[elemType](renderInfo.workPackage, elem); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|