decidim-meetings 0.30.2 → 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.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/meetings/cancel_registration_meeting_button/cancelation_modal.erb +7 -4
  3. data/app/cells/decidim/meetings/cancel_registration_meeting_button/show.erb +1 -1
  4. data/app/cells/decidim/meetings/cancel_registration_meeting_button_cell.rb +36 -0
  5. data/app/cells/decidim/meetings/dates_and_map_cell.rb +1 -1
  6. data/app/cells/decidim/meetings/join_meeting_button/registration_modal.erb +4 -5
  7. data/app/cells/decidim/meetings/join_meeting_button/show.erb +25 -28
  8. data/app/cells/decidim/meetings/join_meeting_button/waitlist_button.erb +22 -0
  9. data/app/cells/decidim/meetings/join_meeting_button_cell.rb +28 -0
  10. data/app/cells/decidim/meetings/question_responses/show.erb +7 -7
  11. data/app/cells/decidim/meetings/question_responses_cell.rb +28 -28
  12. data/app/commands/decidim/meetings/admin/copy_meeting.rb +5 -2
  13. data/app/commands/decidim/meetings/admin/create_agenda.rb +6 -2
  14. data/app/commands/decidim/meetings/admin/create_meeting.rb +7 -3
  15. data/app/commands/decidim/meetings/admin/mark_as_attendee.rb +44 -0
  16. data/app/commands/decidim/meetings/admin/publish_meeting.rb +2 -1
  17. data/app/commands/decidim/meetings/admin/update_agenda.rb +6 -2
  18. data/app/commands/decidim/meetings/admin/update_meeting.rb +15 -6
  19. data/app/commands/decidim/meetings/admin/update_questionnaire.rb +4 -4
  20. data/app/commands/decidim/meetings/admin/update_registrations.rb +19 -7
  21. data/app/commands/decidim/meetings/create_meeting.rb +2 -3
  22. data/app/commands/decidim/meetings/{create_answer.rb → create_response.rb} +11 -11
  23. data/app/commands/decidim/meetings/join_meeting.rb +4 -6
  24. data/app/commands/decidim/meetings/join_waitlist.rb +53 -0
  25. data/app/commands/decidim/meetings/leave_meeting.rb +14 -5
  26. data/app/commands/decidim/meetings/update_meeting.rb +1 -2
  27. data/app/controllers/concerns/decidim/meetings/admin/filterable.rb +1 -1
  28. data/app/controllers/decidim/meetings/admin/agenda_controller.rb +2 -2
  29. data/app/controllers/decidim/meetings/admin/invites_controller.rb +1 -1
  30. data/app/controllers/decidim/meetings/admin/meeting_closes_controller.rb +1 -1
  31. data/app/controllers/decidim/meetings/admin/meeting_copies_controller.rb +1 -1
  32. data/app/controllers/decidim/meetings/admin/meetings_controller.rb +4 -4
  33. data/app/controllers/decidim/meetings/admin/meetings_poll_controller.rb +10 -10
  34. data/app/controllers/decidim/meetings/admin/registrations_attendees_controller.rb +79 -0
  35. data/app/controllers/decidim/meetings/admin/registrations_controller.rb +1 -22
  36. data/app/controllers/decidim/meetings/meeting_closes_controller.rb +1 -1
  37. data/app/controllers/decidim/meetings/meetings_controller.rb +11 -11
  38. data/app/controllers/decidim/meetings/polls/{answers_controller.rb → responses_controller.rb} +7 -7
  39. data/app/controllers/decidim/meetings/registrations_controller.rb +39 -12
  40. data/app/events/decidim/meetings/registration_marked_as_attendee_event.rb +9 -0
  41. data/app/events/decidim/meetings/upcoming_meeting_event.rb +41 -0
  42. data/app/events/decidim/meetings/update_meeting_event.rb +25 -0
  43. data/app/forms/decidim/meetings/admin/close_meeting_form.rb +2 -1
  44. data/app/forms/decidim/meetings/admin/meeting_agenda_items_form.rb +4 -0
  45. data/app/forms/decidim/meetings/admin/meeting_form.rb +28 -3
  46. data/app/forms/decidim/meetings/admin/question_form.rb +3 -3
  47. data/app/forms/decidim/meetings/admin/{answer_option_form.rb → response_option_form.rb} +3 -3
  48. data/app/forms/decidim/meetings/admin/validate_registration_code_form.rb +1 -1
  49. data/app/forms/decidim/meetings/base_meeting_form.rb +0 -2
  50. data/app/forms/decidim/meetings/close_meeting_form.rb +2 -1
  51. data/app/forms/decidim/meetings/join_meeting_form.rb +0 -1
  52. data/app/forms/decidim/meetings/meeting_form.rb +3 -2
  53. data/app/forms/decidim/meetings/response_choice_form.rb +14 -0
  54. data/app/forms/decidim/meetings/{answer_form.rb → response_form.rb} +7 -7
  55. data/app/helpers/decidim/meetings/application_helper.rb +0 -1
  56. data/app/helpers/decidim/meetings/meetings_helper.rb +14 -5
  57. data/app/jobs/decidim/meetings/promote_from_waitlist_job.rb +63 -0
  58. data/app/jobs/decidim/meetings/upcoming_meeting_notification_job.rb +1 -1
  59. data/app/mailers/decidim/meetings/registration_mailer.rb +13 -0
  60. data/app/models/decidim/meetings/agenda_item.rb +5 -0
  61. data/app/models/decidim/meetings/meeting.rb +15 -12
  62. data/app/models/decidim/meetings/question.rb +12 -12
  63. data/app/models/decidim/meetings/questionnaire.rb +1 -1
  64. data/app/models/decidim/meetings/registration.rb +19 -7
  65. data/app/models/decidim/meetings/{answer.rb → response.rb} +6 -6
  66. data/app/models/decidim/meetings/response_choice.rb +15 -0
  67. data/app/models/decidim/meetings/{answer_option.rb → response_option.rb} +5 -5
  68. data/app/packs/src/decidim/meetings/admin/destroy_meeting_alert.js +1 -1
  69. data/app/packs/src/decidim/meetings/admin/meetings_components_form.js +1 -8
  70. data/app/packs/src/decidim/meetings/admin/meetings_form.js +1 -1
  71. data/app/packs/src/decidim/meetings/admin/registrations_form.js +1 -1
  72. data/app/packs/src/decidim/meetings/admin/registrations_invite_form.js +1 -1
  73. data/app/packs/src/decidim/meetings/meetings_form.js +1 -1
  74. data/app/packs/src/decidim/meetings/meetings_polls.js +1 -1
  75. data/app/packs/src/decidim/meetings/poll.component.js +5 -5
  76. data/app/packs/stylesheets/decidim/meetings/_item.scss +5 -1
  77. data/app/packs/stylesheets/decidim/meetings/meetings.scss +4 -4
  78. data/app/permissions/decidim/meetings/admin/agenda_permissions.rb +34 -0
  79. data/app/permissions/decidim/meetings/admin/meeting_permissions.rb +44 -0
  80. data/app/permissions/decidim/meetings/admin/permissions.rb +5 -66
  81. data/app/permissions/decidim/meetings/admin/questionnaire_permissions.rb +30 -0
  82. data/app/permissions/decidim/meetings/meeting_permissions.rb +90 -0
  83. data/app/permissions/decidim/meetings/permissions.rb +9 -105
  84. data/app/presenters/decidim/meetings/admin_log/value_types/meeting_title_description_presenter.rb +1 -1
  85. data/app/presenters/decidim/meetings/agenda_item_presenter.rb +29 -0
  86. data/app/presenters/decidim/meetings/meeting_presenter.rb +11 -15
  87. data/app/presenters/decidim/meetings/registration_presenter.rb +24 -0
  88. data/app/queries/decidim/meetings/{questionnaire_user_answers.rb → questionnaire_user_responses.rb} +5 -5
  89. data/app/serializers/decidim/meetings/registration_serializer.rb +5 -6
  90. data/app/services/decidim/meetings/diff_renderer.rb +0 -1
  91. data/app/views/decidim/meetings/_calendar_modal.html.erb +1 -0
  92. data/app/views/decidim/meetings/admin/agenda/_agenda_item_fields.html.erb +1 -1
  93. data/app/views/decidim/meetings/admin/invites/_form.html.erb +1 -1
  94. data/app/views/decidim/meetings/admin/meeting_closes/_form.html.erb +1 -1
  95. data/app/views/decidim/meetings/admin/meetings/_form.html.erb +3 -2
  96. data/app/views/decidim/meetings/admin/meetings/_linked_spaces.html.erb +1 -1
  97. data/app/views/decidim/meetings/admin/meetings/_meeting-tr.html.erb +11 -8
  98. data/app/views/decidim/meetings/admin/meetings/_meeting_actions.html.erb +200 -69
  99. data/app/views/decidim/meetings/admin/meetings/_reminders.html.erb +19 -0
  100. data/app/views/decidim/meetings/admin/meetings/_services.html.erb +1 -1
  101. data/app/views/decidim/meetings/admin/meetings/index.html.erb +7 -5
  102. data/app/views/decidim/meetings/admin/meetings/manage_trash.html.erb +2 -1
  103. data/app/views/decidim/meetings/admin/poll/_form.html.erb +6 -6
  104. data/app/views/decidim/meetings/admin/poll/_question.html.erb +13 -13
  105. data/app/views/decidim/meetings/admin/poll/_response_option.html.erb +35 -0
  106. data/app/views/decidim/meetings/admin/poll/_response_option_template.html.erb +7 -0
  107. data/app/views/decidim/meetings/admin/poll/edit.html.erb +3 -3
  108. data/app/views/decidim/meetings/admin/registration_form/edit_questions.html.erb +5 -5
  109. data/app/views/decidim/meetings/admin/registrations/edit.html.erb +19 -39
  110. data/app/views/decidim/meetings/admin/registrations_attendees/index.html.erb +126 -0
  111. data/app/views/decidim/meetings/layouts/live_event.html.erb +1 -1
  112. data/app/views/decidim/meetings/meeting_closes/_form.html.erb +2 -2
  113. data/app/views/decidim/meetings/meetings/_form.html.erb +2 -11
  114. data/app/views/decidim/meetings/meetings/_meeting.html.erb +2 -2
  115. data/app/views/decidim/meetings/meetings/_meeting_actions.html.erb +3 -3
  116. data/app/views/decidim/meetings/meetings/_meeting_agenda.html.erb +2 -2
  117. data/app/views/decidim/meetings/meetings/_meeting_aside.html.erb +11 -10
  118. data/app/views/decidim/meetings/meetings/_meeting_poll_actions.html.erb +3 -3
  119. data/app/views/decidim/meetings/meetings/_registration_code_modal.html.erb +16 -0
  120. data/app/views/decidim/meetings/polls/questions/_index_admin.html.erb +1 -1
  121. data/app/views/decidim/meetings/polls/questions/_published_question.html.erb +5 -5
  122. data/app/views/decidim/meetings/polls/responses/_multiple_option.html.erb +13 -0
  123. data/app/views/decidim/meetings/polls/responses/_single_option.html.erb +13 -0
  124. data/app/views/decidim/meetings/polls/{answers → responses}/admin.html.erb +4 -4
  125. data/app/views/decidim/meetings/polls/{answers → responses}/index.html.erb +4 -4
  126. data/app/views/decidim/meetings/registration_mailer/confirmation.html.erb +6 -1
  127. data/config/assets.rb +2 -2
  128. data/config/locales/ar.yml +1 -26
  129. data/config/locales/bg.yml +2 -32
  130. data/config/locales/ca-IT.yml +86 -40
  131. data/config/locales/ca.yml +86 -40
  132. data/config/locales/cs.yml +71 -43
  133. data/config/locales/de.yml +87 -41
  134. data/config/locales/el.yml +1 -25
  135. data/config/locales/en.yml +89 -43
  136. data/config/locales/es-MX.yml +87 -41
  137. data/config/locales/es-PY.yml +87 -41
  138. data/config/locales/es.yml +87 -41
  139. data/config/locales/eu.yml +86 -40
  140. data/config/locales/fi-plain.yml +86 -40
  141. data/config/locales/fi.yml +85 -39
  142. data/config/locales/fr-CA.yml +79 -38
  143. data/config/locales/fr.yml +79 -38
  144. data/config/locales/ga-IE.yml +1 -7
  145. data/config/locales/gl.yml +1 -19
  146. data/config/locales/hu.yml +1 -22
  147. data/config/locales/id-ID.yml +0 -16
  148. data/config/locales/is-IS.yml +0 -10
  149. data/config/locales/it.yml +1 -29
  150. data/config/locales/ja.yml +88 -42
  151. data/config/locales/lb.yml +1 -15
  152. data/config/locales/lt.yml +1 -28
  153. data/config/locales/lv.yml +0 -16
  154. data/config/locales/nl.yml +1 -26
  155. data/config/locales/no.yml +1 -28
  156. data/config/locales/pl.yml +2 -32
  157. data/config/locales/pt-BR.yml +1 -28
  158. data/config/locales/pt.yml +1 -28
  159. data/config/locales/ro-RO.yml +56 -29
  160. data/config/locales/ru.yml +0 -16
  161. data/config/locales/sk.yml +0 -16
  162. data/config/locales/sl.yml +0 -4
  163. data/config/locales/sv.yml +85 -39
  164. data/config/locales/tr-TR.yml +0 -20
  165. data/config/locales/uk.yml +0 -12
  166. data/config/locales/zh-CN.yml +0 -19
  167. data/config/locales/zh-TW.yml +1 -26
  168. data/db/migrate/20181107175558_add_questionnaire_to_existing_meetings.rb +8 -2
  169. data/db/migrate/20200827153856_add_commentable_counter_cache_to_meetings.rb +8 -2
  170. data/db/migrate/20201016065302_fix_meetings_registration_terms.rb +8 -2
  171. data/db/migrate/20210310120731_add_followable_counter_cache_to_meetings.rb +8 -2
  172. data/db/migrate/20250317103343_rename_answer_to_response_in_decidim_meetings.rb +18 -0
  173. data/db/migrate/20250403094034_add_reminder_customization_to_decidim_meetings.rb +9 -0
  174. data/db/migrate/20250408071941_add_status_to_registrations_to_decidim_meetings_registrations.rb +8 -0
  175. data/lib/decidim/api/agenda_item_type.rb +6 -2
  176. data/lib/decidim/api/agenda_type.rb +6 -2
  177. data/lib/decidim/api/linked_resources_interface.rb +1 -1
  178. data/lib/decidim/api/meeting_type.rb +20 -10
  179. data/lib/decidim/api/service_type.rb +3 -0
  180. data/lib/decidim/meetings/admin_engine.rb +9 -1
  181. data/lib/decidim/meetings/component.rb +29 -8
  182. data/lib/decidim/meetings/engine.rb +6 -21
  183. data/lib/decidim/meetings/meeting_serializer.rb +1 -2
  184. data/lib/decidim/meetings/schema_org_event_meeting_serializer.rb +0 -10
  185. data/lib/decidim/meetings/seeds.rb +4 -13
  186. data/lib/decidim/meetings/test/factories.rb +10 -16
  187. data/lib/decidim/meetings/user_responses_serializer.rb +47 -0
  188. data/lib/decidim/meetings/version.rb +1 -1
  189. data/lib/decidim/meetings.rb +7 -9
  190. metadata +49 -35
  191. data/app/cells/decidim/meetings/attending_organizations_list_cell.rb +0 -32
  192. data/app/forms/decidim/meetings/answer_choice_form.rb +0 -14
  193. data/app/models/decidim/meetings/answer_choice.rb +0 -15
  194. data/app/queries/decidim/meetings/metrics/meeting_followers_metric_measure.rb +0 -31
  195. data/app/queries/decidim/meetings/metrics/meetings_metric_manage.rb +0 -48
  196. data/app/views/decidim/meetings/admin/poll/_answer_option.html.erb +0 -35
  197. data/app/views/decidim/meetings/admin/poll/_answer_option_template.html.erb +0 -7
  198. data/app/views/decidim/meetings/polls/answers/_multiple_option.html.erb +0 -13
  199. data/app/views/decidim/meetings/polls/answers/_single_option.html.erb +0 -13
  200. data/lib/decidim/meetings/download_your_data_user_answers_serializer.rb +0 -39
  201. data/lib/decidim/meetings/user_answers_serializer.rb +0 -47
  202. /data/app/views/decidim/meetings/polls/{answers → responses}/create.js.erb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf2072be155206477263a0700986dfa59596a56848676dd71241e0ad753f30ab
4
- data.tar.gz: 54738277914bbc88d29beb0cee291bc4f6a797fe7a7562c7189ea11113008ec4
3
+ metadata.gz: 2b5b62f6ed3b6a46c4fca9ff267502b3d458ca1943067664728a3e731d6d9c81
4
+ data.tar.gz: 5d36373d4d0d4db808762b34ee824b7bd1ed84b83e790a48be3b26ced8ded27a
5
5
  SHA512:
6
- metadata.gz: 84fbedc3e1da611dc83bba0ead74349ab8574e8be2517fb32444d67ab4f455788b35ea8819a96dc54bf2cb32e6dd90cc850b02c502fbc66da6b0484199447d03
7
- data.tar.gz: 89ebd88a8ce1cdb192d6e52a185feb94c7232637262ce817b1a3d19ced1fb9257617f5d327c79e2de4067ec0e7a8957d300fc9f574abe93f91a69c0a77a9b237
6
+ metadata.gz: 5a6c3520821cb57ccdea6c44902abec0ccb566b7e22b32ae0cfe867d66b0d0316cb76219ae2dfc10aed70ba60e7c7f278137c5afa34145944884d3701a29e103
7
+ data.tar.gz: 21d97317fedf76832e2f8a77384ff588ecbd94d2ee16b40df1afed2906617c7318e8551f71dc678042ad25057a76259fb355a60d7cd98ba9a7848560de147693
@@ -2,10 +2,13 @@
2
2
  <%= decidim_form_for(registration_form, url: meeting_registration_path(model), method: :delete) do |form| %>
3
3
  <div data-dialog-container>
4
4
  <%= icon "door-open-line" %>
5
- <h2 id="dialog-title-meeting-cancelation-confirm-<%= model.id %>" data-dialog-title><%= t("leave", scope: "decidim.meetings.meetings.show") %></h2>
5
+ <h2 id="dialog-title-meeting-cancelation-confirm-<%= model.id %>" data-dialog-title>
6
+ <%= i18n_modal_title %>
7
+ </h2>
6
8
  <div>
7
-
8
- <div id="dialog-desc-meeting-cancelation-confirm-<%= model.id %>" class="meeting__cancelation-modal__description"><%= t("leave_confirmation", scope: "decidim.meetings.meetings.show") %></div>
9
+ <div id="dialog-desc-meeting-cancelation-confirm-<%= model.id %>" class="meeting__cancelation-modal__description">
10
+ <%= i18n_modal_confirmation_text %>
11
+ </div>
9
12
  </div>
10
13
  </div>
11
14
  <div data-dialog-actions>
@@ -13,7 +16,7 @@
13
16
  <span><%= t("close", scope: "decidim.shared.flag_modal") %></span>
14
17
  </button>
15
18
  <button type="submit" class="button button__sm md:button__lg button__transparent-secondary">
16
- <span><%= t("leave", scope: "decidim.meetings.meetings.show") %></span>
19
+ <span><%= cancel_button_text %></span>
17
20
  <%= icon "arrow-right-line" %>
18
21
  </button>
19
22
  </div>
@@ -7,6 +7,6 @@
7
7
  class: button_classes,
8
8
  data: { "dialog-open": "meeting-cancelation-confirm-#{model.id}" }
9
9
  ) do %>
10
- <%= t("leave", scope: "decidim.meetings.meetings.show") %>
10
+ <%= cancel_button_text %>
11
11
  <%= icon icon_name %>
12
12
  <% end %>
@@ -19,6 +19,42 @@ module Decidim
19
19
  model.component
20
20
  end
21
21
 
22
+ def registration_status
23
+ model.registrations.find_by(user: current_user)&.status
24
+ end
25
+
26
+ # i18n-tasks-use t('decidim.meetings.meetings.show.leave')
27
+ # i18n-tasks-use t('decidim.meetings.meetings.show.leave_confirmation')
28
+ # i18n-tasks-use t('decidim.meetings.meetings.show.leave_waitlist')
29
+ # i18n-tasks-use t('decidim.meetings.meetings.show.leave_waitlist_confirmation')
30
+ def action_keys
31
+ if registration_status == "waiting_list"
32
+ {
33
+ button: "leave_waitlist",
34
+ modal_title: "leave_waitlist",
35
+ modal_confirmation: "leave_waitlist_confirmation"
36
+ }
37
+ else
38
+ {
39
+ button: "leave",
40
+ modal_title: "leave",
41
+ modal_confirmation: "leave_confirmation"
42
+ }
43
+ end
44
+ end
45
+
46
+ def cancel_button_text
47
+ I18n.t(action_keys[:button], scope: "decidim.meetings.meetings.show")
48
+ end
49
+
50
+ def i18n_modal_title
51
+ I18n.t(action_keys[:modal_title], scope: "decidim.meetings.meetings.show")
52
+ end
53
+
54
+ def i18n_modal_confirmation_text
55
+ I18n.t(action_keys[:modal_confirmation], scope: "decidim.meetings.meetings.show")
56
+ end
57
+
22
58
  def button_classes
23
59
  "button button__sm button__transparent-secondary w-full"
24
60
  end
@@ -32,7 +32,7 @@ module Decidim
32
32
  end
33
33
 
34
34
  def display_map?
35
- maps_enabled? && !online?
35
+ maps_enabled? && !online? && model.address.present?
36
36
  end
37
37
  end
38
38
  end
@@ -1,19 +1,18 @@
1
- <%= decidim_modal id: "meeting-registration-confirm-#{model.id}", class: "meeting__registration-modal" do %>
2
- <%= decidim_form_for(registration_form, url: meeting_registration_path(model), method: :post) do |form| %>
1
+ <%= decidim_modal id: "meeting-#{registration_action}-confirm-#{model.id}", class: "meeting__registration-modal" do %>
2
+ <%= decidim_form_for(registration_form, url: registration_path, method: :post) do |form| %>
3
3
  <div data-dialog-container>
4
4
  <%= icon "login-circle-line" %>
5
- <h2 id="dialog-title-meeting-registration-confirm-<%= model.id %>" data-dialog-title><%= t("join", scope: "decidim.meetings.meetings.show") %></h2>
5
+ <h2 id="dialog-title-meeting-registration-confirm-<%= model.id %>" data-dialog-title><%= t(registration_translation_key, scope: "decidim.meetings.meetings.show") %></h2>
6
6
  <div>
7
7
 
8
8
  <div class="form__wrapper">
9
- <%= cell("decidim/represent_user_group", form) %>
10
9
  <%= cell("decidim/public_participation", form) %>
11
10
  <div class="meeting__registration-modal__terms"><%= registration_terms_text %></div>
12
11
  </div>
13
12
  </div>
14
13
  </div>
15
14
  <div data-dialog-actions>
16
- <button type="button" class="button button__sm md:button__lg button__transparent-secondary" data-dialog-close="meeting-registration-confirm-<%= model.id %>">
15
+ <button type="button" class="button button__sm md:button__lg button__transparent-secondary" data-dialog-close="meeting-<%= registration_action %>-confirm-<%= model.id %>">
17
16
  <span><%= i18n_cancel_text %></span>
18
17
  </button>
19
18
  <button type="submit" class="button button__sm md:button__lg button__secondary">
@@ -1,33 +1,27 @@
1
- <% if model.can_be_joined_by?(current_user) %>
2
- <% unless model.has_registration_for? current_user %>
3
- <% if model.registration_form_enabled? %>
4
- <%= action_authorized_link_to(
5
- :join,
6
- i18n_join_text,
7
- join_meeting_registration_path(model),
8
- class: button_classes,
9
- disabled: !model.has_available_slots?
10
- ) %>
11
- <% else %>
12
- <% unless options[:hide_modal] %>
13
- <%= render :registration_modal %>
14
- <% end %>
15
- <%= action_authorized_button_to(
16
- :join,
17
- i18n_join_text,
18
- "#",
19
- class: button_classes,
20
- disabled: !model.has_available_slots?,
21
- data: { "dialog-open": current_user.present? ? "meeting-registration-confirm-#{model.id}" : "loginModal" },
22
- resource: model
23
- ) %>
24
- <% end %>
25
- <% end %>
1
+ <% if render_waitlist_button? %>
2
+ <%= render :waitlist_button %>
26
3
 
27
- <% if shows_remaining_slots? %>
28
- <%= render :remaining_slots %>
4
+ <% elsif model.can_be_joined_by?(current_user) && !model.has_registration_for?(current_user) %>
5
+ <% if model.registration_form_enabled? %>
6
+ <%= action_authorized_link_to(
7
+ :join,
8
+ i18n_join_text,
9
+ join_meeting_registration_path(model),
10
+ class: button_classes
11
+ ) %>
12
+ <% else %>
13
+ <% unless options[:hide_modal] %>
14
+ <%= render :registration_modal %>
15
+ <% end %>
16
+ <%= action_authorized_button_to(
17
+ :join,
18
+ i18n_join_text,
19
+ "#",
20
+ class: button_classes,
21
+ data: { "dialog-open": current_user.present? ? "meeting-registration-confirm-#{model.id}" : "loginModal" },
22
+ resource: model
23
+ ) %>
29
24
  <% end %>
30
-
31
25
  <% elsif model.on_different_platform? %>
32
26
  <%= action_authorized_link_to(
33
27
  :join,
@@ -36,3 +30,6 @@
36
30
  class: button_classes
37
31
  ) %>
38
32
  <% end %>
33
+ <% if shows_remaining_slots? %>
34
+ <%= render :remaining_slots unless participant_registered_for_meeting? %>
35
+ <% end %>
@@ -0,0 +1,22 @@
1
+ <% if model.registration_form_enabled? %>
2
+ <%= action_authorized_link_to(
3
+ :join_waitlist,
4
+ join_waitlist_meeting_registration_path(model),
5
+ class: button_classes
6
+ ) do %>
7
+ <%= i18n_join_waitlist_text %>
8
+ <% end %>
9
+ <% else %>
10
+ <% unless options[:hide_modal] %>
11
+ <%= render :registration_modal %>
12
+ <% end %>
13
+ <%= action_authorized_button_to(
14
+ :join_waitlist,
15
+ "#",
16
+ class: button_classes,
17
+ data: { "dialog-open": current_user.present? ? "meeting-waitlist-confirm-#{model.id}" : "loginModal" },
18
+ resource: model
19
+ ) do %>
20
+ <%= i18n_join_waitlist_text %>
21
+ <% end %>
22
+ <% end %>
@@ -12,6 +12,10 @@ module Decidim
12
12
  render
13
13
  end
14
14
 
15
+ def render_waitlist_button?
16
+ model.waitlist_enabled? && !model.has_available_slots? && model.can_be_joined_by?(current_user) && !model.has_registration_for?(current_user)
17
+ end
18
+
15
19
  private
16
20
 
17
21
  delegate :current_user, to: :controller, prefix: false
@@ -20,6 +24,10 @@ module Decidim
20
24
  model.component
21
25
  end
22
26
 
27
+ def available_slots?
28
+ @available_slots ||= model.has_available_slots?
29
+ end
30
+
23
31
  def button_classes
24
32
  "button button__xl button__secondary w-full"
25
33
  end
@@ -28,12 +36,20 @@ module Decidim
28
36
  options[:show_remaining_slots] && model.available_slots.positive?
29
37
  end
30
38
 
39
+ def participant_registered_for_meeting?
40
+ registration.present?
41
+ end
42
+
31
43
  def i18n_join_text
32
44
  return I18n.t("join", scope: "decidim.meetings.meetings.show") if model.has_available_slots?
33
45
 
34
46
  I18n.t("no_slots_available", scope: "decidim.meetings.meetings.show")
35
47
  end
36
48
 
49
+ def i18n_join_waitlist_text
50
+ I18n.t("join_waitlist", scope: "decidim.meetings.meetings.show")
51
+ end
52
+
37
53
  def i18n_confirm_text
38
54
  I18n.t("confirm", scope: "decidim.meetings.meetings.registration_confirm")
39
55
  end
@@ -49,6 +65,18 @@ module Decidim
49
65
  def registration_form
50
66
  @registration_form ||= Decidim::Meetings::JoinMeetingForm.new
51
67
  end
68
+
69
+ def registration_action
70
+ @registration_action ||= model.has_available_slots? ? "registration" : "waitlist"
71
+ end
72
+
73
+ def registration_path
74
+ model.has_available_slots? ? meeting_registration_path(model) : join_waitlist_meeting_registration_path(model)
75
+ end
76
+
77
+ def registration_translation_key
78
+ model.has_available_slots? ? :join : :join_waitlist
79
+ end
52
80
  end
53
81
  end
54
82
  end
@@ -1,11 +1,11 @@
1
- <% answer_options_with_percentages.each do |(answer_option_body, answer_percentage)| %>
2
- <div class="meeting-polls__answer">
3
- <div class="meeting-polls__answer--bar">
4
- <div style="width: <%= answer_percentage %>"></div>
1
+ <% response_options_with_percentages.each do |(response_option_body, response_percentage)| %>
2
+ <div class="meeting-polls__response">
3
+ <div class="meeting-polls__response--bar">
4
+ <div style="width: <%= response_percentage %>"></div>
5
5
  </div>
6
- <div class="meeting-polls__answer--value">
7
- <span><%= translated_attribute(answer_option_body) %></span>
8
- <span><%= answer_percentage %></span>
6
+ <div class="meeting-polls__response--value">
7
+ <span><%= translated_attribute(response_option_body) %></span>
8
+ <span><%= response_percentage %></span>
9
9
  </div>
10
10
  </div>
11
11
  <% end %>
@@ -3,7 +3,7 @@
3
3
  module Decidim
4
4
  module Meetings
5
5
  # This cell renders the percentage of responses which chose
6
- # the given answer option in a meeting poll question
6
+ # the given response option in a meeting poll question
7
7
  class QuestionResponsesCell < Decidim::ViewModel
8
8
  def show
9
9
  render
@@ -12,35 +12,35 @@ module Decidim
12
12
  private
13
13
 
14
14
  # Returns an array of arrays, where the internal array contains
15
- # - the body of the answer option
16
- # - the percentage of answers for that option
15
+ # - the body of the response option
16
+ # - the percentage of responses for that option
17
17
  #
18
- def answer_options_with_percentages
19
- # This query joins answer options with answer choices and answers
20
- # and returns for each answer option the count of times it has been answered
21
- # grouping by answer options and answers.
18
+ def response_options_with_percentages
19
+ # This query joins response options with response choices and responses
20
+ # and returns for each response option the count of times it has been responded
21
+ # grouping by response options and responses.
22
22
  #
23
- # This calculation is a bit complex because of multiple option answers
24
- question_answers_choices = Decidim::Meetings::AnswerOption.where(decidim_question_id: model.id)
25
- .joins([choices: :answer])
26
- .group(Arel.sql("#{answers_table_name}.id, #{answer_options_table_name}.id"))
27
- .select(<<~SELECT
28
- #{answer_options_table_name}.id AS id,
29
- #{answer_options_table_name}.body,
30
- #{answers_table_name}.id AS answer_id,
31
- COUNT(decidim_answer_option_id) AS count
32
- SELECT
33
- )
23
+ # This calculation is a bit complex because of multiple option responses
24
+ question_responses_choices = Decidim::Meetings::ResponseOption.where(decidim_question_id: model.id)
25
+ .joins([choices: :response])
26
+ .group(Arel.sql("#{responses_table_name}.id, #{response_options_table_name}.id"))
27
+ .select(<<~SELECT
28
+ #{response_options_table_name}.id AS id,
29
+ #{response_options_table_name}.body,
30
+ #{responses_table_name}.id AS response_id,
31
+ COUNT(decidim_response_option_id) AS count
32
+ SELECT
33
+ )
34
34
 
35
- # Extract the number of uniq answers by the answer_id attribute
36
- total_answers = question_answers_choices.map(&:answer_id).compact.uniq.size
35
+ # Extract the number of uniq responses by the response_id attribute
36
+ total_responses = question_responses_choices.map(&:response_id).compact.uniq.size
37
37
 
38
- # A second grouping is necessary to count the number of answers for each answer_option id
38
+ # A second grouping is necessary to count the number of responses for each response_option id
39
39
  # and calculate the percentages
40
40
  options_with_percentages = []
41
- question_answers_choices.group_by(&:id).each do |_id, values|
42
- answers_count = values.sum(&:count)
43
- options_with_percentages << [values.first.body, calculate_and_format_percentage(answers_count, total_answers)]
41
+ question_responses_choices.group_by(&:id).each do |_id, values|
42
+ responses_count = values.sum(&:count)
43
+ options_with_percentages << [values.first.body, calculate_and_format_percentage(responses_count, total_responses)]
44
44
  end
45
45
 
46
46
  options_with_percentages
@@ -58,12 +58,12 @@ module Decidim
58
58
  format_percentage(calculate_percentage(part, total))
59
59
  end
60
60
 
61
- def answer_options_table_name
62
- @answer_options_table_name ||= Decidim::Meetings::AnswerOption.table_name
61
+ def response_options_table_name
62
+ @response_options_table_name ||= Decidim::Meetings::ResponseOption.table_name
63
63
  end
64
64
 
65
- def answers_table_name
66
- @answers_table_name ||= Decidim::Meetings::Answer.table_name
65
+ def responses_table_name
66
+ @responses_table_name ||= Decidim::Meetings::Response.table_name
67
67
  end
68
68
  end
69
69
  end
@@ -38,8 +38,8 @@ module Decidim
38
38
  attr_reader :form, :meeting, :copied_meeting
39
39
 
40
40
  def copy_meeting!
41
- parsed_title = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.title, current_organization: meeting.organization).rewrite
42
- parsed_description = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.description, current_organization: meeting.organization).rewrite
41
+ parsed_title = Decidim::ContentProcessor.parse(form.title, current_organization: meeting.organization).rewrite
42
+ parsed_description = Decidim::ContentProcessor.parse_with_processor(:inline_images, form.description, current_organization: meeting.organization).rewrite
43
43
 
44
44
  @copied_meeting = Decidim.traceability.create!(
45
45
  Meeting,
@@ -68,6 +68,9 @@ module Decidim
68
68
  comments_end_time: form.comments_end_time,
69
69
  registration_type: form.registration_type,
70
70
  registration_url: form.registration_url,
71
+ reminder_enabled: form.reminder_enabled,
72
+ send_reminders_before_hours: form.send_reminders_before_hours,
73
+ reminder_message_custom_content: form.reminder_message_custom_content || meeting.reminder_message_custom_content,
71
74
  **fields_from_meeting
72
75
  )
73
76
  end
@@ -21,7 +21,7 @@ module Decidim
21
21
  def create_agenda_item(form_agenda_item)
22
22
  agenda_item_attributes = {
23
23
  title: form_agenda_item.title,
24
- description: form_agenda_item.description,
24
+ description: process_description(form_agenda_item.description),
25
25
  position: form_agenda_item.position,
26
26
  duration: form_agenda_item.duration,
27
27
  parent_id: form_agenda_item.parent_id,
@@ -32,7 +32,7 @@ module Decidim
32
32
  form_agenda_item.agenda_item_children.each do |form_agenda_item_child|
33
33
  agenda_item_child_attributes = {
34
34
  title: form_agenda_item_child.title,
35
- description: form_agenda_item_child.description,
35
+ description: process_description(form_agenda_item_child.description),
36
36
  position: form_agenda_item_child.position,
37
37
  duration: form_agenda_item_child.duration,
38
38
  parent_id: agenda_item.id,
@@ -59,6 +59,10 @@ module Decidim
59
59
  record.save!
60
60
  end
61
61
  end
62
+
63
+ def process_description(description)
64
+ Decidim::ContentProcessor.parse(description, current_organization: form.current_organization).rewrite
65
+ end
62
66
  end
63
67
  end
64
68
  end
@@ -9,7 +9,8 @@ module Decidim
9
9
  fetch_form_attributes :end_time, :start_time, :online_meeting_url, :registration_type,
10
10
  :registration_url, :address, :latitude, :longitude, :location, :location_hints,
11
11
  :private_meeting, :transparent, :registrations_enabled, :component, :iframe_embed_type,
12
- :comments_enabled, :taxonomizations, :comments_start_time, :comments_end_time, :iframe_access_level
12
+ :comments_enabled, :taxonomizations, :comments_start_time, :comments_end_time, :iframe_access_level,
13
+ :reminder_enabled
13
14
 
14
15
  protected
15
16
 
@@ -20,15 +21,18 @@ module Decidim
20
21
  end
21
22
 
22
23
  def attributes
23
- parsed_title = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.title, current_organization: form.current_organization).rewrite
24
+ parsed_title = Decidim::ContentProcessor.parse(form.title, current_organization: form.current_organization).rewrite
24
25
  parsed_description = Decidim::ContentProcessor.parse(form.description, current_organization: form.current_organization).rewrite
26
+
25
27
  super.merge({
26
28
  title: parsed_title,
27
29
  description: parsed_description,
28
30
  type_of_meeting: form.clean_type_of_meeting,
29
31
  author: form.current_organization,
30
32
  registration_terms: form.current_component.settings.default_registration_terms,
31
- questionnaire: Decidim::Forms::Questionnaire.new
33
+ questionnaire: Decidim::Forms::Questionnaire.new,
34
+ send_reminders_before_hours: form.reminder_enabled ? form.send_reminders_before_hours : nil,
35
+ reminder_message_custom_content: form.reminder_enabled ? form.reminder_message_custom_content : ""
32
36
  })
33
37
  end
34
38
 
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ module Admin
6
+ # This command is executed when the user marks a registration as attendee
7
+ # from the admin panel.
8
+ class MarkAsAttendee < Decidim::Command
9
+ def initialize(registration)
10
+ @registration = registration
11
+ end
12
+
13
+ def call
14
+ return broadcast(:invalid) if registration.validated?
15
+
16
+ mark_attendee
17
+ send_notification
18
+
19
+ broadcast(:ok)
20
+ end
21
+
22
+ attr_reader :registration
23
+
24
+ protected
25
+
26
+ def mark_attendee
27
+ registration.update!(validated_at: Time.current)
28
+ end
29
+
30
+ def send_notification
31
+ Decidim::EventsManager.publish(
32
+ event: "decidim.events.meetings.registration_marked_as_attendee",
33
+ event_class: Decidim::Meetings::RegistrationMarkedAsAttendeeEvent,
34
+ resource: meeting,
35
+ affected_users: [registration.user],
36
+ extra: {
37
+ registration: registration
38
+ }
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -61,11 +61,12 @@ module Decidim
61
61
 
62
62
  def schedule_upcoming_meeting_notification
63
63
  return if meeting.start_time < Time.zone.now
64
+ return unless meeting.reminder_enabled
64
65
 
65
66
  checksum = Decidim::Meetings::UpcomingMeetingNotificationJob.generate_checksum(meeting)
66
67
 
67
68
  Decidim::Meetings::UpcomingMeetingNotificationJob
68
- .set(wait_until: meeting.start_time - Decidim::Meetings.upcoming_meeting_notification)
69
+ .set(wait_until: meeting.start_time - meeting.send_reminders_before_hours.hours)
69
70
  .perform_later(meeting.id, checksum)
70
71
  end
71
72
  end
@@ -19,7 +19,7 @@ module Decidim
19
19
  def update_agenda_item(form_agenda_item)
20
20
  agenda_item_attributes = {
21
21
  title: form_agenda_item.title,
22
- description: form_agenda_item.description,
22
+ description: process_description(form_agenda_item.description),
23
23
  position: form_agenda_item.position,
24
24
  duration: form_agenda_item.duration,
25
25
  parent_id: form_agenda_item.parent_id
@@ -29,7 +29,7 @@ module Decidim
29
29
  form_agenda_item.agenda_item_children.each do |form_agenda_item_child|
30
30
  agenda_item_child_attributes = {
31
31
  title: form_agenda_item_child.title,
32
- description: form_agenda_item_child.description,
32
+ description: process_description(form_agenda_item_child.description),
33
33
  position: form_agenda_item_child.position,
34
34
  duration: form_agenda_item_child.duration,
35
35
  parent_id: agenda_item.id,
@@ -56,6 +56,10 @@ module Decidim
56
56
  record.save!
57
57
  end
58
58
  end
59
+
60
+ def process_description(description)
61
+ Decidim::ContentProcessor.parse(description, current_organization: form.current_organization).rewrite
62
+ end
59
63
  end
60
64
  end
61
65
  end
@@ -10,7 +10,7 @@ module Decidim
10
10
  :registration_url, :registrations_enabled, :address, :latitude, :longitude, :location,
11
11
  :location_hints, :taxonomizations,
12
12
  :private_meeting, :transparent, :iframe_embed_type, :comments_enabled,
13
- :comments_start_time, :comments_end_time, :iframe_access_level
13
+ :comments_start_time, :comments_end_time, :iframe_access_level, :reminder_enabled
14
14
 
15
15
  protected
16
16
 
@@ -22,12 +22,15 @@ module Decidim
22
22
  end
23
23
 
24
24
  def attributes
25
- parsed_title = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.title, current_organization: form.current_organization).rewrite
25
+ parsed_title = Decidim::ContentProcessor.parse(form.title, current_organization: form.current_organization).rewrite
26
26
  parsed_description = Decidim::ContentProcessor.parse(form.description, current_organization: form.current_organization).rewrite
27
+
27
28
  super.merge({
28
29
  title: parsed_title,
29
30
  description: parsed_description,
30
- type_of_meeting: form.clean_type_of_meeting
31
+ type_of_meeting: form.clean_type_of_meeting,
32
+ send_reminders_before_hours: form.reminder_enabled ? form.send_reminders_before_hours : nil,
33
+ reminder_message_custom_content: form.reminder_enabled ? form.reminder_message_custom_content : {}
31
34
  })
32
35
  end
33
36
 
@@ -48,7 +51,8 @@ module Decidim
48
51
  event: "decidim.events.meetings.meeting_updated",
49
52
  event_class: Decidim::Meetings::UpdateMeetingEvent,
50
53
  resource:,
51
- followers: resource.followers
54
+ followers: resource.followers,
55
+ extra: { changed_fields: resource.previous_changes.keys & important_attributes }
52
56
  )
53
57
  end
54
58
 
@@ -57,20 +61,25 @@ module Decidim
57
61
  end
58
62
 
59
63
  def important_attributes
60
- %w(start_time end_time address)
64
+ %w(start_time end_time address location)
61
65
  end
62
66
 
63
67
  def start_time_changed?
64
68
  resource.previous_changes["start_time"].present?
65
69
  end
66
70
 
71
+ def address_changed?
72
+ resource.previous_changes["address"].present? || resource.previous_changes["location"].present?
73
+ end
74
+
67
75
  def schedule_upcoming_meeting_notification
68
76
  return if resource.start_time < Time.zone.now
77
+ return unless resource.reminder_enabled
69
78
 
70
79
  checksum = Decidim::Meetings::UpcomingMeetingNotificationJob.generate_checksum(resource)
71
80
 
72
81
  Decidim::Meetings::UpcomingMeetingNotificationJob
73
- .set(wait_until: resource.start_time - Decidim::Meetings.upcoming_meeting_notification)
82
+ .set(wait_until: resource.start_time - resource.send_reminders_before_hours.hours)
74
83
  .perform_later(resource.id, checksum)
75
84
  end
76
85
  end
@@ -73,12 +73,12 @@ module Decidim
73
73
  }
74
74
 
75
75
  update_nested_model(form_question, question_attributes, @questionnaire.questions) do |question|
76
- form_question.answer_options.each do |form_answer_option|
77
- answer_option_attributes = {
78
- body: form_answer_option.body
76
+ form_question.response_options.each do |form_response_option|
77
+ response_option_attributes = {
78
+ body: form_response_option.body
79
79
  }
80
80
 
81
- update_nested_model(form_answer_option, answer_option_attributes, question.answer_options)
81
+ update_nested_model(form_response_option, response_option_attributes, question.response_options)
82
82
  end
83
83
  end
84
84
  end