Skip to content

Commit

Permalink
[#54459] Investigate queries and filters to display the project list …
Browse files Browse the repository at this point in the history
…in projects attribute settings view

https://community.openproject.org/work_packages/54459
  • Loading branch information
akabiru committed May 6, 2024
1 parent 4c46d23 commit 96ac329
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 0 deletions.
4 changes: 4 additions & 0 deletions app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ class Project < ApplicationRecord
scope :with_member, ->(user = User.current) { where(id: user.memberships.select(:project_id)) }
scope :without_member, ->(user = User.current) { where.not(id: user.memberships.select(:project_id)) }

scope :with_available_custom_fields, ->(custom_field_ids) do
joins(:project_custom_field_project_mappings).where(project_custom_field_project_mappings: { custom_field_id: custom_field_ids })
end

scopes :activated_time_activity,
:visible_with_activated_time_activity

Expand Down
1 change: 1 addition & 0 deletions app/models/queries/filters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module Queries::Filters
list: Queries::Filters::Strategies::List,
list_all: Queries::Filters::Strategies::ListAll,
list_optional: Queries::Filters::Strategies::ListOptional,
list_contains: Queries::Filters::Strategies::ListContains,
shared_with_user_list_optional: Queries::Filters::Strategies::WorkPackages::SharedWithUser::ListOptional,
integer: Queries::Filters::Strategies::Integer,
date: Queries::Filters::Strategies::Date,
Expand Down
34 changes: 34 additions & 0 deletions app/models/queries/filters/strategies/list_contains.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2024 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-2013 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 COPYRIGHT and LICENSE files for more details.
#++

module Queries::Filters::Strategies
class ListContains < List
self.supported_operators = ["~"]
self.default_operator = "~"
end
end
1 change: 1 addition & 0 deletions app/models/queries/projects.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
module Queries::Projects
::Queries::Register.register(ProjectQuery) do
filter Filters::AncestorFilter
filter Filters::AvailableProjectAttributesFilter
filter Filters::TypeFilter
filter Filters::ActiveFilter
filter Filters::TemplatedFilter
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2023 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-2013 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 COPYRIGHT and LICENSE files for more details.
# ++
#

class Queries::Projects::Filters::AvailableProjectAttributesFilter < Queries::Projects::Filters::ProjectFilter
def self.key
:available_project_attributes
end

def type
:list_contains
end

def allowed_values
@allowed_values ||= ProjectCustomFieldProjectMapping.pluck(:custom_field_id).map { |id| [id, id.to_s] }
end

def available?
User.current.admin?
end

def scope
model.with_available_custom_fields(values)
end

def human_name
I18n.t(:label_available_project_attributes)
end
end
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,7 @@ Project attributes and sections are defined in the <a href=%{admin_settings_url}
label_attribute_expand_text: "The complete text for '%{attribute}'"
label_authentication: "Authentication"
label_available_global_roles: "Available global roles"
label_available_project_attributes: "Available project attributes"
label_available_project_forums: "Available forums"
label_available_project_repositories: "Available repositories"
label_available_project_versions: "Available versions"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2024 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-2013 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 COPYRIGHT and LICENSE files for more details.
#++

require "spec_helper"

RSpec.describe Queries::Projects::Filters::AvailableProjectAttributesFilter do
it_behaves_like "basic query filter" do
let(:class_key) { :available_project_attributes }
let(:type) { :list_contains }
let(:human_name) { "Available project attributes" }
end

it_behaves_like "list_contains query filter" do
let(:project_custom_field_project_mapping1) { build_stubbed(:project_custom_field_project_mapping) }
let(:project_custom_field_project_mapping2) { build_stubbed(:project_custom_field_project_mapping) }

before do
allow(ProjectCustomFieldProjectMapping)
.to receive(:pluck)
.with(:custom_field_id)
.and_return([project_custom_field_project_mapping1.id,
project_custom_field_project_mapping2.id])
end

let(:name) { "Available project attributes" }
let(:valid_values) { [project_custom_field_project_mapping1.id, project_custom_field_project_mapping2.id] }

describe "#allowed_values" do
it "is a list of the possible values" do
expected = [[project_custom_field_project_mapping1.id, project_custom_field_project_mapping1.id.to_s],
[project_custom_field_project_mapping2.id, project_custom_field_project_mapping2.id.to_s]]

expect(instance.allowed_values).to match_array(expected)
end
end
end
end
48 changes: 48 additions & 0 deletions spec/support/queries/filters/shared_filter_examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,54 @@
end
end

RSpec.shared_examples_for "list_contains query filter" do
include_context "filter tests"
let(:type) { :list_contains }

describe "#scope" do
let(:values) { valid_values }

context 'for "~"' do
let(:operator) { "~" }

it "is the same as handwriting the query" do
handwritten_scope_sql = <<-SQL.squish
SELECT "projects".* FROM "projects"
INNER JOIN "project_custom_field_project_mappings" ON "project_custom_field_project_mappings"."project_id" = "projects"."id"
WHERE "project_custom_field_project_mappings"."custom_field_id" IN (#{values.join(', ')})
SQL

expect(instance.scope.to_sql).to eql handwritten_scope_sql
end
end
end

describe "#valid?" do
let(:operator) { "~" }
let(:values) { valid_values }

it "is valid" do
expect(instance).to be_valid
end

context "for an invalid operator" do
let(:operator) { "=" }

it "is invalid" do
expect(instance).not_to be_valid
end
end

context "for an invalid value" do
let(:values) { ["inexistent"] }

it "is invalid" do
expect(instance).not_to be_valid
end
end
end
end

RSpec.shared_examples_for "boolean query filter" do |scope: true|
include_context "filter tests"
let(:attribute) { raise "needs to be defined" }
Expand Down

0 comments on commit 96ac329

Please sign in to comment.