Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions config/i18n-tasks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,13 @@ ignore_unused:
- decidim.meetings.meetings.show.withdraw_btn_hint
- decidim.meetings.meetings.show.withdraw_confirmation_html
- decidim.meetings.meetings.show.withdraw_meeting
- decidim.meetings.meetings.show.cancel_waitlist
- decidim.meetings.meetings.show.join_waitlist
- decidim.meetings.meetings.show.leave
- decidim.meetings.meetings.show.registration_confirmation
- decidim.meetings.meetings.show.registration_title
- decidim.meetings.meetings.show.waitlist_confirmation
- decidim.meetings.meetings.show.waitlist_title
- decidim.proposals.proposals.show.withdraw_btn_hint
- decidim.proposals.proposals.show.withdraw_confirmation_html
- decidim.proposals.proposals.show.withdraw_proposal
Expand Down
2 changes: 1 addition & 1 deletion decidim-assemblies/lib/decidim/assemblies/admin_engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ class AdminEngine < ::Rails::Engine

menu.add_item :assembly_share_tokens,
I18n.t("menu.share_tokens", scope: "decidim.admin"),
decidim_admin_assemblies.assembly_share_tokens_path(current_assembly),
decidim_admin_assemblies.assembly_share_tokens_path(current_participatory_space),
active: is_active_link?(decidim_admin_assemblies.assembly_share_tokens_path(current_participatory_space)),
if: allowed_to?(:read, :share_tokens, current_participatory_space: current_participatory_space)
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<%= action_authorized_link_to(
:join,
meeting_registration_path(model),
resource: model,
method: :delete,
class: button_classes,
data: { disable: true, confirm: i18n_modal_confirmation_text }
) do %>
<% if style == :simple %>
<%= cancel_button_text %>
<%= icon icon_name %>
<% elsif style == :detailed %>
<span class="icon-wrap">
<%= icon icon_name %>
</span>
<span class="text-wrap">
<%= cancel_button_text %>
</span>
<% end %>
<% end %>
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
<%= waiting_list_info %>
<div class="text-center">
<%= action_authorized_link_to(
:join,
meeting_registration_path(model),
resource: model,
method: :delete,
class: button_classes,
data: { disable: true, confirm: t("leave_confirmation", scope: "decidim.meetings.meetings.show") }
) do %>
<%= t("leave", scope: "decidim.meetings.meetings.show") %>
<%= icon icon_name %>
<% end %>
<%= cancel_registration_button(style: :simple) unless registration_status == "on_waiting_list" %>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div class="card extra mt-s">
<div class="card__content">
<%= t("waitlist_info", scope: "decidim.meetings.meetings.show") %>
<%= cancel_registration_button(style: :detailed) %>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,54 @@ def show
render
end

def waiting_list_info
render if registration_status == "on_waiting_list"
end

def cancel_registration_button(style: :simple)
render locals: { style: style }
end

private

def current_component
model.component
end

def registration_status
model.registrations.find_by(user: current_user)&.status
end

def action_keys
if registration_status == "on_waiting_list"
{
button: "cancel_waitlist",
modal_title: "waitlist_title",
modal_confirmation: "waitlist_confirmation"
}
else
{
button: "leave",
modal_title: "registration_title",
modal_confirmation: "registration_confirmation"
}
end
end

def cancel_button_text
I18n.t(action_keys[:button], scope: "decidim.meetings.meetings.show")
end

def i18n_modal_title
I18n.t(action_keys[:modal_title], scope: "decidim.meetings.meetings.show")
end

def i18n_modal_confirmation_text
I18n.t(action_keys[:modal_confirmation], scope: "decidim.meetings.meetings.show")
end

def button_classes
""
registration_status == "on_waiting_list" ? "button expanded button--icon follow-button secondary hollow active small" : ""
end

def icon_name
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<div class="reveal" data-reveal id="meeting-registration-confirm-<%= model.id %>">
<%= decidim_form_for(registration_form, url: meeting_registration_path(model), method: :post) do |form| %>
<% action = model.has_available_slots? ? "registration" : "waitlist" %>
<div class="reveal" data-reveal id="meeting-<%= action %>-confirm-<%= model.id %>">
<%= decidim_form_for(registration_form, url: model.has_available_slots? ? meeting_registration_path(model) : join_waitlist_meeting_registration_path(model), method: :post) do |form| %>
<div class="row">
<div class="columns medium-10 medium-offset-1">
<%= cell("decidim/represent_user_group", form) %>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<% if model.registration_form_enabled? %>
<%= action_authorized_link_to(
:join_waitlist,
i18n_join_waitlist_text,
join_waitlist_meeting_registration_path(model),
class: button_classes
) %>
<% else %>
<%= action_authorized_button_to(
:join_waitlist,
i18n_join_waitlist_text,
"#",
class: button_classes,
data: { open: current_user.present? ? "meeting-waitlist-confirm-#{model.id}" : "loginModal" }
) %>
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# frozen_string_literal: true

module Decidim
module Meetings
# This cell renders the button to join a waitlist.
class JoinWaitlistButtonCell < Decidim::ViewModel
include MeetingCellsHelper

def show
return unless model.waitlist_enabled? && !model.has_available_slots? && model.can_be_joined_by?(current_user)
return if model.has_registration_for?(current_user)

render
end

private

def current_component
model.component
end

def button_classes
"button expanded secondary small mt-s"
end

def i18n_join_waitlist_text
return if !model.waitlist_enabled? && model.has_available_slots?

I18n.t("add_to_waitlist", scope: "decidim.meetings.meetings.show")
end

def icon_name
"clockwise-line"
end

def registration_form
@registration_form ||= Decidim::Meetings::JoinMeetingForm.new
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ def fields_from_meeting
available_slots: meeting.available_slots,
registration_terms: meeting.registration_terms,
reserved_slots: meeting.reserved_slots,
waitlist_enabled: meeting.waitlist_enabled,
customize_registration_email: meeting.customize_registration_email,
registration_form_enabled: meeting.registration_form_enabled,
registration_email_custom_content: meeting.registration_email_custom_content
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def update_meeting_registrations
meeting.available_slots = form.available_slots
meeting.reserved_slots = form.reserved_slots
meeting.registration_terms = form.registration_terms
meeting.waitlist_enabled = form.waitlist_enabled
meeting.customize_registration_email = form.customize_registration_email
meeting.registration_email_custom_content = form.registration_email_custom_content if form.customize_registration_email
end
Expand Down
93 changes: 93 additions & 0 deletions decidim-meetings/app/commands/decidim/meetings/join_waitlist.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# frozen_string_literal: true

module Decidim
module Meetings
# This command is executed when the user joins a waitlist for a meeting.
class JoinWaitlist < Decidim::Command
# Initializes a JoinWaitlist Command.
#
# meeting - The current instance of the meeting to be joined.
# user - The user joining the waitlist.
# registration_form - A form object with params; can be a questionnaire.
def initialize(meeting, user, registration_form)
@meeting = meeting
@user = user
@user_group = Decidim::UserGroup.find_by(id: registration_form.user_group_id)
@registration_form = registration_form
end

# Joins the waitlist for the meeting if valid.
#
# Broadcasts :ok if successful, :invalid otherwise.
def call
return broadcast(:invalid) unless can_join_waitlist?
return broadcast(:invalid_form) unless registration_form.valid?
return broadcast(:invalid) if answer_questionnaire == :invalid

meeting.with_lock do
create_waitlist_entry
send_waitlist_notification
end
follow_meeting
broadcast(:ok)
end

private

attr_reader :meeting, :user, :user_group, :registration, :registration_form

def can_join_waitlist?
meeting.waitlist_enabled? &&
!meeting.registrations.exists?(user: user) &&
!meeting.has_available_slots?
end

def create_waitlist_entry
@registration = Decidim::Meetings::Registration.create!(
meeting: meeting,
user: user,
user_group: user_group,
public_participation: registration_form.public_participation,
status: :on_waiting_list
)
end

def send_waitlist_notification
Decidim::EventsManager.publish(
event: "decidim.events.meetings.meeting_waitlist_added",
event_class: Decidim::Meetings::MeetingRegistrationNotificationEvent,
resource: meeting,
affected_users: [user]
)
end

def answer_questionnaire
return unless questionnaire?

Decidim::Forms::AnswerQuestionnaire.call(registration_form, user, meeting.questionnaire) do
on(:ok) do
return :valid
end

on(:invalid) do
return :invalid
end
end
end

def questionnaire?
registration_form.model_name == "questionnaire"
end

def follow_meeting
Decidim::CreateFollow.call(follow_form, user)
end

def follow_form
Decidim::FollowForm
.from_params(followable_gid: meeting.to_signed_global_id.to_s)
.with_context(current_user: user)
end
end
end
end
25 changes: 25 additions & 0 deletions decidim-meetings/app/commands/decidim/meetings/leave_meeting.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def call
destroy_registration
destroy_questionnaire_answers
decrement_score
move_from_waitlist!
end
broadcast(:ok)
end
Expand All @@ -50,6 +51,30 @@ def destroy_questionnaire_answers
def decrement_score
Decidim::Gamification.decrement_score(@user, :attended_meetings)
end

def send_email_confirmation(registration, user, meeting)
Decidim::Meetings::RegistrationMailer.confirmation(user, meeting, registration).deliver_later
end

def move_from_waitlist!
return unless @meeting.remaining_slots.positive?

on_waiting_list_user = @meeting.registrations.on_waiting_list.order(:created_at).first
return unless on_waiting_list_user

on_waiting_list_user.update!(status: :registered)
send_email_confirmation(on_waiting_list_user, on_waiting_list_user.user, @meeting)

Decidim::EventsManager.publish(
event: "decidim.events.meetings.meeting_registration_confirmed",
event_class: Decidim::Meetings::MeetingRegistrationNotificationEvent,
resource: @meeting,
affected_users: [on_waiting_list_user.user],
extra: {
registration_code: on_waiting_list_user.code
}
)
end
end
end
end
Loading
Loading