Skip to content

Commit

Permalink
make use of the default query loading for meetings
Browse files Browse the repository at this point in the history
  • Loading branch information
ulferts committed Jul 1, 2024
1 parent 7147950 commit bb84895
Show file tree
Hide file tree
Showing 12 changed files with 312 additions and 126 deletions.
10 changes: 9 additions & 1 deletion app/controllers/queries/loading.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,15 @@ def permitted_query_params
end

def query_class
"#{self.class.name.chomp('Controller').singularize}Query".constantize
controller_name = self.class.name.demodulize

model_name = if controller_name == "QueriesController"
self.class.name.deconstantize
else
controller_name.chomp("Controller")
end

"#{model_name.singularize}Query".constantize
end
end
end
16 changes: 14 additions & 2 deletions app/models/queries/factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,32 @@ def find_persisted_query_and_set_attributes(id, query_class, params, user, dupli
end

def duplicate_query(query)
query.class.new(query.attributes.slice("filters", "orders", "selects"))
if query.is_a?(ApplicationRecord)
query.class.new(query.attributes.slice("filters", "orders", "selects"))
else
query
end
end

def set_query_attributes(query, query_class, params, user)
query_namespace(query_class)::SetAttributesService
.new(user:,
model: query,
contract_class: Queries::LoadingContract)
contract_class: query_loading_contract_class(query_class))
.call(params)
.result
end

def query_namespace(query_class)
query_class.name.pluralize.constantize
end

def query_loading_contract_class(query_class)
if query_class.is_a?(ApplicationRecord)
Queries::LoadingContract
else
EmptyContract
end
end
end
end
54 changes: 3 additions & 51 deletions app/services/project_queries/set_attributes_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,71 +27,23 @@
# ++

class ProjectQueries::SetAttributesService < BaseServices::SetAttributes
private

def set_attributes(params)
set_filters(params.delete(:filters))
set_order(params.delete(:orders))
set_select(params.delete(:selects))

super
end

def set_default_attributes(_params)
set_default_user
set_default_filter
set_default_order
set_default_selects
end
include Queries::AttributeSetting

def set_default_user
model.change_by_system do
model.user = user
end
end
private

def set_default_order
return if model.orders.any?

model.order(lft: :asc)
end

def set_default_filter
return if model.filters.any?

model.where("active", "=", OpenProject::Database::DB_VALUE_TRUE)
end

def set_default_selects
return if model.selects.any?

model.select(*default_columns, add_not_existing: false)
end

def set_filters(filters)
return unless filters

model.filters.clear
filters.each do |filter|
model.where(filter[:attribute], filter[:operator], filter[:values])
end
end

def set_order(orders)
return unless orders

model.orders.clear
model.order(orders.to_h { |o| [o[:attribute], o[:direction]] })
end

def set_select(selects)
return unless selects

model.selects.clear
model.select(*selects)
end

def default_columns
(["favored", "name"] + Setting.enabled_projects_columns).uniq
(%w[favored name] + Setting.enabled_projects_columns).uniq
end
end
91 changes: 91 additions & 0 deletions app/services/queries/attribute_setting.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# -- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2010-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::AttributeSetting
private

def set_attributes(params)
set_filters(params.delete(:filters))
set_order(params.delete(:orders))
set_select(params.delete(:selects))

if model.is_a?(ApplicationRecord)
super
else
set_default_attributes(params)
end
end

def set_default_attributes(_params)
set_default_user if model.is_a?(ApplicationRecord)
set_default_filter if model.filters.empty?
set_default_order if model.orders.empty?
set_default_selects if model.selects.empty?
end

def set_default_user
model.change_by_system do
model.user = user
end
end

def set_default_order
# Nothing or now but overwritable by including class
end

def set_default_filter
# Nothing or now but overwritable by including class
end

def set_default_selects
# Nothing or now but overwritable by including class
end

def set_filters(filters)
return unless filters

model.filters.clear
filters.each do |filter|
model.where(filter[:attribute], filter[:operator], filter[:values])
end
end

def set_order(orders)
return unless orders

model.orders.clear
model.order(orders.to_h { |o| [o[:attribute], o[:direction]] })
end

def set_select(selects)
return unless selects

model.selects.clear
model.select(*selects)
end
end
45 changes: 14 additions & 31 deletions modules/meeting/app/controllers/meetings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
class MeetingsController < ApplicationController
around_action :set_time_zone
before_action :load_and_authorize_in_optional_project, only: %i[index new show create history]
before_action :load_query_or_deny_access, only: %i[index]
before_action :verify_activities_module_activated, only: %i[history]
before_action :determine_date_range, only: %i[history]
before_action :determine_author, only: %i[history]
Expand All @@ -47,6 +48,7 @@ class MeetingsController < ApplicationController
include WatchersHelper
include PaginationHelper
include SortHelper
include Queries::Loading

include OpTurbo::ComponentStream
include ApplicationComponentStreams
Expand All @@ -56,7 +58,6 @@ class MeetingsController < ApplicationController
menu_item :new_meeting, only: %i[new create]

def index
@query = load_query
render "index", locals: { menu_name: project_or_global_menu }
end

Expand Down Expand Up @@ -247,38 +248,20 @@ def notify

private

def load_query
# TODO: move into Factory
query = ParamsToQueryService.new(
Meeting,
current_user
).call(params)

query = apply_default_filter_if_none_given(query)
query = apply_default_order_if_none_given(query)
def load_query(duplicate:)
super.tap do |query|
# We want the project column in here in case the request is not executed inside a project.
# At the same time, we want the project filter if the request is executed inside a project.
# Both is currently not possible to be handled inside the factory loading the query.
if @project
query.where("project_id", "=", @project.id)
end

if @project
query.where("project_id", "=", @project.id)
query.selects.clear
query.select(:title)
query.select(:project) unless @project
query.select(:type, :start_time, :duration, :location)
end

query.select(:title)
query.select(:project) unless @project
query.select(:type, :start_time, :duration, :location)

query
end

def apply_default_filter_if_none_given(query)
return query if query.filters.any?

query.where("time", "=", Queries::Meetings::Filters::TimeFilter::FUTURE_VALUE)
query.where("invited_user_id", "=", [User.current.id.to_s])
end

def apply_default_order_if_none_given(query)
return query if query.orders.any?

query.order(start_time: :asc)
end

def set_time_zone(&)
Expand Down
28 changes: 7 additions & 21 deletions modules/meeting/app/menus/meetings/menu.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,43 +44,29 @@ def menu_items
end

def top_level_menu_items
upcoming_filter = [{ time: { operator: "=", values: ["future"] } }].to_json
past_filter = [{ time: { operator: "=", values: ["past"] } }].to_json

[
menu_item(I18n.t(:label_upcoming_meetings),
filters: upcoming_filter, sort: "start_time"),
query_id: MeetingQueries::Static::UPCOMING),
menu_item(I18n.t(:label_past_meetings),
filters: past_filter, sort: "start_time:desc")
query_id: MeetingQueries::Static::PAST)
]
end

def involvement_sidebar_menu_items
past_filter = [
{ time: { operator: "=", values: ["past"] } },
{ invited_user_id: { operator: "=", values: [User.current.id.to_s] } }
].to_json
attendee_filter = [{ attended_user_id: { operator: "=", values: [User.current.id.to_s] } }].to_json
author_filter = [{ author_id: { operator: "=", values: [User.current.id.to_s] } }].to_json

[
menu_item(I18n.t(:label_upcoming_invitations),
{}),
query_id: MeetingQueries::Static::UPCOMING_INVITATIONS),
menu_item(I18n.t(:label_past_invitations),
{ filters: past_filter, sort: "start_time:desc" }),
query_id: MeetingQueries::Static::PAST_INVITATIONS),
menu_item(I18n.t(:label_attendee),
{ filters: attendee_filter }),
query_id: MeetingQueries::Static::ATTENDEE),
menu_item(I18n.t(:label_author),
{ filters: author_filter })
query_id: MeetingQueries::Static::CREATOR)
]
end

def query_path(query_params)
if project.present?
project_meetings_path(project, params.permit(query_params.keys).merge!(query_params))
else
meetings_path(params.permit(query_params.keys).merge!(query_params))
end
polymorphic_path([@project, :meetings], query_params)
end
end
end
Loading

0 comments on commit bb84895

Please sign in to comment.