decidim-meetings 0.30.2 → 0.31.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/cells/decidim/meetings/cancel_registration_meeting_button/cancelation_modal.erb +7 -4
- data/app/cells/decidim/meetings/cancel_registration_meeting_button/show.erb +1 -1
- data/app/cells/decidim/meetings/cancel_registration_meeting_button_cell.rb +36 -0
- data/app/cells/decidim/meetings/dates_and_map_cell.rb +1 -1
- data/app/cells/decidim/meetings/join_meeting_button/registration_modal.erb +4 -5
- data/app/cells/decidim/meetings/join_meeting_button/show.erb +25 -28
- data/app/cells/decidim/meetings/join_meeting_button/waitlist_button.erb +22 -0
- data/app/cells/decidim/meetings/join_meeting_button_cell.rb +28 -0
- data/app/cells/decidim/meetings/question_responses/show.erb +7 -7
- data/app/cells/decidim/meetings/question_responses_cell.rb +28 -28
- data/app/commands/decidim/meetings/admin/copy_meeting.rb +5 -2
- data/app/commands/decidim/meetings/admin/create_agenda.rb +6 -2
- data/app/commands/decidim/meetings/admin/create_meeting.rb +7 -3
- data/app/commands/decidim/meetings/admin/mark_as_attendee.rb +44 -0
- data/app/commands/decidim/meetings/admin/publish_meeting.rb +2 -1
- data/app/commands/decidim/meetings/admin/update_agenda.rb +6 -2
- data/app/commands/decidim/meetings/admin/update_meeting.rb +15 -6
- data/app/commands/decidim/meetings/admin/update_questionnaire.rb +4 -4
- data/app/commands/decidim/meetings/admin/update_registrations.rb +19 -7
- data/app/commands/decidim/meetings/create_meeting.rb +2 -3
- data/app/commands/decidim/meetings/{create_answer.rb → create_response.rb} +11 -11
- data/app/commands/decidim/meetings/join_meeting.rb +4 -6
- data/app/commands/decidim/meetings/join_waitlist.rb +53 -0
- data/app/commands/decidim/meetings/leave_meeting.rb +14 -5
- data/app/commands/decidim/meetings/update_meeting.rb +1 -2
- data/app/controllers/concerns/decidim/meetings/admin/filterable.rb +1 -1
- data/app/controllers/decidim/meetings/admin/agenda_controller.rb +2 -2
- data/app/controllers/decidim/meetings/admin/invites_controller.rb +1 -1
- data/app/controllers/decidim/meetings/admin/meeting_closes_controller.rb +1 -1
- data/app/controllers/decidim/meetings/admin/meeting_copies_controller.rb +1 -1
- data/app/controllers/decidim/meetings/admin/meetings_controller.rb +4 -4
- data/app/controllers/decidim/meetings/admin/meetings_poll_controller.rb +10 -10
- data/app/controllers/decidim/meetings/admin/registrations_attendees_controller.rb +79 -0
- data/app/controllers/decidim/meetings/admin/registrations_controller.rb +1 -22
- data/app/controllers/decidim/meetings/meeting_closes_controller.rb +1 -1
- data/app/controllers/decidim/meetings/meetings_controller.rb +11 -11
- data/app/controllers/decidim/meetings/polls/{answers_controller.rb → responses_controller.rb} +7 -7
- data/app/controllers/decidim/meetings/registrations_controller.rb +39 -12
- data/app/events/decidim/meetings/registration_marked_as_attendee_event.rb +9 -0
- data/app/events/decidim/meetings/upcoming_meeting_event.rb +41 -0
- data/app/events/decidim/meetings/update_meeting_event.rb +25 -0
- data/app/forms/decidim/meetings/admin/close_meeting_form.rb +2 -1
- data/app/forms/decidim/meetings/admin/meeting_agenda_items_form.rb +4 -0
- data/app/forms/decidim/meetings/admin/meeting_form.rb +28 -3
- data/app/forms/decidim/meetings/admin/question_form.rb +3 -3
- data/app/forms/decidim/meetings/admin/{answer_option_form.rb → response_option_form.rb} +3 -3
- data/app/forms/decidim/meetings/admin/validate_registration_code_form.rb +1 -1
- data/app/forms/decidim/meetings/base_meeting_form.rb +0 -2
- data/app/forms/decidim/meetings/close_meeting_form.rb +2 -1
- data/app/forms/decidim/meetings/join_meeting_form.rb +0 -1
- data/app/forms/decidim/meetings/meeting_form.rb +3 -2
- data/app/forms/decidim/meetings/response_choice_form.rb +14 -0
- data/app/forms/decidim/meetings/{answer_form.rb → response_form.rb} +7 -7
- data/app/helpers/decidim/meetings/application_helper.rb +0 -1
- data/app/helpers/decidim/meetings/meetings_helper.rb +14 -5
- data/app/jobs/decidim/meetings/promote_from_waitlist_job.rb +63 -0
- data/app/jobs/decidim/meetings/upcoming_meeting_notification_job.rb +1 -1
- data/app/mailers/decidim/meetings/registration_mailer.rb +13 -0
- data/app/models/decidim/meetings/agenda_item.rb +5 -0
- data/app/models/decidim/meetings/meeting.rb +15 -12
- data/app/models/decidim/meetings/question.rb +12 -12
- data/app/models/decidim/meetings/questionnaire.rb +1 -1
- data/app/models/decidim/meetings/registration.rb +19 -7
- data/app/models/decidim/meetings/{answer.rb → response.rb} +6 -6
- data/app/models/decidim/meetings/response_choice.rb +15 -0
- data/app/models/decidim/meetings/{answer_option.rb → response_option.rb} +5 -5
- data/app/packs/src/decidim/meetings/admin/destroy_meeting_alert.js +1 -1
- data/app/packs/src/decidim/meetings/admin/meetings_components_form.js +1 -8
- data/app/packs/src/decidim/meetings/admin/meetings_form.js +1 -1
- data/app/packs/src/decidim/meetings/admin/registrations_form.js +1 -1
- data/app/packs/src/decidim/meetings/admin/registrations_invite_form.js +1 -1
- data/app/packs/src/decidim/meetings/meetings_form.js +1 -1
- data/app/packs/src/decidim/meetings/meetings_polls.js +1 -1
- data/app/packs/src/decidim/meetings/poll.component.js +5 -5
- data/app/packs/stylesheets/decidim/meetings/_item.scss +5 -1
- data/app/packs/stylesheets/decidim/meetings/meetings.scss +4 -4
- data/app/permissions/decidim/meetings/admin/agenda_permissions.rb +34 -0
- data/app/permissions/decidim/meetings/admin/meeting_permissions.rb +44 -0
- data/app/permissions/decidim/meetings/admin/permissions.rb +5 -66
- data/app/permissions/decidim/meetings/admin/questionnaire_permissions.rb +30 -0
- data/app/permissions/decidim/meetings/meeting_permissions.rb +90 -0
- data/app/permissions/decidim/meetings/permissions.rb +9 -105
- data/app/presenters/decidim/meetings/admin_log/value_types/meeting_title_description_presenter.rb +1 -1
- data/app/presenters/decidim/meetings/agenda_item_presenter.rb +29 -0
- data/app/presenters/decidim/meetings/meeting_presenter.rb +11 -15
- data/app/presenters/decidim/meetings/registration_presenter.rb +24 -0
- data/app/queries/decidim/meetings/{questionnaire_user_answers.rb → questionnaire_user_responses.rb} +5 -5
- data/app/serializers/decidim/meetings/registration_serializer.rb +5 -6
- data/app/services/decidim/meetings/diff_renderer.rb +0 -1
- data/app/views/decidim/meetings/_calendar_modal.html.erb +1 -0
- data/app/views/decidim/meetings/admin/agenda/_agenda_item_fields.html.erb +1 -1
- data/app/views/decidim/meetings/admin/invites/_form.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meeting_closes/_form.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meetings/_form.html.erb +3 -2
- data/app/views/decidim/meetings/admin/meetings/_linked_spaces.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meetings/_meeting-tr.html.erb +11 -8
- data/app/views/decidim/meetings/admin/meetings/_meeting_actions.html.erb +200 -69
- data/app/views/decidim/meetings/admin/meetings/_reminders.html.erb +19 -0
- data/app/views/decidim/meetings/admin/meetings/_services.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meetings/index.html.erb +7 -5
- data/app/views/decidim/meetings/admin/meetings/manage_trash.html.erb +2 -1
- data/app/views/decidim/meetings/admin/poll/_form.html.erb +6 -6
- data/app/views/decidim/meetings/admin/poll/_question.html.erb +13 -13
- data/app/views/decidim/meetings/admin/poll/_response_option.html.erb +35 -0
- data/app/views/decidim/meetings/admin/poll/_response_option_template.html.erb +7 -0
- data/app/views/decidim/meetings/admin/poll/edit.html.erb +3 -3
- data/app/views/decidim/meetings/admin/registration_form/edit_questions.html.erb +5 -5
- data/app/views/decidim/meetings/admin/registrations/edit.html.erb +19 -39
- data/app/views/decidim/meetings/admin/registrations_attendees/index.html.erb +126 -0
- data/app/views/decidim/meetings/layouts/live_event.html.erb +1 -1
- data/app/views/decidim/meetings/meeting_closes/_form.html.erb +2 -2
- data/app/views/decidim/meetings/meetings/_form.html.erb +2 -11
- data/app/views/decidim/meetings/meetings/_meeting.html.erb +2 -2
- data/app/views/decidim/meetings/meetings/_meeting_actions.html.erb +3 -3
- data/app/views/decidim/meetings/meetings/_meeting_agenda.html.erb +2 -2
- data/app/views/decidim/meetings/meetings/_meeting_aside.html.erb +11 -10
- data/app/views/decidim/meetings/meetings/_meeting_poll_actions.html.erb +3 -3
- data/app/views/decidim/meetings/meetings/_registration_code_modal.html.erb +16 -0
- data/app/views/decidim/meetings/polls/questions/_index_admin.html.erb +1 -1
- data/app/views/decidim/meetings/polls/questions/_published_question.html.erb +5 -5
- data/app/views/decidim/meetings/polls/responses/_multiple_option.html.erb +13 -0
- data/app/views/decidim/meetings/polls/responses/_single_option.html.erb +13 -0
- data/app/views/decidim/meetings/polls/{answers → responses}/admin.html.erb +4 -4
- data/app/views/decidim/meetings/polls/{answers → responses}/index.html.erb +4 -4
- data/app/views/decidim/meetings/registration_mailer/confirmation.html.erb +6 -1
- data/config/assets.rb +2 -2
- data/config/locales/ar.yml +1 -26
- data/config/locales/bg.yml +2 -32
- data/config/locales/ca-IT.yml +86 -40
- data/config/locales/ca.yml +86 -40
- data/config/locales/cs.yml +71 -43
- data/config/locales/de.yml +87 -41
- data/config/locales/el.yml +1 -25
- data/config/locales/en.yml +89 -43
- data/config/locales/es-MX.yml +87 -41
- data/config/locales/es-PY.yml +87 -41
- data/config/locales/es.yml +87 -41
- data/config/locales/eu.yml +86 -40
- data/config/locales/fi-plain.yml +86 -40
- data/config/locales/fi.yml +85 -39
- data/config/locales/fr-CA.yml +79 -38
- data/config/locales/fr.yml +79 -38
- data/config/locales/ga-IE.yml +1 -7
- data/config/locales/gl.yml +1 -19
- data/config/locales/hu.yml +1 -22
- data/config/locales/id-ID.yml +0 -16
- data/config/locales/is-IS.yml +0 -10
- data/config/locales/it.yml +1 -29
- data/config/locales/ja.yml +88 -42
- data/config/locales/lb.yml +1 -15
- data/config/locales/lt.yml +1 -28
- data/config/locales/lv.yml +0 -16
- data/config/locales/nl.yml +1 -26
- data/config/locales/no.yml +1 -28
- data/config/locales/pl.yml +2 -32
- data/config/locales/pt-BR.yml +1 -28
- data/config/locales/pt.yml +1 -28
- data/config/locales/ro-RO.yml +56 -29
- data/config/locales/ru.yml +0 -16
- data/config/locales/sk.yml +0 -16
- data/config/locales/sl.yml +0 -4
- data/config/locales/sv.yml +85 -39
- data/config/locales/tr-TR.yml +0 -20
- data/config/locales/uk.yml +0 -12
- data/config/locales/zh-CN.yml +0 -19
- data/config/locales/zh-TW.yml +1 -26
- data/db/migrate/20181107175558_add_questionnaire_to_existing_meetings.rb +8 -2
- data/db/migrate/20200827153856_add_commentable_counter_cache_to_meetings.rb +8 -2
- data/db/migrate/20201016065302_fix_meetings_registration_terms.rb +8 -2
- data/db/migrate/20210310120731_add_followable_counter_cache_to_meetings.rb +8 -2
- data/db/migrate/20250317103343_rename_answer_to_response_in_decidim_meetings.rb +18 -0
- data/db/migrate/20250403094034_add_reminder_customization_to_decidim_meetings.rb +9 -0
- data/db/migrate/20250408071941_add_status_to_registrations_to_decidim_meetings_registrations.rb +8 -0
- data/lib/decidim/api/agenda_item_type.rb +6 -2
- data/lib/decidim/api/agenda_type.rb +6 -2
- data/lib/decidim/api/linked_resources_interface.rb +1 -1
- data/lib/decidim/api/meeting_type.rb +20 -10
- data/lib/decidim/api/service_type.rb +3 -0
- data/lib/decidim/meetings/admin_engine.rb +9 -1
- data/lib/decidim/meetings/component.rb +29 -8
- data/lib/decidim/meetings/engine.rb +6 -21
- data/lib/decidim/meetings/meeting_serializer.rb +1 -2
- data/lib/decidim/meetings/schema_org_event_meeting_serializer.rb +0 -10
- data/lib/decidim/meetings/seeds.rb +4 -13
- data/lib/decidim/meetings/test/factories.rb +10 -16
- data/lib/decidim/meetings/user_responses_serializer.rb +47 -0
- data/lib/decidim/meetings/version.rb +1 -1
- data/lib/decidim/meetings.rb +7 -9
- metadata +49 -35
- data/app/cells/decidim/meetings/attending_organizations_list_cell.rb +0 -32
- data/app/forms/decidim/meetings/answer_choice_form.rb +0 -14
- data/app/models/decidim/meetings/answer_choice.rb +0 -15
- data/app/queries/decidim/meetings/metrics/meeting_followers_metric_measure.rb +0 -31
- data/app/queries/decidim/meetings/metrics/meetings_metric_manage.rb +0 -48
- data/app/views/decidim/meetings/admin/poll/_answer_option.html.erb +0 -35
- data/app/views/decidim/meetings/admin/poll/_answer_option_template.html.erb +0 -7
- data/app/views/decidim/meetings/polls/answers/_multiple_option.html.erb +0 -13
- data/app/views/decidim/meetings/polls/answers/_single_option.html.erb +0 -13
- data/lib/decidim/meetings/download_your_data_user_answers_serializer.rb +0 -39
- data/lib/decidim/meetings/user_answers_serializer.rb +0 -47
- /data/app/views/decidim/meetings/polls/{answers → responses}/create.js.erb +0 -0
@@ -1,9 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class AddQuestionnaireToExistingMeetings < ActiveRecord::Migration[5.2]
|
4
|
+
class Meeting < ApplicationRecord
|
5
|
+
self.table_name = :decidim_meetings_meetings
|
6
|
+
include Decidim::HasComponent
|
7
|
+
include Decidim::Forms::HasQuestionnaire
|
8
|
+
end
|
9
|
+
|
4
10
|
def change
|
5
|
-
|
6
|
-
|
11
|
+
Meeting.transaction do
|
12
|
+
Meeting.unscoped.find_each do |meeting|
|
7
13
|
if meeting.component.present? && meeting.questionnaire.blank?
|
8
14
|
meeting.update!(
|
9
15
|
questionnaire: Decidim::Forms::Questionnaire.new
|
@@ -1,9 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class AddCommentableCounterCacheToMeetings < ActiveRecord::Migration[5.2]
|
4
|
+
class Meeting < ApplicationRecord
|
5
|
+
self.table_name = :decidim_meetings_meetings
|
6
|
+
include Decidim::HasComponent
|
7
|
+
include Decidim::Comments::CommentableWithComponent
|
8
|
+
end
|
9
|
+
|
4
10
|
def change
|
5
11
|
add_column :decidim_meetings_meetings, :comments_count, :integer, null: false, default: 0
|
6
|
-
|
7
|
-
|
12
|
+
Meeting.reset_column_information
|
13
|
+
Meeting.unscoped.find_each(&:update_comments_count)
|
8
14
|
end
|
9
15
|
end
|
@@ -1,11 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class FixMeetingsRegistrationTerms < ActiveRecord::Migration[5.2]
|
4
|
+
class Meeting < ApplicationRecord
|
5
|
+
self.table_name = :decidim_meetings_meetings
|
6
|
+
include Decidim::HasComponent
|
7
|
+
include Decidim::Authorable
|
8
|
+
end
|
9
|
+
|
4
10
|
def up
|
5
11
|
reset_column_information
|
6
12
|
|
7
13
|
PaperTrail.request(enabled: false) do
|
8
|
-
|
14
|
+
Meeting.unscoped.find_each do |meeting|
|
9
15
|
next if meeting.component.nil?
|
10
16
|
# Only user-created meetings have this problem
|
11
17
|
next if meeting.official?
|
@@ -23,7 +29,7 @@ class FixMeetingsRegistrationTerms < ActiveRecord::Migration[5.2]
|
|
23
29
|
def down; end
|
24
30
|
|
25
31
|
def reset_column_information
|
26
|
-
|
32
|
+
Meeting.reset_column_information
|
27
33
|
Decidim::Component.reset_column_information
|
28
34
|
end
|
29
35
|
end
|
@@ -1,13 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class AddFollowableCounterCacheToMeetings < ActiveRecord::Migration[5.2]
|
4
|
+
class Meeting < ApplicationRecord
|
5
|
+
self.table_name = :decidim_meetings_meetings
|
6
|
+
include Decidim::HasComponent
|
7
|
+
include Decidim::Followable
|
8
|
+
end
|
9
|
+
|
4
10
|
def change
|
5
11
|
add_column :decidim_meetings_meetings, :follows_count, :integer, null: false, default: 0, index: true
|
6
12
|
|
7
13
|
reversible do |dir|
|
8
14
|
dir.up do
|
9
|
-
|
10
|
-
|
15
|
+
Meeting.reset_column_information
|
16
|
+
Meeting.unscoped.find_each do |record|
|
11
17
|
record.class.reset_counters(record.id, :follows)
|
12
18
|
end
|
13
19
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RenameAnswerToResponseInDecidimMeetings < ActiveRecord::Migration[7.0]
|
4
|
+
def change
|
5
|
+
rename_index :decidim_meetings_response_choices, "index_decidim_meetings_answer_choices_answer_id", "index_decidim_meetings_response_choices_response_id"
|
6
|
+
rename_index :decidim_meetings_response_choices, "index_decidim_meetings_answer_choices_answer_option_id", "index_decidim_meetings_response_choices_response_option_id"
|
7
|
+
rename_index :decidim_meetings_response_options, "index_decidim_meetings_answer_options_question_id", "index_decidim_meetings_response_options_question_id"
|
8
|
+
rename_index :decidim_meetings_responses, "index_decidim_meetings_answers_question_id", "index_decidim_meetings_responses_question_id"
|
9
|
+
rename_index :decidim_meetings_responses, "index_decidim_meetings_answers_on_decidim_questionnaire_id", "index_decidim_meetings_responses_on_decidim_questionnaire_id"
|
10
|
+
|
11
|
+
rename_table :decidim_meetings_answers, :decidim_meetings_responses
|
12
|
+
rename_table :decidim_meetings_answer_choices, :decidim_meetings_response_choices
|
13
|
+
rename_table :decidim_meetings_answer_options, :decidim_meetings_response_options
|
14
|
+
|
15
|
+
rename_column :decidim_meetings_response_choices, :decidim_answer_id, :decidim_response_id
|
16
|
+
rename_column :decidim_meetings_response_choices, :decidim_answer_option_id, :decidim_response_option_id
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AddReminderCustomizationToDecidimMeetings < ActiveRecord::Migration[7.0]
|
4
|
+
def change
|
5
|
+
add_column :decidim_meetings_meetings, :reminder_enabled, :boolean, default: true, null: false
|
6
|
+
add_column :decidim_meetings_meetings, :send_reminders_before_hours, :integer
|
7
|
+
add_column :decidim_meetings_meetings, :reminder_message_custom_content, :jsonb, default: {}, null: false
|
8
|
+
end
|
9
|
+
end
|
data/db/migrate/20250408071941_add_status_to_registrations_to_decidim_meetings_registrations.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AddStatusToRegistrationsToDecidimMeetingsRegistrations < ActiveRecord::Migration[7.0]
|
4
|
+
def change
|
5
|
+
add_column :decidim_meetings_registrations, :status, :string, default: "registered"
|
6
|
+
add_index :decidim_meetings_registrations, :status
|
7
|
+
end
|
8
|
+
end
|
@@ -3,11 +3,11 @@
|
|
3
3
|
module Decidim
|
4
4
|
module Meetings
|
5
5
|
class AgendaItemType < Decidim::Api::Types::BaseObject
|
6
|
-
implements Decidim::Core::TimestampsInterface
|
7
|
-
|
8
6
|
graphql_name "MeetingAgendaItem"
|
9
7
|
description "A meeting agenda item"
|
10
8
|
|
9
|
+
implements Decidim::Core::TimestampsInterface
|
10
|
+
|
11
11
|
field :agenda, Decidim::Meetings::AgendaType, "Belonging agenda", null: true
|
12
12
|
field :description, Decidim::Core::TranslatedFieldType, "The description for this agenda item", null: true
|
13
13
|
field :duration, GraphQL::Types::Int, "Duration in number of minutes for this item in this agenda", null: false
|
@@ -16,6 +16,10 @@ module Decidim
|
|
16
16
|
field :parent, Decidim::Meetings::AgendaItemType, "Parent agenda item, if available", null: true
|
17
17
|
field :position, GraphQL::Types::Int, "Order position for this agenda item", null: false
|
18
18
|
field :title, Decidim::Core::TranslatedFieldType, "The title for this agenda item", null: true
|
19
|
+
|
20
|
+
def self.authorized?(object, _context)
|
21
|
+
object.agenda.visible?
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -11,8 +11,12 @@ module Decidim
|
|
11
11
|
field :id, GraphQL::Types::ID, "The ID for the agenda", null: false
|
12
12
|
field :items, [Decidim::Meetings::AgendaItemType, { null: true }], "Items and sub-items of the agenda", method: :agenda_items, null: false
|
13
13
|
field :title, Decidim::Core::TranslatedFieldType, "The title for the agenda", null: true
|
14
|
-
|
15
|
-
|
14
|
+
|
15
|
+
def self.authorized?(object, context)
|
16
|
+
super && object.visible?
|
17
|
+
rescue Decidim::PermissionAction::PermissionNotSetError
|
18
|
+
false
|
19
|
+
end
|
16
20
|
end
|
17
21
|
end
|
18
22
|
end
|
@@ -8,7 +8,7 @@ module Decidim
|
|
8
8
|
graphql_name "MeetingsLinkedResourcesInterface"
|
9
9
|
description "An interface that can be used with Resourceable models."
|
10
10
|
|
11
|
-
if Decidim
|
11
|
+
if Decidim.module_installed?(:proposals)
|
12
12
|
field(
|
13
13
|
:proposals_from_meeting,
|
14
14
|
[Decidim::Proposals::ProposalType, { null: true }],
|
@@ -9,43 +9,57 @@ module Decidim
|
|
9
9
|
implements Decidim::Core::AuthorableInterface
|
10
10
|
implements Decidim::Core::TaxonomizableInterface
|
11
11
|
implements Decidim::Core::AttachableInterface
|
12
|
+
implements Decidim::Core::FollowableInterface
|
13
|
+
implements Decidim::Core::ReferableInterface
|
14
|
+
implements Decidim::Core::LocalizableInterface
|
12
15
|
implements Decidim::Core::TimestampsInterface
|
13
16
|
implements Decidim::Meetings::ServicesInterface
|
14
|
-
implements Decidim::Meetings::LinkedResourcesInterface if Decidim
|
17
|
+
implements Decidim::Meetings::LinkedResourcesInterface if Decidim.module_installed?(:proposals)
|
15
18
|
implements Decidim::Forms::QuestionnaireEntityInterface
|
16
19
|
|
17
|
-
field :address, GraphQL::Types::String, "The physical address of this meeting (used for geolocation)", null: true
|
18
20
|
field :agenda, Decidim::Meetings::AgendaType, "Agenda for this meeting, if available", null: true
|
19
|
-
field :
|
21
|
+
field :attendees_count, GraphQL::Types::Int, "Amount of attendees to this meeting", null: true
|
20
22
|
field :attending_organizations, GraphQL::Types::String, "list of attending organizations", null: true
|
21
23
|
field :audio_url, GraphQL::Types::String, "URL for the audio of the session, if any", null: true
|
22
24
|
field :closed, GraphQL::Types::Boolean, "Whether this meeting is closed or not.", method: :closed?, null: false
|
25
|
+
field :closed_at, Decidim::Core::DateTimeType, "The date and time this meeting was closed", null: true
|
23
26
|
field :closing_report, Decidim::Core::TranslatedFieldType, "The closing report of this meeting.", null: true
|
27
|
+
field :comments_enabled, GraphQL::Types::Boolean, "Whether the comments are enabled or not", null: false
|
28
|
+
field :comments_end_time, Decidim::Core::DateTimeType, "The ending time when the comments will be allowed on this meeting", null: true
|
29
|
+
field :comments_start_time, Decidim::Core::DateTimeType, "The starting time when the comments will be allowed on this meeting", null: true
|
24
30
|
field :contribution_count, GraphQL::Types::Int, "Amount of contributions to this meeting", method: :contributions_count, null: true
|
25
|
-
field :
|
31
|
+
field :customize_registration_email, GraphQL::Types::Boolean, "The email to customize for the registration", null: true
|
26
32
|
field :description, Decidim::Core::TranslatedFieldType, "The description of this meeting.", null: true
|
27
33
|
field :end_time, Decidim::Core::DateTimeType, "The time this meeting ends", null: false
|
28
34
|
field :id, GraphQL::Types::ID, "ID of this meeting", null: false
|
35
|
+
field :iframe_access_level, GraphQL::Types::String, "The iframe access level of the meeting ", null: true
|
29
36
|
field :iframe_embed_type, GraphQL::Types::String, "The type of displaying of the online meeting URL", null: true
|
30
|
-
field :is_withdrawn, GraphQL::Types::Boolean, "Whether this meeting is withdrawn or not.", method: :withdrawn?, null: false
|
31
37
|
field :location, Decidim::Core::TranslatedFieldType, "The location of this meeting (free format)", null: true
|
32
38
|
field :location_hints, Decidim::Core::TranslatedFieldType, "The location of this meeting (free format)", null: true
|
33
39
|
field :online_meeting_url, GraphQL::Types::String, "The URL of the meeting (when the type is online)", null: false
|
34
40
|
field :private_meeting, GraphQL::Types::Boolean, "Whether the meeting is private or not (it can only be true if transparent)", null: false
|
35
|
-
field :
|
41
|
+
field :public_participants, [Decidim::Core::UserType, { null: true }], "The list of users participating to this meeting", null: false
|
42
|
+
field :published_at, Decidim::Core::DateTimeType, "The time this page was published", null: false
|
36
43
|
field :registration_form, Decidim::Forms::QuestionnaireType, description: "If registration requires to fill a form, this is the questionnaire", null: true
|
37
44
|
field :registration_form_enabled, GraphQL::Types::Boolean, "Whether the registrations have a form or not", null: false
|
38
45
|
field :registration_terms, Decidim::Core::TranslatedFieldType, "The registration terms", null: true
|
46
|
+
field :registration_type, GraphQL::Types::String, "The type of registration (disabled, on this platform or different platform)", null: false
|
47
|
+
field :registration_url, GraphQL::Types::String, "URL for the registration form", null: true
|
39
48
|
field :registrations_enabled, GraphQL::Types::Boolean, "Whether the registrations are enabled or not", null: false
|
40
49
|
field :remaining_slots, GraphQL::Types::Int, "Amount of slots available for this meeting", null: true
|
41
50
|
field :start_time, Decidim::Core::DateTimeType, "The time this meeting starts", null: false
|
42
51
|
field :title, Decidim::Core::TranslatedFieldType, "The title of this meeting.", null: false
|
43
52
|
field :transparent, GraphQL::Types::Boolean, "For private meetings, information is public if transparent", null: false
|
44
53
|
field :type_of_meeting, GraphQL::Types::String, "The type of the meeting (online or in-person)", null: false
|
54
|
+
field :url, GraphQL::Types::String, "The URL for this meeting", null: false
|
45
55
|
field :video_url, GraphQL::Types::String, "URL for the video of the session, if any", null: true
|
46
56
|
field :withdrawn, GraphQL::Types::Boolean, "Whether this meeting has been withdrawn or not", method: :withdrawn?, null: true
|
47
57
|
field :withdrawn_at, Decidim::Core::DateTimeType, description: "The date and time this meeting was withdrawn", null: true
|
48
58
|
|
59
|
+
def url
|
60
|
+
Decidim::ResourceLocatorPresenter.new(object).url
|
61
|
+
end
|
62
|
+
|
49
63
|
def registration_form
|
50
64
|
object.questionnaire if object.registration_form_enabled?
|
51
65
|
end
|
@@ -66,10 +80,6 @@ module Decidim
|
|
66
80
|
object.audio_url if object.closing_visible?
|
67
81
|
end
|
68
82
|
|
69
|
-
def coordinates
|
70
|
-
[object.latitude, object.longitude]
|
71
|
-
end
|
72
|
-
|
73
83
|
def self.authorized?(object, context)
|
74
84
|
context[:meeting] = object
|
75
85
|
|
@@ -6,7 +6,10 @@ module Decidim
|
|
6
6
|
graphql_name "MeetingService"
|
7
7
|
description "A meeting service"
|
8
8
|
|
9
|
+
implements Decidim::Core::TimestampsInterface
|
10
|
+
|
9
11
|
field :description, Decidim::Core::TranslatedFieldType, "The description for the service", null: true
|
12
|
+
field :id, GraphQL::Types::ID, "The ID of the service", null: false
|
10
13
|
field :title, Decidim::Core::TranslatedFieldType, "The title for the service", null: true
|
11
14
|
end
|
12
15
|
end
|
@@ -12,7 +12,7 @@ module Decidim
|
|
12
12
|
paths["lib/tasks"] = nil
|
13
13
|
|
14
14
|
routes do
|
15
|
-
get "/
|
15
|
+
get "/response_options", to: "registration_form#response_options", as: :response_options_meeting
|
16
16
|
|
17
17
|
resources :meetings do
|
18
18
|
member do
|
@@ -34,8 +34,16 @@ module Decidim
|
|
34
34
|
end
|
35
35
|
collection do
|
36
36
|
get :export
|
37
|
+
end
|
38
|
+
end
|
39
|
+
resources :registrations_attendees, only: [:index] do
|
40
|
+
collection do
|
37
41
|
post :validate_registration_code
|
38
42
|
end
|
43
|
+
member do
|
44
|
+
get :qr_mark_as_attendee
|
45
|
+
put :mark_as_attendee
|
46
|
+
end
|
39
47
|
end
|
40
48
|
resources :agenda, except: [:index, :destroy]
|
41
49
|
resources :attachment_collections, except: [:show]
|
@@ -27,22 +27,43 @@ Decidim.register_component(:meetings) do |component|
|
|
27
27
|
resource.searchable = true
|
28
28
|
end
|
29
29
|
|
30
|
-
component.register_stat :meetings_count,
|
30
|
+
component.register_stat :meetings_count,
|
31
|
+
primary: true,
|
32
|
+
admin: false,
|
33
|
+
priority: Decidim::StatsRegistry::HIGH_PRIORITY,
|
34
|
+
icon_name: "map-pin-line",
|
35
|
+
tooltip_key: "meetings_count_tooltip" do |components, start_at, end_at|
|
31
36
|
meetings = Decidim::Meetings::FilteredMeetings.for(components, start_at, end_at).not_withdrawn
|
32
37
|
meetings.count
|
33
38
|
end
|
34
39
|
|
35
|
-
component.register_stat :
|
40
|
+
component.register_stat :participatory_space_meetings_count,
|
41
|
+
priority: Decidim::StatsRegistry::MEDIUM_PRIORITY,
|
42
|
+
icon_name: "map-pin-line",
|
43
|
+
tooltip_key: "meetings_count_tooltip" do |components, start_at, end_at|
|
44
|
+
meetings = Decidim::Meetings::FilteredMeetings.for(components, start_at, end_at).not_withdrawn
|
45
|
+
meetings.count
|
46
|
+
end
|
47
|
+
|
48
|
+
component.register_stat :followers_count,
|
49
|
+
tag: :followers,
|
50
|
+
icon_name: "user-follow-line",
|
51
|
+
tooltip_key: "followers_count_tooltip",
|
52
|
+
priority: Decidim::StatsRegistry::MEDIUM_PRIORITY do |components, start_at, end_at|
|
36
53
|
meetings_ids = Decidim::Meetings::FilteredMeetings.for(components, start_at, end_at).pluck(:id)
|
37
54
|
Decidim::Follow.where(decidim_followable_type: "Decidim::Meetings::Meeting", decidim_followable_id: meetings_ids).count
|
38
55
|
end
|
39
56
|
|
40
|
-
component.register_stat :comments_count,
|
57
|
+
component.register_stat :comments_count,
|
58
|
+
priority: Decidim::StatsRegistry::HIGH_PRIORITY,
|
59
|
+
icon_name: "chat-1-line",
|
60
|
+
tooltip_key: "comments_count",
|
61
|
+
tag: :comments do |components, start_at, end_at|
|
41
62
|
meetings = Decidim::Meetings::FilteredMeetings.for(components, start_at, end_at).not_hidden
|
42
63
|
meetings.sum(:comments_count)
|
43
64
|
end
|
44
65
|
|
45
|
-
component.register_stat :attendees_count, primary: true, priority: Decidim::StatsRegistry::
|
66
|
+
component.register_stat :attendees_count, primary: true, priority: Decidim::StatsRegistry::LOW_PRIORITY do |components, start_at, end_at|
|
46
67
|
meetings = Decidim::Meetings::Meeting.closed.not_hidden.published.where(component: components, closing_visible: true)
|
47
68
|
meetings = meetings.where(closed_at: start_at..) if start_at.present?
|
48
69
|
meetings = meetings.where(closed_at: ..end_at) if end_at.present?
|
@@ -67,7 +88,7 @@ Decidim.register_component(:meetings) do |component|
|
|
67
88
|
exports.collection do |component_instance|
|
68
89
|
Decidim::Comments::Export.comments_for_resource(
|
69
90
|
Decidim::Meetings::Meeting, component_instance
|
70
|
-
).includes(:author,
|
91
|
+
).includes(:author, root_commentable: { component: { participatory_space: :organization } })
|
71
92
|
end
|
72
93
|
|
73
94
|
exports.include_in_open_data = true
|
@@ -75,14 +96,14 @@ Decidim.register_component(:meetings) do |component|
|
|
75
96
|
exports.serializer Decidim::Comments::CommentSerializer
|
76
97
|
end
|
77
98
|
|
78
|
-
component.exports :
|
99
|
+
component.exports :responses do |exports|
|
79
100
|
exports.collection do |_component, _user, resource_id|
|
80
|
-
Decidim::Meetings::
|
101
|
+
Decidim::Meetings::QuestionnaireUserResponses.for(resource_id)
|
81
102
|
end
|
82
103
|
|
83
104
|
exports.formats %w(CSV JSON Excel FormPDF)
|
84
105
|
|
85
|
-
exports.serializer Decidim::Meetings::
|
106
|
+
exports.serializer Decidim::Meetings::UserResponsesSerializer
|
86
107
|
end
|
87
108
|
|
88
109
|
component.actions = %w(join comment)
|
@@ -25,14 +25,16 @@ module Decidim
|
|
25
25
|
get :create
|
26
26
|
get :decline_invitation
|
27
27
|
get :join, action: :show
|
28
|
-
post :
|
28
|
+
post :respond
|
29
|
+
get :join_waitlist, action: :show
|
30
|
+
post :join_waitlist
|
29
31
|
end
|
30
32
|
end
|
31
33
|
resources :versions, only: [:show]
|
32
34
|
resource :live_event, only: :show
|
33
35
|
namespace :polls do
|
34
36
|
resources :questions, only: [:index, :update]
|
35
|
-
resources :
|
37
|
+
resources :responses, only: [:index, :create] do
|
36
38
|
collection do
|
37
39
|
get :admin
|
38
40
|
end
|
@@ -126,24 +128,7 @@ module Decidim
|
|
126
128
|
end
|
127
129
|
end
|
128
130
|
|
129
|
-
initializer "decidim_meetings.
|
130
|
-
Decidim.metrics_registry.register(:meetings) do |metric_registry|
|
131
|
-
metric_registry.manager_class = "Decidim::Meetings::Metrics::MeetingsMetricManage"
|
132
|
-
|
133
|
-
metric_registry.settings do |settings|
|
134
|
-
settings.attribute :highlighted, type: :boolean, default: false
|
135
|
-
settings.attribute :scopes, type: :array, default: %w(home participatory_process)
|
136
|
-
settings.attribute :weight, type: :integer, default: 5
|
137
|
-
settings.attribute :stat_block, type: :string, default: "small"
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
Decidim.metrics_operation.register(:followers, :meetings) do |metric_operation|
|
142
|
-
metric_operation.manager_class = "Decidim::Meetings::Metrics::MeetingFollowersMetricMeasure"
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
initializer "decidim_meetings.webpacker.assets_path" do
|
131
|
+
initializer "decidim_meetings.shakapacker.assets_path" do
|
147
132
|
Decidim.register_assets_path File.expand_path("app/packs", root)
|
148
133
|
end
|
149
134
|
|
@@ -168,7 +153,7 @@ module Decidim
|
|
168
153
|
Decidim::AuthorizationTransfer.register(:meetings) do |transfer|
|
169
154
|
transfer.move_records(Decidim::Meetings::Meeting, :decidim_author_id)
|
170
155
|
transfer.move_records(Decidim::Meetings::Registration, :decidim_user_id)
|
171
|
-
transfer.move_records(Decidim::Meetings::
|
156
|
+
transfer.move_records(Decidim::Meetings::Response, :decidim_user_id)
|
172
157
|
end
|
173
158
|
end
|
174
159
|
end
|
@@ -55,7 +55,6 @@ module Decidim
|
|
55
55
|
closing_report: resource.closing_report,
|
56
56
|
attending_organizations: resource.attending_organizations,
|
57
57
|
registration_url: resource.registration_url,
|
58
|
-
decidim_user_group_id: resource.decidim_user_group_id,
|
59
58
|
decidim_author_type: resource.decidim_author_type,
|
60
59
|
video_url: resource.video_url,
|
61
60
|
audio_url: resource.audio_url,
|
@@ -88,7 +87,7 @@ module Decidim
|
|
88
87
|
|
89
88
|
def author_url(author)
|
90
89
|
if author.respond_to?(:nickname)
|
91
|
-
profile_url(author) # is a Decidim::User
|
90
|
+
profile_url(author) # is a Decidim::User
|
92
91
|
else
|
93
92
|
root_url # is a Decidim::Organization
|
94
93
|
end
|
@@ -40,8 +40,6 @@ module Decidim
|
|
40
40
|
alias resource meeting
|
41
41
|
|
42
42
|
def organizer
|
43
|
-
return organizer_user_group if meeting.decidim_user_group_id?
|
44
|
-
|
45
43
|
case meeting.author.class.name
|
46
44
|
when "Decidim::Organization"
|
47
45
|
organizer_organization
|
@@ -50,14 +48,6 @@ module Decidim
|
|
50
48
|
end
|
51
49
|
end
|
52
50
|
|
53
|
-
def organizer_user_group
|
54
|
-
{
|
55
|
-
"@type": "Organization",
|
56
|
-
name: meeting.author.name,
|
57
|
-
url: profile_url(meeting.user_group)
|
58
|
-
}
|
59
|
-
end
|
60
|
-
|
61
51
|
def organizer_organization
|
62
52
|
{
|
63
53
|
"@type": "Organization",
|
@@ -15,19 +15,19 @@ module Decidim
|
|
15
15
|
def call
|
16
16
|
component = create_component!
|
17
17
|
|
18
|
-
|
18
|
+
number_of_records.times do
|
19
19
|
create_meeting!(component:, type: :online)
|
20
20
|
create_meeting!(component:, type: :online_live_event)
|
21
21
|
create_meeting!(component:, type: :hybrid)
|
22
22
|
meeting = create_meeting!(component:, type: :in_person)
|
23
23
|
|
24
|
-
|
24
|
+
number_of_records.times do
|
25
25
|
create_service!(meeting:)
|
26
26
|
end
|
27
27
|
|
28
28
|
create_questionnaire_for!(meeting:)
|
29
29
|
|
30
|
-
|
30
|
+
number_of_records.times do |_n|
|
31
31
|
create_meeting_registration!(meeting:)
|
32
32
|
end
|
33
33
|
|
@@ -35,7 +35,6 @@ module Decidim
|
|
35
35
|
end
|
36
36
|
|
37
37
|
create_meeting!(component:, type: [:in_person, :online, :hybrid].sample, author_type: :user)
|
38
|
-
create_meeting!(component:, type: [:in_person, :online, :hybrid].sample, author_type: :user_group)
|
39
38
|
end
|
40
39
|
|
41
40
|
def create_component!
|
@@ -132,14 +131,6 @@ module Decidim
|
|
132
131
|
params.merge(
|
133
132
|
author: Decidim::User.where(decidim_organization_id: participatory_space.decidim_organization_id).all.sample
|
134
133
|
)
|
135
|
-
when :user_group
|
136
|
-
user_group = Decidim::UserGroup.where(decidim_organization_id: participatory_space.decidim_organization_id).verified.sample
|
137
|
-
author = user_group.users.sample
|
138
|
-
|
139
|
-
params.merge(
|
140
|
-
author:,
|
141
|
-
user_group:
|
142
|
-
)
|
143
134
|
else
|
144
135
|
params # official
|
145
136
|
end
|
@@ -149,7 +140,7 @@ module Decidim
|
|
149
140
|
#
|
150
141
|
# @param component [Decidim::Component] The component where this class will be created
|
151
142
|
# @param type [:in_person, :hybrid, :online, :online_live_event] The meeting type
|
152
|
-
# @param author_type [:official, :user
|
143
|
+
# @param author_type [:official, :user] Which type the author of the meeting will be
|
153
144
|
#
|
154
145
|
# @return [Decidim::Meeting]
|
155
146
|
def create_meeting!(component:, type: :in_person, author_type: :official)
|
@@ -37,6 +37,9 @@ FactoryBot.define do
|
|
37
37
|
longitude { Faker::Address.longitude }
|
38
38
|
start_time { 1.day.from_now }
|
39
39
|
end_time { start_time.advance(hours: 2) }
|
40
|
+
reminder_enabled { true }
|
41
|
+
send_reminders_before_hours { 48 }
|
42
|
+
reminder_message_custom_content { generate_localized_description(:meeting_reminder_message, skip_injection:) }
|
40
43
|
private_meeting { false }
|
41
44
|
transparent { true }
|
42
45
|
questionnaire { build(:questionnaire) }
|
@@ -105,15 +108,6 @@ FactoryBot.define do
|
|
105
108
|
|
106
109
|
trait(:participant_author) { not_official }
|
107
110
|
|
108
|
-
trait :user_group_author do
|
109
|
-
author do
|
110
|
-
create(:user, organization: component.organization, skip_injection:) if component
|
111
|
-
end
|
112
|
-
user_group do
|
113
|
-
create(:user_group, :verified, organization: component.organization, users: [author], skip_injection:) if component
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
111
|
trait :closed do
|
118
112
|
closing_report { generate_localized_title(:meeting_closing_report, skip_injection:) }
|
119
113
|
attendees_count { rand(50) }
|
@@ -291,8 +285,8 @@ FactoryBot.define do
|
|
291
285
|
status { 0 }
|
292
286
|
question_type { Decidim::Meetings::Question::QUESTION_TYPES.first }
|
293
287
|
questionnaire factory: :meetings_poll_questionnaire
|
294
|
-
|
295
|
-
Array.new(3).collect { build(:
|
288
|
+
response_options do
|
289
|
+
Array.new(3).collect { build(:meetings_poll_response_option, question: nil, skip_injection:) }
|
296
290
|
end
|
297
291
|
|
298
292
|
trait :unpublished do
|
@@ -308,7 +302,7 @@ FactoryBot.define do
|
|
308
302
|
end
|
309
303
|
end
|
310
304
|
|
311
|
-
factory :
|
305
|
+
factory :meetings_poll_response, class: "Decidim::Meetings::Response" do
|
312
306
|
transient do
|
313
307
|
skip_injection { false }
|
314
308
|
end
|
@@ -317,7 +311,7 @@ FactoryBot.define do
|
|
317
311
|
user { create(:user, organization: questionnaire.questionnaire_for.organization, skip_injection:) }
|
318
312
|
end
|
319
313
|
|
320
|
-
factory :
|
314
|
+
factory :meetings_poll_response_option, class: "Decidim::Meetings::ResponseOption" do
|
321
315
|
transient do
|
322
316
|
skip_injection { false }
|
323
317
|
end
|
@@ -325,11 +319,11 @@ FactoryBot.define do
|
|
325
319
|
body { generate_localized_title }
|
326
320
|
end
|
327
321
|
|
328
|
-
factory :
|
322
|
+
factory :meetings_poll_response_choice, class: "Decidim::Meetings::ResponseChoice" do
|
329
323
|
transient do
|
330
324
|
skip_injection { false }
|
331
325
|
end
|
332
|
-
|
333
|
-
|
326
|
+
response factory: :meetings_poll_response
|
327
|
+
response_option { create(:meetings_poll_response_option, question: response.question, skip_injection:) }
|
334
328
|
end
|
335
329
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Meetings
|
5
|
+
# This class serializes the responses given by a User for questionnaire so can be
|
6
|
+
# exported to CSV, JSON or other formats.
|
7
|
+
class UserResponsesSerializer < Decidim::Exporters::Serializer
|
8
|
+
include Decidim::TranslationsHelper
|
9
|
+
|
10
|
+
# Public: Initializes the serializer with a collection of Responses.
|
11
|
+
def initialize(responses)
|
12
|
+
@responses = responses
|
13
|
+
end
|
14
|
+
|
15
|
+
# Public: Exports a hash with the serialized data for the user responses.
|
16
|
+
def serialize
|
17
|
+
@responses.each_with_index.inject({}) do |serialized, (response, idx)|
|
18
|
+
serialized.update(
|
19
|
+
response_translated_attribute_name(:id) => [response.id, response.user.id].join("_"),
|
20
|
+
response_translated_attribute_name(:created_at) => response.created_at,
|
21
|
+
response_translated_attribute_name(:user_status) => response_translated_attribute_name(response.decidim_user_id.present? ? "registered" : "unregistered"),
|
22
|
+
"#{idx + 1}. #{translated_attribute(response.question.body)}" => normalize_body(response)
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :responses
|
30
|
+
alias resource responses
|
31
|
+
|
32
|
+
def normalize_body(response)
|
33
|
+
normalize_choices(response.choices)
|
34
|
+
end
|
35
|
+
|
36
|
+
def normalize_choices(choices)
|
37
|
+
choices.map do |choice|
|
38
|
+
choice.try(:body)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def response_translated_attribute_name(attribute)
|
43
|
+
I18n.t(attribute.to_sym, scope: "decidim.forms.user_responses_serializer")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|