Merge branch 'feature/notifications-group-by' into feature/38520-Sidebar-in-Notification-Center-with-project-filter
commit
f4f247b456
@ -1,127 +0,0 @@ |
|||||||
#-- encoding: UTF-8 |
|
||||||
|
|
||||||
#-- copyright |
|
||||||
# OpenProject is an open source project management software. |
|
||||||
# Copyright (C) 2012-2021 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_dependency 'queries/filters' |
|
||||||
|
|
||||||
module Queries::AvailableFilters |
|
||||||
def self.included(base) |
|
||||||
base.extend(ClassMethods) |
|
||||||
end |
|
||||||
|
|
||||||
module ClassMethods |
|
||||||
def registered_filters |
|
||||||
Queries::Register.filters[self] |
|
||||||
end |
|
||||||
|
|
||||||
def find_registered_filter(key) |
|
||||||
registered_filters.detect do |f| |
|
||||||
f.key === key.to_sym |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
def available_filters |
|
||||||
uninitialized = registered_filters - already_initialized_filters |
|
||||||
|
|
||||||
uninitialized.each do |filter| |
|
||||||
initialize_filter(filter) |
|
||||||
end |
|
||||||
|
|
||||||
initialized_filters.select(&:available?) |
|
||||||
end |
|
||||||
|
|
||||||
def filter_for(key, no_memoization = false) |
|
||||||
filter = get_initialized_filter(key, no_memoization) |
|
||||||
|
|
||||||
raise ::Queries::Filters::MissingError if filter.nil? |
|
||||||
|
|
||||||
filter |
|
||||||
rescue ::Queries::Filters::InvalidError => e |
|
||||||
Rails.logger.error "Failed to register filter for #{key}: #{e} \n" \ |
|
||||||
"Falling back to non-existing filter." |
|
||||||
non_existing_filter(key) |
|
||||||
rescue ::Queries::Filters::MissingError => e |
|
||||||
Rails.logger.error "Failed to find filter for #{key}: #{e} \n" \ |
|
||||||
"Falling back to non-existing filter." |
|
||||||
non_existing_filter(key) |
|
||||||
end |
|
||||||
|
|
||||||
private |
|
||||||
|
|
||||||
def non_existing_filter(key) |
|
||||||
Queries::NotExistingFilter.create!(name: key) |
|
||||||
end |
|
||||||
|
|
||||||
def get_initialized_filter(key, no_memoization) |
|
||||||
filter = find_registered_filter(key) |
|
||||||
|
|
||||||
return unless filter |
|
||||||
|
|
||||||
if no_memoization |
|
||||||
filter.create!(name: key) |
|
||||||
else |
|
||||||
initialize_filter(filter) |
|
||||||
|
|
||||||
find_initialized_filter(key) |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
def initialize_filter(filter) |
|
||||||
return if already_initialized_filters.include?(filter) |
|
||||||
|
|
||||||
already_initialized_filters << filter |
|
||||||
|
|
||||||
new_filters = filter.all_for(context) |
|
||||||
|
|
||||||
initialized_filters.push(*Array(new_filters)) |
|
||||||
end |
|
||||||
|
|
||||||
def find_registered_filter(key) |
|
||||||
self.class.find_registered_filter(key) |
|
||||||
end |
|
||||||
|
|
||||||
def find_initialized_filter(key) |
|
||||||
initialized_filters.detect do |f| |
|
||||||
f.name == key.to_sym |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
def already_initialized_filters |
|
||||||
@already_initialized_filters ||= [] |
|
||||||
end |
|
||||||
|
|
||||||
def initialized_filters |
|
||||||
@initialized_filters ||= [] |
|
||||||
end |
|
||||||
|
|
||||||
def registered_filters |
|
||||||
self.class.registered_filters |
|
||||||
end |
|
||||||
end |
|
@ -0,0 +1,131 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
|
||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 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_dependency 'queries/filters' |
||||||
|
|
||||||
|
module Queries |
||||||
|
module Filters |
||||||
|
module AvailableFilters |
||||||
|
def self.included(base) |
||||||
|
base.extend(ClassMethods) |
||||||
|
end |
||||||
|
|
||||||
|
module ClassMethods |
||||||
|
def registered_filters |
||||||
|
::Queries::Register.filters[self] |
||||||
|
end |
||||||
|
|
||||||
|
def find_registered_filter(key) |
||||||
|
registered_filters.detect do |f| |
||||||
|
f.key === key.to_sym |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def available_filters |
||||||
|
uninitialized = registered_filters - already_initialized_filters |
||||||
|
|
||||||
|
uninitialized.each do |filter| |
||||||
|
initialize_filter(filter) |
||||||
|
end |
||||||
|
|
||||||
|
initialized_filters.select(&:available?) |
||||||
|
end |
||||||
|
|
||||||
|
def filter_for(key, no_memoization: false) |
||||||
|
filter = get_initialized_filter(key, no_memoization) |
||||||
|
|
||||||
|
raise ::Queries::Filters::MissingError if filter.nil? |
||||||
|
|
||||||
|
filter |
||||||
|
rescue ::Queries::Filters::InvalidError => e |
||||||
|
Rails.logger.error "Failed to register filter for #{key}: #{e} \n" \ |
||||||
|
"Falling back to non-existing filter." |
||||||
|
non_existing_filter(key) |
||||||
|
rescue ::Queries::Filters::MissingError => e |
||||||
|
Rails.logger.error "Failed to find filter for #{key}: #{e} \n" \ |
||||||
|
"Falling back to non-existing filter." |
||||||
|
non_existing_filter(key) |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
def non_existing_filter(key) |
||||||
|
::Queries::Filters::NotExistingFilter.create!(name: key) |
||||||
|
end |
||||||
|
|
||||||
|
def get_initialized_filter(key, no_memoization) |
||||||
|
filter = find_registered_filter(key) |
||||||
|
|
||||||
|
return unless filter |
||||||
|
|
||||||
|
if no_memoization |
||||||
|
filter.create!(name: key) |
||||||
|
else |
||||||
|
initialize_filter(filter) |
||||||
|
|
||||||
|
find_initialized_filter(key) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def initialize_filter(filter) |
||||||
|
return if already_initialized_filters.include?(filter) |
||||||
|
|
||||||
|
already_initialized_filters << filter |
||||||
|
|
||||||
|
new_filters = filter.all_for(context) |
||||||
|
|
||||||
|
initialized_filters.push(*Array(new_filters)) |
||||||
|
end |
||||||
|
|
||||||
|
def find_registered_filter(key) |
||||||
|
self.class.find_registered_filter(key) |
||||||
|
end |
||||||
|
|
||||||
|
def find_initialized_filter(key) |
||||||
|
initialized_filters.detect do |f| |
||||||
|
f.name == key.to_sym |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def already_initialized_filters |
||||||
|
@already_initialized_filters ||= [] |
||||||
|
end |
||||||
|
|
||||||
|
def initialized_filters |
||||||
|
@initialized_filters ||= [] |
||||||
|
end |
||||||
|
|
||||||
|
def registered_filters |
||||||
|
self.class.registered_filters |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,85 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
|
||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 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 |
||||||
|
module Filters |
||||||
|
class NotExistingFilter < Base |
||||||
|
def available? |
||||||
|
false |
||||||
|
end |
||||||
|
|
||||||
|
def type |
||||||
|
:inexistent |
||||||
|
end |
||||||
|
|
||||||
|
def self.key |
||||||
|
:not_existent |
||||||
|
end |
||||||
|
|
||||||
|
def human_name |
||||||
|
name.to_s.presence || type |
||||||
|
end |
||||||
|
|
||||||
|
validate :always_false |
||||||
|
|
||||||
|
def always_false |
||||||
|
errors.add :base, I18n.t(:'activerecord.errors.messages.does_not_exist') |
||||||
|
end |
||||||
|
|
||||||
|
# deactivating superclass validation |
||||||
|
def validate_inclusion_of_operator; end |
||||||
|
|
||||||
|
def to_hash |
||||||
|
{ |
||||||
|
non_existent_filter: { |
||||||
|
operator: operator, |
||||||
|
values: values |
||||||
|
} |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
def scope |
||||||
|
# TODO: remove switch once the WP query is a |
||||||
|
# subclass of Queries::Base |
||||||
|
model = if context.respond_to?(:model) |
||||||
|
context.model |
||||||
|
else |
||||||
|
WorkPackage |
||||||
|
end |
||||||
|
|
||||||
|
model.unscoped |
||||||
|
end |
||||||
|
|
||||||
|
def attributes_hash |
||||||
|
nil |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,51 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
|
||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 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 |
||||||
|
module GroupBys |
||||||
|
module AvailableGroupBys |
||||||
|
def group_by_for(key) |
||||||
|
(find_registered_group_by(key) || ::Queries::GroupBys::NotExistingGroupBy).new(key) |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
def find_registered_group_by(key) |
||||||
|
group_by_register.detect do |s| |
||||||
|
s.key === key.to_sym |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
def group_by_register |
||||||
|
::Queries::Register.group_bys[self.class] |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,82 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
|
||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 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 |
||||||
|
module GroupBys |
||||||
|
class Base |
||||||
|
include ActiveModel::Validations |
||||||
|
|
||||||
|
def self.i18n_scope |
||||||
|
:activerecord |
||||||
|
end |
||||||
|
|
||||||
|
class_attribute :model |
||||||
|
attr_accessor :attribute |
||||||
|
|
||||||
|
def initialize(attribute) |
||||||
|
self.attribute = attribute |
||||||
|
end |
||||||
|
|
||||||
|
def self.key |
||||||
|
raise NotImplementedError |
||||||
|
end |
||||||
|
|
||||||
|
def association_class |
||||||
|
nil |
||||||
|
end |
||||||
|
|
||||||
|
def scope |
||||||
|
scope = model |
||||||
|
scope = model.joins(joins) if joins |
||||||
|
group_by scope |
||||||
|
end |
||||||
|
|
||||||
|
def name |
||||||
|
attribute |
||||||
|
end |
||||||
|
|
||||||
|
def joins |
||||||
|
nil |
||||||
|
end |
||||||
|
|
||||||
|
# Default to the same key for order |
||||||
|
# as the one for group |
||||||
|
def order_key |
||||||
|
self.class.key |
||||||
|
end |
||||||
|
|
||||||
|
protected |
||||||
|
|
||||||
|
def group_by(scope) |
||||||
|
scope.group(name) |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,47 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
|
||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 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 |
||||||
|
module GroupBys |
||||||
|
class NotExistingGroupBy < Base |
||||||
|
validate :always_false |
||||||
|
|
||||||
|
def self.key |
||||||
|
:inexistent |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
def always_false |
||||||
|
errors.add :base, I18n.t(:'activerecord.errors.messages.does_not_exist') |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,41 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
|
||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 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::Notifications::GroupBys::GroupByReason < Queries::GroupBys::Base |
||||||
|
self.model = Notification |
||||||
|
|
||||||
|
def self.key |
||||||
|
:reason |
||||||
|
end |
||||||
|
|
||||||
|
def name |
||||||
|
:reason_ian |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,90 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
|
||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 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 |
||||||
|
module Orders |
||||||
|
class Base |
||||||
|
include ActiveModel::Validations |
||||||
|
|
||||||
|
VALID_DIRECTIONS = %i(asc desc).freeze |
||||||
|
|
||||||
|
def self.i18n_scope |
||||||
|
:activerecord |
||||||
|
end |
||||||
|
|
||||||
|
validates :direction, inclusion: { in: VALID_DIRECTIONS } |
||||||
|
|
||||||
|
class_attribute :model |
||||||
|
attr_accessor :direction, |
||||||
|
:attribute |
||||||
|
|
||||||
|
def initialize(attribute) |
||||||
|
self.attribute = attribute |
||||||
|
end |
||||||
|
|
||||||
|
def self.key |
||||||
|
raise NotImplementedError |
||||||
|
end |
||||||
|
|
||||||
|
def scope |
||||||
|
scope = order |
||||||
|
scope = scope.joins(joins) if joins |
||||||
|
scope = scope.left_outer_joins(left_outer_joins) if left_outer_joins |
||||||
|
scope |
||||||
|
end |
||||||
|
|
||||||
|
def name |
||||||
|
attribute |
||||||
|
end |
||||||
|
|
||||||
|
private |
||||||
|
|
||||||
|
def order |
||||||
|
model.order(name => direction) |
||||||
|
end |
||||||
|
|
||||||
|
def joins |
||||||
|
nil |
||||||
|
end |
||||||
|
|
||||||
|
def left_outer_joins |
||||||
|
nil |
||||||
|
end |
||||||
|
|
||||||
|
def with_raise_on_invalid |
||||||
|
if VALID_DIRECTIONS.include?(direction) |
||||||
|
yield |
||||||
|
else |
||||||
|
raise ArgumentError, "Only one of #{VALID_DIRECTIONS} allowed. #{direction} is provided." |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,73 @@ |
|||||||
|
#-- encoding: UTF-8 |
||||||
|
|
||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 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 API |
||||||
|
module V3 |
||||||
|
module WorkPackages |
||||||
|
class WorkPackageAggregationGroup < ::API::Decorators::AggregationGroup |
||||||
|
def initialize(group_key, count, query:, current_user:, sums: nil) |
||||||
|
@sums = sums |
||||||
|
|
||||||
|
super(group_key, count, query: query, current_user: current_user) |
||||||
|
end |
||||||
|
|
||||||
|
property :sums, |
||||||
|
exec_context: :decorator, |
||||||
|
getter: ->(*) { |
||||||
|
::API::V3::WorkPackages::WorkPackageSumsRepresenter.create(sums, current_user) if sums |
||||||
|
}, |
||||||
|
render_nil: false |
||||||
|
|
||||||
|
link :groupBy do |
||||||
|
converted_name = convert_attribute(query.group_by_column.name) |
||||||
|
|
||||||
|
{ |
||||||
|
href: api_v3_paths.query_group_by(converted_name), |
||||||
|
title: query.group_by_column.caption |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
def has_sums? |
||||||
|
sums.present? |
||||||
|
end |
||||||
|
|
||||||
|
attr_reader :sums |
||||||
|
|
||||||
|
def value |
||||||
|
if query.group_by_column.name == :done_ratio |
||||||
|
"#{represented}%" |
||||||
|
else |
||||||
|
super |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,84 @@ |
|||||||
|
#-- copyright |
||||||
|
# OpenProject is an open source project management software. |
||||||
|
# Copyright (C) 2012-2021 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' |
||||||
|
|
||||||
|
describe ::API::V3::Notifications::NotificationCollectionRepresenter do |
||||||
|
let(:self_base_link) { '/api/v3/notifications' } |
||||||
|
let(:user) { FactoryBot.build_stubbed :user } |
||||||
|
let(:notifications) do |
||||||
|
FactoryBot.build_stubbed_list(:notification, |
||||||
|
3).tap do |items| |
||||||
|
allow(items) |
||||||
|
.to receive(:per_page) |
||||||
|
.with(page_size) |
||||||
|
.and_return(items) |
||||||
|
|
||||||
|
allow(items) |
||||||
|
.to receive(:page) |
||||||
|
.with(page) |
||||||
|
.and_return(items) |
||||||
|
end |
||||||
|
end |
||||||
|
let(:current_user) { FactoryBot.build_stubbed(:user) } |
||||||
|
let(:representer) do |
||||||
|
described_class.new(notifications, |
||||||
|
self_link: self_base_link, |
||||||
|
per_page: page_size, |
||||||
|
page: page, |
||||||
|
groups: groups, |
||||||
|
current_user: current_user) |
||||||
|
end |
||||||
|
let(:total) { 3 } |
||||||
|
let(:page) { 1 } |
||||||
|
let(:page_size) { 2 } |
||||||
|
let(:actual_count) { 3 } |
||||||
|
let(:collection_inner_type) { 'Notification' } |
||||||
|
let(:groups) { nil } |
||||||
|
|
||||||
|
include API::V3::Utilities::PathHelper |
||||||
|
|
||||||
|
describe 'generation' do |
||||||
|
subject(:collection) { representer.to_json } |
||||||
|
|
||||||
|
it_behaves_like 'offset-paginated APIv3 collection', 3, 'notifications', 'Notification' |
||||||
|
|
||||||
|
context 'when passing groups' do |
||||||
|
let(:groups) do |
||||||
|
[ |
||||||
|
{ value: 'mentioned', count: 34 }, |
||||||
|
{ value: 'involved', count: 5 } |
||||||
|
] |
||||||
|
end |
||||||
|
|
||||||
|
it 'renders the groups object as json' do |
||||||
|
expect(subject).to be_json_eql(groups.to_json).at_path('groups') |
||||||
|
end |
||||||
|
end |
||||||
|
end |
||||||
|
end |
Loading…
Reference in new issue