# frozen_string_literal: true
module Decidim
module Meetings
# Exposes the meeting resource so users can view them
class MeetingsController < Decidim::Meetings::ApplicationController
include FilterResource
include ComponentFilterable
include Flaggable
include Withdrawable
include FormFactory
include Paginable
helper Decidim::ResourceVersionsHelper
helper Decidim::ShortLinkHelper
include Decidim::AttachmentsHelper
helper_method :meetings, :meeting, :registration, :search, :nav_paths, :tab_panel_items
before_action :add_addtional_csp_directives, only: [:show]
def new
enforce_permission_to :create, :meeting
@form = meeting_form.instance
end
def create
enforce_permission_to :create, :meeting
@form = meeting_form.from_params(params, current_component:)
CreateMeeting.call(@form) do
on(:ok) do |meeting|
flash[:notice] = I18n.t("meetings.create.success", scope: "decidim.meetings")
redirect_to meeting_path(meeting)
end
on(:invalid) do
flash.now[:alert] = I18n.t("meetings.create.invalid", scope: "decidim.meetings")
render action: "new"
end
end
end
def index
return unless search.result.blank? && params.dig("filter", "date") != %w(past)
@past_meetings ||= search_with(filter_params.merge(with_any_date: %w(past)))
if @past_meetings.result.present?
params[:filter] ||= {}
params[:filter][:with_any_date] = %w(past)
@forced_past_meetings = true
@search = @past_meetings
end
end
def show
raise ActionController::RoutingError, "Not Found" unless meeting
return if meeting.current_user_can_visit_meeting?(current_user)
flash[:alert] = I18n.t("meeting.not_allowed", scope: "decidim.meetings")
redirect_to(ResourceLocatorPresenter.new(meeting).index)
end
def edit
enforce_permission_to(:update, :meeting, meeting:)
@form = meeting_form.from_model(meeting)
end
def update
enforce_permission_to(:update, :meeting, meeting:)
@form = meeting_form.from_params(params)
UpdateMeeting.call(@form, current_user, meeting) do
on(:ok) do |meeting|
flash[:notice] = I18n.t("meetings.update.success", scope: "decidim.meetings")
redirect_to Decidim::ResourceLocatorPresenter.new(meeting).path
end
on(:invalid) do
flash.now[:alert] = I18n.t("meetings.update.invalid", scope: "decidim.meetings")
render :edit
end
end
end
def withdraw
enforce_permission_to(:withdraw, :meeting, meeting:)
WithdrawMeeting.call(@meeting, current_user) do
on(:ok) do
flash[:notice] = I18n.t("meetings.withdraw.success", scope: "decidim")
redirect_to Decidim::ResourceLocatorPresenter.new(@meeting).path
end
on(:invalid) do
flash[:alert] = I18n.t("meetings.withdraw.error", scope: "decidim")
redirect_to Decidim::ResourceLocatorPresenter.new(@meeting).path
end
end
end
private
def meeting
@meeting ||= Meeting.not_hidden.where(component: current_component).find_by(id: params[:id])
end
def next_meeting
return if search_collection.size < 2
search_collection.order(:start_time, :id).where(
Decidim::Meetings::Meeting.arel_table[:start_time].gt(meeting.start_time).or(
Decidim::Meetings::Meeting.arel_table[:start_time].eq(meeting.start_time).and(
Decidim::Meetings::Meeting.arel_table[:id].gt(meeting.id)
)
)
).first
end
def prev_meeting
return if search_collection.size < 2
search_collection.order(:start_time, :id).where(
Decidim::Meetings::Meeting.arel_table[:start_time].lt(meeting.start_time).or(
Decidim::Meetings::Meeting.arel_table[:start_time].eq(meeting.start_time).and(
Decidim::Meetings::Meeting.arel_table[:id].lt(meeting.id)
)
)
).last
end
def nav_paths
return {} if meeting.blank?
{ prev_path: prev_meeting, next_path: next_meeting }.compact_blank.transform_values { |meeting| meeting_path(meeting) }
end
def meetings
is_past_meetings = params.dig("filter", "with_any_date")&.include?("past")
@meetings ||= paginate(search.result.order(start_time: is_past_meetings ? :desc : :asc))
end
def registration
@registration ||= meeting.registrations.find_by(user: current_user)
end
def search_collection
Meeting.where(component: current_component).published.not_hidden.visible_for(current_user).with_availability(
filter_params[:with_availability]
).includes(
:component,
attachments: :file_attachment
)
end
def meeting_form
form(Decidim::Meetings::MeetingForm)
end
def tab_panel_items
@tab_panel_items ||= [
{
enabled: meeting.public_participants.any?,
id: "participants",
text: t("attending_participants", scope: "decidim.meetings.public_participants_list"),
icon: "group-line",
method: :cell,
args: ["decidim/meetings/public_participants_list", meeting]
},
{
enabled: !meeting.closed? && meeting.user_group_registrations.any?,
id: "organizations",
text: t("attending_organizations", scope: "decidim.meetings.public_participants_list"),
icon: "community-line",
method: :cell,
args: ["decidim/meetings/attending_organizations_list", meeting]
},
{
enabled: meeting.linked_resources(:proposals, "proposals_from_meeting").present?,
id: "included_proposals",
text: t("decidim/proposals/proposal", scope: "activerecord.models", count: 2),
icon: resource_type_icon_key("Decidim::Proposals::Proposal"),
method: :cell,
args: ["decidim/linked_resources_for", meeting, { type: :proposals, link_name: "proposals_from_meeting" }]
},
{
enabled: meeting.linked_resources(:results, "meetings_through_proposals").present?,
id: "included_meetings",
text: t("decidim/accountability/result", scope: "activerecord.models", count: 2),
icon: resource_type_icon_key("Decidim::Accountability::Result"),
method: :cell,
args: ["decidim/linked_resources_for", meeting, { type: :results, link_name: "meetings_through_proposals" }]
}
] + attachments_tab_panel_items(@meeting)
end
end
end
end