decidim-meetings 0.25.0.rc4 → 0.26.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/meetings/content_blocks/highlighted_meetings/heading.erb +1 -1
  3. data/app/cells/decidim/meetings/content_blocks/highlighted_meetings_cell.rb +1 -1
  4. data/app/cells/decidim/meetings/content_blocks/{upcoming_events → upcoming_meetings}/show.erb +6 -6
  5. data/app/cells/decidim/meetings/content_blocks/{upcoming_events_cell.rb → upcoming_meetings_cell.rb} +11 -10
  6. data/app/cells/decidim/meetings/highlighted_meetings_for_component_cell.rb +1 -1
  7. data/app/cells/decidim/meetings/join_meeting_button_cell.rb +1 -1
  8. data/app/cells/decidim/meetings/meeting_list_item_cell.rb +10 -0
  9. data/app/cells/decidim/meetings/meeting_m_cell.rb +48 -0
  10. data/app/cells/decidim/meetings/meeting_s_cell.rb +22 -0
  11. data/app/cells/decidim/meetings/meetings_map_cell.rb +6 -0
  12. data/app/cells/decidim/meetings/online_meeting_cell.rb +23 -8
  13. data/app/cells/decidim/meetings/online_meeting_link/show.erb +2 -2
  14. data/app/cells/decidim/meetings/online_meeting_link_cell.rb +1 -5
  15. data/app/cells/decidim/meetings/public_participants_list_cell.rb +1 -0
  16. data/app/cells/decidim/meetings/question_responses_cell.rb +1 -1
  17. data/app/commands/decidim/meetings/admin/create_meeting.rb +11 -1
  18. data/app/commands/decidim/meetings/admin/publish_meeting.rb +3 -1
  19. data/app/commands/decidim/meetings/admin/update_meeting.rb +8 -2
  20. data/app/commands/decidim/meetings/create_meeting.rb +14 -2
  21. data/app/commands/decidim/meetings/update_meeting.rb +5 -2
  22. data/app/commands/decidim/meetings/withdraw_meeting.rb +39 -0
  23. data/app/controllers/concerns/decidim/meetings/filterable.rb +33 -0
  24. data/app/controllers/decidim/meetings/directory/application_controller.rb +16 -0
  25. data/app/controllers/decidim/meetings/directory/meetings_controller.rb +31 -20
  26. data/app/controllers/decidim/meetings/live_events_controller.rb +7 -1
  27. data/app/controllers/decidim/meetings/meetings_controller.rb +19 -17
  28. data/app/events/decidim/meetings/close_meeting_event.rb +1 -3
  29. data/app/events/decidim/meetings/create_meeting_event.rb +2 -4
  30. data/app/events/decidim/meetings/meeting_event.rb +37 -0
  31. data/app/events/decidim/meetings/meeting_registrations_enabled_event.rb +1 -3
  32. data/app/events/decidim/meetings/meeting_registrations_over_percentage_event.rb +2 -4
  33. data/app/events/decidim/meetings/registration_code_validated_event.rb +2 -4
  34. data/app/events/decidim/meetings/upcoming_meeting_event.rb +1 -3
  35. data/app/events/decidim/meetings/update_meeting_event.rb +1 -3
  36. data/app/forms/decidim/meetings/admin/close_meeting_form.rb +1 -1
  37. data/app/forms/decidim/meetings/admin/meeting_copy_form.rb +4 -13
  38. data/app/forms/decidim/meetings/admin/meeting_form.rb +34 -46
  39. data/app/forms/decidim/meetings/base_meeting_form.rb +59 -0
  40. data/app/forms/decidim/meetings/close_meeting_form.rb +6 -6
  41. data/app/forms/decidim/meetings/meeting_form.rb +30 -46
  42. data/app/helpers/decidim/meetings/application_helper.rb +13 -1
  43. data/app/helpers/decidim/meetings/directory/application_helper.rb +150 -0
  44. data/app/helpers/decidim/meetings/meeting_cells_helper.rb +4 -1
  45. data/app/helpers/decidim/meetings/meetings_helper.rb +3 -0
  46. data/app/models/decidim/meetings/meeting.rb +53 -1
  47. data/app/packs/src/decidim/meetings/admin/meetings_form.js +27 -11
  48. data/app/packs/src/decidim/meetings/meetings_form.js +19 -0
  49. data/app/packs/src/decidim/meetings/meetings_polls.js +31 -26
  50. data/app/permissions/decidim/meetings/permissions.rb +9 -1
  51. data/app/presenters/decidim/meetings/meeting_edition_presenter.rb +14 -0
  52. data/app/presenters/decidim/meetings/meeting_presenter.rb +13 -6
  53. data/app/services/decidim/meetings/diff_renderer.rb +4 -4
  54. data/app/services/decidim/meetings/directory/meeting_search.rb +53 -0
  55. data/app/services/decidim/meetings/meeting_iframe_embedder.rb +1 -1
  56. data/app/services/decidim/meetings/meeting_search.rb +15 -2
  57. data/app/views/decidim/meetings/admin/meeting_copies/_form.html.erb +16 -1
  58. data/app/views/decidim/meetings/admin/meeting_copies/new.html.erb +1 -1
  59. data/app/views/decidim/meetings/admin/meetings/_form.html.erb +15 -3
  60. data/app/views/decidim/meetings/directory/meetings/_filters.html.erb +34 -0
  61. data/app/views/decidim/meetings/directory/meetings/index.html.erb +1 -18
  62. data/app/views/decidim/meetings/meetings/_filters.html.erb +2 -0
  63. data/app/views/decidim/meetings/meetings/_filters_small_view.html.erb +3 -3
  64. data/app/views/decidim/meetings/meetings/_form.html.erb +14 -3
  65. data/app/views/decidim/meetings/meetings/_linked_meetings.html.erb +1 -1
  66. data/app/views/decidim/meetings/meetings/_meetings.html.erb +18 -0
  67. data/app/views/decidim/meetings/meetings/index.html.erb +1 -0
  68. data/app/views/decidim/meetings/meetings/show.html.erb +12 -13
  69. data/config/locales/ar.yml +2 -9
  70. data/config/locales/ca.yml +87 -22
  71. data/config/locales/cs.yml +83 -13
  72. data/config/locales/de.yml +2 -11
  73. data/config/locales/el.yml +2 -9
  74. data/config/locales/en.yml +41 -13
  75. data/config/locales/es-MX.yml +96 -9
  76. data/config/locales/es-PY.yml +96 -9
  77. data/config/locales/es.yml +136 -8
  78. data/config/locales/eu.yml +230 -11
  79. data/config/locales/fi-plain.yml +82 -13
  80. data/config/locales/fi.yml +83 -13
  81. data/config/locales/fr-CA.yml +114 -11
  82. data/config/locales/fr.yml +118 -14
  83. data/config/locales/ga-IE.yml +213 -0
  84. data/config/locales/gl.yml +30 -11
  85. data/config/locales/hu.yml +2 -9
  86. data/config/locales/id-ID.yml +2 -9
  87. data/config/locales/it.yml +43 -13
  88. data/config/locales/ja.yml +86 -16
  89. data/config/locales/lb-LU.yml +210 -0
  90. data/config/locales/lb.yml +410 -0
  91. data/config/locales/lv.yml +2 -9
  92. data/config/locales/nl.yml +66 -13
  93. data/config/locales/no.yml +2 -9
  94. data/config/locales/pl.yml +36 -11
  95. data/config/locales/pt-BR.yml +4 -14
  96. data/config/locales/pt.yml +153 -9
  97. data/config/locales/ro-RO.yml +193 -101
  98. data/config/locales/ru.yml +0 -8
  99. data/config/locales/sk.yml +2 -9
  100. data/config/locales/sl.yml +0 -3
  101. data/config/locales/sv.yml +108 -9
  102. data/config/locales/tr-TR.yml +2 -9
  103. data/config/locales/val-ES.yml +1 -0
  104. data/config/locales/zh-CN.yml +2 -9
  105. data/db/migrate/20210519133705_add_comments_availability_columns_to_meetings_table.rb +14 -0
  106. data/db/migrate/20210727085318_add_state_field_to_meeting.rb +7 -0
  107. data/db/migrate/20210903143040_add_iframe_access_level_to_decidim_meetings.rb +7 -0
  108. data/db/migrate/20210922140454_transform_show_embedded_iframe_column.rb +15 -0
  109. data/db/migrate/20210928095036_rename_upcoming_events_content_block_to_upcoming_meetings.rb +13 -0
  110. data/lib/decidim/api/meeting_type.rb +2 -1
  111. data/lib/decidim/meetings/component.rb +17 -7
  112. data/lib/decidim/meetings/directory_engine.rb +3 -3
  113. data/lib/decidim/meetings/engine.rb +8 -1
  114. data/lib/decidim/meetings/meeting_serializer.rb +2 -2
  115. data/lib/decidim/meetings/test/factories.rb +24 -3
  116. data/lib/decidim/meetings/test/notifications_handling.rb +39 -0
  117. data/lib/decidim/meetings/test/translated_event.rb +22 -0
  118. data/lib/decidim/meetings/version.rb +1 -1
  119. data/lib/decidim/meetings.rb +5 -0
  120. metadata +38 -20
@@ -4,10 +4,11 @@ module Decidim
4
4
  module Meetings
5
5
  module Directory
6
6
  # Exposes the meeting resource so users can view them
7
- class MeetingsController < Decidim::ApplicationController
7
+ class MeetingsController < Decidim::Meetings::Directory::ApplicationController
8
8
  layout "layouts/decidim/application"
9
9
 
10
10
  include FilterResource
11
+ include Filterable
11
12
  include Paginable
12
13
 
13
14
  helper Decidim::WidgetUrlsHelper
@@ -17,17 +18,6 @@ module Decidim
17
18
 
18
19
  helper_method :meetings, :search
19
20
 
20
- def index
21
- @meeting_spaces = search.results.map do |meeting|
22
- klass = meeting.component.participatory_space.class
23
- [klass.model_name.name.underscore, klass.model_name.human(count: 2)]
24
- end.uniq
25
- @meeting_spaces = @meeting_spaces.sort_by do |_param, name|
26
- name
27
- end
28
- @meeting_spaces.prepend(["all", t(".all")])
29
- end
30
-
31
21
  def calendar
32
22
  render plain: CalendarRenderer.for(current_organization), content_type: "type/calendar"
33
23
  end
@@ -39,26 +29,47 @@ module Decidim
39
29
  end
40
30
 
41
31
  def search_klass
42
- MeetingSearch
32
+ ::Decidim::Meetings::Directory::MeetingSearch
43
33
  end
44
34
 
45
35
  def default_filter_params
46
36
  {
47
37
  date: "upcoming",
48
38
  search_text: "",
49
- scope_id: "",
50
- space: "all"
39
+ activity: "all",
40
+ scope_id: default_filter_scope_params,
41
+ space: default_filter_space_params,
42
+ type: default_filter_type_params,
43
+ origin: default_filter_origin_params,
44
+ category_id: default_filter_category_params
51
45
  }
52
46
  end
53
47
 
54
- def default_search_params
55
- {
56
- scope: Meeting.not_hidden.visible_meeting_for(current_user)
57
- }
48
+ def default_filter_category_params
49
+ participatory_spaces = current_organization.public_participatory_spaces
50
+ list_of_ps = []
51
+ participatory_spaces.flat_map do |current_participatory_space|
52
+ next unless current_participatory_space.respond_to?(:categories)
53
+
54
+ key_point = current_participatory_space.class.name.gsub("::", "__") + current_participatory_space.id.to_s
55
+
56
+ list_of_ps.push(key_point)
57
+ list_of_ps += current_participatory_space.categories.pluck(:id).map(&:to_s)
58
+ end
59
+
60
+ ["all"] + list_of_ps
61
+ end
62
+
63
+ def default_filter_space_params
64
+ %w(all) + current_organization.public_participatory_spaces.collect(&:model_name).uniq.collect(&:name).collect(&:underscore)
65
+ end
66
+
67
+ def default_filter_scope_params
68
+ %w(all global) + current_organization.scopes.pluck(:id).map(&:to_s)
58
69
  end
59
70
 
60
71
  def context_params
61
- { component: meeting_components, organization: current_organization }
72
+ { component: meeting_components, organization: current_organization, current_user: current_user }
62
73
  end
63
74
 
64
75
  def meeting_components
@@ -13,7 +13,7 @@ module Decidim
13
13
  def show
14
14
  raise ActionController::RoutingError, "Not Found" unless meeting
15
15
 
16
- return if meeting.current_user_can_visit_meeting?(current_user)
16
+ return if allowed_for_current_user?
17
17
 
18
18
  flash[:alert] = I18n.t("meeting.not_allowed", scope: "decidim.meetings")
19
19
  redirect_to(ResourceLocatorPresenter.new(meeting).index)
@@ -21,6 +21,12 @@ module Decidim
21
21
 
22
22
  private
23
23
 
24
+ def allowed_for_current_user?
25
+ meeting.current_user_can_visit_meeting?(current_user) &&
26
+ meeting.iframe_access_level_allowed_for_user?(current_user) &&
27
+ meeting.live?
28
+ end
29
+
24
30
  def live_meeting_embed_code
25
31
  MeetingIframeEmbedder.new(meeting.online_meeting_url).embed_code(request.host)
26
32
  end
@@ -5,9 +5,12 @@ module Decidim
5
5
  # Exposes the meeting resource so users can view them
6
6
  class MeetingsController < Decidim::Meetings::ApplicationController
7
7
  include FilterResource
8
+ include Filterable
8
9
  include Flaggable
10
+ include Withdrawable
9
11
  include FormFactory
10
12
  include Paginable
13
+
11
14
  helper Decidim::WidgetUrlsHelper
12
15
  helper Decidim::ResourceVersionsHelper
13
16
 
@@ -83,6 +86,21 @@ module Decidim
83
86
  end
84
87
  end
85
88
 
89
+ def withdraw
90
+ enforce_permission_to :withdraw, :meeting, meeting: meeting
91
+
92
+ WithdrawMeeting.call(@meeting, current_user) do
93
+ on(:ok) do
94
+ flash[:notice] = I18n.t("meetings.withdraw.success", scope: "decidim")
95
+ redirect_to Decidim::ResourceLocatorPresenter.new(@meeting).path
96
+ end
97
+ on(:invalid) do
98
+ flash[:alert] = I18n.t("meetings.withdraw.error", scope: "decidim")
99
+ redirect_to Decidim::ResourceLocatorPresenter.new(@meeting).path
100
+ end
101
+ end
102
+ end
103
+
86
104
  private
87
105
 
88
106
  def meeting
@@ -112,27 +130,11 @@ module Decidim
112
130
  activity: "all",
113
131
  scope_id: default_filter_scope_params,
114
132
  category_id: default_filter_category_params,
133
+ state: nil,
115
134
  origin: default_filter_origin_params,
116
135
  type: default_filter_type_params
117
136
  }
118
137
  end
119
-
120
- def default_filter_origin_params
121
- filter_origin_params = %w(citizens)
122
- filter_origin_params << "official"
123
- filter_origin_params << "user_group" if current_organization.user_groups_enabled?
124
- filter_origin_params
125
- end
126
-
127
- def default_filter_type_params
128
- %w(all) + Decidim::Meetings::Meeting::TYPE_OF_MEETING
129
- end
130
-
131
- def default_search_params
132
- {
133
- scope: Meeting.not_hidden.visible_meeting_for(current_user)
134
- }
135
- end
136
138
  end
137
139
  end
138
140
  end
@@ -3,9 +3,7 @@
3
3
  module Decidim
4
4
  module Meetings
5
5
  class CloseMeetingEvent < Decidim::Events::SimpleEvent
6
- def resource_text
7
- translated_attribute(resource.description)
8
- end
6
+ include Decidim::Meetings::MeetingEvent
9
7
 
10
8
  def event_has_roles?
11
9
  true
@@ -3,11 +3,9 @@
3
3
  module Decidim
4
4
  module Meetings
5
5
  class CreateMeetingEvent < Decidim::Events::SimpleEvent
6
- delegate :organization, to: :user, prefix: false
6
+ include Decidim::Meetings::MeetingEvent
7
7
 
8
- def resource_text
9
- translated_attribute(resource.description)
10
- end
8
+ delegate :organization, to: :user, prefix: false
11
9
 
12
10
  def button_text
13
11
  I18n.t("meeting_created.button_text", scope: "decidim.events.meetings") if resource.can_be_joined_by?(user)
@@ -0,0 +1,37 @@
1
+ # frozen-string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ # This module is used to be included in events triggered by comments.
6
+ #
7
+ module MeetingEvent
8
+ extend ActiveSupport::Concern
9
+ include Decidim::Events::MachineTranslatedEvent
10
+
11
+ included do
12
+ def resource_text
13
+ translated_attribute(resource.description)
14
+ end
15
+
16
+ def translatable_resource
17
+ resource
18
+ end
19
+
20
+ def translatable_text
21
+ resource.description
22
+ end
23
+
24
+ def safe_resource_text
25
+ locale = resource.respond_to?(:content_original_language) ? resource.content_original_language : I18n.locale
26
+ I18n.with_locale(locale) { translated_attribute(resource.description).to_s.html_safe }
27
+ end
28
+
29
+ def safe_resource_translated_text
30
+ return safe_resource_text unless perform_translation?
31
+
32
+ I18n.with_locale(I18n.locale) { translated_attribute(resource.description, nil, true).to_s.html_safe }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -3,9 +3,7 @@
3
3
  module Decidim
4
4
  module Meetings
5
5
  class MeetingRegistrationsEnabledEvent < Decidim::Events::SimpleEvent
6
- def resource_text
7
- translated_attribute(resource.description)
8
- end
6
+ include Decidim::Meetings::MeetingEvent
9
7
  end
10
8
  end
11
9
  end
@@ -3,11 +3,9 @@
3
3
  module Decidim
4
4
  module Meetings
5
5
  class MeetingRegistrationsOverPercentageEvent < Decidim::Events::SimpleEvent
6
- i18n_attributes :percentage
6
+ include Decidim::Meetings::MeetingEvent
7
7
 
8
- def resource_text
9
- translated_attribute(resource.description)
10
- end
8
+ i18n_attributes :percentage
11
9
 
12
10
  def percentage
13
11
  extra["percentage"] * 100
@@ -3,11 +3,9 @@
3
3
  module Decidim
4
4
  module Meetings
5
5
  class RegistrationCodeValidatedEvent < Decidim::Events::SimpleEvent
6
- i18n_attributes :registration_code
6
+ include Decidim::Meetings::MeetingEvent
7
7
 
8
- def resource_text
9
- translated_attribute(resource.description)
10
- end
8
+ i18n_attributes :registration_code
11
9
 
12
10
  private
13
11
 
@@ -3,9 +3,7 @@
3
3
  module Decidim
4
4
  module Meetings
5
5
  class UpcomingMeetingEvent < Decidim::Events::SimpleEvent
6
- def resource_text
7
- translated_attribute(resource.description)
8
- end
6
+ include Decidim::Meetings::MeetingEvent
9
7
  end
10
8
  end
11
9
  end
@@ -3,9 +3,7 @@
3
3
  module Decidim
4
4
  module Meetings
5
5
  class UpdateMeetingEvent < Decidim::Events::SimpleEvent
6
- def resource_text
7
- translated_attribute(resource.description)
8
- end
6
+ include Decidim::Meetings::MeetingEvent
9
7
  end
10
8
  end
11
9
  end
@@ -19,7 +19,7 @@ module Decidim
19
19
  attribute :closed_at, Decidim::Attributes::TimeWithZone, default: ->(_form, _attribute) { Time.current }
20
20
 
21
21
  validates :closing_report, translatable_presence: true
22
- validates :attendees_count, presence: true, numericality: { greater_than_or_equal_to: 0 }
22
+ validates :attendees_count, presence: true, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 999, only_integer: true }
23
23
  validates :contributions_count, numericality: true, allow_blank: true
24
24
 
25
25
  # Private: Gets the proposals from the meeting and injects them to the form.
@@ -6,7 +6,7 @@ module Decidim
6
6
  # A form object used to copy a meeting from the admin
7
7
  # dashboard.
8
8
  #
9
- class MeetingCopyForm < Form
9
+ class MeetingCopyForm < ::Decidim::Meetings::BaseMeetingForm
10
10
  include TranslatableAttributes
11
11
 
12
12
  translatable_attribute :title, String
@@ -14,26 +14,17 @@ module Decidim
14
14
  translatable_attribute :location, String
15
15
  translatable_attribute :location_hints, String
16
16
 
17
- attribute :address, String
18
- attribute :latitude, Float
19
- attribute :longitude, Float
20
- attribute :start_time, Decidim::Attributes::TimeWithZone
21
- attribute :end_time, Decidim::Attributes::TimeWithZone
17
+ attribute :show_embedded_iframe, Boolean, default: false
22
18
  attribute :private_meeting, Boolean
23
19
  attribute :transparent, Boolean
24
20
  attribute :services, Array[MeetingServiceForm]
25
21
 
26
22
  mimic :meeting
27
23
 
28
- validates :current_component, presence: true
29
-
24
+ validates :online_meeting_url, url: true, if: ->(form) { form.online_meeting? || form.hybrid_meeting? }
30
25
  validates :title, translatable_presence: true
31
26
  validates :description, translatable_presence: true
32
- validates :location, translatable_presence: true
33
- validates :address, presence: true
34
- validates :address, geocoding: true, if: -> { Decidim::Map.available?(:geocoding) }
35
- validates :start_time, presence: true, date: { before: :end_time }
36
- validates :end_time, presence: true, date: { after: :start_time }
27
+ validates :location, translatable_presence: true, if: ->(form) { form.in_person_meeting? || form.hybrid_meeting? }
37
28
 
38
29
  def map_model(model)
39
30
  self.services = model.services.map do |service|
@@ -4,26 +4,23 @@ module Decidim
4
4
  module Meetings
5
5
  module Admin
6
6
  # This class holds a Form to create/update translatable meetings from Decidim's admin panel.
7
- class MeetingForm < Decidim::Form
7
+ class MeetingForm < ::Decidim::Meetings::BaseMeetingForm
8
8
  include TranslatableAttributes
9
9
 
10
- attribute :address, String
11
- attribute :latitude, Float
12
- attribute :longitude, Float
13
- attribute :start_time, Decidim::Attributes::TimeWithZone
14
- attribute :end_time, Decidim::Attributes::TimeWithZone
15
10
  attribute :services, Array[MeetingServiceForm]
16
11
  attribute :decidim_scope_id, Integer
17
12
  attribute :decidim_category_id, Integer
18
13
  attribute :private_meeting, Boolean
19
14
  attribute :transparent, Boolean
20
- attribute :online_meeting_url, String
21
- attribute :type_of_meeting, String
22
15
  attribute :registration_type, String
23
16
  attribute :registration_url, String
24
17
  attribute :available_slots, Integer, default: 0
25
18
  attribute :customize_registration_email, Boolean
26
- attribute :show_embedded_iframe, Boolean, default: false
19
+ attribute :iframe_embed_type, String, default: "none"
20
+ attribute :comments_enabled, Boolean, default: true
21
+ attribute :comments_start_time, Decidim::Attributes::TimeWithZone
22
+ attribute :comments_end_time, Decidim::Attributes::TimeWithZone
23
+ attribute :iframe_access_level, String
27
24
 
28
25
  translatable_attribute :title, String
29
26
  translatable_attribute :description, String
@@ -31,6 +28,7 @@ module Decidim
31
28
  translatable_attribute :location_hints, String
32
29
  translatable_attribute :registration_email_custom_content, String
33
30
 
31
+ validates :iframe_embed_type, inclusion: { in: Decidim::Meetings::Meeting.iframe_embed_types }
34
32
  validates :title, translatable_presence: true
35
33
  validates :description, translatable_presence: true
36
34
  validates :registration_type, presence: true
@@ -38,18 +36,18 @@ module Decidim
38
36
  validates :registration_url, presence: true, url: true, if: ->(form) { form.on_different_platform? }
39
37
  validates :type_of_meeting, presence: true
40
38
  validates :location, translatable_presence: true, if: ->(form) { form.in_person_meeting? || form.hybrid_meeting? }
41
-
42
- validates :address, presence: true, if: ->(form) { form.needs_address? }
43
- validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? && form.needs_address? }
44
39
  validates :online_meeting_url, url: true, if: ->(form) { form.online_meeting? || form.hybrid_meeting? }
45
- validates :start_time, presence: true, date: { before: :end_time }
46
- validates :end_time, presence: true, date: { after: :start_time }
47
-
48
- validates :current_component, presence: true
40
+ validates :comments_start_time, date: { before: :comments_end_time, allow_blank: true, if: proc { |obj| obj.comments_end_time.present? } }
41
+ validates :comments_end_time, date: { after: :comments_start_time, allow_blank: true, if: proc { |obj| obj.comments_start_time.present? } }
49
42
  validates :category, presence: true, if: ->(form) { form.decidim_category_id.present? }
50
43
  validates :scope, presence: true, if: ->(form) { form.decidim_scope_id.present? }
51
44
  validates :decidim_scope_id, scope_belongs_to_component: true, if: ->(form) { form.decidim_scope_id.present? }
52
45
  validates :clean_type_of_meeting, presence: true
46
+ validates(
47
+ :iframe_access_level,
48
+ inclusion: { in: Decidim::Meetings::Meeting.iframe_access_levels },
49
+ if: ->(form) { %w(embed_in_meeting_page open_in_live_event_page open_in_new_tab).include?(form.iframe_embed_type) }
50
+ )
53
51
  validate :embeddable_meeting_url
54
52
 
55
53
  delegate :categories, to: :current_component
@@ -97,34 +95,6 @@ module Decidim
97
95
  @category ||= categories.find_by(id: decidim_category_id)
98
96
  end
99
97
 
100
- def geocoding_enabled?
101
- Decidim::Map.available?(:geocoding)
102
- end
103
-
104
- def has_address?
105
- geocoding_enabled? && address.present?
106
- end
107
-
108
- def needs_address?
109
- in_person_meeting? || hybrid_meeting?
110
- end
111
-
112
- def geocoded?
113
- latitude.present? && longitude.present?
114
- end
115
-
116
- def online_meeting?
117
- type_of_meeting == "online"
118
- end
119
-
120
- def in_person_meeting?
121
- type_of_meeting == "in_person"
122
- end
123
-
124
- def hybrid_meeting?
125
- type_of_meeting == "hybrid"
126
- end
127
-
128
98
  def clean_type_of_meeting
129
99
  type_of_meeting.presence
130
100
  end
@@ -138,6 +108,24 @@ module Decidim
138
108
  end
139
109
  end
140
110
 
111
+ def iframe_access_level_select
112
+ Decidim::Meetings::Meeting.iframe_access_levels.map do |level, _value|
113
+ [
114
+ I18n.t("iframe_access_level.#{level}", scope: "decidim.meetings"),
115
+ level
116
+ ]
117
+ end
118
+ end
119
+
120
+ def iframe_embed_type_select
121
+ Decidim::Meetings::Meeting.iframe_embed_types.map do |type, _value|
122
+ [
123
+ I18n.t("iframe_embed_type.#{type}", scope: "decidim.meetings"),
124
+ type
125
+ ]
126
+ end
127
+ end
128
+
141
129
  def on_this_platform?
142
130
  registration_type == "on_this_platform"
143
131
  end
@@ -156,9 +144,9 @@ module Decidim
156
144
  end
157
145
 
158
146
  def embeddable_meeting_url
159
- if online_meeting_url.present? && show_embedded_iframe
147
+ if online_meeting_url.present? && %w(embed_in_meeting_page open_in_live_event_page).include?(iframe_embed_type)
160
148
  embedder_service = Decidim::Meetings::MeetingIframeEmbedder.new(online_meeting_url)
161
- errors.add(:show_embedded_iframe, :not_embeddable) unless embedder_service.embeddable?
149
+ errors.add(:iframe_embed_type, :not_embeddable) unless embedder_service.embeddable?
162
150
  end
163
151
  end
164
152
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ class BaseMeetingForm < Decidim::Form
6
+ attribute :address, String
7
+ attribute :latitude, Float
8
+ attribute :longitude, Float
9
+ attribute :online_meeting_url, String
10
+ attribute :type_of_meeting, String
11
+ attribute :start_time, Decidim::Attributes::TimeWithZone
12
+ attribute :end_time, Decidim::Attributes::TimeWithZone
13
+
14
+ validates :current_component, presence: true
15
+
16
+ validates :address, presence: true, if: ->(form) { form.needs_address? }
17
+ validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? && form.needs_address? }
18
+ validates :start_time, presence: true, date: { before: :end_time }
19
+ validates :end_time, presence: true, date: { after: :start_time }
20
+
21
+ def type_of_meeting_select
22
+ Decidim::Meetings::Meeting::TYPE_OF_MEETING.map do |type|
23
+ [
24
+ I18n.t("type_of_meeting.#{type}", scope: "decidim.meetings"),
25
+ type
26
+ ]
27
+ end
28
+ end
29
+
30
+ def geocoding_enabled?
31
+ Decidim::Map.available?(:geocoding)
32
+ end
33
+
34
+ def geocoded?
35
+ latitude.present? && longitude.present?
36
+ end
37
+
38
+ def has_address?
39
+ geocoding_enabled? && address.present?
40
+ end
41
+
42
+ def needs_address?
43
+ in_person_meeting? || hybrid_meeting?
44
+ end
45
+
46
+ def online_meeting?
47
+ type_of_meeting == "online"
48
+ end
49
+
50
+ def in_person_meeting?
51
+ type_of_meeting == "in_person"
52
+ end
53
+
54
+ def hybrid_meeting?
55
+ type_of_meeting == "hybrid"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -13,22 +13,22 @@ module Decidim
13
13
  validates :closing_report, presence: true
14
14
  validates :attendees_count,
15
15
  presence: true,
16
- numericality: { greater_than_or_equal_to: 0, only_integer: true }
16
+ numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 999, only_integer: true }
17
17
 
18
18
  # Private: Gets the proposals from the meeting and injects them to the form.
19
19
  #
20
20
  # Returns nothing.
21
21
  def map_model(model)
22
22
  self.proposal_ids = model.linked_resources(:proposals, "proposals_from_meeting").pluck(:id)
23
- presenter = MeetingPresenter.new(model)
23
+ presenter = MeetingEditionPresenter.new(model)
24
24
  self.closing_report = presenter.closing_report(all_locales: false)
25
25
  end
26
26
 
27
27
  def proposals
28
- @proposals ||= Decidim.find_resource_manifest(:proposals)
29
- .try(:resource_scope, current_component)
30
- &.where(id: proposal_ids)
31
- &.order(title: :asc)
28
+ @proposals = Decidim.find_resource_manifest(:proposals)
29
+ .try(:resource_scope, current_component)
30
+ &.where(id: proposal_ids)
31
+ &.order(title: :asc)
32
32
  end
33
33
  end
34
34
  end