add milestone type filter for default project gantt query (#8869)

pull/8876/head
ulferts 4 years ago committed by GitHub
parent 428d23f267
commit 2ad215fed1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      app/models/type.rb
  2. 39
      app/models/types/scopes/milestone.rb
  3. 26
      app/services/projects/gantt_query_generator_service.rb
  4. 6
      spec/features/projects/projects_portfolio_spec.rb
  5. 45
      spec/models/types/scopes/milestone_spec.rb
  6. 42
      spec/services/projects/gantt_query_generator_service_spec.rb

@ -35,6 +35,8 @@ class ::Type < ApplicationRecord
include ::Type::Attributes
include ::Type::AttributeGroups
include ::Scopes::Scoped
before_destroy :check_integrity
has_many :work_packages
@ -64,6 +66,8 @@ class ::Type < ApplicationRecord
validates_inclusion_of :is_default, :is_milestone, in: [true, false]
scope_classes Types::Scopes::Milestone
default_scope { order('position ASC') }
scope :without_standard, -> {

@ -0,0 +1,39 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# 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 docs/COPYRIGHT.rdoc for more details.
#++
module Types::Scopes
class Milestone
class << self
def fetch
Type.where(is_milestone: true)
end
end
end
end

@ -42,10 +42,24 @@ module Projects
attr_reader :selected_project_ids
##
# Returns the current query or the default one if none was saved
def self.current_query
Setting.project_gantt_query.presence || DEFAULT_GANTT_QUERY
class << self
##
# Returns the current query or the default one if none was saved
def current_query
Setting.project_gantt_query.presence || default_gantt_query
end
def default_gantt_query
default_with_filter = JSON
.parse(Projects::GanttQueryGeneratorService::DEFAULT_GANTT_QUERY)
milestone_ids = Type.milestone.pluck(:id).map(&:to_s)
if milestone_ids.any?
default_with_filter.merge!('f' => [{ 'n' => 'type', 'o' => '=', 'v' => milestone_ids }])
end
JSON.dump(default_with_filter)
end
end
def initialize(selected_project_ids)
@ -83,9 +97,9 @@ module Projects
JSON.parse(self.class.current_query)
rescue JSON::JSONError => e
Rails.logger.error "Failed to read project gantt view, resetting to default. Error was: #{e.message}"
Setting.project_gantt_query = DEFAULT_GANTT_QUERY
Setting.project_gantt_query = self.class.default_gantt_query
JSON.parse(DEFAULT_GANTT_QUERY)
JSON.parse(self.class.default_gantt_query)
end
end
end

@ -116,7 +116,7 @@ describe 'Projects index page',
# Add a project filter that gets overridden
model_filters.add_filter_by('Project', 'is', project_a.name)
model_filters.add_filter_by('Type', 'is', type_milestone.name)
model_filters.expect_filter_by('Type', 'is', type_milestone.name)
model_filters.save
# Save the page
@ -141,8 +141,8 @@ describe 'Projects index page',
expect(page).to have_selector '.group--value', text: 'A'
expect(page).to have_selector '.group--value', text: 'B'
# Expect status, type and project filters
filters.expect_filter_count 3
# Expect type and project filters
filters.expect_filter_count 2
filters.open
filters.expect_filter_by('Type', 'is', [type_milestone.name])

@ -0,0 +1,45 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# 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 docs/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
describe Types::Scopes::Milestone, type: :model do
let!(:milestone) { FactoryBot.create(:type, is_milestone: true) }
let!(:other_type) { FactoryBot.create(:type, is_milestone: false) }
describe '.fetch' do
subject { described_class.fetch }
it 'returns only milestones' do
is_expected
.to match_array [milestone]
end
end
end

@ -35,26 +35,55 @@ describe Projects::GanttQueryGeneratorService, type: :model do
let(:instance) { described_class.new selected }
let(:subject) { instance.call }
let(:json) { JSON.parse(subject) }
let(:default_json) { JSON.parse(Projects::GanttQueryGeneratorService::DEFAULT_GANTT_QUERY) }
let(:milestone_ids) { [123, 234] }
let(:default_json) do
scope = double('scope')
allow(Type)
.to receive(:milestone)
.and_return(scope)
allow(scope)
.to receive(:pluck)
.with(:id)
.and_return(milestone_ids)
JSON
.parse(Projects::GanttQueryGeneratorService::DEFAULT_GANTT_QUERY)
.merge('f' => [{ 'n' => 'type', 'o' => '=', 'v' => milestone_ids.map(&:to_s) }])
end
def build_project_filter(ids)
{ 'n' => 'project', 'o' => '=', 'v' => ids }
end
context 'with empty setting' do
it 'uses the default' do
before do
Setting.project_gantt_query = ''
end
expected = default_json.merge('f' => [build_project_filter(selected)])
it 'uses the default' do
expected = default_json.deep_dup
expected['f'] << build_project_filter(selected)
expect(json).to eq(expected)
end
context 'without configured milestones' do
let(:milestone_ids) { [] }
it 'uses the default but without the type filter' do
expected = default_json
.deep_dup
.merge('f' => [build_project_filter(selected)])
expect(json).to eq(expected)
end
end
end
context 'with existing filter' do
it 'overrides the filter' do
Setting.project_gantt_query = default_json.merge('f' => [build_project_filter(%w[other values])]).to_json
Setting.project_gantt_query = default_json.deep_dup.merge('f' => [build_project_filter(%w[other values])]).to_json
expected = default_json.merge('f' => [build_project_filter(selected)])
expected = default_json.deep_dup.merge('f' => [build_project_filter(selected)])
expect(json).to eq(expected)
end
end
@ -63,7 +92,8 @@ describe Projects::GanttQueryGeneratorService, type: :model do
it 'returns the default' do
Setting.project_gantt_query = 'invalid!1234'
expected = default_json.merge('f' => [build_project_filter(selected)])
expected = default_json.deep_dup
expected['f'] << build_project_filter(selected)
expect(json).to eq(expected)
end
end

Loading…
Cancel
Save