Merge pull request #5486 from opf/fix/only_follows_precedes_drawn_in_timeliens

Fix/only follows precedes drawn in timeliens

[ci skip]
pull/5469/merge
Oliver Günther 8 years ago committed by GitHub
commit 46ad508a78
  1. 17
      app/models/queries/relations/filters/type_filter.rb
  2. 53
      frontend/app/components/wp-table/timeline/global-elements/wp-timeline-relations.directive.ts
  3. 76
      spec/models/queries/relations/relation_query_spec.rb

@ -1,4 +1,5 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2017 the OpenProject Foundation (OPF)
@ -31,12 +32,24 @@ module Queries
module Relations
module Filters
class TypeFilter < ::Queries::Relations::Filters::RelationFilter
def allowed_values
::Relation::TYPES.map do |_, value|
[I18n.t(value[:name]), value[:sym]]
end
end
def type
:string
:list
end
def self.key
:relation_type
:type
end
def where
operator_strategy.sql_for_field(values,
self.class.model.table_name,
'relation_type')
end
end
end

@ -28,32 +28,32 @@
import {
timelineElementCssClass,
TimelineViewParameters,
} from "../wp-timeline";
import {WorkPackageTimelineTableController} from "../container/wp-timeline-container.directive";
} 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 {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";
} 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";
export const timelineGlobalElementCssClassname = 'relation-line';
function newSegment(vp: TimelineViewParameters,
classNames: string[],
color: string,
top: number,
left: number,
width: number,
height: number): HTMLElement {
function newSegment(vp:TimelineViewParameters,
classNames:string[],
color:string,
top:number,
left:number,
width:number,
height:number):HTMLElement {
const segment = document.createElement('div');
segment.classList.add(
@ -136,17 +136,18 @@ export class WorkPackageTableTimelineRelations {
.withLatestFrom(
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.wpTimeline.cells[workPackageId]) {
this.refreshRelations(workPackageId, relations!);
}
.map(([[workPackageId, relations]]) => {
let relevantRelations = _.pickBy(!relations, (relation:RelationResource) => (relation.type === 'precedes' || relation.type === 'follows'));
return [workPackageId, relevantRelations];
})
.filter(([workPackageId, relations]) => !!(workPackageId && this.wpTimeline.cells[workPackageId as string]))
.subscribe(([workPackageId, relations]) => {
this.refreshRelations(workPackageId as string, relations);
});
}
private refreshRelations(workPackageId:string, relations:RelationsStateValue) {
private refreshRelations(workPackageId:string, relations:Object) {
// Remove all previous relations for the work package
const prefix = TimelineRelationElement.workPackagePrefix(workPackageId);
jQuery(`.${prefix}`).remove();
@ -247,7 +248,7 @@ export class WorkPackageTableTimelineRelations {
}
openprojectModule.component("wpTimelineRelations", {
openprojectModule.component('wpTimelineRelations', {
template: '<div class="wp-table-timeline--relations"></div>',
controller: WorkPackageTableTimelineRelations,
require: {

@ -0,0 +1,76 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2017 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.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
describe Queries::Relations::RelationQuery, type: :model do
let(:instance) { described_class.new }
let(:base_scope) { Relation.all }
context 'without a filter' do
describe '#results' do
it 'is the same as getting all the relations' do
expect(instance.results.to_sql).to eql base_scope.to_sql
end
end
describe '#valid?' do
it 'is true' do
expect(instance).to be_valid
end
end
end
context 'with a type filter' do
before do
instance.where('type', '=', ['follows', 'precedes'])
end
describe '#results' do
it 'is the same as handwriting the query' do
expected = base_scope
.merge(Relation
.where("relations.relation_type IN ('follows','precedes')"))
expect(instance.results.to_sql).to eql expected.to_sql
end
end
describe '#valid?' do
it 'is true' do
expect(instance).to be_valid
end
it 'is invalid if the filter is invalid' do
instance.where('type', '=', [''])
expect(instance).to be_invalid
end
end
end
end
Loading…
Cancel
Save