decidim-meetings 0.19.1 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_meetings_manifest.js +2 -0
  3. data/app/assets/images/decidim/gamification/badges/attended_meetings.svg +1 -106
  4. data/app/assets/images/decidim/meetings/icon.svg +1 -5
  5. data/app/assets/javascripts/decidim/meetings/admin/destroy_meeting_alert.js.es6 +16 -0
  6. data/app/assets/javascripts/decidim/meetings/admin/meetings_form.js.es6 +3 -0
  7. data/app/assets/javascripts/decidim/meetings/meetings_form.js.es6 +9 -0
  8. data/app/cells/decidim/meetings/content_blocks/upcoming_events_cell.rb +2 -1
  9. data/app/cells/decidim/meetings/highlighted_meetings_for_component/show.erb +7 -7
  10. data/app/cells/decidim/meetings/highlighted_meetings_for_component_cell.rb +1 -1
  11. data/app/cells/decidim/meetings/join_meeting_button/show.erb +2 -2
  12. data/app/cells/decidim/meetings/meeting_cell.rb +1 -0
  13. data/app/cells/decidim/meetings/meeting_list_item/show.erb +3 -3
  14. data/app/cells/decidim/meetings/meeting_list_item_cell.rb +1 -1
  15. data/app/cells/decidim/meetings/meeting_m/date.erb +1 -1
  16. data/app/cells/decidim/meetings/meeting_m/footer.erb +1 -1
  17. data/app/cells/decidim/meetings/meeting_m/multiple_dates.erb +1 -1
  18. data/app/cells/decidim/meetings/meeting_m_cell.rb +9 -1
  19. data/app/cells/decidim/meetings/meeting_s/show.erb +6 -6
  20. data/app/cells/decidim/meetings/meetings_map/show.erb +0 -2
  21. data/app/cells/decidim/meetings/meetings_map_cell.rb +3 -1
  22. data/app/commands/decidim/meetings/admin/close_meeting.rb +1 -2
  23. data/app/commands/decidim/meetings/admin/copy_meeting.rb +38 -28
  24. data/app/commands/decidim/meetings/admin/create_meeting.rb +36 -24
  25. data/app/commands/decidim/meetings/admin/destroy_meeting.rb +6 -1
  26. data/app/commands/decidim/meetings/admin/invite_user_to_join_meeting.rb +2 -1
  27. data/app/commands/decidim/meetings/admin/update_meeting.rb +9 -3
  28. data/app/commands/decidim/meetings/create_meeting.rb +78 -0
  29. data/app/commands/decidim/meetings/join_meeting.rb +11 -0
  30. data/app/commands/decidim/meetings/update_meeting.rb +94 -0
  31. data/app/controllers/decidim/meetings/admin/application_controller.rb +1 -1
  32. data/app/controllers/decidim/meetings/admin/meeting_closes_controller.rb +2 -0
  33. data/app/controllers/decidim/meetings/admin/meetings_controller.rb +21 -7
  34. data/app/controllers/decidim/meetings/admin/registration_form_controller.rb +4 -0
  35. data/app/controllers/decidim/meetings/calendars_controller.rb +1 -0
  36. data/app/controllers/decidim/meetings/directory/meetings_controller.rb +1 -1
  37. data/app/controllers/decidim/meetings/meetings_controller.rb +75 -12
  38. data/app/controllers/decidim/meetings/registrations_controller.rb +2 -2
  39. data/app/controllers/decidim/meetings/versions_controller.rb +14 -0
  40. data/app/controllers/decidim/meetings/{meeting_widgets_controller.rb → widgets_controller.rb} +2 -2
  41. data/app/forms/decidim/meetings/admin/close_meeting_form.rb +7 -1
  42. data/app/forms/decidim/meetings/admin/meeting_copy_form.rb +2 -8
  43. data/app/forms/decidim/meetings/admin/meeting_form.rb +24 -23
  44. data/app/forms/decidim/meetings/meeting_form.rb +78 -0
  45. data/app/helpers/decidim/meetings/admin/application_helper.rb +1 -6
  46. data/app/helpers/decidim/meetings/application_helper.rb +26 -0
  47. data/app/helpers/decidim/meetings/map_helper.rb +2 -1
  48. data/app/helpers/decidim/meetings/meetings_helper.rb +13 -1
  49. data/app/models/decidim/meetings/agenda.rb +3 -0
  50. data/app/models/decidim/meetings/agenda_item.rb +3 -0
  51. data/app/models/decidim/meetings/meeting.rb +43 -15
  52. data/app/models/decidim/meetings/minutes.rb +3 -0
  53. data/app/models/decidim/meetings/service.rb +13 -0
  54. data/app/permissions/decidim/meetings/admin/permissions.rb +2 -0
  55. data/app/permissions/decidim/meetings/permissions.rb +20 -0
  56. data/app/presenters/decidim/meetings/admin_log/invite_presenter.rb +5 -1
  57. data/app/presenters/decidim/meetings/admin_log/meeting_presenter.rb +1 -2
  58. data/app/presenters/decidim/meetings/meeting_presenter.rb +21 -6
  59. data/app/presenters/decidim/meetings/official_author_presenter.rb +14 -0
  60. data/app/queries/decidim/meetings/filtered_meetings.rb +37 -0
  61. data/app/queries/decidim/meetings/metrics/meetings_metric_manage.rb +2 -8
  62. data/app/services/decidim/meetings/calendar/meeting_to_event.rb +3 -3
  63. data/app/services/decidim/meetings/diff_renderer.rb +21 -0
  64. data/app/services/decidim/meetings/meeting_search.rb +3 -25
  65. data/app/types/decidim/meetings/agenda_item_type.rb +28 -0
  66. data/app/types/decidim/meetings/agenda_type.rb +25 -0
  67. data/app/types/decidim/meetings/meeting_type.rb +35 -8
  68. data/app/types/decidim/meetings/meetings_type.rb +1 -1
  69. data/app/types/decidim/meetings/minutes_type.rb +26 -0
  70. data/app/types/decidim/meetings/service_type.rb +13 -0
  71. data/app/views/decidim/meetings/_calendar_modal.html.erb +4 -4
  72. data/app/views/decidim/meetings/admin/invites/index.html.erb +2 -2
  73. data/app/views/decidim/meetings/admin/meeting_closes/_form.html.erb +1 -6
  74. data/app/views/decidim/meetings/admin/meeting_closes/proposals_picker.html.erb +1 -0
  75. data/app/views/decidim/meetings/admin/meeting_copies/_form.html.erb +2 -9
  76. data/app/views/decidim/meetings/admin/meetings/_form.html.erb +8 -12
  77. data/app/views/decidim/meetings/admin/meetings/edit.html.erb +1 -1
  78. data/app/views/decidim/meetings/admin/meetings/index.html.erb +22 -3
  79. data/app/views/decidim/meetings/admin/registrations/_form.html.erb +4 -0
  80. data/app/views/decidim/meetings/directory/meetings/index.html.erb +5 -3
  81. data/app/views/decidim/meetings/directory/meetings/index.js.erb +11 -4
  82. data/app/views/decidim/meetings/meetings/_count.html.erb +1 -0
  83. data/app/views/decidim/meetings/meetings/_filters.html.erb +13 -7
  84. data/app/views/decidim/meetings/meetings/_form.html.erb +51 -0
  85. data/app/views/decidim/meetings/meetings/_linked_meetings.html.erb +2 -2
  86. data/app/views/decidim/meetings/meetings/_meeting_agenda.html.erb +2 -2
  87. data/app/views/decidim/meetings/meetings/_meeting_minutes.html.erb +8 -8
  88. data/app/views/decidim/meetings/meetings/edit.html.erb +25 -0
  89. data/app/views/decidim/meetings/meetings/index.html.erb +16 -1
  90. data/app/views/decidim/meetings/meetings/index.js.erb +13 -4
  91. data/app/views/decidim/meetings/meetings/new.html.erb +25 -0
  92. data/app/views/decidim/meetings/meetings/show.html.erb +30 -8
  93. data/app/views/decidim/meetings/versions/index.html.erb +8 -0
  94. data/app/views/decidim/meetings/versions/show.html.erb +10 -0
  95. data/app/views/decidim/participatory_processes/participatory_process_groups/_meeting.html.erb +2 -2
  96. data/app/views/decidim/participatory_spaces/_conference_venues.html.erb +1 -1
  97. data/app/views/decidim/participatory_spaces/_upcoming_meeting_for_card.html.erb +1 -3
  98. data/config/locales/am-ET.yml +1 -0
  99. data/config/locales/ar.yml +4 -8
  100. data/config/locales/bg-BG.yml +21 -0
  101. data/config/locales/bg.yml +21 -0
  102. data/config/locales/ca.yml +64 -8
  103. data/config/locales/cs.yml +70 -8
  104. data/config/locales/da-DK.yml +1 -0
  105. data/config/locales/da.yml +1 -0
  106. data/config/locales/de.yml +64 -7
  107. data/config/locales/el-GR.yml +1 -0
  108. data/config/locales/el.yml +449 -0
  109. data/config/locales/en.yml +65 -9
  110. data/config/locales/eo.yml +1 -0
  111. data/config/locales/es-MX.yml +63 -7
  112. data/config/locales/es-PY.yml +63 -7
  113. data/config/locales/es.yml +65 -9
  114. data/config/locales/et-EE.yml +1 -0
  115. data/config/locales/et.yml +1 -0
  116. data/config/locales/eu.yml +0 -8
  117. data/config/locales/fi-plain.yml +63 -7
  118. data/config/locales/fi.yml +89 -33
  119. data/config/locales/fr-CA.yml +504 -0
  120. data/config/locales/fr.yml +63 -7
  121. data/config/locales/ga-IE.yml +1 -0
  122. data/config/locales/gl.yml +0 -8
  123. data/config/locales/hr-HR.yml +1 -0
  124. data/config/locales/hr.yml +1 -0
  125. data/config/locales/hu.yml +14 -7
  126. data/config/locales/id-ID.yml +0 -8
  127. data/config/locales/is-IS.yml +228 -0
  128. data/config/locales/is.yml +228 -0
  129. data/config/locales/it.yml +62 -8
  130. data/config/locales/ja-JP.yml +494 -0
  131. data/config/locales/ja.yml +496 -0
  132. data/config/locales/ko-KR.yml +1 -0
  133. data/config/locales/ko.yml +1 -0
  134. data/config/locales/lt-LT.yml +1 -0
  135. data/config/locales/lt.yml +1 -0
  136. data/config/locales/lv.yml +452 -0
  137. data/config/locales/mt-MT.yml +1 -0
  138. data/config/locales/mt.yml +1 -0
  139. data/config/locales/nl.yml +95 -47
  140. data/config/locales/no.yml +358 -1
  141. data/config/locales/om-ET.yml +1 -0
  142. data/config/locales/pl.yml +210 -147
  143. data/config/locales/pt-BR.yml +1 -9
  144. data/config/locales/pt.yml +232 -177
  145. data/config/locales/ro-RO.yml +500 -0
  146. data/config/locales/ru.yml +0 -8
  147. data/config/locales/sk-SK.yml +463 -0
  148. data/config/locales/sk.yml +458 -0
  149. data/config/locales/sl.yml +29 -0
  150. data/config/locales/so-SO.yml +1 -0
  151. data/config/locales/sr-CS.yml +13 -0
  152. data/config/locales/sv.yml +67 -13
  153. data/config/locales/ti-ER.yml +1 -0
  154. data/config/locales/tr-TR.yml +0 -8
  155. data/config/locales/uk.yml +0 -8
  156. data/config/locales/vi-VN.yml +1 -0
  157. data/config/locales/vi.yml +1 -0
  158. data/config/locales/zh-CN.yml +496 -0
  159. data/config/locales/zh-TW.yml +1 -0
  160. data/db/migrate/20200320105922_index_foreign_keys_in_decidim_meetings_registrations.rb +7 -0
  161. data/db/migrate/20200526110940_add_author_to_meetings.rb +30 -0
  162. data/db/migrate/20200702123209_create_meeting_services_table.rb +13 -0
  163. data/db/migrate/20200702123210_move_meeting_services_to_own_model.rb +31 -0
  164. data/db/migrate/20200827153856_add_commentable_counter_cache_to_meetings.rb +9 -0
  165. data/db/migrate/20201016065302_fix_meetings_registration_terms.rb +29 -0
  166. data/lib/decidim/api/linked_resources_interface.rb +17 -0
  167. data/lib/decidim/api/services_interface.rb +13 -0
  168. data/lib/decidim/meetings.rb +1 -0
  169. data/lib/decidim/meetings/admin_engine.rb +5 -1
  170. data/lib/decidim/meetings/api.rb +8 -0
  171. data/lib/decidim/meetings/component.rb +69 -14
  172. data/lib/decidim/meetings/engine.rb +3 -6
  173. data/lib/decidim/meetings/meeting_serializer.rb +1 -1
  174. data/lib/decidim/meetings/seeds/city.jpeg +0 -0
  175. data/lib/decidim/meetings/test/factories.rb +45 -8
  176. data/lib/decidim/meetings/version.rb +1 -1
  177. data/lib/tasks/decidim_meetings.rake +16 -0
  178. metadata +92 -20
  179. data/app/presenters/decidim/meetings/admin_log/value_types/organizer_presenter.rb +0 -70
  180. data/app/views/decidim/meetings/meeting_widgets/show.html.erb +0 -9
@@ -7,12 +7,7 @@ module Decidim
7
7
  #
8
8
  module ApplicationHelper
9
9
  include Decidim::MapHelper
10
-
11
- def meeting_organizer_picker_text(form)
12
- return "" if form.object.organizer.blank?
13
-
14
- "#{form.object.organizer.name} (@#{form.object.organizer.nickname})"
15
- end
10
+ include Decidim::Admin::ResourceScopeHelper
16
11
 
17
12
  def tabs_id_for_service(service)
18
13
  "meeting_service_#{service.to_param}"
@@ -10,6 +10,32 @@ module Decidim
10
10
  include Decidim::Meetings::MapHelper
11
11
  include Decidim::Meetings::MeetingsHelper
12
12
  include Decidim::Comments::CommentsHelper
13
+ include Decidim::SanitizeHelper
14
+ include Decidim::CheckBoxesTreeHelper
15
+
16
+ def filter_origin_values
17
+ origin_values = []
18
+ origin_values << TreePoint.new("official", t("decidim.meetings.meetings.filters.origin_values.official"))
19
+ origin_values << TreePoint.new("citizens", t("decidim.meetings.meetings.filters.origin_values.citizens")) # todo
20
+ # if component_settings enabled enabled
21
+ origin_values << TreePoint.new("user_group", t("decidim.meetings.meetings.filters.origin_values.user_groups")) # todo
22
+ # if current_organization.user_groups_enabled? and component_settings enabled enabled
23
+
24
+ TreeNode.new(
25
+ TreePoint.new("", t("decidim.meetings.meetings.filters.origin_values.all")),
26
+ origin_values
27
+ )
28
+ end
29
+
30
+ def filter_date_values
31
+ TreeNode.new(
32
+ TreePoint.new("", t("decidim.meetings.meetings.filters.date_values.all")),
33
+ [
34
+ TreePoint.new("upcoming", t("decidim.meetings.meetings.filters.date_values.upcoming")),
35
+ TreePoint.new("past", t("decidim.meetings.meetings.filters.date_values.past"))
36
+ ]
37
+ )
38
+ end
13
39
  end
14
40
  end
15
41
  end
@@ -4,6 +4,7 @@ module Decidim
4
4
  module Meetings
5
5
  # This helper include some methods for rendering meetings dynamic maps.
6
6
  module MapHelper
7
+ include Decidim::SanitizeHelper
7
8
  # Serialize a collection of geocoded meetings to be used by the dynamic map component
8
9
  #
9
10
  # meetings - A collection of meetings
@@ -18,7 +19,7 @@ module Decidim
18
19
  startTime: "#{meeting.start_time.strftime("%H:%M")} - #{meeting.end_time.strftime("%H:%M")}",
19
20
  icon: icon("meetings", width: 40, height: 70, remove_icon_class: true),
20
21
  location: translated_attribute(meeting.location),
21
- locationHints: translated_attribute(meeting.location_hints),
22
+ locationHints: decidim_html_escape(translated_attribute(meeting.location_hints)),
22
23
  link: resource_locator(meeting).path)
23
24
  end
24
25
  end
@@ -16,7 +16,7 @@ module Decidim
16
16
  # Returns the meeting's description truncated.
17
17
  def meeting_description(meeting, max_length = 120)
18
18
  link = resource_locator(meeting).path
19
- description = present(meeting).description
19
+ description = CGI.unescapeHTML present(meeting).description
20
20
  tail = "... #{link_to(t("read_more", scope: "decidim.meetings"), link)}".html_safe
21
21
  CGI.unescapeHTML html_truncate(description, max_length: max_length, tail: tail)
22
22
  end
@@ -107,6 +107,18 @@ module Decidim
107
107
  t("validation_pending", scope: "decidim.meetings.meetings.show.registration_state")
108
108
  end
109
109
  end
110
+
111
+ def author_presenter_for(author)
112
+ if author.is_a?(Decidim::Organization)
113
+ Decidim::Meetings::OfficialAuthorPresenter.new
114
+ else
115
+ present(author)
116
+ end
117
+ end
118
+
119
+ def current_user_groups?
120
+ current_organization.user_groups_enabled? && Decidim::UserGroups::ManageableUserGroups.for(current_user).verified.any?
121
+ end
110
122
  end
111
123
  end
112
124
  end
@@ -7,6 +7,9 @@ module Decidim
7
7
  class Agenda < Meetings::ApplicationRecord
8
8
  include Decidim::Traceable
9
9
  include Decidim::Loggable
10
+ include Decidim::TranslatableResource
11
+
12
+ translatable_fields :title
10
13
 
11
14
  belongs_to :meeting, foreign_key: "decidim_meeting_id", class_name: "Decidim::Meetings::Meeting"
12
15
  has_many :agenda_items, foreign_key: "decidim_agenda_id", class_name: "Decidim::Meetings::AgendaItem", dependent: :destroy, inverse_of: :agenda
@@ -7,6 +7,9 @@ module Decidim
7
7
  class AgendaItem < Meetings::ApplicationRecord
8
8
  include Decidim::Traceable
9
9
  include Decidim::Loggable
10
+ include Decidim::TranslatableResource
11
+
12
+ translatable_fields :title, :description
10
13
 
11
14
  belongs_to :agenda, -> { order(:position) }, foreign_key: "decidim_agenda_id", class_name: "Decidim::Meetings::Agenda"
12
15
 
@@ -10,29 +10,33 @@ module Decidim
10
10
  include Decidim::HasAttachmentCollections
11
11
  include Decidim::HasComponent
12
12
  include Decidim::HasReference
13
- include Decidim::ScopableComponent
13
+ include Decidim::ScopableResource
14
14
  include Decidim::HasCategory
15
15
  include Decidim::Followable
16
16
  include Decidim::Comments::Commentable
17
17
  include Decidim::Searchable
18
18
  include Decidim::Traceable
19
19
  include Decidim::Loggable
20
- include Decidim::Hashtaggable
21
20
  include Decidim::Forms::HasQuestionnaire
22
21
  include Decidim::Paddable
22
+ include Decidim::ActsAsAuthor
23
+ include Decidim::Reportable
24
+ include Decidim::Authorable
25
+ include Decidim::TranslatableResource
26
+
27
+ translatable_fields :title, :description, :location, :location_hints, :closing_report, :registration_terms
23
28
 
24
- belongs_to :organizer, foreign_key: "organizer_id", class_name: "Decidim::User", optional: true
25
29
  has_many :registrations, class_name: "Decidim::Meetings::Registration", foreign_key: "decidim_meeting_id", dependent: :destroy
26
30
  has_many :invites, class_name: "Decidim::Meetings::Invite", foreign_key: "decidim_meeting_id", dependent: :destroy
31
+ has_many :services, class_name: "Decidim::Meetings::Service", foreign_key: "decidim_meeting_id", dependent: :destroy
27
32
  has_one :minutes, class_name: "Decidim::Meetings::Minutes", foreign_key: "decidim_meeting_id", dependent: :destroy
28
33
  has_one :agenda, class_name: "Decidim::Meetings::Agenda", foreign_key: "decidim_meeting_id", dependent: :destroy
29
34
 
30
35
  component_manifest_name "meetings"
31
36
 
32
37
  validates :title, presence: true
33
- validate :organizer_belongs_to_organization
34
38
 
35
- geocoded_by :address, http_headers: ->(proposal) { { "Referer" => proposal.component.organization.host } }
39
+ geocoded_by :address
36
40
 
37
41
  scope :past, -> { where(arel_table[:end_time].lteq(Time.current)) }
38
42
  scope :upcoming, -> { where(arel_table[:end_time].gteq(Time.current)) }
@@ -61,6 +65,12 @@ module Decidim
61
65
  registrations.where.not(decidim_user_group_id: nil)
62
66
  end
63
67
 
68
+ # Returns the presenter for this author, to be used in the views.
69
+ # Required by ActsAsAuthor.
70
+ def presenter
71
+ Decidim::Meetings::MeetingPresenter.new(self)
72
+ end
73
+
64
74
  def self.log_presenter_class_for(_log)
65
75
  Decidim::Meetings::AdminLog::MeetingPresenter
66
76
  end
@@ -69,6 +79,11 @@ module Decidim
69
79
  !closed? && registrations_enabled? && can_participate?(user)
70
80
  end
71
81
 
82
+ def can_register_invitation?(user)
83
+ !closed? && registrations_enabled? &&
84
+ can_participate_in_space?(user) && user_has_invitation_for_meeting?(user)
85
+ end
86
+
72
87
  def closed?
73
88
  closed_at.present?
74
89
  end
@@ -126,16 +141,6 @@ module Decidim
126
141
  can_participate_in_space?(user) && can_participate_in_meeting?(user)
127
142
  end
128
143
 
129
- def organizer_belongs_to_organization
130
- return if !organizer || !organization
131
-
132
- errors.add(:organizer, :invalid) unless organizer.organization == organization
133
- end
134
-
135
- def official?
136
- organizer.nil?
137
- end
138
-
139
144
  def current_user_can_visit_meeting?(current_user)
140
145
  (private_meeting? && registrations.exists?(decidim_user_id: current_user.try(:id))) ||
141
146
  !private_meeting? || (private_meeting? && transparent?)
@@ -166,6 +171,22 @@ module Decidim
166
171
  (Time.current - end_time) < 72.hours
167
172
  end
168
173
 
174
+ def authored_proposals
175
+ Decidim::Proposals::Proposal
176
+ .joins(:coauthorships)
177
+ .where(
178
+ decidim_coauthorships: {
179
+ decidim_author_type: "Decidim::Meetings::Meeting",
180
+ decidim_author_id: id
181
+ }
182
+ )
183
+ end
184
+
185
+ # Public: Overrides the `reported_content_url` Reportable concern method.
186
+ def reported_content_url
187
+ ResourceLocatorPresenter.new(self).url
188
+ end
189
+
169
190
  private
170
191
 
171
192
  def can_participate_in_meeting?(user)
@@ -174,6 +195,13 @@ module Decidim
174
195
 
175
196
  registrations.exists?(decidim_user_id: user.id)
176
197
  end
198
+
199
+ def user_has_invitation_for_meeting?(user)
200
+ return true unless private_meeting?
201
+ return false unless user
202
+
203
+ invites.exists?(decidim_user_id: user.id)
204
+ end
177
205
  end
178
206
  end
179
207
  end
@@ -6,6 +6,9 @@ module Decidim
6
6
  class Minutes < Meetings::ApplicationRecord
7
7
  include Decidim::Traceable
8
8
  include Decidim::Loggable
9
+ include Decidim::TranslatableResource
10
+
11
+ translatable_fields :description
9
12
 
10
13
  belongs_to :meeting, foreign_key: "decidim_meeting_id", class_name: "Decidim::Meetings::Meeting"
11
14
 
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ class Service < Meetings::ApplicationRecord
6
+ include Decidim::Traceable
7
+ include Decidim::TranslatableResource
8
+
9
+ translatable_fields :title, :description
10
+ belongs_to :meeting, foreign_key: "decidim_meeting_id", class_name: "Decidim::Meetings::Meeting"
11
+ end
12
+ end
13
+ end
@@ -37,6 +37,8 @@ module Decidim
37
37
  def allowed_meeting_action?
38
38
  return unless permission_action.subject == :meeting
39
39
 
40
+ return disallow! if meeting && !meeting.official?
41
+
40
42
  case permission_action.action
41
43
  when :close, :copy, :destroy, :export_registrations, :update, :read_invites
42
44
  toggle_allow(meeting.present?)
@@ -19,6 +19,12 @@ module Decidim
19
19
  toggle_allow(can_leave_meeting?)
20
20
  when :decline_invitation
21
21
  toggle_allow(can_decline_invitation?)
22
+ when :create
23
+ toggle_allow(can_create_meetings?)
24
+ when :update
25
+ toggle_allow(can_update_meeting?)
26
+ when :register
27
+ toggle_allow(can_register_invitation_meeting?)
22
28
  end
23
29
 
24
30
  permission_action
@@ -43,6 +49,20 @@ module Decidim
43
49
  meeting.registrations_enabled? &&
44
50
  meeting.invites.where(user: user).exists?
45
51
  end
52
+
53
+ def can_create_meetings?
54
+ component_settings&.creation_enabled_for_participants?
55
+ end
56
+
57
+ def can_update_meeting?
58
+ component_settings&.creation_enabled_for_participants? &&
59
+ meeting.authored_by?(user)
60
+ end
61
+
62
+ def can_register_invitation_meeting?
63
+ meeting.can_register_invitation?(user) &&
64
+ authorized?(:register, resource: meeting)
65
+ end
46
66
  end
47
67
  end
48
68
  end
@@ -24,9 +24,13 @@ module Decidim
24
24
  end
25
25
  end
26
26
 
27
+ # Tries to use the attendee name from the invitation (resource).
28
+ # If invitation does not exist anymore use the one in extras.
27
29
  def i18n_params
30
+ attendee_name = action_log.resource ? action_log.resource.user.name : action_log.extra["attendee_name"]
28
31
  super.merge(
29
- attendee_name: action_log.resource.user.name
32
+ # before Decidim v0.23.0 attendee_name was not being copied into the extras so it may be nil
33
+ attendee_name: attendee_name || "????"
30
34
  )
31
35
  end
32
36
  end
@@ -33,8 +33,7 @@ module Decidim
33
33
  start_date: :date,
34
34
  title: "Decidim::Meetings::AdminLog::ValueTypes::MeetingTitleDescriptionPresenter",
35
35
  private_meeting: :boolean,
36
- transparent: :boolean,
37
- organizer_id: "Decidim::Meetings::AdminLog::ValueTypes::OrganizerPresenter"
36
+ transparent: :boolean
38
37
  }
39
38
  end
40
39
 
@@ -18,8 +18,7 @@ module Decidim
18
18
  return unless meeting
19
19
 
20
20
  handle_locales(meeting.title, all_locales) do |content|
21
- content = decidim_html_escape(content)
22
- renderer = Decidim::ContentRenderers::HashtagRenderer.new(content)
21
+ renderer = Decidim::ContentRenderers::HashtagRenderer.new(decidim_html_escape(content))
23
22
  renderer.render(links: links).html_safe
24
23
  end
25
24
  end
@@ -28,7 +27,7 @@ module Decidim
28
27
  return unless meeting
29
28
 
30
29
  handle_locales(meeting.description, all_locales) do |content|
31
- renderer = Decidim::ContentRenderers::HashtagRenderer.new(content)
30
+ renderer = Decidim::ContentRenderers::HashtagRenderer.new(decidim_sanitize(content))
32
31
  renderer.render(links: links).html_safe
33
32
  end
34
33
  end
@@ -66,12 +65,28 @@ module Decidim
66
65
  false
67
66
  end
68
67
 
68
+ def proposals
69
+ return unless meeting
70
+
71
+ @proposals ||= meeting.authored_proposals.load
72
+ end
73
+
74
+ def formatted_proposals_titles
75
+ return unless meeting
76
+
77
+ proposals.map.with_index { |proposal, index| "#{index + 1}) #{proposal.title}\n" }
78
+ end
79
+
69
80
  private
70
81
 
71
- def handle_locales(content, all_locales)
82
+ def handle_locales(content, all_locales, &block)
72
83
  if all_locales
73
- content.each_with_object({}) do |(locale, string), parsed_content|
74
- parsed_content[locale] = yield(string)
84
+ content.each_with_object({}) do |(key, value), parsed_content|
85
+ parsed_content[key] = if key == "machine_translations"
86
+ handle_locales(value, all_locales, &block)
87
+ else
88
+ block.call(value)
89
+ end
75
90
  end
76
91
  else
77
92
  yield(translated_attribute(content))
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ #
6
+ # A dummy presenter to abstract out the author of an official meeting.
7
+ #
8
+ class OfficialAuthorPresenter < Decidim::OfficialAuthorPresenter
9
+ def name
10
+ I18n.t("decidim.meetings.models.meeting.fields.official_meeting")
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ # A class used to find meetings filtered by components and a date range
6
+ class FilteredMeetings < Rectify::Query
7
+ # Syntactic sugar to initialize the class and return the queried objects.
8
+ #
9
+ # components - An array of Decidim::Component
10
+ # start_at - A date to filter resources created after it
11
+ # end_at - A date to filter resources created before it.
12
+ def self.for(components, start_at = nil, end_at = nil)
13
+ new(components, start_at, end_at).query
14
+ end
15
+
16
+ # Initializes the class.
17
+ #
18
+ # components - An array of Decidim::Component
19
+ # start_at - A date to filter resources created after it
20
+ # end_at - A date to filter resources created before it.
21
+ def initialize(components, start_at = nil, end_at = nil)
22
+ @components = components
23
+ @start_at = start_at
24
+ @end_at = end_at
25
+ end
26
+
27
+ # Finds the Projects scoped to an array of components and filtered
28
+ # by a range of dates.
29
+ def query
30
+ meetings = Decidim::Meetings::Meeting.not_hidden.where(component: @components)
31
+ meetings = meetings.where("created_at >= ?", @start_at) if @start_at.present?
32
+ meetings = meetings.where("created_at <= ?", @end_at) if @end_at.present?
33
+ meetings
34
+ end
35
+ end
36
+ end
37
+ end
@@ -9,9 +9,6 @@ module Decidim
9
9
  end
10
10
 
11
11
  def save
12
- return @registry if @registry
13
-
14
- @registry = []
15
12
  cumulative.each do |key, cumulative_value|
16
13
  next if cumulative_value.zero?
17
14
 
@@ -21,10 +18,8 @@ module Decidim
21
18
  organization: @organization, decidim_category_id: category_id,
22
19
  participatory_space_type: space_type, participatory_space_id: space_id)
23
20
  record.assign_attributes(cumulative: cumulative_value, quantity: quantity_value)
24
- @registry << record
21
+ record.save!
25
22
  end
26
- @registry.each(&:save!)
27
- @registry
28
23
  end
29
24
 
30
25
  private
@@ -35,8 +30,7 @@ module Decidim
35
30
  spaces = Decidim.participatory_space_manifests.flat_map do |manifest|
36
31
  manifest.participatory_spaces.call(@organization).public_spaces
37
32
  end
38
- components = Decidim::Component.where(participatory_space: spaces).published
39
- @query = Decidim::Meetings::Meeting.where(component: components).joins(:component)
33
+ @query = Decidim::Meetings::Meeting.where(component: visible_component_ids_from_spaces(spaces)).joins(:component)
40
34
  .left_outer_joins(:category).visible
41
35
  @query = @query.where("decidim_meetings_meetings.created_at <= ?", end_time)
42
36
  @query = @query.group("decidim_categorizations.decidim_category_id",