From fd4b5b03c707b0b1c411d871b6d52c1e06106f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20G=C3=BCnther?= Date: Mon, 8 May 2017 16:34:07 +0200 Subject: [PATCH] Restore relations display [ci skip] --- .../wp-timeline-container.directive.ts | 39 ++--- .../container/wp-timeline-container.html | 1 + .../wp-timeline-relations.directive.ts} | 145 +++++++++--------- .../wp-timeline.today-line.ts | 2 +- .../grid/wp-timeline-grid.directive.ts | 1 - .../header/wp-timeline-header.directive.ts | 1 - .../wp-table/timeline/wp-timeline-cell.ts | 4 +- .../wp-table/wp-table.directive.html | 5 +- 8 files changed, 98 insertions(+), 100 deletions(-) rename frontend/app/components/wp-table/timeline/{wp-timeline-global.directive.ts => global-elements/wp-timeline-relations.directive.ts} (69%) rename frontend/app/components/wp-table/timeline/{ => global-elements}/wp-timeline.today-line.ts (98%) diff --git a/frontend/app/components/wp-table/timeline/container/wp-timeline-container.directive.ts b/frontend/app/components/wp-table/timeline/container/wp-timeline-container.directive.ts index be0328d831..a33f3d52b2 100644 --- a/frontend/app/components/wp-table/timeline/container/wp-timeline-container.directive.ts +++ b/frontend/app/components/wp-table/timeline/container/wp-timeline-container.directive.ts @@ -34,7 +34,6 @@ import { TimelineViewParameters } from "../wp-timeline"; import {WorkPackageResourceInterface} from "../../../api/api-v3/hal-resources/work-package-resource.service"; -import {WpTimelineGlobalService} from "../wp-timeline-global.directive"; import {States} from "../../../states.service"; import {WorkPackageTableTimelineService} from "../../../wp-fast-table/state/wp-table-timeline.service"; import {WorkPackageNotificationService} from "../../../wp-edit/wp-notification.service"; @@ -45,6 +44,7 @@ import {debugLog} from "../../../../helpers/debug_output"; import {openprojectModule} from "../../../../angular-modules"; import {WorkPackageTimelineHeaderController} from "../header/wp-timeline-header.directive"; import {TypeResource} from "../../../api/api-v3/hal-resources/type-resource.service"; +import {WorkPackageTimelineCell} from "../wp-timeline-cell"; export class WorkPackageTimelineTableController { @@ -54,8 +54,6 @@ export class WorkPackageTimelineTableController { private workPackagesInView: {[id: string]: WorkPackageResourceInterface} = {}; - public readonly globalService = new WpTimelineGlobalService(this.$scope); - private updateAllWorkPackagesSubject = new BehaviorSubject(true); private refreshViewRequested = false; @@ -64,7 +62,9 @@ export class WorkPackageTimelineTableController { public header:WorkPackageTimelineHeaderController; - private members:{ [name:string]: (vp:TimelineViewParameters) => void } = {}; + public cells:{[id: string]:WorkPackageTimelineCell} = {}; + + private renderers:{ [name:string]: (vp:TimelineViewParameters) => void } = {}; constructor(private $scope:IScope, private $element:ng.IAugmentedJQuery, @@ -108,15 +108,25 @@ export class WorkPackageTimelineTableController { } onRefreshRequested(name:string, callback:(vp:TimelineViewParameters) => void) { - this.members[name] = callback; + this.renderers[name] = callback; } + refreshScrollOnly() { + jQuery("." + timelineElementCssClass).css("margin-left", this._viewParameters.scrollOffsetInPx + "px"); + } - /** - * Returns a defensive copy of the currently used view parameters. - */ - getViewParametersCopy(): TimelineViewParameters { - return _.cloneDeep(this._viewParameters); + public updateWorkPackageInfo(cell: WorkPackageTimelineCell) { + this.cells[cell.latestRenderInfo.workPackage.id] = cell; + this.refreshView(); + } + + public removeWorkPackageInfo(id: string) { + delete this.cells[id]; + this.refreshView(); + } + + get viewParameters(): TimelineViewParameters { + return this._viewParameters; } get viewParameterSettings() { @@ -140,22 +150,17 @@ export class WorkPackageTimelineTableController { this.updateAllWorkPackagesSubject.next(true); this.header.refreshView(this._viewParameters); - _.each(this.members, (cb, key) => { + _.each(this.renderers, (cb, key) => { debugLog(`Refreshing timeline member ${key}`); cb(this._viewParameters); }); - this.refreshScrollOnly(); this.refreshViewRequested = false; }, 30); } this.refreshViewRequested = true; } - refreshScrollOnly() { - jQuery("." + timelineElementCssClass).css("margin-left", this._viewParameters.scrollOffsetInPx + "px"); - } - addWorkPackage(wpId: string): Observable { const wpObs = this.states.workPackages.get(wpId).values$() .takeUntil(scopeDestroyed$(this.$scope)) @@ -163,8 +168,6 @@ export class WorkPackageTimelineTableController { this.workPackagesInView[wp.id] = wp; const viewParamsChanged = this.calculateViewParams(this._viewParameters); if (viewParamsChanged) { - // view params have changed, notify all cells - this.globalService.updateViewParameter(this._viewParameters); this.refreshView(); } diff --git a/frontend/app/components/wp-table/timeline/container/wp-timeline-container.html b/frontend/app/components/wp-table/timeline/container/wp-timeline-container.html index 328a6f3b8e..4d04fa856a 100644 --- a/frontend/app/components/wp-table/timeline/container/wp-timeline-container.html +++ b/frontend/app/components/wp-table/timeline/container/wp-timeline-container.html @@ -3,6 +3,7 @@
+
diff --git a/frontend/app/components/wp-table/timeline/wp-timeline-global.directive.ts b/frontend/app/components/wp-table/timeline/global-elements/wp-timeline-relations.directive.ts similarity index 69% rename from frontend/app/components/wp-table/timeline/wp-timeline-global.directive.ts rename to frontend/app/components/wp-table/timeline/global-elements/wp-timeline-relations.directive.ts index 8054e258e2..bec53c9be8 100644 --- a/frontend/app/components/wp-table/timeline/wp-timeline-global.directive.ts +++ b/frontend/app/components/wp-table/timeline/global-elements/wp-timeline-relations.directive.ts @@ -1,7 +1,6 @@ - // -- copyright // OpenProject is a project management system. -// Copyright (C) 2012-2017 the OpenProject Foundation (OPF) +// Copyright (C) 2012-2015 the OpenProject Foundation (OPF) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License version 3. @@ -26,23 +25,25 @@ // // See doc/COPYRIGHT.rdoc for more details. // ++ - -import IDirective = angular.IDirective; -import IComponentOptions = angular.IComponentOptions; -import {Observable} from "rxjs/Rx"; -import {scopeDestroyed$} from "../../../helpers/angular-rx-utils"; -import {debugLog} from "../../../helpers/debug_output"; -import {injectorBridge} from "../../angular/angular-injector-bridge.functions"; -import {RelationResource} from "../../api/api-v3/hal-resources/relation-resource.service"; -import {WorkPackageResource} from "../../api/api-v3/hal-resources/work-package-resource.service"; -import {States} from "../../states.service"; -import {WorkPackageStates} from "../../work-package-states.service"; -import {RelationsStateValue, WorkPackageRelationsService} from "../../wp-relations/wp-relations.service"; -import {TimelineRelationElement} from "./global-elements/timeline-relation-element"; -import {timelineElementCssClass, TimelineViewParameters} from "./wp-timeline"; -import {WorkPackageTimelineCell} from "./wp-timeline-cell"; -import IScope = angular.IScope; - +import { + timelineElementCssClass, + TimelineViewParameters, +} from "../wp-timeline"; +import {WorkPackageTimelineTableController} from "../container/wp-timeline-container.directive"; + +import {Observable} from 'rxjs'; +import * as moment from 'moment'; +import Moment = moment.Moment; +import {openprojectModule} from "../../../../angular-modules"; +import {States} from "../../../states.service"; +import {WorkPackageStates} from "../../../work-package-states.service"; +import { + RelationsStateValue, + WorkPackageRelationsService +} from "../../../wp-relations/wp-relations.service"; +import {scopeDestroyed$} from "../../../../helpers/angular-rx-utils"; +import {TimelineRelationElement} from "./timeline-relation-element"; +import {RelationResource} from "../../../api/api-v3/hal-resources/relation-resource.service"; export const timelineGlobalElementCssClassname = "relation-line"; @@ -70,40 +71,33 @@ function newSegment(vp: TimelineViewParameters, return segment; } -export class WpTimelineGlobalService { +export class WorkPackageTableTimelineRelations { - // Injected arguments - public states:States; - public wpStates:WorkPackageStates; - public wpRelations:WorkPackageRelationsService; + public wpTimeline:WorkPackageTimelineTableController; - private workPackageIdOrder:string[] = []; + private container:ng.IAugmentedJQuery; - private viewParameters:TimelineViewParameters; - - private cells:{[id: string]:WorkPackageTimelineCell} = {}; + private workPackageIdOrder:string[] = []; private elements:TimelineRelationElement[] = []; - constructor(private scope:IScope) { - injectorBridge(this); - this.requireVisibleRelations(); - this.setupRelationSubscription(); + constructor(public $element:ng.IAugmentedJQuery, + public $scope:ng.IScope, + public states:States, + public wpStates:WorkPackageStates, + public wpRelations:WorkPackageRelationsService) { } - updateViewParameter(viewParams: TimelineViewParameters) { - this.viewParameters = viewParams; - this.update(); - } + $onInit() { + this.container = this.$element.find('.wp-table-timeline--relations'); + this.wpTimeline.onRefreshRequested('relations', (vp:TimelineViewParameters) => this.refreshView(vp)); - updateWorkPackageInfo(cell: WorkPackageTimelineCell) { - this.cells[cell.latestRenderInfo.workPackage.id] = cell; - this.update(); + this.requireVisibleRelations(); + this.setupRelationSubscription(); } - removeWorkPackageInfo(id: string) { - delete this.cells[id]; - this.update(); + private refreshView(vp:TimelineViewParameters) { + this.update(vp); } /** @@ -114,31 +108,40 @@ export class WpTimelineGlobalService { // Observe the rows and request relations if changed // AND timeline is visible. Observable.combineLatest( - this.states.table.timelineVisible.values$().takeUntil(scopeDestroyed$(this.scope)), - this.states.table.rows.values$().takeUntil(scopeDestroyed$(this.scope)) + this.states.table.timelineVisible.values$().takeUntil(scopeDestroyed$(this.$scope)), + this.states.table.rendered.values$().takeUntil(scopeDestroyed$(this.$scope)) ) - .filter(([timelineState, rows]) => timelineState.isVisible) - .map(([_timelineState, rows]) => rows) - .subscribe((rows:WorkPackageResource[]) => { - this.workPackageIdOrder = rows.map(wp => wp.id.toString()); + .filter(([timelineState, rendered]) => timelineState.isVisible) + .subscribe(() => { + this.workPackageIdOrder = this.getVisibleWorkPackageOrder(); this.wpRelations.requireInvolved(this.workPackageIdOrder); }); } + private getVisibleWorkPackageOrder():string[] { + const ids:string[] = []; + + jQuery('.wp-table--row').each((i, el) => { + ids.push(el.getAttribute('data-work-package-id')!); + }); + + return ids; + } + /** * Refresh relations of visible rows. */ private setupRelationSubscription() { this.wpStates.relations.observeChange() - .takeUntil(scopeDestroyed$(this.scope)) + .takeUntil(scopeDestroyed$(this.$scope)) .withLatestFrom( - this.states.table.timelineVisible.values$().takeUntil(scopeDestroyed$(this.scope))) + this.states.table.timelineVisible.values$().takeUntil(scopeDestroyed$(this.$scope))) .filter(([relations, timelineVisible]) => relations && timelineVisible.isVisible) .map(([relations]) => relations) .subscribe((nextVal) => { const [workPackageId, relations] = nextVal; - if (workPackageId && this.cells[workPackageId]) { + if (workPackageId && this.wpTimeline.cells[workPackageId]) { this.refreshRelations(workPackageId, relations!); } }); @@ -154,45 +157,32 @@ export class WpTimelineGlobalService { const elem = new TimelineRelationElement(workPackageId, relation); this.elements.push(elem); - if (this.viewParameters !== undefined) { - this.renderElement(elem); - } + this.renderElement(this.wpTimeline.viewParameters, elem); }); } - private update() { - this.removeAllVisibleElements(); - this.renderElements(); - } - - private removeAllElements() { + private update(vp:TimelineViewParameters) { this.removeAllVisibleElements(); - this.elements = []; + this.renderElements(vp); } private removeAllVisibleElements() { jQuery('.' + timelineGlobalElementCssClassname).remove(); } - private renderElements() { - if (this.viewParameters === undefined) { - debugLog('renderElements() aborted - no viewParameters'); - return; - } - + private renderElements(vp:TimelineViewParameters) { for (const e of this.elements) { - this.renderElement(e); + this.renderElement(vp, e); } } - private renderElement(e:TimelineRelationElement) { - const vp = this.viewParameters; + private renderElement(vp:TimelineViewParameters, e:TimelineRelationElement) { const involved = e.relation.ids; const idxFrom = this.workPackageIdOrder.indexOf(involved.from); const idxTo = this.workPackageIdOrder.indexOf(involved.to); - const startCell = this.cells[involved.from]; - const endCell = this.cells[involved.to]; + const startCell = this.wpTimeline.cells[involved.from]; + const endCell = this.wpTimeline.cells[involved.to]; if (idxFrom === -1 || idxTo === -1 || _.isNil(startCell) || _.isNil(endCell)) { return; @@ -225,7 +215,7 @@ export class WpTimelineGlobalService { // vert segment for (let index = idxFrom + directionY; index !== idxTo; index += directionY) { const id = this.workPackageIdOrder[index]; - const cell = this.cells[id]; + const cell = this.wpTimeline.cells[id]; if (_.isNil(cell)) { continue; } @@ -255,6 +245,13 @@ export class WpTimelineGlobalService { } } } + } -WpTimelineGlobalService.$inject = ['states', 'wpStates', 'wpRelations']; +openprojectModule.component("wpTimelineRelations", { + template: '
', + controller: WorkPackageTableTimelineRelations, + require: { + wpTimeline: '^wpTimelineContainer' + } +}); diff --git a/frontend/app/components/wp-table/timeline/wp-timeline.today-line.ts b/frontend/app/components/wp-table/timeline/global-elements/wp-timeline.today-line.ts similarity index 98% rename from frontend/app/components/wp-table/timeline/wp-timeline.today-line.ts rename to frontend/app/components/wp-table/timeline/global-elements/wp-timeline.today-line.ts index 3319a3fc29..68a96aa990 100644 --- a/frontend/app/components/wp-table/timeline/wp-timeline.today-line.ts +++ b/frontend/app/components/wp-table/timeline/global-elements/wp-timeline.today-line.ts @@ -26,7 +26,7 @@ // See doc/COPYRIGHT.rdoc for more details. // ++ -import {calculatePositionValueForDayCount, TimelineViewParameters} from "./wp-timeline"; +import {calculatePositionValueForDayCount, TimelineViewParameters} from "../wp-timeline"; import * as moment from 'moment'; diff --git a/frontend/app/components/wp-table/timeline/grid/wp-timeline-grid.directive.ts b/frontend/app/components/wp-table/timeline/grid/wp-timeline-grid.directive.ts index 33941e1c04..9cf6d801e9 100644 --- a/frontend/app/components/wp-table/timeline/grid/wp-timeline-grid.directive.ts +++ b/frontend/app/components/wp-table/timeline/grid/wp-timeline-grid.directive.ts @@ -31,7 +31,6 @@ import { ZoomLevel, calculatePositionValueForDayCount, timelineGridElementCssClass } from "../wp-timeline"; -import {todayLine} from "../wp-timeline.today-line"; import {WorkPackageTimelineTableController} from "../container/wp-timeline-container.directive"; import * as moment from 'moment'; import Moment = moment.Moment; diff --git a/frontend/app/components/wp-table/timeline/header/wp-timeline-header.directive.ts b/frontend/app/components/wp-table/timeline/header/wp-timeline-header.directive.ts index c06e0c20c8..90066b5d77 100644 --- a/frontend/app/components/wp-table/timeline/header/wp-timeline-header.directive.ts +++ b/frontend/app/components/wp-table/timeline/header/wp-timeline-header.directive.ts @@ -31,7 +31,6 @@ import { ZoomLevel, calculatePositionValueForDayCount } from "../wp-timeline"; -import {todayLine} from "../wp-timeline.today-line"; import {WorkPackageTimelineTableController} from "../container/wp-timeline-container.directive"; import * as moment from 'moment'; import Moment = moment.Moment; diff --git a/frontend/app/components/wp-table/timeline/wp-timeline-cell.ts b/frontend/app/components/wp-table/timeline/wp-timeline-cell.ts index 9f8ea7bc44..5391afe639 100644 --- a/frontend/app/components/wp-table/timeline/wp-timeline-cell.ts +++ b/frontend/app/components/wp-table/timeline/wp-timeline-cell.ts @@ -74,13 +74,13 @@ export class WorkPackageTimelineCell { .map(([renderInfo, _visible]) => renderInfo) .subscribe(renderInfo => { this.updateView(renderInfo); - this.workPackageTimeline.globalService.updateWorkPackageInfo(this); + this.workPackageTimeline.cells[this.workPackageId] = this; }); } deactivate() { this.clear(); - this.workPackageTimeline.globalService.removeWorkPackageInfo(this.workPackageId); + delete this.workPackageTimeline.cells[this.workPackageId]; this.subscription && this.subscription.unsubscribe(); } diff --git a/frontend/app/components/wp-table/wp-table.directive.html b/frontend/app/components/wp-table/wp-table.directive.html index 7f613cb50d..90e7ae3ae1 100644 --- a/frontend/app/components/wp-table/wp-table.directive.html +++ b/frontend/app/components/wp-table/wp-table.directive.html @@ -1,6 +1,5 @@ -
-
+
+