WIP Timeline: generalized display of global elements, e.g. today line

pull/5091/head
Roman Roelofsen 8 years ago
parent 0cfd0bc3a8
commit deb6c2ddc7
  1. 72
      frontend/app/components/wp-table/timeline/wp-timeline-cell.ts
  2. 29
      frontend/app/components/wp-table/timeline/wp-timeline.service.ts

@ -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);
}
} }

@ -53,8 +53,20 @@ export class TimelineViewParameters {
export interface RenderInfo { export interface RenderInfo {
viewParams: TimelineViewParameters; viewParams: TimelineViewParameters;
workPackage: WorkPackage; workPackage: WorkPackage;
globalElements: GlobalElementsRegistry;
} }
export function calculatePositionValueForDayCount(viewParams: TimelineViewParameters, days: number): string {
const daysInPx = days * viewParams.pixelPerDay;
if (viewParams.showDurationInPx) {
return daysInPx + "px";
} else {
return (daysInPx / viewParams.maxWidthInPx * 100) + "%";
}
}
type GlobalElementsRegistry = {[type: string]: (wp: WorkPackage, elem: HTMLDivElement) => any};
export class WorkPackageTimelineService { export class WorkPackageTimelineService {
private _viewParameters: TimelineViewParameters = new TimelineViewParameters(); private _viewParameters: TimelineViewParameters = new TimelineViewParameters();
@ -63,8 +75,21 @@ export class WorkPackageTimelineService {
private viewParamsSubject = new Rx.BehaviorSubject<TimelineViewParameters>(new TimelineViewParameters()); private viewParamsSubject = new Rx.BehaviorSubject<TimelineViewParameters>(new TimelineViewParameters());
private globalElementsRegistry: GlobalElementsRegistry = {};
constructor(private states: States) { constructor(private states: States) {
"ngInject"; "ngInject";
// Today Line
this.globalElementsRegistry["today"] = (wp: WorkPackage, elem: HTMLDivElement) => {
elem.style.position = "absolute";
elem.style.width = "2px";
elem.style.borderLeft = "2px dotted red";
elem.style.zIndex = "10";
const offsetToday = this._viewParameters.now.diff(this._viewParameters.dateDisplayStart, "days");
elem.style.left = calculatePositionValueForDayCount(this._viewParameters, offsetToday);
};
} }
get viewParameters() { get viewParameters() {
@ -79,7 +104,8 @@ export class WorkPackageTimelineService {
(vp: TimelineViewParameters, wp: any) => { (vp: TimelineViewParameters, wp: any) => {
return { return {
viewParams: vp, viewParams: vp,
workPackage: wp workPackage: wp,
globalElements: this.globalElementsRegistry
}; };
} }
) )
@ -97,7 +123,6 @@ export class WorkPackageTimelineService {
return Observable.just(renderInfo); return Observable.just(renderInfo);
} }
}); });
} }
private calculateViewParams(): boolean { private calculateViewParams(): boolean {

Loading…
Cancel
Save