decidim-meetings 0.30.5 → 0.31.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/cells/decidim/meetings/cancel_registration_meeting_button/cancelation_modal.erb +7 -4
- data/app/cells/decidim/meetings/cancel_registration_meeting_button/show.erb +1 -1
- data/app/cells/decidim/meetings/cancel_registration_meeting_button_cell.rb +36 -0
- data/app/cells/decidim/meetings/dates_and_map_cell.rb +1 -1
- data/app/cells/decidim/meetings/join_meeting_button/registration_modal.erb +4 -5
- data/app/cells/decidim/meetings/join_meeting_button/show.erb +25 -28
- data/app/cells/decidim/meetings/join_meeting_button/waitlist_button.erb +22 -0
- data/app/cells/decidim/meetings/join_meeting_button_cell.rb +28 -0
- data/app/cells/decidim/meetings/meeting_cell.rb +6 -1
- data/app/cells/decidim/meetings/meeting_s_cell.rb +15 -0
- data/app/cells/decidim/meetings/question_responses/show.erb +7 -7
- data/app/cells/decidim/meetings/question_responses_cell.rb +28 -28
- data/app/commands/decidim/meetings/admin/copy_meeting.rb +5 -2
- data/app/commands/decidim/meetings/admin/create_agenda.rb +6 -2
- data/app/commands/decidim/meetings/admin/create_meeting.rb +7 -3
- data/app/commands/decidim/meetings/admin/mark_as_attendee.rb +44 -0
- data/app/commands/decidim/meetings/admin/publish_meeting.rb +2 -1
- data/app/commands/decidim/meetings/admin/update_agenda.rb +6 -2
- data/app/commands/decidim/meetings/admin/update_meeting.rb +15 -6
- data/app/commands/decidim/meetings/admin/update_questionnaire.rb +4 -4
- data/app/commands/decidim/meetings/admin/update_registrations.rb +19 -7
- data/app/commands/decidim/meetings/create_meeting.rb +2 -3
- data/app/commands/decidim/meetings/{create_answer.rb → create_response.rb} +11 -11
- data/app/commands/decidim/meetings/join_meeting.rb +4 -6
- data/app/commands/decidim/meetings/join_waitlist.rb +53 -0
- data/app/commands/decidim/meetings/leave_meeting.rb +14 -5
- data/app/commands/decidim/meetings/update_meeting.rb +1 -2
- data/app/controllers/concerns/decidim/meetings/admin/filterable.rb +1 -1
- data/app/controllers/decidim/meetings/admin/agenda_controller.rb +2 -2
- data/app/controllers/decidim/meetings/admin/invites_controller.rb +1 -1
- data/app/controllers/decidim/meetings/admin/meeting_closes_controller.rb +1 -1
- data/app/controllers/decidim/meetings/admin/meeting_copies_controller.rb +1 -1
- data/app/controllers/decidim/meetings/admin/meetings_controller.rb +4 -4
- data/app/controllers/decidim/meetings/admin/meetings_poll_controller.rb +10 -10
- data/app/controllers/decidim/meetings/admin/registrations_attendees_controller.rb +79 -0
- data/app/controllers/decidim/meetings/admin/registrations_controller.rb +1 -22
- data/app/controllers/decidim/meetings/meeting_closes_controller.rb +1 -1
- data/app/controllers/decidim/meetings/meetings_controller.rb +11 -44
- data/app/controllers/decidim/meetings/polls/{answers_controller.rb → responses_controller.rb} +7 -7
- data/app/controllers/decidim/meetings/registrations_controller.rb +39 -12
- data/app/events/decidim/meetings/registration_marked_as_attendee_event.rb +9 -0
- data/app/events/decidim/meetings/upcoming_meeting_event.rb +41 -0
- data/app/events/decidim/meetings/update_meeting_event.rb +25 -0
- data/app/forms/decidim/meetings/admin/close_meeting_form.rb +2 -1
- data/app/forms/decidim/meetings/admin/meeting_agenda_items_form.rb +4 -0
- data/app/forms/decidim/meetings/admin/meeting_form.rb +28 -3
- data/app/forms/decidim/meetings/admin/question_form.rb +3 -3
- data/app/forms/decidim/meetings/admin/{answer_option_form.rb → response_option_form.rb} +3 -3
- data/app/forms/decidim/meetings/admin/validate_registration_code_form.rb +1 -1
- data/app/forms/decidim/meetings/base_meeting_form.rb +0 -2
- data/app/forms/decidim/meetings/close_meeting_form.rb +2 -1
- data/app/forms/decidim/meetings/join_meeting_form.rb +0 -1
- data/app/forms/decidim/meetings/meeting_form.rb +3 -2
- data/app/forms/decidim/meetings/response_choice_form.rb +14 -0
- data/app/forms/decidim/meetings/{answer_form.rb → response_form.rb} +7 -7
- data/app/helpers/decidim/meetings/application_helper.rb +0 -1
- data/app/helpers/decidim/meetings/meetings_helper.rb +14 -5
- data/app/jobs/decidim/meetings/promote_from_waitlist_job.rb +63 -0
- data/app/jobs/decidim/meetings/upcoming_meeting_notification_job.rb +1 -1
- data/app/mailers/decidim/meetings/registration_mailer.rb +13 -0
- data/app/models/decidim/meetings/agenda_item.rb +5 -0
- data/app/models/decidim/meetings/meeting.rb +15 -12
- data/app/models/decidim/meetings/question.rb +12 -12
- data/app/models/decidim/meetings/questionnaire.rb +1 -1
- data/app/models/decidim/meetings/registration.rb +19 -7
- data/app/models/decidim/meetings/{answer.rb → response.rb} +6 -6
- data/app/models/decidim/meetings/response_choice.rb +15 -0
- data/app/models/decidim/meetings/{answer_option.rb → response_option.rb} +5 -5
- data/app/packs/src/decidim/meetings/admin/destroy_meeting_alert.js +1 -1
- data/app/packs/src/decidim/meetings/admin/meetings_components_form.js +1 -8
- data/app/packs/src/decidim/meetings/admin/meetings_form.js +1 -1
- data/app/packs/src/decidim/meetings/admin/registrations_form.js +1 -1
- data/app/packs/src/decidim/meetings/admin/registrations_invite_form.js +1 -1
- data/app/packs/src/decidim/meetings/meetings_form.js +1 -1
- data/app/packs/src/decidim/meetings/meetings_polls.js +1 -1
- data/app/packs/src/decidim/meetings/poll.component.js +5 -5
- data/app/packs/stylesheets/decidim/meetings/_item.scss +5 -1
- data/app/packs/stylesheets/decidim/meetings/meetings.scss +4 -4
- data/app/permissions/decidim/meetings/admin/agenda_permissions.rb +34 -0
- data/app/permissions/decidim/meetings/admin/meeting_permissions.rb +44 -0
- data/app/permissions/decidim/meetings/admin/permissions.rb +5 -66
- data/app/permissions/decidim/meetings/admin/questionnaire_permissions.rb +30 -0
- data/app/permissions/decidim/meetings/meeting_permissions.rb +90 -0
- data/app/permissions/decidim/meetings/permissions.rb +9 -105
- data/app/presenters/decidim/meetings/admin_log/value_types/meeting_title_description_presenter.rb +1 -1
- data/app/presenters/decidim/meetings/agenda_item_presenter.rb +29 -0
- data/app/presenters/decidim/meetings/meeting_presenter.rb +12 -15
- data/app/presenters/decidim/meetings/registration_presenter.rb +24 -0
- data/app/queries/decidim/meetings/{questionnaire_user_answers.rb → questionnaire_user_responses.rb} +5 -5
- data/app/serializers/decidim/meetings/registration_serializer.rb +5 -6
- data/app/services/decidim/meetings/diff_renderer.rb +0 -1
- data/app/views/decidim/meetings/_calendar_modal.html.erb +1 -0
- data/app/views/decidim/meetings/admin/agenda/_agenda_item_fields.html.erb +1 -1
- data/app/views/decidim/meetings/admin/invites/_form.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meeting_closes/_form.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meetings/_form.html.erb +3 -2
- data/app/views/decidim/meetings/admin/meetings/_linked_spaces.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meetings/_meeting-tr.html.erb +9 -14
- data/app/views/decidim/meetings/admin/meetings/_meeting_actions.html.erb +200 -69
- data/app/views/decidim/meetings/admin/meetings/_meetings-thead.html.erb +0 -3
- data/app/views/decidim/meetings/admin/meetings/_reminders.html.erb +19 -0
- data/app/views/decidim/meetings/admin/meetings/_services.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meetings/index.html.erb +7 -5
- data/app/views/decidim/meetings/admin/meetings/manage_trash.html.erb +2 -1
- data/app/views/decidim/meetings/admin/poll/_form.html.erb +9 -9
- data/app/views/decidim/meetings/admin/poll/_question.html.erb +19 -9
- data/app/views/decidim/meetings/admin/poll/_response_option.html.erb +35 -0
- data/app/views/decidim/meetings/admin/poll/_response_option_template.html.erb +7 -0
- data/app/views/decidim/meetings/admin/poll/edit.html.erb +3 -3
- data/app/views/decidim/meetings/admin/registration_form/edit_questions.html.erb +5 -5
- data/app/views/decidim/meetings/admin/registrations/edit.html.erb +19 -39
- data/app/views/decidim/meetings/admin/registrations_attendees/index.html.erb +126 -0
- data/app/views/decidim/meetings/layouts/live_event.html.erb +1 -1
- data/app/views/decidim/meetings/meeting_closes/_form.html.erb +2 -2
- data/app/views/decidim/meetings/meetings/_form.html.erb +2 -11
- data/app/views/decidim/meetings/meetings/_meeting.html.erb +2 -2
- data/app/views/decidim/meetings/meetings/_meeting_actions.html.erb +3 -3
- data/app/views/decidim/meetings/meetings/_meeting_agenda.html.erb +2 -2
- data/app/views/decidim/meetings/meetings/_meeting_aside.html.erb +11 -10
- data/app/views/decidim/meetings/meetings/_meeting_poll_actions.html.erb +3 -3
- data/app/views/decidim/meetings/meetings/_registration_code_modal.html.erb +16 -0
- data/app/views/decidim/meetings/polls/questions/_index_admin.html.erb +1 -1
- data/app/views/decidim/meetings/polls/questions/_published_question.html.erb +5 -5
- data/app/views/decidim/meetings/polls/responses/_multiple_option.html.erb +13 -0
- data/app/views/decidim/meetings/polls/responses/_single_option.html.erb +13 -0
- data/app/views/decidim/meetings/polls/{answers → responses}/admin.html.erb +4 -4
- data/app/views/decidim/meetings/polls/{answers → responses}/index.html.erb +4 -4
- data/app/views/decidim/meetings/registration_mailer/confirmation.html.erb +6 -1
- data/config/assets.rb +2 -2
- data/config/locales/ar.yml +1 -26
- data/config/locales/bg.yml +2 -32
- data/config/locales/ca-IT.yml +87 -44
- data/config/locales/ca.yml +87 -44
- data/config/locales/cs.yml +71 -46
- data/config/locales/de.yml +89 -46
- data/config/locales/el.yml +1 -25
- data/config/locales/en.yml +89 -46
- data/config/locales/es-MX.yml +87 -44
- data/config/locales/es-PY.yml +87 -44
- data/config/locales/es.yml +87 -44
- data/config/locales/eu.yml +114 -71
- data/config/locales/fi-plain.yml +86 -43
- data/config/locales/fi.yml +85 -42
- data/config/locales/fr-CA.yml +79 -41
- data/config/locales/fr.yml +79 -41
- data/config/locales/ga-IE.yml +1 -8
- data/config/locales/gl.yml +1 -19
- data/config/locales/hu.yml +1 -23
- data/config/locales/id-ID.yml +0 -16
- data/config/locales/is-IS.yml +0 -10
- data/config/locales/it.yml +1 -38
- data/config/locales/ja.yml +88 -45
- data/config/locales/lb.yml +1 -16
- data/config/locales/lt.yml +1 -28
- data/config/locales/lv.yml +0 -16
- data/config/locales/nl.yml +1 -26
- data/config/locales/no.yml +1 -29
- data/config/locales/pl.yml +2 -32
- data/config/locales/pt-BR.yml +13 -205
- data/config/locales/pt.yml +1 -29
- data/config/locales/ro-RO.yml +56 -32
- data/config/locales/ru.yml +0 -16
- data/config/locales/sk.yml +0 -16
- data/config/locales/sl.yml +0 -4
- data/config/locales/sv.yml +89 -46
- data/config/locales/tr-TR.yml +0 -20
- data/config/locales/uk.yml +0 -12
- data/config/locales/zh-CN.yml +0 -19
- data/config/locales/zh-TW.yml +1 -26
- data/db/migrate/20181107175558_add_questionnaire_to_existing_meetings.rb +8 -2
- data/db/migrate/20200827153856_add_commentable_counter_cache_to_meetings.rb +8 -2
- data/db/migrate/20201016065302_fix_meetings_registration_terms.rb +8 -2
- data/db/migrate/20210310120731_add_followable_counter_cache_to_meetings.rb +8 -2
- data/db/migrate/20250317103343_rename_answer_to_response_in_decidim_meetings.rb +18 -0
- data/db/migrate/20250403094034_add_reminder_customization_to_decidim_meetings.rb +9 -0
- data/db/migrate/20250408071941_add_status_to_registrations_to_decidim_meetings_registrations.rb +8 -0
- data/lib/decidim/api/agenda_item_type.rb +6 -2
- data/lib/decidim/api/agenda_type.rb +6 -2
- data/lib/decidim/api/linked_resources_interface.rb +1 -1
- data/lib/decidim/api/meeting_type.rb +20 -10
- data/lib/decidim/api/service_type.rb +3 -0
- data/lib/decidim/meetings/admin_engine.rb +9 -1
- data/lib/decidim/meetings/component.rb +29 -20
- data/lib/decidim/meetings/engine.rb +6 -21
- data/lib/decidim/meetings/meeting_serializer.rb +1 -2
- data/lib/decidim/meetings/schema_org_event_meeting_serializer.rb +0 -10
- data/lib/decidim/meetings/seeds.rb +4 -13
- data/lib/decidim/meetings/test/factories.rb +10 -16
- data/lib/decidim/meetings/user_responses_serializer.rb +47 -0
- data/lib/decidim/meetings/version.rb +1 -1
- data/lib/decidim/meetings.rb +7 -9
- metadata +50 -35
- data/app/cells/decidim/meetings/attending_organizations_list_cell.rb +0 -32
- data/app/forms/decidim/meetings/answer_choice_form.rb +0 -14
- data/app/models/decidim/meetings/answer_choice.rb +0 -15
- data/app/queries/decidim/meetings/metrics/meeting_followers_metric_measure.rb +0 -31
- data/app/queries/decidim/meetings/metrics/meetings_metric_manage.rb +0 -48
- data/app/views/decidim/meetings/admin/poll/_answer_option.html.erb +0 -35
- data/app/views/decidim/meetings/admin/poll/_answer_option_template.html.erb +0 -7
- data/app/views/decidim/meetings/polls/answers/_multiple_option.html.erb +0 -13
- data/app/views/decidim/meetings/polls/answers/_single_option.html.erb +0 -13
- data/lib/decidim/meetings/download_your_data_user_answers_serializer.rb +0 -39
- data/lib/decidim/meetings/user_answers_serializer.rb +0 -47
- /data/app/views/decidim/meetings/polls/{answers → responses}/create.js.erb +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "rqrcode"
|
|
4
|
+
|
|
3
5
|
module Decidim
|
|
4
6
|
module Meetings
|
|
5
7
|
# Exposes the meeting resource so users can view them
|
|
@@ -16,7 +18,7 @@ module Decidim
|
|
|
16
18
|
include Decidim::AttachmentsHelper
|
|
17
19
|
include Decidim::SanitizeHelper
|
|
18
20
|
|
|
19
|
-
helper_method :meetings, :meeting, :registration, :search, :tab_panel_items
|
|
21
|
+
helper_method :meetings, :meeting, :registration, :registration_qr_code_image, :search, :tab_panel_items
|
|
20
22
|
|
|
21
23
|
before_action :add_additional_csp_directives, only: [:show]
|
|
22
24
|
|
|
@@ -39,7 +41,7 @@ module Decidim
|
|
|
39
41
|
|
|
40
42
|
on(:invalid) do
|
|
41
43
|
flash.now[:alert] = I18n.t("meetings.create.invalid", scope: "decidim.meetings")
|
|
42
|
-
render action: "new"
|
|
44
|
+
render action: "new", status: :unprocessable_entity
|
|
43
45
|
end
|
|
44
46
|
end
|
|
45
47
|
end
|
|
@@ -86,7 +88,7 @@ module Decidim
|
|
|
86
88
|
|
|
87
89
|
on(:invalid) do
|
|
88
90
|
flash.now[:alert] = I18n.t("meetings.update.invalid", scope: "decidim.meetings")
|
|
89
|
-
render :edit
|
|
91
|
+
render :edit, status: :unprocessable_entity
|
|
90
92
|
end
|
|
91
93
|
end
|
|
92
94
|
end
|
|
@@ -121,6 +123,12 @@ module Decidim
|
|
|
121
123
|
@registration ||= meeting.registrations.find_by(user: current_user)
|
|
122
124
|
end
|
|
123
125
|
|
|
126
|
+
def registration_qr_code_image
|
|
127
|
+
Base64.encode64(
|
|
128
|
+
RQRCode::QRCode.new(registration.validation_code_short_link.short_url).as_png(size: 500).to_s
|
|
129
|
+
).gsub("\n", "")
|
|
130
|
+
end
|
|
131
|
+
|
|
124
132
|
def search_collection
|
|
125
133
|
Meeting
|
|
126
134
|
.where(component: current_component)
|
|
@@ -151,14 +159,6 @@ module Decidim
|
|
|
151
159
|
method: :cell,
|
|
152
160
|
args: ["decidim/meetings/public_participants_list", meeting]
|
|
153
161
|
},
|
|
154
|
-
{
|
|
155
|
-
enabled: !meeting.closed? && meeting.user_group_registrations.any?,
|
|
156
|
-
id: "organizations",
|
|
157
|
-
text: t("attending_organizations", scope: "decidim.meetings.public_participants_list"),
|
|
158
|
-
icon: "community-line",
|
|
159
|
-
method: :cell,
|
|
160
|
-
args: ["decidim/meetings/attending_organizations_list", meeting]
|
|
161
|
-
},
|
|
162
162
|
{
|
|
163
163
|
enabled: meeting.linked_resources(:proposals, "proposals_from_meeting").present?,
|
|
164
164
|
id: "included_proposals",
|
|
@@ -201,39 +201,6 @@ module Decidim
|
|
|
201
201
|
rescue NameError, LoadError
|
|
202
202
|
nil
|
|
203
203
|
end
|
|
204
|
-
|
|
205
|
-
def conference_context?
|
|
206
|
-
return false unless Decidim.module_installed?(:conferences)
|
|
207
|
-
return false if current_participatory_space.blank?
|
|
208
|
-
|
|
209
|
-
current_participatory_space.is_a?(Decidim::Conference)
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
def set_component_breadcrumb_item
|
|
213
|
-
super
|
|
214
|
-
return {} if meeting.blank?
|
|
215
|
-
|
|
216
|
-
breadcrumb = {
|
|
217
|
-
label: translated_attribute(meeting.title),
|
|
218
|
-
url: Decidim::EngineRouter.main_proxy(current_component).meeting_path(meeting),
|
|
219
|
-
active: false
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
# If this meeting is being accessed from within a conference program context,
|
|
223
|
-
# add program breadcrumb to maintain proper navigation hierarchy
|
|
224
|
-
if conference_context?
|
|
225
|
-
program_path = decidim_conferences.conference_conference_program_path(current_participatory_space, current_component)
|
|
226
|
-
|
|
227
|
-
context_breadcrumb_items << {
|
|
228
|
-
label: t("conference_program.index.title", scope: "decidim"),
|
|
229
|
-
url: program_path,
|
|
230
|
-
active: false,
|
|
231
|
-
resource: current_component
|
|
232
|
-
}
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
context_breadcrumb_items << breadcrumb
|
|
236
|
-
end
|
|
237
204
|
end
|
|
238
205
|
end
|
|
239
206
|
end
|
data/app/controllers/decidim/meetings/polls/{answers_controller.rb → responses_controller.rb}
RENAMED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Decidim
|
|
4
4
|
module Meetings
|
|
5
5
|
module Polls
|
|
6
|
-
class
|
|
6
|
+
class ResponsesController < Decidim::Meetings::ApplicationController
|
|
7
7
|
include Decidim::Meetings::PollsResources
|
|
8
8
|
include FormFactory
|
|
9
9
|
|
|
@@ -18,10 +18,10 @@ module Decidim
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def create
|
|
21
|
-
enforce_permission_to(:create, :
|
|
22
|
-
@form = form(
|
|
21
|
+
enforce_permission_to(:create, :response, question:)
|
|
22
|
+
@form = form(ResponseForm).from_params(params.merge(question:, current_user:))
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
CreateResponse.call(@form, questionnaire) do
|
|
25
25
|
# Both :ok and :invalid render the same template, because
|
|
26
26
|
# validation errors are displayed in the template
|
|
27
27
|
respond_to do |format|
|
|
@@ -33,11 +33,11 @@ module Decidim
|
|
|
33
33
|
private
|
|
34
34
|
|
|
35
35
|
def question
|
|
36
|
-
@question ||= questionnaire.questions.find(
|
|
36
|
+
@question ||= questionnaire.questions.find(response_params[:question_id]) if questionnaire
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
def
|
|
40
|
-
params.require(:
|
|
39
|
+
def response_params
|
|
40
|
+
params.require(:response).permit(:question_id, choices: [:body, :response_option_id])
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
end
|
|
@@ -6,25 +6,28 @@ module Decidim
|
|
|
6
6
|
class RegistrationsController < Decidim::Meetings::ApplicationController
|
|
7
7
|
include Decidim::Forms::Concerns::HasQuestionnaire
|
|
8
8
|
|
|
9
|
-
def
|
|
9
|
+
def respond
|
|
10
10
|
enforce_permission_to(:join, :meeting, meeting:)
|
|
11
11
|
|
|
12
12
|
@form = form(Decidim::Forms::QuestionnaireForm).from_params(params, session_token:)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
command = should_join_waitlist? ? JoinWaitlist : JoinMeeting
|
|
15
|
+
joining_waitlist = should_join_waitlist?
|
|
16
|
+
|
|
17
|
+
command.call(meeting, @form) do
|
|
15
18
|
on(:ok) do
|
|
16
|
-
flash[:notice] = I18n.t("registrations.create.success", scope: "decidim.meetings")
|
|
17
|
-
redirect_to
|
|
19
|
+
flash[:notice] = I18n.t(joining_waitlist ? "registrations.waitlist.success" : "registrations.create.success", scope: "decidim.meetings")
|
|
20
|
+
redirect_to after_response_path
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
on(:invalid) do
|
|
21
|
-
flash.now[:alert] = I18n.t("registrations.create.invalid", scope: "decidim.meetings")
|
|
22
|
-
render template: "decidim/forms/questionnaires/show"
|
|
24
|
+
flash.now[:alert] = I18n.t(joining_waitlist ? "registrations.waitlist.invalid" : "registrations.create.invalid", scope: "decidim.meetings")
|
|
25
|
+
render template: "decidim/forms/questionnaires/show", status: :unprocessable_entity
|
|
23
26
|
end
|
|
24
27
|
|
|
25
28
|
on(:invalid_form) do
|
|
26
|
-
flash.now[:alert] = I18n.t("
|
|
27
|
-
render template: "decidim/forms/questionnaires/show"
|
|
29
|
+
flash.now[:alert] = I18n.t("response.invalid", scope: i18n_flashes_scope)
|
|
30
|
+
render template: "decidim/forms/questionnaires/show", status: :unprocessable_entity
|
|
28
31
|
end
|
|
29
32
|
end
|
|
30
33
|
end
|
|
@@ -47,6 +50,24 @@ module Decidim
|
|
|
47
50
|
end
|
|
48
51
|
end
|
|
49
52
|
|
|
53
|
+
def join_waitlist
|
|
54
|
+
enforce_permission_to(:join_waitlist, :meeting, meeting:)
|
|
55
|
+
|
|
56
|
+
@form = JoinMeetingForm.from_params(params).with_context(current_user:)
|
|
57
|
+
|
|
58
|
+
JoinWaitlist.call(meeting, @form) do
|
|
59
|
+
on(:ok) do
|
|
60
|
+
flash[:notice] = I18n.t("registrations.waitlist.success", scope: "decidim.meetings")
|
|
61
|
+
redirect_after_path
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
on(:invalid) do
|
|
65
|
+
flash.now[:alert] = I18n.t("registrations.waitlist.invalid", scope: "decidim.meetings")
|
|
66
|
+
redirect_after_path
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
50
71
|
def destroy
|
|
51
72
|
enforce_permission_to(:leave, :meeting, meeting:)
|
|
52
73
|
|
|
@@ -79,18 +100,24 @@ module Decidim
|
|
|
79
100
|
end
|
|
80
101
|
end
|
|
81
102
|
|
|
82
|
-
def
|
|
83
|
-
meeting.
|
|
103
|
+
def should_join_waitlist?
|
|
104
|
+
meeting.waitlist_enabled? && !meeting.has_available_slots? && !meeting.has_registration_for?(current_user)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def allow_responses?
|
|
108
|
+
return false unless meeting.registrations_enabled? && meeting.registration_form_enabled?
|
|
109
|
+
|
|
110
|
+
meeting.has_available_slots? || should_join_waitlist?
|
|
84
111
|
end
|
|
85
112
|
|
|
86
|
-
def
|
|
113
|
+
def after_response_path
|
|
87
114
|
meeting_path(meeting)
|
|
88
115
|
end
|
|
89
116
|
|
|
90
117
|
# You can implement this method in your controller to change the URL
|
|
91
118
|
# where the questionnaire will be submitted.
|
|
92
119
|
def update_url
|
|
93
|
-
|
|
120
|
+
respond_meeting_registration_path(meeting_id: meeting.id)
|
|
94
121
|
end
|
|
95
122
|
|
|
96
123
|
def questionnaire_for
|
|
@@ -4,6 +4,47 @@ module Decidim
|
|
|
4
4
|
module Meetings
|
|
5
5
|
class UpcomingMeetingEvent < Decidim::Events::SimpleEvent
|
|
6
6
|
include Decidim::Meetings::MeetingEvent
|
|
7
|
+
|
|
8
|
+
i18n_attributes :reminders_before_hours
|
|
9
|
+
|
|
10
|
+
def email_intro
|
|
11
|
+
(custom_message.presence || default_email_intro).to_s.html_safe
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def i18n_options
|
|
15
|
+
{
|
|
16
|
+
resource_title:,
|
|
17
|
+
resource_path:,
|
|
18
|
+
resource_url:,
|
|
19
|
+
participatory_space_url:,
|
|
20
|
+
participatory_space_title:,
|
|
21
|
+
reminders_before_hours: resource.send_reminders_before_hours,
|
|
22
|
+
scope: event_name
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def reminder_message
|
|
29
|
+
translated_attribute(resource.reminder_message_custom_content)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def default_email_intro
|
|
33
|
+
I18n.t("email_intro", **i18n_options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def custom_message
|
|
37
|
+
template = translated_attribute(resource.reminder_message_custom_content)
|
|
38
|
+
interpolate_custom_message(template).html_safe
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def interpolate_custom_message(template)
|
|
42
|
+
title = translated_attribute(resource.title).to_s
|
|
43
|
+
hours = resource.send_reminders_before_hours.to_s
|
|
44
|
+
template
|
|
45
|
+
.gsub("{{meeting_title}}", title)
|
|
46
|
+
.gsub("{{before_hours}}", hours)
|
|
47
|
+
end
|
|
7
48
|
end
|
|
8
49
|
end
|
|
9
50
|
end
|
|
@@ -4,6 +4,31 @@ module Decidim
|
|
|
4
4
|
module Meetings
|
|
5
5
|
class UpdateMeetingEvent < Decidim::Events::SimpleEvent
|
|
6
6
|
include Decidim::Meetings::MeetingEvent
|
|
7
|
+
|
|
8
|
+
i18n_attributes :changed_fields
|
|
9
|
+
|
|
10
|
+
def notification_title
|
|
11
|
+
I18n.t(
|
|
12
|
+
"notification_title",
|
|
13
|
+
scope: i18n_scope,
|
|
14
|
+
changed_fields: changed_fields,
|
|
15
|
+
resource_title: translated_attribute(resource.title),
|
|
16
|
+
resource_path: resource_path
|
|
17
|
+
).html_safe
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def changed_field_keys
|
|
23
|
+
extra[:changed_fields] || []
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def changed_fields
|
|
27
|
+
keys = changed_field_keys
|
|
28
|
+
return "" if keys.empty?
|
|
29
|
+
|
|
30
|
+
keys.map { |key| I18n.t("field_names.#{key}", scope: i18n_scope) }.to_sentence
|
|
31
|
+
end
|
|
7
32
|
end
|
|
8
33
|
end
|
|
9
34
|
end
|
|
@@ -11,7 +11,7 @@ module Decidim
|
|
|
11
11
|
attribute :video_url, String
|
|
12
12
|
attribute :audio_url, String
|
|
13
13
|
attribute :closing_visible, Boolean, default: true
|
|
14
|
-
attribute :attendees_count, Integer
|
|
14
|
+
attribute :attendees_count, Integer
|
|
15
15
|
attribute :contributions_count, Integer, default: 0
|
|
16
16
|
attribute :attending_organizations, String
|
|
17
17
|
attribute :proposal_ids, Array[Integer]
|
|
@@ -27,6 +27,7 @@ module Decidim
|
|
|
27
27
|
# Returns nothing.
|
|
28
28
|
def map_model(model)
|
|
29
29
|
self.proposal_ids = model.linked_resources(:proposals, "proposals_from_meeting").pluck(:id)
|
|
30
|
+
self.attendees_count = model.attendees_count || model.registrations.where.not(validated_at: nil).count
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
def proposals
|
|
@@ -20,23 +20,28 @@ module Decidim
|
|
|
20
20
|
attribute :comments_start_time, Decidim::Attributes::TimeWithZone
|
|
21
21
|
attribute :comments_end_time, Decidim::Attributes::TimeWithZone
|
|
22
22
|
attribute :iframe_access_level, String
|
|
23
|
+
attribute :reminder_enabled, Boolean, default: true
|
|
24
|
+
attribute :send_reminders_before_hours, Integer, default: Decidim::Meetings.upcoming_meeting_notification.in_hours.to_i
|
|
23
25
|
|
|
24
26
|
translatable_attribute :title, String
|
|
25
27
|
translatable_attribute :description, Decidim::Attributes::RichText
|
|
26
28
|
translatable_attribute :location, String
|
|
27
29
|
translatable_attribute :location_hints, String
|
|
30
|
+
translatable_attribute :reminder_message_custom_content, String
|
|
28
31
|
|
|
29
32
|
validates :iframe_embed_type, inclusion: { in: Decidim::Meetings::Meeting.iframe_embed_types }
|
|
30
|
-
validates :title, :description, translatable_presence: true
|
|
31
|
-
validates :title, :description, translated_etiquette: true
|
|
33
|
+
validates :title, :description, translatable_presence: true, translated_etiquette: true
|
|
32
34
|
validates :registration_type, presence: true
|
|
33
35
|
validates :registration_url, presence: true, url: true, if: ->(form) { form.on_different_platform? }
|
|
34
36
|
validates :type_of_meeting, presence: true
|
|
35
|
-
validates :
|
|
37
|
+
validates :address, presence: true, if: ->(form) { form.needs_address? && form.location.values.any?(&:present?) && form.address.blank? }
|
|
38
|
+
validates :location, translatable_presence: true, if: ->(form) { form.needs_address? && form.address.present? }
|
|
39
|
+
validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? && form.needs_address? }
|
|
36
40
|
validates :online_meeting_url, url: true, if: ->(form) { form.online_meeting? || form.hybrid_meeting? }
|
|
37
41
|
validates :comments_start_time, date: { before: :comments_end_time, allow_blank: true, if: proc { |obj| obj.comments_end_time.present? } }
|
|
38
42
|
validates :comments_end_time, date: { after: :comments_start_time, allow_blank: true, if: proc { |obj| obj.comments_start_time.present? } }
|
|
39
43
|
validates :clean_type_of_meeting, presence: true
|
|
44
|
+
validates :send_reminders_before_hours, numericality: { only_integer: true, greater_than: 0 }, if: :reminder_enabled
|
|
40
45
|
validates(
|
|
41
46
|
:iframe_access_level,
|
|
42
47
|
inclusion: { in: Decidim::Meetings::Meeting.iframe_access_levels },
|
|
@@ -83,6 +88,26 @@ module Decidim
|
|
|
83
88
|
type_of_meeting.presence
|
|
84
89
|
end
|
|
85
90
|
|
|
91
|
+
def reminder_message_custom_content
|
|
92
|
+
return unless reminder_enabled
|
|
93
|
+
|
|
94
|
+
return super if super.respond_to?(:values) && super.values.any?(&:present?)
|
|
95
|
+
|
|
96
|
+
@default_reminder_message ||= if current_organization
|
|
97
|
+
current_organization.available_locales.index_with do |locale|
|
|
98
|
+
I18n.t("decidim.events.meetings.upcoming_meeting.default_body", locale:)
|
|
99
|
+
end
|
|
100
|
+
else
|
|
101
|
+
{}
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def send_reminders_before_hours
|
|
106
|
+
return nil unless reminder_enabled
|
|
107
|
+
|
|
108
|
+
super.presence&.to_i
|
|
109
|
+
end
|
|
110
|
+
|
|
86
111
|
def iframe_access_level_select
|
|
87
112
|
Decidim::Meetings::Meeting.iframe_access_levels.map do |level, _value|
|
|
88
113
|
[
|
|
@@ -10,7 +10,7 @@ module Decidim
|
|
|
10
10
|
attribute :position, Integer
|
|
11
11
|
attribute :mandatory, Boolean, default: false
|
|
12
12
|
attribute :question_type, String
|
|
13
|
-
attribute :
|
|
13
|
+
attribute :response_options, Array[ResponseOptionForm]
|
|
14
14
|
attribute :max_choices, Integer
|
|
15
15
|
attribute :deleted, Boolean, default: false
|
|
16
16
|
|
|
@@ -21,7 +21,7 @@ module Decidim
|
|
|
21
21
|
validates :question_type, inclusion: { in: Decidim::Meetings::Question::QUESTION_TYPES }, if: :editable?
|
|
22
22
|
validates :max_choices, numericality: { only_integer: true, greater_than: 1, less_than_or_equal_to: ->(form) { form.number_of_options } }, allow_blank: true, if: :editable?
|
|
23
23
|
validates :body, translatable_presence: true, if: :requires_body?
|
|
24
|
-
validates :
|
|
24
|
+
validates :response_options, presence: true, if: :editable?
|
|
25
25
|
|
|
26
26
|
def to_param
|
|
27
27
|
return id if id.present?
|
|
@@ -34,7 +34,7 @@ module Decidim
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def number_of_options
|
|
37
|
-
|
|
37
|
+
response_options.size
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
private
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
module Decidim
|
|
4
4
|
module Meetings
|
|
5
5
|
module Admin
|
|
6
|
-
# This class holds a Form to update
|
|
7
|
-
class
|
|
6
|
+
# This class holds a Form to update response options
|
|
7
|
+
class ResponseOptionForm < Decidim::Form
|
|
8
8
|
include TranslatableAttributes
|
|
9
9
|
|
|
10
10
|
attribute :deleted, Boolean, default: false
|
|
@@ -16,7 +16,7 @@ module Decidim
|
|
|
16
16
|
def to_param
|
|
17
17
|
return id if id.present?
|
|
18
18
|
|
|
19
|
-
"questionnaire-question-
|
|
19
|
+
"questionnaire-question-response-option-id"
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -25,7 +25,7 @@ module Decidim
|
|
|
25
25
|
|
|
26
26
|
errors.add(
|
|
27
27
|
:code,
|
|
28
|
-
I18n.t("
|
|
28
|
+
I18n.t("registrations_attendees.validate_registration_code.invalid", scope: "decidim.meetings.admin")
|
|
29
29
|
)
|
|
30
30
|
end
|
|
31
31
|
end
|
|
@@ -15,8 +15,6 @@ module Decidim
|
|
|
15
15
|
|
|
16
16
|
validates :current_component, presence: true
|
|
17
17
|
|
|
18
|
-
validates :address, presence: true, if: ->(form) { form.needs_address? }
|
|
19
|
-
validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? && form.needs_address? }
|
|
20
18
|
validates :start_time, presence: true, date: { before: :end_time }
|
|
21
19
|
validates :end_time, presence: true, date: { after: :start_time }
|
|
22
20
|
|
|
@@ -8,7 +8,7 @@ module Decidim
|
|
|
8
8
|
attribute :proposal_ids, Array[Integer]
|
|
9
9
|
attribute :proposals
|
|
10
10
|
attribute :closed_at, Decidim::Attributes::TimeWithZone, default: -> { Time.current }
|
|
11
|
-
attribute :attendees_count, Integer
|
|
11
|
+
attribute :attendees_count, Integer
|
|
12
12
|
|
|
13
13
|
validates :closing_report, presence: true
|
|
14
14
|
validates :attendees_count,
|
|
@@ -22,6 +22,7 @@ module Decidim
|
|
|
22
22
|
self.proposal_ids = model.linked_resources(:proposals, "proposals_from_meeting").pluck(:id)
|
|
23
23
|
presenter = MeetingEditionPresenter.new(model)
|
|
24
24
|
self.closing_report = presenter.closing_report(all_locales: false)
|
|
25
|
+
self.attendees_count = model.attendees_count || model.registrations.where.not(validated_at: nil).count
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
def proposals
|
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
module Decidim
|
|
4
4
|
module Meetings
|
|
5
|
-
# This class holds a Form to create/update meetings for Participants
|
|
5
|
+
# This class holds a Form to create/update meetings for Participants
|
|
6
6
|
class MeetingForm < ::Decidim::Meetings::BaseMeetingForm
|
|
7
7
|
attribute :title, String
|
|
8
8
|
attribute :description, String
|
|
9
9
|
attribute :location, String
|
|
10
10
|
attribute :location_hints, String
|
|
11
11
|
|
|
12
|
-
attribute :user_group_id, Integer
|
|
13
12
|
attribute :registration_type, String
|
|
14
13
|
attribute :registrations_enabled, Boolean, default: false
|
|
15
14
|
attribute :registration_url, String
|
|
@@ -18,6 +17,8 @@ module Decidim
|
|
|
18
17
|
attribute :iframe_embed_type, String, default: "none"
|
|
19
18
|
attribute :iframe_access_level, String
|
|
20
19
|
|
|
20
|
+
validates :address, presence: true, if: ->(form) { form.needs_address? }
|
|
21
|
+
validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? && form.needs_address? }
|
|
21
22
|
validates :iframe_embed_type, inclusion: { in: Decidim::Meetings::Meeting.participants_iframe_embed_types }
|
|
22
23
|
validates :title, presence: true, etiquette: true
|
|
23
24
|
validates :description, presence: true, etiquette: true
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Meetings
|
|
5
|
+
# This class holds a Form to save the chosen option for an response
|
|
6
|
+
class ResponseChoiceForm < Decidim::Form
|
|
7
|
+
attribute :body, String
|
|
8
|
+
attribute :position, Integer
|
|
9
|
+
attribute :response_option_id, Integer
|
|
10
|
+
|
|
11
|
+
validates :response_option_id, presence: true
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
module Decidim
|
|
4
4
|
module Meetings
|
|
5
|
-
# This class holds a Form to save the questionnaire
|
|
6
|
-
class
|
|
5
|
+
# This class holds a Form to save the questionnaire responses from Decidim's public page
|
|
6
|
+
class ResponseForm < Decidim::Form
|
|
7
7
|
include Decidim::TranslationsHelper
|
|
8
8
|
|
|
9
9
|
attribute :question_id, String
|
|
10
10
|
attribute :body, String
|
|
11
|
-
attribute :choices, Array[
|
|
11
|
+
attribute :choices, Array[ResponseChoiceForm]
|
|
12
12
|
attribute :current_user, Decidim::User
|
|
13
13
|
|
|
14
14
|
validates :selected_choices, presence: true
|
|
@@ -20,8 +20,8 @@ module Decidim
|
|
|
20
20
|
@question ||= Decidim::Meetings::Question.find(question_id)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def
|
|
24
|
-
@
|
|
23
|
+
def response
|
|
24
|
+
@response ||= Decidim::Meetings::Response.find_by(decidim_user_id: current_user.id, decidim_question_id: question_id) if current_user
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def label
|
|
@@ -38,12 +38,12 @@ module Decidim
|
|
|
38
38
|
self.question = model.question
|
|
39
39
|
|
|
40
40
|
self.choices = model.choices.map do |choice|
|
|
41
|
-
|
|
41
|
+
ResponseChoiceForm.from_model(choice)
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def selected_choices
|
|
46
|
-
choices.select(&:
|
|
46
|
+
choices.select(&:response_option_id)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
private
|
|
@@ -15,7 +15,6 @@ module Decidim
|
|
|
15
15
|
|
|
16
16
|
def filter_origin_values
|
|
17
17
|
origin_keys = %w(official participants)
|
|
18
|
-
origin_keys << "user_group" if current_organization.user_groups_enabled?
|
|
19
18
|
|
|
20
19
|
origin_values = flat_filter_values(*origin_keys, scope: "decidim.meetings.meetings.filters.origin_values")
|
|
21
20
|
origin_values.prepend(["", t("all", scope: "decidim.meetings.meetings.filters.origin_values")])
|
|
@@ -8,7 +8,7 @@ module Decidim
|
|
|
8
8
|
include Decidim::Meetings::ApplicationHelper
|
|
9
9
|
include Decidim::TranslationsHelper
|
|
10
10
|
include Decidim::ResourceHelper
|
|
11
|
-
include Decidim::
|
|
11
|
+
include Decidim::LikeableHelper
|
|
12
12
|
|
|
13
13
|
# Public: truncates the meeting description
|
|
14
14
|
#
|
|
@@ -23,6 +23,19 @@ module Decidim
|
|
|
23
23
|
CGI.unescapeHTML html_truncate(description, max_length:, tail:)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
def waitlist_status_block(registration)
|
|
27
|
+
return unless registration.waiting_list?
|
|
28
|
+
|
|
29
|
+
render layout: "decidim/meetings/layouts/aside_block", locals: { emoji: "ticket-line" } do
|
|
30
|
+
content_tag(:div) do
|
|
31
|
+
safe_join([
|
|
32
|
+
content_tag(:h3, t("waitlist.status", scope: "decidim.meetings.meetings.show"), class: "meeting__aside-block__title"),
|
|
33
|
+
content_tag(:p, t("waitlist.description", scope: "decidim.meetings.meetings.show"), class: "text-sm")
|
|
34
|
+
])
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
26
39
|
# Public: The css class applied based on the meeting type to
|
|
27
40
|
# the css class.
|
|
28
41
|
#
|
|
@@ -118,10 +131,6 @@ module Decidim
|
|
|
118
131
|
end
|
|
119
132
|
end
|
|
120
133
|
|
|
121
|
-
def current_user_groups?
|
|
122
|
-
current_organization.user_groups_enabled? && Decidim::UserGroups::ManageableUserGroups.for(current_user).verified.any?
|
|
123
|
-
end
|
|
124
|
-
|
|
125
134
|
# Public: URL to create an event in Google Calendars based on meeting
|
|
126
135
|
# data.
|
|
127
136
|
#
|