decidim-meetings 0.26.5 → 0.27.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/cells/decidim/meetings/content_blocks/highlighted_meetings_cell.rb +1 -1
- data/app/cells/decidim/meetings/content_blocks/upcoming_meetings/show.erb +1 -1
- data/app/cells/decidim/meetings/content_blocks/upcoming_meetings_cell.rb +2 -2
- data/app/cells/decidim/meetings/highlighted_meetings_for_component_cell.rb +10 -1
- data/app/cells/decidim/meetings/meeting_list_item_cell.rb +1 -1
- data/app/cells/decidim/meetings/meeting_m_cell.rb +1 -1
- data/app/cells/decidim/meetings/meeting_s_cell.rb +6 -0
- data/app/commands/decidim/meetings/admin/close_meeting.rb +1 -1
- data/app/commands/decidim/meetings/admin/copy_meeting.rb +5 -24
- data/app/commands/decidim/meetings/admin/create_agenda.rb +1 -1
- data/app/commands/decidim/meetings/admin/create_meeting.rb +1 -4
- data/app/commands/decidim/meetings/admin/destroy_meeting.rb +1 -1
- data/app/commands/decidim/meetings/admin/export_meeting_registrations.rb +1 -1
- data/app/commands/decidim/meetings/admin/invite_user_to_join_meeting.rb +9 -11
- data/app/commands/decidim/meetings/admin/publish_meeting.rb +1 -1
- data/app/commands/decidim/meetings/admin/unpublish_meeting.rb +1 -1
- data/app/commands/decidim/meetings/admin/update_agenda.rb +1 -1
- data/app/commands/decidim/meetings/admin/update_meeting.rb +1 -4
- data/app/commands/decidim/meetings/admin/update_question_status.rb +1 -1
- data/app/commands/decidim/meetings/admin/update_questionnaire.rb +10 -7
- data/app/commands/decidim/meetings/admin/update_registrations.rb +5 -3
- data/app/commands/decidim/meetings/admin/validate_registration_code.rb +1 -1
- data/app/commands/decidim/meetings/close_meeting.rb +1 -1
- data/app/commands/decidim/meetings/create_answer.rb +1 -1
- data/app/commands/decidim/meetings/create_meeting.rb +1 -1
- data/app/commands/decidim/meetings/decline_invitation.rb +1 -1
- data/app/commands/decidim/meetings/join_meeting.rb +6 -7
- data/app/commands/decidim/meetings/leave_meeting.rb +3 -3
- data/app/commands/decidim/meetings/update_meeting.rb +1 -1
- data/app/commands/decidim/meetings/withdraw_meeting.rb +1 -1
- data/app/controllers/concerns/decidim/meetings/admin/filterable.rb +4 -4
- data/app/controllers/concerns/decidim/meetings/filterable.rb +1 -7
- data/app/controllers/decidim/meetings/admin/meeting_copies_controller.rb +2 -2
- data/app/controllers/decidim/meetings/calendars_controller.rb +1 -1
- data/app/controllers/decidim/meetings/directory/meetings_controller.rb +17 -16
- data/app/controllers/decidim/meetings/meetings_controller.rb +21 -15
- data/app/events/decidim/meetings/meeting_registration_notification_event.rb +1 -1
- data/app/forms/decidim/meetings/admin/close_meeting_form.rb +1 -1
- data/app/forms/decidim/meetings/admin/meeting_copy_form.rb +51 -0
- data/app/forms/decidim/meetings/admin/meeting_form.rb +11 -10
- data/app/forms/decidim/meetings/admin/meeting_registration_invite_form.rb +1 -1
- data/app/forms/decidim/meetings/admin/meeting_registrations_form.rb +3 -0
- data/app/forms/decidim/meetings/answer_form.rb +0 -1
- data/app/forms/decidim/meetings/close_meeting_form.rb +1 -1
- data/app/forms/decidim/meetings/meeting_form.rb +2 -2
- data/app/helpers/decidim/meetings/application_helper.rb +8 -6
- data/app/helpers/decidim/meetings/directory/application_helper.rb +8 -6
- data/app/helpers/decidim/meetings/meetings_helper.rb +1 -3
- data/app/jobs/decidim/meetings/send_close_meeting_reminder_job.rb +17 -0
- data/app/mailers/decidim/meetings/close_meeting_reminder_mailer.rb +43 -0
- data/app/models/decidim/meetings/agenda_item.rb +1 -1
- data/app/models/decidim/meetings/answer.rb +2 -2
- data/app/models/decidim/meetings/invite.rb +2 -2
- data/app/models/decidim/meetings/meeting.rb +36 -21
- data/app/models/decidim/meetings/questionnaire.rb +6 -0
- data/app/models/decidim/meetings/registration.rb +2 -2
- data/app/packs/src/decidim/meetings/admin/meetings_form.js +0 -4
- data/app/packs/src/decidim/meetings/admin/registrations_form.js +2 -0
- data/app/presenters/decidim/meetings/admin_log/questionnaire_presenter.rb +39 -0
- data/app/queries/decidim/meetings/admin/invites.rb +1 -1
- data/app/queries/decidim/meetings/filtered_meetings.rb +1 -1
- data/app/queries/decidim/meetings/questionnaire_user_answers.rb +1 -1
- data/app/serializers/decidim/meetings/{data_portability_invite_serializer.rb → download_your_data_invite_serializer.rb} +2 -2
- data/app/serializers/decidim/meetings/{data_portability_registration_serializer.rb → download_your_data_registration_serializer.rb} +2 -2
- data/app/services/decidim/meetings/calendar/base_calendar.rb +4 -3
- data/app/services/decidim/meetings/calendar/component_calendar.rb +7 -9
- data/app/services/decidim/meetings/calendar/organization_calendar.rb +1 -1
- data/app/services/decidim/meetings/calendar_renderer.rb +4 -4
- data/app/services/decidim/meetings/close_meeting_reminder_generator.rb +68 -0
- data/app/services/decidim/meetings/meeting_iframe_embedder.rb +10 -6
- data/app/services/decidim/meetings/meeting_search.rb +7 -53
- data/app/views/decidim/meetings/_calendar_modal.html.erb +19 -2
- data/app/views/decidim/meetings/admin/meeting_copies/_form.html.erb +64 -0
- data/app/views/decidim/meetings/admin/meeting_copies/new.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meetings/_form.html.erb +5 -17
- data/app/views/decidim/meetings/admin/meetings/index.html.erb +1 -1
- data/app/views/decidim/meetings/admin/registrations/_form.html.erb +9 -0
- data/app/views/decidim/meetings/close_meeting_reminder_mailer/close_meeting_reminder.html.erb +5 -0
- data/app/views/decidim/meetings/directory/meetings/_filters.html.erb +7 -7
- data/app/views/decidim/meetings/directory/meetings/_meetings.html.erb +6 -1
- data/app/views/decidim/meetings/directory/meetings/index.html.erb +1 -1
- data/app/views/decidim/meetings/directory/meetings/index.js.erb +7 -1
- data/app/views/decidim/meetings/layouts/live_event.html.erb +6 -2
- data/app/views/decidim/meetings/meetings/_count.html.erb +1 -1
- data/app/views/decidim/meetings/meetings/_filters.html.erb +7 -7
- data/app/views/decidim/meetings/meetings/_form.html.erb +4 -2
- data/app/views/decidim/meetings/meetings/_meetings.html.erb +11 -6
- data/app/views/decidim/meetings/meetings/index.html.erb +2 -2
- data/app/views/decidim/meetings/meetings/index.js.erb +2 -2
- data/config/locales/am-ET.yml +1 -0
- data/config/locales/ar.yml +10 -7
- data/config/locales/bg.yml +7 -0
- data/config/locales/ca.yml +34 -27
- data/config/locales/cs.yml +35 -28
- data/config/locales/da.yml +1 -0
- data/config/locales/de.yml +16 -77
- data/config/locales/el.yml +7 -0
- data/config/locales/en.yml +33 -27
- data/config/locales/eo.yml +1 -0
- data/config/locales/es-MX.yml +34 -27
- data/config/locales/es-PY.yml +34 -27
- data/config/locales/es.yml +34 -27
- data/config/locales/et.yml +1 -0
- data/config/locales/eu.yml +164 -204
- data/config/locales/fi-plain.yml +34 -27
- data/config/locales/fi.yml +34 -27
- data/config/locales/fr-CA.yml +31 -26
- data/config/locales/fr.yml +31 -26
- data/config/locales/ga-IE.yml +5 -9
- data/config/locales/gl.yml +23 -2
- data/config/locales/hr.yml +1 -0
- data/config/locales/hu.yml +20 -147
- data/config/locales/id-ID.yml +7 -0
- data/config/locales/is-IS.yml +4 -1
- data/config/locales/it.yml +14 -11
- data/config/locales/ja.yml +36 -29
- data/config/locales/ko.yml +1 -0
- data/config/locales/lb.yml +12 -6
- data/config/locales/lt.yml +1 -664
- data/config/locales/lv.yml +7 -0
- data/config/locales/mt.yml +1 -0
- data/config/locales/nl.yml +64 -91
- data/config/locales/no.yml +17 -12
- data/config/locales/om-ET.yml +1 -0
- data/config/locales/pl.yml +9 -14
- data/config/locales/pt-BR.yml +9 -13
- data/config/locales/pt.yml +13 -11
- data/config/locales/ro-RO.yml +18 -28
- data/config/locales/ru.yml +7 -0
- data/config/locales/si-LK.yml +1 -0
- data/config/locales/sk.yml +7 -0
- data/config/locales/sl.yml +4 -0
- data/config/locales/so-SO.yml +1 -0
- data/config/locales/sr-CS.yml +1 -0
- data/config/locales/sv.yml +20 -22
- data/config/locales/sw-KE.yml +1 -0
- data/config/locales/ti-ER.yml +1 -0
- data/config/locales/tr-TR.yml +7 -11
- data/config/locales/uk.yml +7 -0
- data/config/locales/val-ES.yml +1 -0
- data/config/locales/vi.yml +1 -0
- data/config/locales/zh-CN.yml +7 -7
- data/config/locales/zh-TW.yml +1 -0
- data/db/migrate/20210512100333_drop_decidim_meetings_minutes_table.rb +2 -2
- data/db/migrate/20210518133236_merge_minutes_with_closing_report_in_meetings_table.rb +1 -1
- data/db/migrate/20211105115625_remove_not_null_on_customize_registration_email.rb +7 -0
- data/lib/decidim/api/meeting_type.rb +1 -1
- data/lib/decidim/meetings/component.rb +7 -7
- data/lib/decidim/meetings/{data_portability_user_answers_serializer.rb → download_your_data_user_answers_serializer.rb} +2 -2
- data/lib/decidim/meetings/engine.rb +15 -1
- data/lib/decidim/meetings/test/factories.rb +3 -1
- data/lib/decidim/meetings/test/notifications_handling.rb +1 -1
- data/lib/decidim/meetings/test/translated_event.rb +2 -2
- data/lib/decidim/meetings/version.rb +1 -1
- data/lib/decidim/meetings.rb +5 -1
- metadata +29 -26
- data/app/services/decidim/meetings/directory/meeting_search.rb +0 -53
- data/config/locales/gn-PY.yml +0 -1
- data/config/locales/ka-GE.yml +0 -1
- data/config/locales/lo-LA.yml +0 -1
- data/config/locales/oc-FR.yml +0 -1
@@ -15,34 +15,39 @@ module Decidim
|
|
15
15
|
helper Decidim::FiltersHelper
|
16
16
|
helper Decidim::Meetings::MapHelper
|
17
17
|
helper Decidim::ResourceHelper
|
18
|
+
helper Decidim::ShortLinkHelper
|
18
19
|
|
19
20
|
helper_method :meetings, :search
|
20
21
|
|
21
22
|
def calendar
|
22
|
-
render plain: CalendarRenderer.for(current_organization), content_type: "type/calendar"
|
23
|
+
render plain: CalendarRenderer.for(current_organization, params[:filter]), content_type: "type/calendar"
|
23
24
|
end
|
24
25
|
|
25
26
|
private
|
26
27
|
|
27
28
|
def meetings
|
28
|
-
|
29
|
-
@meetings ||= paginate(search.results.order(start_time: is_past_meetings ? :desc : :asc))
|
29
|
+
@meetings ||= paginate(search.result)
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
|
32
|
+
def search_collection
|
33
|
+
Meeting.where(component: meeting_components).published.not_hidden.visible_for(current_user).with_availability(
|
34
|
+
filter_params[:availability]
|
35
|
+
).includes(
|
36
|
+
:component,
|
37
|
+
attachments: :file_attachment
|
38
|
+
)
|
34
39
|
end
|
35
40
|
|
36
41
|
def default_filter_params
|
37
42
|
{
|
38
|
-
|
39
|
-
|
43
|
+
with_any_date: "upcoming",
|
44
|
+
title_or_description_cont: "",
|
40
45
|
activity: "all",
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
with_any_scope: default_filter_scope_params,
|
47
|
+
with_any_space: default_filter_space_params,
|
48
|
+
with_any_type: default_filter_type_params,
|
49
|
+
with_any_origin: default_filter_origin_params,
|
50
|
+
with_any_global_category: default_filter_category_params
|
46
51
|
}
|
47
52
|
end
|
48
53
|
|
@@ -69,10 +74,6 @@ module Decidim
|
|
69
74
|
%w(all global) + current_organization.scopes.pluck(:id).map(&:to_s)
|
70
75
|
end
|
71
76
|
|
72
|
-
def context_params
|
73
|
-
{ component: meeting_components, organization: current_organization, current_user: current_user }
|
74
|
-
end
|
75
|
-
|
76
77
|
def meeting_components
|
77
78
|
@meeting_components ||= Decidim::Component
|
78
79
|
.where(manifest_name: "meetings")
|
@@ -13,6 +13,7 @@ module Decidim
|
|
13
13
|
|
14
14
|
helper Decidim::WidgetUrlsHelper
|
15
15
|
helper Decidim::ResourceVersionsHelper
|
16
|
+
helper Decidim::ShortLinkHelper
|
16
17
|
|
17
18
|
helper_method :meetings, :meeting, :registration, :search
|
18
19
|
|
@@ -41,13 +42,13 @@ module Decidim
|
|
41
42
|
end
|
42
43
|
|
43
44
|
def index
|
44
|
-
return unless search.
|
45
|
+
return unless search.result.blank? && params.dig("filter", "date") != %w(past)
|
45
46
|
|
46
|
-
@past_meetings
|
47
|
+
@past_meetings ||= search_with(filter_params.merge(with_any_date: %w(past)))
|
47
48
|
|
48
|
-
if @past_meetings.
|
49
|
+
if @past_meetings.result.present?
|
49
50
|
params[:filter] ||= {}
|
50
|
-
params[:filter][:
|
51
|
+
params[:filter][:with_any_date] = %w(past)
|
51
52
|
@forced_past_meetings = true
|
52
53
|
@search = @past_meetings
|
53
54
|
end
|
@@ -108,16 +109,20 @@ module Decidim
|
|
108
109
|
end
|
109
110
|
|
110
111
|
def meetings
|
111
|
-
|
112
|
-
@meetings ||= paginate(search.results.order(start_time: is_past_meetings ? :desc : :asc))
|
112
|
+
@meetings ||= paginate(search.result.order(start_time: :desc))
|
113
113
|
end
|
114
114
|
|
115
115
|
def registration
|
116
116
|
@registration ||= meeting.registrations.find_by(user: current_user)
|
117
117
|
end
|
118
118
|
|
119
|
-
def
|
120
|
-
|
119
|
+
def search_collection
|
120
|
+
Meeting.where(component: current_component).published.not_hidden.visible_for(current_user).with_availability(
|
121
|
+
filter_params[:with_availability]
|
122
|
+
).includes(
|
123
|
+
:component,
|
124
|
+
attachments: :file_attachment
|
125
|
+
)
|
121
126
|
end
|
122
127
|
|
123
128
|
def meeting_form
|
@@ -126,14 +131,15 @@ module Decidim
|
|
126
131
|
|
127
132
|
def default_filter_params
|
128
133
|
{
|
129
|
-
|
130
|
-
|
134
|
+
search_text_cont: "",
|
135
|
+
with_any_date: %w(upcoming),
|
131
136
|
activity: "all",
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
+
with_availability: "",
|
138
|
+
with_any_scope: default_filter_scope_params,
|
139
|
+
with_any_category: default_filter_category_params,
|
140
|
+
with_any_state: nil,
|
141
|
+
with_any_origin: default_filter_origin_params,
|
142
|
+
with_any_type: default_filter_type_params
|
137
143
|
}
|
138
144
|
end
|
139
145
|
end
|
@@ -16,7 +16,7 @@ module Decidim
|
|
16
16
|
attribute :attending_organizations, String
|
17
17
|
attribute :proposal_ids, Array[Integer]
|
18
18
|
attribute :proposals
|
19
|
-
attribute :closed_at, Decidim::Attributes::TimeWithZone, default: ->
|
19
|
+
attribute :closed_at, Decidim::Attributes::TimeWithZone, default: -> { Time.current }
|
20
20
|
|
21
21
|
validates :closing_report, translatable_presence: true
|
22
22
|
validates :attendees_count, presence: true, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 999, only_integer: true }
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Meetings
|
5
|
+
module Admin
|
6
|
+
# A form object used to copy a meeting from the admin
|
7
|
+
# dashboard.
|
8
|
+
#
|
9
|
+
class MeetingCopyForm < ::Decidim::Meetings::BaseMeetingForm
|
10
|
+
include TranslatableAttributes
|
11
|
+
|
12
|
+
translatable_attribute :title, String
|
13
|
+
translatable_attribute :description, String
|
14
|
+
translatable_attribute :location, String
|
15
|
+
translatable_attribute :location_hints, String
|
16
|
+
|
17
|
+
attribute :show_embedded_iframe, Boolean, default: false
|
18
|
+
attribute :private_meeting, Boolean
|
19
|
+
attribute :transparent, Boolean
|
20
|
+
attribute :services, Array[MeetingServiceForm]
|
21
|
+
|
22
|
+
mimic :meeting
|
23
|
+
|
24
|
+
validates :online_meeting_url, url: true, if: ->(form) { form.online_meeting? || form.hybrid_meeting? }
|
25
|
+
validates :title, translatable_presence: true
|
26
|
+
validates :description, translatable_presence: true
|
27
|
+
validates :location, translatable_presence: true, if: ->(form) { form.in_person_meeting? || form.hybrid_meeting? }
|
28
|
+
|
29
|
+
def map_model(model)
|
30
|
+
self.services = model.services.map do |service|
|
31
|
+
MeetingServiceForm.new(service.attributes)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def services_to_persist
|
36
|
+
services.reject(&:deleted)
|
37
|
+
end
|
38
|
+
|
39
|
+
def number_of_services
|
40
|
+
services.size
|
41
|
+
end
|
42
|
+
|
43
|
+
alias component current_component
|
44
|
+
|
45
|
+
def questionnaire
|
46
|
+
Decidim::Forms::Questionnaire.new
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -14,7 +14,6 @@ module Decidim
|
|
14
14
|
attribute :transparent, Boolean
|
15
15
|
attribute :registration_type, String
|
16
16
|
attribute :registration_url, String
|
17
|
-
attribute :available_slots, Integer, default: 0
|
18
17
|
attribute :customize_registration_email, Boolean
|
19
18
|
attribute :iframe_embed_type, String, default: "none"
|
20
19
|
attribute :comments_enabled, Boolean, default: true
|
@@ -26,13 +25,11 @@ module Decidim
|
|
26
25
|
translatable_attribute :description, String
|
27
26
|
translatable_attribute :location, String
|
28
27
|
translatable_attribute :location_hints, String
|
29
|
-
translatable_attribute :registration_email_custom_content, String
|
30
28
|
|
31
29
|
validates :iframe_embed_type, inclusion: { in: Decidim::Meetings::Meeting.iframe_embed_types }
|
32
30
|
validates :title, translatable_presence: true
|
33
31
|
validates :description, translatable_presence: true
|
34
32
|
validates :registration_type, presence: true
|
35
|
-
validates :available_slots, numericality: { greater_than_or_equal_to: 0 }, presence: true, if: ->(form) { form.on_this_platform? }
|
36
33
|
validates :registration_url, presence: true, url: true, if: ->(form) { form.on_different_platform? }
|
37
34
|
validates :type_of_meeting, presence: true
|
38
35
|
validates :location, translatable_presence: true, if: ->(form) { form.in_person_meeting? || form.hybrid_meeting? }
|
@@ -75,14 +72,14 @@ module Decidim
|
|
75
72
|
#
|
76
73
|
# Returns a Decidim::Scope
|
77
74
|
def scope
|
78
|
-
@scope ||= @decidim_scope_id ? current_component.scopes.find_by(id: @decidim_scope_id) : current_component.scope
|
75
|
+
@scope ||= @attributes["decidim_scope_id"].value ? current_component.scopes.find_by(id: @attributes["decidim_scope_id"].value) : current_component.scope
|
79
76
|
end
|
80
77
|
|
81
78
|
# Scope identifier
|
82
79
|
#
|
83
80
|
# Returns the scope identifier related to the meeting
|
84
81
|
def decidim_scope_id
|
85
|
-
|
82
|
+
super || scope&.id
|
86
83
|
end
|
87
84
|
|
88
85
|
def category
|
@@ -95,6 +92,15 @@ module Decidim
|
|
95
92
|
type_of_meeting.presence
|
96
93
|
end
|
97
94
|
|
95
|
+
def type_of_meeting_select
|
96
|
+
Decidim::Meetings::Meeting::TYPE_OF_MEETING.map do |type|
|
97
|
+
[
|
98
|
+
I18n.t("type_of_meeting.#{type}", scope: "decidim.meetings"),
|
99
|
+
type
|
100
|
+
]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
98
104
|
def iframe_access_level_select
|
99
105
|
Decidim::Meetings::Meeting.iframe_access_levels.map do |level, _value|
|
100
106
|
[
|
@@ -113,11 +119,6 @@ module Decidim
|
|
113
119
|
end
|
114
120
|
end
|
115
121
|
|
116
|
-
# Support for copy meeting
|
117
|
-
def questionnaire
|
118
|
-
Decidim::Forms::Questionnaire.new
|
119
|
-
end
|
120
|
-
|
121
122
|
def on_this_platform?
|
122
123
|
registration_type == "on_this_platform"
|
123
124
|
end
|
@@ -12,7 +12,7 @@ module Decidim
|
|
12
12
|
attribute :existing_user, Boolean, default: false
|
13
13
|
|
14
14
|
validates :name, presence: true, unless: proc { |object| object.existing_user }
|
15
|
-
validates :email, presence: true,
|
15
|
+
validates :email, presence: true, "valid_email_2/email": { disposable: true }, unless: proc { |object| object.existing_user }
|
16
16
|
validates :user, presence: true, if: proc { |object| object.existing_user }
|
17
17
|
|
18
18
|
def user
|
@@ -11,9 +11,12 @@ module Decidim
|
|
11
11
|
|
12
12
|
attribute :registrations_enabled, Boolean
|
13
13
|
attribute :registration_form_enabled, Boolean
|
14
|
+
attribute :customize_registration_email, Boolean
|
14
15
|
attribute :available_slots, Integer
|
15
16
|
attribute :reserved_slots, Integer
|
17
|
+
|
16
18
|
translatable_attribute :registration_terms, String
|
19
|
+
translatable_attribute :registration_email_custom_content, String
|
17
20
|
|
18
21
|
validates :registration_terms, translatable_presence: true, if: ->(form) { form.registrations_enabled? }
|
19
22
|
validates :available_slots, :reserved_slots, presence: true, if: ->(form) { form.registrations_enabled? }
|
@@ -10,7 +10,6 @@ module Decidim
|
|
10
10
|
attribute :body, String
|
11
11
|
attribute :choices, Array[AnswerChoiceForm]
|
12
12
|
attribute :current_user, Decidim::User
|
13
|
-
attribute :answer, Decidim::Meetings::Answer
|
14
13
|
|
15
14
|
validates :selected_choices, presence: true
|
16
15
|
validate :max_choices, if: -> { question.max_choices }
|
@@ -7,7 +7,7 @@ module Decidim
|
|
7
7
|
attribute :closing_report, String
|
8
8
|
attribute :proposal_ids, Array[Integer]
|
9
9
|
attribute :proposals
|
10
|
-
attribute :closed_at, Decidim::Attributes::TimeWithZone, default: ->
|
10
|
+
attribute :closed_at, Decidim::Attributes::TimeWithZone, default: -> { Time.current }
|
11
11
|
attribute :attendees_count, Integer, default: 0
|
12
12
|
|
13
13
|
validates :closing_report, presence: true
|
@@ -60,14 +60,14 @@ module Decidim
|
|
60
60
|
#
|
61
61
|
# Returns a Decidim::Scope
|
62
62
|
def scope
|
63
|
-
@scope ||= @decidim_scope_id ? current_component.scopes.find_by(id: @decidim_scope_id) : current_component.scope
|
63
|
+
@scope ||= @attributes["decidim_scope_id"].value ? current_component.scopes.find_by(id: @attributes["decidim_scope_id"].value) : current_component.scope
|
64
64
|
end
|
65
65
|
|
66
66
|
# Scope identifier
|
67
67
|
#
|
68
68
|
# Returns the scope identifier related to the meeting
|
69
69
|
def decidim_scope_id
|
70
|
-
|
70
|
+
super || scope&.id
|
71
71
|
end
|
72
72
|
|
73
73
|
def category
|
@@ -16,7 +16,7 @@ module Decidim
|
|
16
16
|
def filter_origin_values
|
17
17
|
origin_values = []
|
18
18
|
origin_values << TreePoint.new("official", t("decidim.meetings.meetings.filters.origin_values.official"))
|
19
|
-
origin_values << TreePoint.new("
|
19
|
+
origin_values << TreePoint.new("participants", t("decidim.meetings.meetings.filters.origin_values.participants")) # todo
|
20
20
|
if current_organization.user_groups_enabled?
|
21
21
|
origin_values << TreePoint.new("user_group", t("decidim.meetings.meetings.filters.origin_values.user_groups")) # todo
|
22
22
|
end
|
@@ -41,11 +41,13 @@ module Decidim
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def filter_date_values
|
44
|
-
|
45
|
-
|
46
|
-
[
|
47
|
-
|
48
|
-
|
44
|
+
TreeNode.new(
|
45
|
+
TreePoint.new("", t("decidim.meetings.meetings.filters.date_values.all")),
|
46
|
+
[
|
47
|
+
TreePoint.new("upcoming", t("decidim.meetings.meetings.filters.date_values.upcoming")),
|
48
|
+
TreePoint.new("past", t("decidim.meetings.meetings.filters.date_values.past"))
|
49
|
+
]
|
50
|
+
)
|
49
51
|
end
|
50
52
|
|
51
53
|
# Options to filter meetings by activity.
|
@@ -27,11 +27,13 @@ module Decidim
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def filter_date_values
|
30
|
-
|
31
|
-
|
32
|
-
[
|
33
|
-
|
34
|
-
|
30
|
+
TreeNode.new(
|
31
|
+
TreePoint.new("", t("decidim.meetings.meetings.filters.date_values.all")),
|
32
|
+
[
|
33
|
+
TreePoint.new("upcoming", t("decidim.meetings.meetings.filters.date_values.upcoming")),
|
34
|
+
TreePoint.new("past", t("decidim.meetings.meetings.filters.date_values.past"))
|
35
|
+
]
|
36
|
+
)
|
35
37
|
end
|
36
38
|
|
37
39
|
def directory_filter_scopes_values
|
@@ -107,7 +109,7 @@ module Decidim
|
|
107
109
|
def directory_filter_origin_values
|
108
110
|
origin_values = []
|
109
111
|
origin_values << TreePoint.new("official", t("decidim.meetings.meetings.filters.origin_values.official"))
|
110
|
-
origin_values << TreePoint.new("
|
112
|
+
origin_values << TreePoint.new("participants", t("decidim.meetings.meetings.filters.origin_values.participants"))
|
111
113
|
origin_values << TreePoint.new("user_group", t("decidim.meetings.meetings.filters.origin_values.user_groups")) if current_organization.user_groups_enabled?
|
112
114
|
|
113
115
|
TreeNode.new(
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Meetings
|
5
|
+
class SendCloseMeetingReminderJob < ApplicationJob
|
6
|
+
queue_as :close_meeting_reminder
|
7
|
+
|
8
|
+
def perform(record)
|
9
|
+
return if record.remindable.closed?
|
10
|
+
|
11
|
+
::Decidim::ReminderDelivery.create(reminder: record.reminder)
|
12
|
+
::Decidim::Meetings::CloseMeetingReminderMailer.close_meeting_reminder(record).deliver_now
|
13
|
+
record.update(state: "completed")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Meetings
|
5
|
+
# A custom mailer for sending notifications for overdue meetings
|
6
|
+
class CloseMeetingReminderMailer < Decidim::ApplicationMailer
|
7
|
+
include Decidim::TranslationsHelper
|
8
|
+
include ActionView::Helpers::SanitizeHelper
|
9
|
+
include Decidim::ApplicationHelper
|
10
|
+
|
11
|
+
helper Decidim::ResourceHelper
|
12
|
+
helper Decidim::TranslationsHelper
|
13
|
+
helper Decidim::ApplicationHelper
|
14
|
+
|
15
|
+
helper_method :routes
|
16
|
+
|
17
|
+
# Send the user an email reminder to close the meetings
|
18
|
+
#
|
19
|
+
# record - the reminder record specific to a past meeting.
|
20
|
+
def close_meeting_reminder(record)
|
21
|
+
@reminder = record.reminder
|
22
|
+
@user = record.reminder.user
|
23
|
+
with_user(@user) do
|
24
|
+
@meeting = record.remindable
|
25
|
+
@organization = @user.organization
|
26
|
+
mail(
|
27
|
+
to: @user.email,
|
28
|
+
subject: I18n.t(
|
29
|
+
"decidim.meetings.close_meeting_reminder_mailer.close_meeting_reminder.subject",
|
30
|
+
organization_name: @organization.name
|
31
|
+
)
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def routes
|
39
|
+
@routes ||= Decidim::EngineRouter.main_proxy(@reminder.component)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -11,7 +11,7 @@ module Decidim
|
|
11
11
|
|
12
12
|
translatable_fields :title, :description
|
13
13
|
|
14
|
-
belongs_to :agenda, foreign_key: "decidim_agenda_id", class_name: "Decidim::Meetings::Agenda"
|
14
|
+
belongs_to :agenda, -> { order(:position) }, foreign_key: "decidim_agenda_id", class_name: "Decidim::Meetings::Agenda"
|
15
15
|
|
16
16
|
has_many :agenda_item_children, foreign_key: "parent_id", class_name: "Decidim::Meetings::AgendaItem", inverse_of: :parent, dependent: :destroy
|
17
17
|
belongs_to :parent, class_name: "Decidim::Meetings::AgendaItem", inverse_of: :agenda_item_children, optional: true
|
@@ -4,7 +4,7 @@ module Decidim
|
|
4
4
|
module Meetings
|
5
5
|
# The data store for an Answer in the Decidim::Meetings
|
6
6
|
class Answer < Meetings::ApplicationRecord
|
7
|
-
include Decidim::
|
7
|
+
include Decidim::DownloadYourData
|
8
8
|
|
9
9
|
belongs_to :user, class_name: "Decidim::User", foreign_key: "decidim_user_id", optional: true
|
10
10
|
belongs_to :questionnaire, class_name: "Decidim::Meetings::Questionnaire", foreign_key: "decidim_questionnaire_id"
|
@@ -24,7 +24,7 @@ module Decidim
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.export_serializer
|
27
|
-
Decidim::Meetings::
|
27
|
+
Decidim::Meetings::DownloadYourDataUserAnswersSerializer
|
28
28
|
end
|
29
29
|
|
30
30
|
def organization
|
@@ -6,7 +6,7 @@ module Decidim
|
|
6
6
|
class Invite < Meetings::ApplicationRecord
|
7
7
|
include Decidim::Traceable
|
8
8
|
include Decidim::Loggable
|
9
|
-
include Decidim::
|
9
|
+
include Decidim::DownloadYourData
|
10
10
|
|
11
11
|
belongs_to :meeting, foreign_key: "decidim_meeting_id", class_name: "Decidim::Meetings::Meeting"
|
12
12
|
belongs_to :user, foreign_key: "decidim_user_id", class_name: "Decidim::User"
|
@@ -14,7 +14,7 @@ module Decidim
|
|
14
14
|
validates :user, uniqueness: { scope: :meeting }
|
15
15
|
|
16
16
|
def self.export_serializer
|
17
|
-
Decidim::Meetings::
|
17
|
+
Decidim::Meetings::DownloadYourDataInviteSerializer
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.log_presenter_class_for(_log)
|
@@ -25,6 +25,7 @@ module Decidim
|
|
25
25
|
include Decidim::Authorable
|
26
26
|
include Decidim::TranslatableResource
|
27
27
|
include Decidim::Publicable
|
28
|
+
include Decidim::FilterableResource
|
28
29
|
|
29
30
|
TYPE_OF_MEETING = %w(in_person online hybrid).freeze
|
30
31
|
REGISTRATION_TYPE = %w(registration_disabled on_this_platform on_different_platform).freeze
|
@@ -59,16 +60,31 @@ module Decidim
|
|
59
60
|
scope :upcoming, -> { where(arel_table[:end_time].gteq(Time.current)) }
|
60
61
|
scope :withdrawn, -> { where(state: "withdrawn") }
|
61
62
|
scope :except_withdrawn, -> { where.not(state: "withdrawn").or(where(state: nil)) }
|
63
|
+
scope :with_availability, lambda { |state_key|
|
64
|
+
case state_key
|
65
|
+
when "withdrawn"
|
66
|
+
withdrawn
|
67
|
+
else
|
68
|
+
except_withdrawn
|
69
|
+
end
|
70
|
+
}
|
71
|
+
scope_search_multi :with_any_date, [:upcoming, :past]
|
72
|
+
scope :with_any_space, lambda { |*target_space|
|
73
|
+
target_spaces = target_space.compact.compact_blank
|
74
|
+
|
75
|
+
return self if target_spaces.blank? || target_spaces.include?("all")
|
62
76
|
|
63
|
-
|
77
|
+
joins(:component).where(
|
78
|
+
decidim_components: { participatory_space_type: target_spaces.map(&:classify) }
|
79
|
+
)
|
80
|
+
}
|
81
|
+
|
82
|
+
scope :visible_for, lambda { |user|
|
64
83
|
(all.distinct if user&.admin?) ||
|
65
84
|
if user.present?
|
66
|
-
spaces = Decidim.participatory_space_registry.manifests.
|
67
|
-
table_name = manifest.model_class_name.constantize.try(:table_name)
|
68
|
-
next if table_name.blank?
|
69
|
-
|
85
|
+
spaces = Decidim.participatory_space_registry.manifests.map do |manifest|
|
70
86
|
{
|
71
|
-
name: table_name.singularize,
|
87
|
+
name: manifest.model_class_name.constantize.table_name.singularize,
|
72
88
|
class_name: manifest.model_class_name
|
73
89
|
}
|
74
90
|
end
|
@@ -112,6 +128,10 @@ module Decidim
|
|
112
128
|
|
113
129
|
scope :visible, -> { where("decidim_meetings_meetings.private_meeting != ? OR decidim_meetings_meetings.transparent = ?", true, true) }
|
114
130
|
|
131
|
+
scope :authored_by, ->(author) { where(decidim_author_id: author) }
|
132
|
+
|
133
|
+
scope_search_multi :with_any_type, TYPE_OF_MEETING.map(&:to_sym)
|
134
|
+
|
115
135
|
TYPE_OF_MEETING.each do |type|
|
116
136
|
scope type.to_sym, -> { where(type_of_meeting: type.to_sym) }
|
117
137
|
scope "not_#{type}".to_sym, -> { where.not(type_of_meeting: type.to_sym) }
|
@@ -218,7 +238,7 @@ module Decidim
|
|
218
238
|
end
|
219
239
|
|
220
240
|
def current_user_can_visit_meeting?(user)
|
221
|
-
Decidim::Meetings::Meeting.
|
241
|
+
Decidim::Meetings::Meeting.visible_for(user).exists?(id: id)
|
222
242
|
end
|
223
243
|
|
224
244
|
def iframe_access_level_allowed_for_user?(user)
|
@@ -345,13 +365,9 @@ module Decidim
|
|
345
365
|
order(Arel::Nodes::InfixOperation.new("", field, Arel.sql("DESC")))
|
346
366
|
end
|
347
367
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
ransacker :title do
|
353
|
-
Arel.sql(%{cast("decidim_meetings_meetings"."title" as text)})
|
354
|
-
end
|
368
|
+
# Create i18n ransackers for :title and :description.
|
369
|
+
# Create the :search_text ransacker alias for searching from both of these.
|
370
|
+
ransacker_i18n_multi :search_text, [:title, :description]
|
355
371
|
|
356
372
|
ransacker :id_string do
|
357
373
|
Arel.sql(%{cast("decidim_meetings_meetings"."id" as text)})
|
@@ -361,13 +377,12 @@ module Decidim
|
|
361
377
|
Arel.sql("(start_time > NOW())")
|
362
378
|
end
|
363
379
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
")
|
380
|
+
def self.ransackable_scopes(_auth_object = nil)
|
381
|
+
[:with_any_type, :with_any_date, :with_any_space, :with_any_origin, :with_any_scope, :with_any_category, :with_any_global_category]
|
382
|
+
end
|
383
|
+
|
384
|
+
def self.ransack(params = {}, options = {})
|
385
|
+
MeetingSearch.new(self, params, options)
|
371
386
|
end
|
372
387
|
|
373
388
|
private
|
@@ -4,6 +4,8 @@ module Decidim
|
|
4
4
|
module Meetings
|
5
5
|
# The data store for a Questionnaire in the Decidim::Meetings component.
|
6
6
|
class Questionnaire < Meetings::ApplicationRecord
|
7
|
+
include Decidim::Traceable
|
8
|
+
|
7
9
|
belongs_to :questionnaire_for, polymorphic: true
|
8
10
|
|
9
11
|
has_many :questions, -> { order(:position) }, class_name: "Question", foreign_key: "decidim_questionnaire_id", dependent: :destroy
|
@@ -18,6 +20,10 @@ module Decidim
|
|
18
20
|
def all_questions_unpublished?
|
19
21
|
questions.all?(&:unpublished?)
|
20
22
|
end
|
23
|
+
|
24
|
+
def self.log_presenter_class_for(_log)
|
25
|
+
Decidim::Meetings::AdminLog::QuestionnairePresenter
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
23
29
|
end
|
@@ -4,7 +4,7 @@ module Decidim
|
|
4
4
|
module Meetings
|
5
5
|
# The data store for a Registration in the Decidim::Meetings component.
|
6
6
|
class Registration < Meetings::ApplicationRecord
|
7
|
-
include Decidim::
|
7
|
+
include Decidim::DownloadYourData
|
8
8
|
|
9
9
|
belongs_to :meeting, foreign_key: "decidim_meeting_id", class_name: "Decidim::Meetings::Meeting"
|
10
10
|
belongs_to :user, foreign_key: "decidim_user_id", class_name: "Decidim::User"
|
@@ -23,7 +23,7 @@ module Decidim
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.export_serializer
|
26
|
-
Decidim::Meetings::
|
26
|
+
Decidim::Meetings::DownloadYourDataRegistrationSerializer
|
27
27
|
end
|
28
28
|
|
29
29
|
# Pluck all Decidim::UserGroup ID's
|