Skip to content

Commit

Permalink
apply query based column to meetings
Browse files Browse the repository at this point in the history
  • Loading branch information
ulferts committed Jun 28, 2024
1 parent 4bb80d7 commit fe01f52
Show file tree
Hide file tree
Showing 15 changed files with 404 additions and 42 deletions.
8 changes: 6 additions & 2 deletions app/components/row_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,19 @@ def row
end

def column_value(column)
send(column)
if column.respond_to?(:attribute)
send(column.attribute)
else
send(column)
end
end

def column_css_class(column)
column_css_classes[column]
end

def column_css_classes
@column_css_classes ||= columns.to_h { |name| [name, name] }
@column_css_classes ||= columns.index_with { |column| column.respond_to?(:attribute) ? column.attribute : column }
end

def button_links
Expand Down
12 changes: 10 additions & 2 deletions app/services/params_to_query_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ def apply_filters(query, params)
end

def apply_order(query, params)
return query unless params[:sortBy]
return query unless params[:sortBy] || params[:sort]

sort = parse_sorting_from_json(params[:sortBy])
sort = params[:sortBy] ? parse_sorting_from_json(params[:sortBy]) : parse_sort_helper_params(params[:sort])

hash_sort = sort.each_with_object({}) do |(attribute, direction), hash|
hash[attribute.to_sym] = direction.downcase.to_sym
Expand Down Expand Up @@ -107,6 +107,14 @@ def parse_sorting_from_json(json)
end
end

def parse_sort_helper_params(sort_params)
sort_params
.to_s
.split(",")
.map { |s| s.split(":")[0..1] }
.map { |attribute, direction| [attribute, direction || "asc"] }
end

def convert_attribute(attribute, append_id: false)
::API::Utilities::PropertyNameConverter.to_ar_name(attribute,
context: conversion_model,
Expand Down
2 changes: 1 addition & 1 deletion modules/meeting/app/components/meetings/row_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

module Meetings
class RowComponent < ::RowComponent
def project_name
def project
helpers.link_to_project model.project, {}, {}, false
end

Expand Down
71 changes: 71 additions & 0 deletions modules/meeting/app/components/meetings/table_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<%#-- 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.
++#%>

<div class="project-list-page--table">
<div class="generic-table--flex-container">
<div class="generic-table--container <%= container_class %>">
<div class="generic-table--results-container">
<table class="generic-table" <%= table_id ? "id=\"#{table_id}\"".html_safe : '' %>>
<colgroup>
<% (columns.length + 1).times do %>
<col opHighlightCol>
<% end %>
</colgroup>
<thead class="-sticky">
<tr>
<%= render_column_headers %>
<th class="-right">
<div class="generic-table--header-outer">
</div>
</th>
</tr>
</thead>
<tbody>
<% if rows.empty? %>
<tr class="generic-table--empty-row">
<td colspan="<%= columns.length + 1 %>"><%= empty_row_message %></td>
</tr>
<% end %>
<%= render_rows %>
</tbody>
</table>

<% if inline_create_link && show_inline_create %>
<div class="wp-inline-create-button">
<%= inline_create_link %>
</div>
<% end %>
</div>
</div>
</div>
</div>

<% if paginated? %>
<%= helpers.pagination_links_full rows, pagination_options %>
<% end %>
81 changes: 56 additions & 25 deletions modules/meeting/app/components/meetings/table_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,45 +29,76 @@
#++

module Meetings
class TableComponent < ::TableComponent
options :current_project # used to determine if displaying the projects column
class TableComponent < ApplicationComponent # rubocop:disable OpenProject/AddPreviewForViewComponent
options :params # We read collapsed state from params
options :current_user # adds this option to those of the base class
options :query

sortable_columns :title, :project_name, :type, :start_time, :duration, :location

def initial_sort
%i[start_time asc]
def table_id
"meeting-table"
end

def sortable_columns_correlation
super.merge(
project_name: "projects.name",
type: "meetings.type"
)
def container_class
"generic-table--container_visible-overflow generic-table--container_height-100"
end

def initialize_sorted_model
helpers.sort_clear

super
def rows
@rows ||= query.results.paginate(page: helpers.page_param(params), per_page: helpers.per_page_param(params))
end

def paginated?
true
end

def headers
@headers ||= [
[:title, { caption: Meeting.human_attribute_name(:title) }],
current_project.blank? ? [:project_name, { caption: Meeting.human_attribute_name(:project) }] : nil,
[:type, { caption: Meeting.human_attribute_name(:type) }],
[:start_time, { caption: Meeting.human_attribute_name(:start_time) }],
[:duration, { caption: Meeting.human_attribute_name(:duration) }],
[:location, { caption: Meeting.human_attribute_name(:location) }]
].compact
def pagination_options
default_pagination_options.merge(optional_pagination_options)
end

def default_pagination_options
{ allowed_params: %i[query_id filters columns sortBy] }
end

def optional_pagination_options
{}
end

def sortable_column?(select)
sortable? && query.known_order?(select.attribute)
end

def columns
@columns ||= headers.map(&:first)
@columns ||= query.selects.reject { |select| select.is_a?(::Queries::Selects::NotExistingSelect) }
end

def render_rows
render(self.class.row_class.with_collection(rows, table: self))
end

def render_column_headers
# TODO: turn the Projects::ColumnHeaderComponent into generic component
render(Projects::ColumnHeaderComponent.with_collection(columns, query:))
end

def inline_create_link
nil
end

def empty_row_message
I18n.t :no_results_title_text
end

class << self
def row_class
mod = name.deconstantize

"#{mod}::RowComponent".constantize
rescue NameError
raise(
NameError,
"#{mod}::RowComponent required by #{mod}::TableComponent not defined. " +
"Expected to be defined in `app/components/#{mod.underscore}/row_component.rb`."
)
end
end
end
end
15 changes: 10 additions & 5 deletions modules/meeting/app/controllers/meetings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ class MeetingsController < ApplicationController

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

Expand Down Expand Up @@ -249,17 +248,23 @@ 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)

if @project
query.where("project_id", "=", @project.id)
end

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

query
end

Expand All @@ -270,10 +275,10 @@ def apply_default_filter_if_none_given(query)
query.where("invited_user_id", "=", [User.current.id.to_s])
end

def load_meetings(query)
query
.results
.paginate(page: page_param, per_page: per_page_param)
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
3 changes: 0 additions & 3 deletions modules/meeting/app/models/meeting.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ class Meeting < ApplicationRecord
has_many :sections, dependent: :destroy, class_name: "MeetingSection"
has_many :agenda_items, dependent: :destroy, class_name: "MeetingAgendaItem"

default_scope do
order("#{Meeting.table_name}.start_time DESC")
end
scope :from_tomorrow, -> { where(["start_time >= ?", Date.tomorrow.beginning_of_day]) }
scope :from_today, -> { where(["start_time >= ?", Time.zone.today.beginning_of_day]) }
scope :with_users_by_date, -> {
Expand Down
6 changes: 6 additions & 0 deletions modules/meeting/app/models/queries/meetings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,11 @@ module Queries::Meetings
filter Filters::InvitedUserFilter
filter Filters::AuthorFilter
filter Filters::DatesIntervalFilter

order Orders::Default
order Orders::Project

select Selects::Default
select Selects::Project
end
end
35 changes: 35 additions & 0 deletions modules/meeting/app/models/queries/meetings/orders/default.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# -- 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.
# ++

class Queries::Meetings::Orders::Default < Queries::Orders::Base
self.model = Meeting

def self.key
/\A(title|type|start_time|duration|location)\z/
end
end
43 changes: 43 additions & 0 deletions modules/meeting/app/models/queries/meetings/orders/project.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# -- 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.
# ++

class Queries::Meetings::Orders::Project < Queries::Orders::Base
self.model = Meeting

def self.key
:project
end

def joins
:project
end

def name
"#{Project.table_name}.name"
end
end
Loading

0 comments on commit fe01f52

Please sign in to comment.