decidim-meetings 0.22.0 → 0.23.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_meetings_manifest.js +1 -0
  3. data/app/assets/javascripts/decidim/meetings/admin/meetings_form.js.es6 +3 -0
  4. data/app/assets/javascripts/decidim/meetings/meetings_form.js.es6 +9 -0
  5. data/app/cells/decidim/meetings/content_blocks/upcoming_events_cell.rb +2 -1
  6. data/app/cells/decidim/meetings/highlighted_meetings_for_component_cell.rb +1 -1
  7. data/app/cells/decidim/meetings/meeting_cell.rb +1 -1
  8. data/app/cells/decidim/meetings/meeting_list_item_cell.rb +2 -2
  9. data/app/cells/decidim/meetings/meeting_m_cell.rb +9 -1
  10. data/app/cells/decidim/meetings/meetings_map/show.erb +0 -2
  11. data/app/cells/decidim/meetings/meetings_map_cell.rb +3 -1
  12. data/app/commands/decidim/meetings/admin/close_meeting.rb +1 -2
  13. data/app/commands/decidim/meetings/admin/copy_meeting.rb +38 -28
  14. data/app/commands/decidim/meetings/admin/create_meeting.rb +36 -24
  15. data/app/commands/decidim/meetings/admin/invite_user_to_join_meeting.rb +2 -1
  16. data/app/commands/decidim/meetings/admin/update_meeting.rb +9 -3
  17. data/app/commands/decidim/meetings/create_meeting.rb +78 -0
  18. data/app/commands/decidim/meetings/update_meeting.rb +94 -0
  19. data/app/controllers/decidim/meetings/admin/application_controller.rb +1 -1
  20. data/app/controllers/decidim/meetings/admin/meetings_controller.rb +11 -7
  21. data/app/controllers/decidim/meetings/admin/registration_form_controller.rb +4 -0
  22. data/app/controllers/decidim/meetings/meetings_controller.rb +76 -13
  23. data/app/controllers/decidim/meetings/registrations_controller.rb +1 -1
  24. data/app/controllers/decidim/meetings/versions_controller.rb +14 -0
  25. data/app/controllers/decidim/meetings/{meeting_widgets_controller.rb → widgets_controller.rb} +2 -2
  26. data/app/forms/decidim/meetings/admin/meeting_copy_form.rb +2 -8
  27. data/app/forms/decidim/meetings/admin/meeting_form.rb +24 -23
  28. data/app/forms/decidim/meetings/meeting_form.rb +78 -0
  29. data/app/helpers/decidim/meetings/admin/application_helper.rb +1 -6
  30. data/app/helpers/decidim/meetings/application_helper.rb +25 -0
  31. data/app/helpers/decidim/meetings/meetings_helper.rb +12 -0
  32. data/app/models/decidim/meetings/agenda.rb +3 -0
  33. data/app/models/decidim/meetings/agenda_item.rb +3 -0
  34. data/app/models/decidim/meetings/meeting.rb +69 -23
  35. data/app/models/decidim/meetings/minutes.rb +3 -0
  36. data/app/models/decidim/meetings/service.rb +13 -0
  37. data/app/permissions/decidim/meetings/admin/permissions.rb +2 -0
  38. data/app/permissions/decidim/meetings/permissions.rb +20 -0
  39. data/app/presenters/decidim/meetings/admin_log/invite_presenter.rb +5 -1
  40. data/app/presenters/decidim/meetings/admin_log/meeting_presenter.rb +3 -4
  41. data/app/presenters/decidim/meetings/meeting_presenter.rb +7 -3
  42. data/app/presenters/decidim/meetings/official_author_presenter.rb +14 -0
  43. data/app/queries/decidim/meetings/filtered_meetings.rb +1 -1
  44. data/app/services/decidim/meetings/diff_renderer.rb +21 -0
  45. data/app/services/decidim/meetings/meeting_search.rb +3 -25
  46. data/app/types/decidim/meetings/meeting_type.rb +1 -1
  47. data/app/views/decidim/meetings/admin/meeting_copies/_form.html.erb +2 -9
  48. data/app/views/decidim/meetings/admin/meetings/_form.html.erb +4 -11
  49. data/app/views/decidim/meetings/admin/meetings/edit.html.erb +1 -1
  50. data/app/views/decidim/meetings/admin/meetings/index.html.erb +4 -2
  51. data/app/views/decidim/meetings/directory/meetings/index.js.erb +11 -4
  52. data/app/views/decidim/meetings/meetings/_count.html.erb +1 -0
  53. data/app/views/decidim/meetings/meetings/_filters.html.erb +8 -10
  54. data/app/views/decidim/meetings/meetings/_form.html.erb +51 -0
  55. data/app/views/decidim/meetings/meetings/edit.html.erb +25 -0
  56. data/app/views/decidim/meetings/meetings/index.html.erb +15 -0
  57. data/app/views/decidim/meetings/meetings/index.js.erb +13 -4
  58. data/app/views/decidim/meetings/meetings/new.html.erb +25 -0
  59. data/app/views/decidim/meetings/meetings/show.html.erb +24 -9
  60. data/app/views/decidim/meetings/versions/index.html.erb +8 -0
  61. data/app/views/decidim/meetings/versions/show.html.erb +10 -0
  62. data/config/locales/am-ET.yml +1 -0
  63. data/config/locales/ar.yml +0 -8
  64. data/config/locales/bg-BG.yml +0 -8
  65. data/config/locales/bg.yml +21 -0
  66. data/config/locales/ca.yml +49 -7
  67. data/config/locales/cs.yml +57 -13
  68. data/config/locales/da.yml +1 -0
  69. data/config/locales/de.yml +113 -71
  70. data/config/locales/el.yml +2 -7
  71. data/config/locales/en.yml +49 -7
  72. data/config/locales/eo.yml +1 -0
  73. data/config/locales/es-MX.yml +49 -7
  74. data/config/locales/es-PY.yml +50 -8
  75. data/config/locales/es.yml +50 -8
  76. data/config/locales/et.yml +1 -0
  77. data/config/locales/eu.yml +0 -8
  78. data/config/locales/fi-plain.yml +49 -7
  79. data/config/locales/fi.yml +168 -126
  80. data/config/locales/fr-CA.yml +57 -7
  81. data/config/locales/fr.yml +57 -7
  82. data/config/locales/gl.yml +3 -7
  83. data/config/locales/hr.yml +1 -0
  84. data/config/locales/hu.yml +2 -7
  85. data/config/locales/id-ID.yml +0 -8
  86. data/config/locales/is-IS.yml +0 -7
  87. data/config/locales/is.yml +228 -0
  88. data/config/locales/it.yml +47 -7
  89. data/config/locales/ja-JP.yml +48 -9
  90. data/config/locales/ja.yml +496 -0
  91. data/config/locales/ko-KR.yml +1 -0
  92. data/config/locales/ko.yml +1 -0
  93. data/config/locales/lt.yml +1 -0
  94. data/config/locales/{lv-LV.yml → lv.yml} +2 -2
  95. data/config/locales/mt.yml +1 -0
  96. data/config/locales/nl.yml +49 -7
  97. data/config/locales/no.yml +34 -8
  98. data/config/locales/om-ET.yml +1 -0
  99. data/config/locales/pl.yml +193 -149
  100. data/config/locales/pt-BR.yml +1 -9
  101. data/config/locales/pt.yml +47 -7
  102. data/config/locales/ro-RO.yml +48 -7
  103. data/config/locales/ru.yml +0 -8
  104. data/config/locales/si-LK.yml +1 -0
  105. data/config/locales/sk.yml +2 -7
  106. data/config/locales/sl.yml +25 -2
  107. data/config/locales/so-SO.yml +1 -0
  108. data/config/locales/sv.yml +56 -8
  109. data/config/locales/sw-KE.yml +1 -0
  110. data/config/locales/ti-ER.yml +1 -0
  111. data/config/locales/tr-TR.yml +154 -98
  112. data/config/locales/uk.yml +0 -7
  113. data/config/locales/vi-VN.yml +1 -0
  114. data/config/locales/vi.yml +1 -0
  115. data/config/locales/zh-CN.yml +496 -0
  116. data/config/locales/zh-TW.yml +1 -0
  117. data/db/migrate/20200526110940_add_author_to_meetings.rb +30 -0
  118. data/db/migrate/20200702123209_create_meeting_services_table.rb +13 -0
  119. data/db/migrate/20200702123210_move_meeting_services_to_own_model.rb +31 -0
  120. data/db/migrate/20200827153856_add_commentable_counter_cache_to_meetings.rb +9 -0
  121. data/db/migrate/20201016065302_fix_meetings_registration_terms.rb +29 -0
  122. data/db/migrate/20201111133246_add_salt_to_decidim_meetings.rb +8 -0
  123. data/lib/decidim/api/services_interface.rb +1 -7
  124. data/lib/decidim/meetings/admin_engine.rb +2 -0
  125. data/lib/decidim/meetings/component.rb +63 -11
  126. data/lib/decidim/meetings/engine.rb +3 -2
  127. data/lib/decidim/meetings/meeting_serializer.rb +1 -1
  128. data/lib/decidim/meetings/test/factories.rb +45 -8
  129. data/lib/decidim/meetings/version.rb +1 -1
  130. metadata +62 -22
  131. data/app/presenters/decidim/meetings/admin_log/value_types/organizer_presenter.rb +0 -70
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ # This class holds a Form to create/update meetings for Participants and UserGroups.
6
+ class MeetingForm < Decidim::Form
7
+ attribute :title, String
8
+ attribute :description, String
9
+ attribute :location, String
10
+ attribute :location_hints, String
11
+
12
+ attribute :address, String
13
+ attribute :latitude, Float
14
+ attribute :longitude, Float
15
+ attribute :start_time, Decidim::Attributes::TimeWithZone
16
+ attribute :end_time, Decidim::Attributes::TimeWithZone
17
+ attribute :decidim_scope_id, Integer
18
+ attribute :decidim_category_id, Integer
19
+ attribute :user_group_id, Integer
20
+
21
+ validates :title, presence: true
22
+ validates :description, presence: true
23
+ validates :location, presence: true
24
+ validates :address, presence: true
25
+ validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? }
26
+ validates :start_time, presence: true, date: { before: :end_time }
27
+ validates :end_time, presence: true, date: { after: :start_time }
28
+
29
+ validates :current_component, presence: true
30
+ validates :category, presence: true, if: ->(form) { form.decidim_category_id.present? }
31
+ validates :scope, presence: true, if: ->(form) { form.decidim_scope_id.present? }
32
+ validates :decidim_scope_id, scope_belongs_to_component: true, if: ->(form) { form.decidim_scope_id.present? }
33
+
34
+ delegate :categories, to: :current_component
35
+
36
+ def map_model(model)
37
+ self.decidim_category_id = model.categorization.decidim_category_id if model.categorization
38
+ presenter = MeetingPresenter.new(model)
39
+ self.title = presenter.title(all_locales: false)
40
+ self.description = presenter.description(all_locales: false)
41
+ end
42
+
43
+ alias component current_component
44
+
45
+ # Finds the Scope from the given decidim_scope_id, uses the compoenent scope if missing.
46
+ #
47
+ # Returns a Decidim::Scope
48
+ def scope
49
+ @scope ||= @decidim_scope_id ? current_component.scopes.find_by(id: @decidim_scope_id) : current_component.scope
50
+ end
51
+
52
+ # Scope identifier
53
+ #
54
+ # Returns the scope identifier related to the meeting
55
+ def decidim_scope_id
56
+ @decidim_scope_id || scope&.id
57
+ end
58
+
59
+ def category
60
+ return unless current_component
61
+
62
+ @category ||= categories.find_by(id: decidim_category_id)
63
+ end
64
+
65
+ def geocoding_enabled?
66
+ Decidim::Map.available?(:geocoding)
67
+ end
68
+
69
+ def has_address?
70
+ geocoding_enabled? && address.present?
71
+ end
72
+
73
+ def geocoded?
74
+ latitude.present? && longitude.present?
75
+ end
76
+ end
77
+ end
78
+ end
@@ -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}"
@@ -11,6 +11,31 @@ module Decidim
11
11
  include Decidim::Meetings::MeetingsHelper
12
12
  include Decidim::Comments::CommentsHelper
13
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
14
39
  end
15
40
  end
16
41
  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,40 +10,72 @@ 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
23
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
24
28
 
25
- belongs_to :organizer, foreign_key: "organizer_id", class_name: "Decidim::User", optional: true
26
29
  has_many :registrations, class_name: "Decidim::Meetings::Registration", foreign_key: "decidim_meeting_id", dependent: :destroy
27
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
28
32
  has_one :minutes, class_name: "Decidim::Meetings::Minutes", foreign_key: "decidim_meeting_id", dependent: :destroy
29
33
  has_one :agenda, class_name: "Decidim::Meetings::Agenda", foreign_key: "decidim_meeting_id", dependent: :destroy
30
34
 
31
35
  component_manifest_name "meetings"
32
36
 
33
37
  validates :title, presence: true
34
- validate :organizer_belongs_to_organization
35
38
 
36
- geocoded_by :address, http_headers: ->(proposal) { { "Referer" => proposal.component.organization.host } }
39
+ geocoded_by :address
37
40
 
38
41
  scope :past, -> { where(arel_table[:end_time].lteq(Time.current)) }
39
42
  scope :upcoming, -> { where(arel_table[:end_time].gteq(Time.current)) }
40
43
 
41
44
  scope :visible_meeting_for, lambda { |user|
42
- joins("LEFT JOIN decidim_meetings_registrations ON
43
- decidim_meetings_registrations.decidim_meeting_id = #{table_name}.id")
44
- .where("(private_meeting = ? and decidim_meetings_registrations.decidim_user_id = ?)
45
- or private_meeting = ? or (private_meeting = ? and transparent = ?)", true, user, false, true, true).distinct
46
- }
45
+ (all.distinct if user&.admin?) ||
46
+ if user.present?
47
+ spaces = %w(assembly participatory_process)
48
+ spaces << "conference" if defined?(Decidim::Conference)
49
+ user_role_queries = spaces.map do |participatory_space_name|
50
+ "SELECT decidim_components.id FROM decidim_components
51
+ WHERE CONCAT(decidim_components.participatory_space_id, '-', decidim_components.participatory_space_type)
52
+ IN
53
+ (SELECT CONCAT(decidim_#{participatory_space_name}_user_roles.decidim_#{participatory_space_name}_id, '-Decidim::#{participatory_space_name.classify}')
54
+ FROM decidim_#{participatory_space_name}_user_roles WHERE decidim_#{participatory_space_name}_user_roles.decidim_user_id = ?)
55
+ "
56
+ end
57
+
58
+ where("decidim_meetings_meetings.private_meeting = ?
59
+ OR decidim_meetings_meetings.transparent = ?
60
+ OR decidim_meetings_meetings.id IN
61
+ (SELECT decidim_meetings_registrations.decidim_meeting_id FROM decidim_meetings_registrations WHERE decidim_meetings_registrations.decidim_user_id = ?)
62
+ OR decidim_meetings_meetings.decidim_component_id IN
63
+ (SELECT decidim_components.id FROM decidim_components
64
+ WHERE CONCAT(decidim_components.participatory_space_id, '-', decidim_components.participatory_space_type)
65
+ IN
66
+ (SELECT CONCAT(decidim_participatory_space_private_users.privatable_to_id, '-', decidim_participatory_space_private_users.privatable_to_type)
67
+ FROM decidim_participatory_space_private_users WHERE decidim_participatory_space_private_users.decidim_user_id = ?)
68
+ )
69
+ OR decidim_meetings_meetings.decidim_component_id IN
70
+ (
71
+ #{user_role_queries.compact.join(" UNION ")}
72
+ )
73
+ ", false, true, user.id, user.id, *user_role_queries.compact.map { user.id })
74
+ .distinct
75
+ else
76
+ visible
77
+ end
78
+ }
47
79
 
48
80
  scope :visible, -> { where("decidim_meetings_meetings.private_meeting != ? OR decidim_meetings_meetings.transparent = ?", true, true) }
49
81
 
@@ -57,6 +89,9 @@ module Decidim
57
89
  index_on_create: ->(meeting) { meeting.visible? },
58
90
  index_on_update: ->(meeting) { meeting.visible? })
59
91
 
92
+ # we create a salt for the meeting only on new meetings to prevent changing old IDs for existing (Ether)PADs
93
+ before_create :set_default_salt
94
+
60
95
  # Return registrations of a particular meeting made by users representing a group
61
96
  def user_group_registrations
62
97
  registrations.where.not(decidim_user_group_id: nil)
@@ -76,6 +111,11 @@ module Decidim
76
111
  !closed? && registrations_enabled? && can_participate?(user)
77
112
  end
78
113
 
114
+ def can_register_invitation?(user)
115
+ !closed? && registrations_enabled? &&
116
+ can_participate_in_space?(user) && user_has_invitation_for_meeting?(user)
117
+ end
118
+
79
119
  def closed?
80
120
  closed_at.present?
81
121
  end
@@ -133,19 +173,8 @@ module Decidim
133
173
  can_participate_in_space?(user) && can_participate_in_meeting?(user)
134
174
  end
135
175
 
136
- def organizer_belongs_to_organization
137
- return if !organizer || !organization
138
-
139
- errors.add(:organizer, :invalid) unless organizer.organization == organization
140
- end
141
-
142
- def official?
143
- organizer.nil?
144
- end
145
-
146
- def current_user_can_visit_meeting?(current_user)
147
- (private_meeting? && registrations.exists?(decidim_user_id: current_user.try(:id))) ||
148
- !private_meeting? || (private_meeting? && transparent?)
176
+ def current_user_can_visit_meeting?(user)
177
+ Decidim::Meetings::Meeting.visible_meeting_for(user).find_by(id: id)
149
178
  end
150
179
 
151
180
  # Return the duration of the meeting in minutes
@@ -184,6 +213,11 @@ module Decidim
184
213
  )
185
214
  end
186
215
 
216
+ # Public: Overrides the `reported_content_url` Reportable concern method.
217
+ def reported_content_url
218
+ ResourceLocatorPresenter.new(self).url
219
+ end
220
+
187
221
  private
188
222
 
189
223
  def can_participate_in_meeting?(user)
@@ -192,6 +226,18 @@ module Decidim
192
226
 
193
227
  registrations.exists?(decidim_user_id: user.id)
194
228
  end
229
+
230
+ def user_has_invitation_for_meeting?(user)
231
+ return true unless private_meeting?
232
+ return false unless user
233
+
234
+ invites.exists?(decidim_user_id: user.id)
235
+ end
236
+
237
+ # salt is used to generate secure hash in pads
238
+ def set_default_salt
239
+ self.salt ||= Tokenizer.random_salt
240
+ end
195
241
  end
196
242
  end
197
243
  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
 
@@ -51,8 +50,8 @@ module Decidim
51
50
  "activemodel.attributes.meeting"
52
51
  end
53
52
 
54
- def has_diff?
55
- action == "close" || super
53
+ def diff_actions
54
+ super + %w(close)
56
55
  end
57
56
  end
58
57
  end
@@ -79,10 +79,14 @@ module Decidim
79
79
 
80
80
  private
81
81
 
82
- def handle_locales(content, all_locales)
82
+ def handle_locales(content, all_locales, &block)
83
83
  if all_locales
84
- content.each_with_object({}) do |(locale, string), parsed_content|
85
- 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
86
90
  end
87
91
  else
88
92
  yield(translated_attribute(content))