Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add conference registration types CRUD + Public view #4408

Merged
merged 13 commits into from Nov 7, 2018
8 changes: 2 additions & 6 deletions CHANGELOG.md
Expand Up @@ -34,20 +34,16 @@ end

**Added**:

- **decidim-conferences**: Add conference registration types. [\#4408](https://github.com/decidim/decidim/pull/4408)
- **decidim-forms**: Create a new gem to hold reusable surveys logic [\#3877](https://github.com/decidim/decidim/pull/3877)
- **decidim-verifications**: Add SMS verification workflow [\#4429](https://github.com/decidim/decidim/pull/4429)
- **decidim-proposals**: Split & merge proposals to the same component [\#4415](https://github.com/decidim/decidim/pull/4415)
- **decidim-meetings**: Add a meetings calendar at organization and component levels [\#4376](https://github.com/decidim/decidim/pull/4376)

**Changed**:

- **decidim-surveys**: Extract surveys logic to decidim-forms [\#3877](https://github.com/decidim/decidim/pull/3877)

**Added**:

**Changed**:

- **decidim-core**: Improve static pages layout and make them groupable by topic. [\#4338](https://github.com/decidim/decidim/pull/4338)
- **decidim-surveys**: Extract surveys logic to decidim-forms [\#3877](https://github.com/decidim/decidim/pull/3877)

**Fixed**:

Expand Down
1 change: 1 addition & 0 deletions config/i18n-tasks.yml
Expand Up @@ -172,6 +172,7 @@ ignore_unused:
- decidim.conferences.conference_speaker.*
- decidim.conferences.statistics.*
- decidim.conferences.show.*
- decidim.conferences.models.conference_registration.fields.states.*
- decidim.proposals.admin.participatory_texts.sections.*
- decidim.gamification.badges.*
- decidim.surveys.surveys.answer.*
Expand Down
@@ -1,9 +1,10 @@
<% if model.registrations_enabled? %>
<% if model.has_registration_for? current_user %>
<% if conference.registrations_enabled? %>
<% if conference.has_registration_for_user_and_registration_type?(current_user, model) %>
<% if allowed? %>
<%= button_to conference_conference_registration_path(model),
<%= button_to conference_registration_type_conference_registration_path(conference, model),
method: :delete,
class: "#{button_classes} secondary light",
style: "margin-bottom: 0;",
data: { disable: true } do %>
<%= icon("check", class: "icon--small") %>
<%= t("going", scope: "decidim.conferences.conference.show") %>
Expand All @@ -14,12 +15,10 @@
<% if allowed? %>
<%= button_to i18n_join_text, "",
class: button_classes,
disabled: !model.has_available_slots?,
disabled: !conference.has_available_slots? || conference.has_registration_for?(current_user),
style: "margin-bottom: 0;",
onclick: "event.preventDefault()",
data: { open: current_user.present? ? "conference-registration-confirm-#{model.id}" : "loginModal" } %>
<% end %>
<% end %>
<% if shows_remaining_slots? %>
<span><%= t("remaining_slots", scope: "decidim.conferences.conference.show", count: model.remaining_slots) %></span>
<% end %>
<% end %>
@@ -1,12 +1,12 @@
<div class="reveal" data-reveal id="conference-registration-confirm-<%= model.id %>">
<div class="row">
<div class="columns medium-10 medium-offset-1 help-text">
<%= decidim_sanitize translated_attribute(model.registration_terms) %>
<%= decidim_sanitize translated_attribute(conference.registration_terms) %>
</div>
</div>
<div class="row">
<div class="columns medium-8 medium-offset-2">
<%= button_to t("confirm", scope: "decidim.conferences.conference.registration_confirm"), conference_conference_registration_path(model), class: "button expanded", data: { disable: true } %>
<%= button_to t("confirm", scope: "decidim.conferences.conference.registration_confirm"), conference_registration_type_conference_registration_path(conference, model), class: "button expanded", data: { disable: true } %>
</div>
</div>
<div class="text-center">
Expand Down
@@ -0,0 +1,16 @@
<div class="conference-registration card__block" id="registration-type-<%= model.id %>">
<div class="row flex--cc">
<div class="columns medium-8">
<div class="registration__text">
<strong><%= title %></strong>
<span> <%= description %></span>
</div>
</div>
<div class="columns medium-4">
<div class="registration__buttons">
<button type="button" class="small-5 small"><strong><%= price %></strong></button>
<%= render :join_conference %>
</div>
</div>
</div>
</div>
Expand Up @@ -2,11 +2,12 @@

module Decidim
module Conferences
# This cell renders the button to join a conference.
class JoinConferenceButtonCell < Decidim::ViewModel
include Decidim::LayoutHelper
# This cell renders the media link card for an instance of a RegistrationType
class RegistrationTypeCell < Decidim::ViewModel
include ActionView::Helpers::NumberHelper
include Decidim::SanitizeHelper
include Decidim::Conferences::Engine.routes.url_helpers
include Decidim::LayoutHelper

def show
render
Expand All @@ -16,25 +17,32 @@ def show

delegate :current_user, to: :controller, prefix: false

def allowed?
options[:allowed]
def title
translated_attribute model.title
end

def description
translated_attribute model.description
end

def price
number_to_currency(model.price, locale: I18n.locale, unit: Decidim.currency_unit)
end

def shows_remaining_slots?
options[:show_remaining_slots] && model.available_slots.positive?
def allowed?
options[:allowed]
end

def button_classes
return "button expanded button--sc" if big_button?
"button card__button button--sc small"
"button button--sc small"
end

def big_button?
options[:big_button]
def conference
model.conference
end

def i18n_join_text
return I18n.t("join", scope: "decidim.conferences.conference.show") if model.has_available_slots?
return I18n.t("join", scope: "decidim.conferences.conference.show") if conference.has_available_slots?
I18n.t("no_slots_available", scope: "decidim.conferences.conference.show")
end
end
Expand Down
@@ -0,0 +1,62 @@
# frozen_string_literal: true

module Decidim
module Conferences
module Admin
# This command is executed when the user joins a conference.
class ConfirmConferenceRegistration < Rectify::Command
# Initializes a JoinConference Command.
#
# conference_registration - The registration to be confirmed
def initialize(conference_registration, current_user)
@conference_registration = conference_registration
@current_user = current_user
end

# Creates a conference registration if the conference has registrations enabled
# and there are available slots.
#
# Broadcasts :ok if successful, :invalid otherwise.
def call
@conference_registration.with_lock do
return broadcast(:invalid) unless can_join_conference?
confirm_registration
send_email_confirmation
end
broadcast(:ok)
end

private

attr_reader :conference, :user

def confirm_registration
extra_info = {
resource: {
title: @conference_registration.conference.title
}
}

Decidim.traceability.perform_action!(
"confirm",
@conference_registration,
@current_user,
extra_info
) do
@conference_registration.update!(confirmed_at: Time.current)
@conference_registration
end
end

def can_join_conference?
@conference_registration.conference.registrations_enabled? && @conference_registration.conference.has_available_slots?
end

def send_email_confirmation
Decidim::Conferences::ConferenceRegistrationMailer.confirmation(@conference_registration.user,
@conference_registration.conference, @conference_registration.registration_type).deliver_later
end
end
end
end
end
@@ -0,0 +1,77 @@
# frozen_string_literal: true

module Decidim
module Conferences
module Admin
# A command with all the business logic when creating a new registration type
# in the system.
class CreateRegistrationType < Rectify::Command
# Public: Initializes the command.
#
# form - A form object with the params.
# current_user - The current user hwo do the action of create
# conference - The Conference that will hold the speaker
def initialize(form, current_user, conference)
@form = form
@current_user = current_user
@conference = conference
end

# Executes the command. Broadcasts these events:
#
# - :ok when everything is valid.
# - :invalid if the form wasn't valid and we couldn't proceed.
#
# Returns nothing.
def call
return broadcast(:invalid) if form.invalid?

transaction do
create_registration_type!
link_meetings(@registration_type)
end

broadcast(:ok)
end

private

attr_reader :form, :conference, :current_user

def create_registration_type!
log_info = {
resource: {
title: form.title
},
participatory_space: {
title: conference.title
}
}

@registration_type = Decidim.traceability.create!(
Decidim::Conferences::RegistrationType,
form.current_user,
form.attributes.slice(
:title,
:description,
:price,
:weight
).merge(
conference: conference
),
log_info
)
end

def conference_meetings(registration_type)
meeting_components = registration_type.conference.components.where(manifest_name: "meetings")
Decidim::ConferenceMeeting.where(component: meeting_components).where(id: @form.attributes[:conference_meeting_ids])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's a Decidim::ConferenceMeeting? Shouldn't it be scoped to Decidim::Conferences?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe yes, but 'Decidim::ConferenceMeeting' is already in master. If 'ConferenceMeeting' should be scoped to 'Decidim::Conferences', in my opinion is out of this scope and it will be better to do in another PR.
What you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fair, let's do it in another PR!

end

def link_meetings(registration_type)
registration_type.conference_meetings = conference_meetings(registration_type)
end
end
end
end
end
@@ -0,0 +1,56 @@
# frozen_string_literal: true

module Decidim
module Conferences
module Admin
# A command with all the business logic when destroying a conference
# registration type in the system.
class DestroyRegistrationType < Rectify::Command
# Public: Initializes the command.
#
# registration_type - the Partner to destroy
# current_user - the user performing this action
def initialize(registration_type, current_user)
@registration_type = registration_type
@current_user = current_user
end

# Executes the command. Broadcasts these events:
#
# - :ok when everything is valid.
# - :invalid if the form wasn't valid and we couldn't proceed.
#
# Returns nothing.
def call
destroy_registration_type!
broadcast(:ok)
end

private

attr_reader :registration_type, :current_user

def destroy_registration_type!
log_info = {
resource: {
title: registration_type.title
},
participatory_space: {
title: registration_type.conference.title
}
}

Decidim.traceability.perform_action!(
"delete",
registration_type,
current_user,
log_info
) do
registration_type.destroy!
registration_type
end
end
end
end
end
end
Expand Up @@ -59,6 +59,7 @@ def create_invitation!
{
user: user,
conference: conference,
registration_type: form.registration_type,
sent_at: Time.current
},
log_info
Expand All @@ -74,7 +75,7 @@ def invite_user
if user.invited_to_sign_up?
invite_user_to_sign_up
else
InviteJoinConferenceMailer.invite(user, conference, invited_by).deliver_later
InviteJoinConferenceMailer.invite(user, conference, form.registration_type, invited_by).deliver_later
end
else
user.name = form.name
Expand Down