decidim-meetings 0.24.3 → 0.25.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/join_meeting_button/registration_confirm.erb +6 -0
- data/app/cells/decidim/meetings/join_meeting_button/show.erb +8 -6
- data/app/cells/decidim/meetings/meeting_m_cell.rb +4 -0
- data/app/cells/decidim/meetings/meeting_url/show.erb +7 -2
- data/app/cells/decidim/meetings/meeting_url_cell.rb +14 -2
- data/app/cells/decidim/meetings/meetings_map/show.erb +1 -1
- data/app/cells/decidim/meetings/online_meeting_cell.rb +30 -0
- data/app/cells/decidim/meetings/online_meeting_link/show.erb +44 -0
- data/app/cells/decidim/meetings/online_meeting_link_cell.rb +34 -0
- data/app/cells/decidim/meetings/public_participants_list/show.erb +16 -0
- data/app/cells/decidim/meetings/public_participants_list_cell.rb +31 -0
- data/app/cells/decidim/meetings/question_responses/show.erb +7 -0
- data/app/cells/decidim/meetings/question_responses_cell.rb +72 -0
- data/app/commands/decidim/meetings/admin/close_meeting.rb +3 -0
- data/app/commands/decidim/meetings/admin/copy_meeting.rb +0 -9
- data/app/commands/decidim/meetings/admin/create_meeting.rb +4 -20
- data/app/commands/decidim/meetings/admin/destroy_meeting.rb +2 -0
- data/app/commands/decidim/meetings/admin/publish_meeting.rb +72 -0
- data/app/commands/decidim/meetings/admin/unpublish_meeting.rb +45 -0
- data/app/commands/decidim/meetings/admin/update_meeting.rb +6 -3
- data/app/commands/decidim/meetings/admin/update_question_status.rb +57 -0
- data/app/commands/decidim/meetings/admin/update_questionnaire.rb +93 -0
- data/app/commands/decidim/meetings/close_meeting.rb +2 -0
- data/app/commands/decidim/meetings/create_answer.rb +52 -0
- data/app/commands/decidim/meetings/create_meeting.rb +3 -1
- data/app/commands/decidim/meetings/join_meeting.rb +2 -1
- data/app/commands/decidim/meetings/update_meeting.rb +2 -1
- data/app/controllers/concerns/decidim/meetings/admin/filterable.rb +55 -0
- data/app/controllers/concerns/decidim/meetings/polls_resources.rb +29 -0
- data/app/controllers/decidim/meetings/admin/application_controller.rb +6 -2
- data/app/controllers/decidim/meetings/admin/invites_controller.rb +0 -2
- data/app/controllers/decidim/meetings/admin/meeting_closes_controller.rb +1 -1
- data/app/controllers/decidim/meetings/admin/meetings_controller.rb +46 -1
- data/app/controllers/decidim/meetings/admin/meetings_poll_controller.rb +107 -0
- data/app/controllers/decidim/meetings/calendars_controller.rb +8 -0
- data/app/controllers/decidim/meetings/live_events_controller.rb +29 -0
- data/app/controllers/decidim/meetings/meeting_closes_controller.rb +1 -1
- data/app/controllers/decidim/meetings/polls/answers_controller.rb +37 -0
- data/app/controllers/decidim/meetings/polls/questions_controller.rb +45 -0
- data/app/events/decidim/meetings/create_meeting_event.rb +16 -0
- data/app/forms/decidim/meetings/admin/answer_option_form.rb +24 -0
- data/app/forms/decidim/meetings/admin/close_meeting_form.rb +3 -1
- data/app/forms/decidim/meetings/admin/meeting_form.rb +12 -1
- data/app/forms/decidim/meetings/admin/question_form.rb +44 -0
- data/app/forms/decidim/meetings/admin/questionnaire_form.rb +19 -0
- data/app/forms/decidim/meetings/answer_choice_form.rb +14 -0
- data/app/forms/decidim/meetings/answer_form.rb +65 -0
- data/app/forms/decidim/meetings/close_meeting_form.rb +4 -0
- data/app/forms/decidim/meetings/join_meeting_form.rb +1 -0
- data/app/forms/decidim/meetings/meeting_form.rb +9 -0
- data/app/helpers/decidim/meetings/admin/filterable_helper.rb +13 -0
- data/app/helpers/decidim/meetings/application_helper.rb +3 -2
- data/app/helpers/decidim/meetings/meetings_helper.rb +21 -0
- data/app/models/decidim/meetings/answer.rb +48 -0
- data/app/models/decidim/meetings/answer_choice.rb +15 -0
- data/app/models/decidim/meetings/answer_option.rb +24 -0
- data/app/models/decidim/meetings/meeting.rb +88 -42
- data/app/models/decidim/meetings/poll.rb +19 -0
- data/app/models/decidim/meetings/question.rb +54 -0
- data/app/models/decidim/meetings/questionnaire.rb +23 -0
- data/app/models/decidim/meetings/registration.rb +2 -0
- data/app/packs/entrypoints/decidim_meetings.js +6 -0
- data/app/packs/entrypoints/decidim_meetings_admin.js +5 -0
- data/app/{assets/images/decidim/gamification/badges/attended_meetings.svg → packs/images/decidim/gamification/badges/decidim_gamification_badges_attended_meetings.svg} +0 -0
- data/app/{assets/images/decidim/meetings/icon.svg → packs/images/decidim/meetings/decidim_meetings.svg} +0 -0
- data/app/packs/src/decidim/meetings/admin/agendas.js +159 -0
- data/app/{assets/javascripts/decidim/meetings/admin/destroy_meeting_alert.js.es6 → packs/src/decidim/meetings/admin/destroy_meeting_alert.js} +0 -0
- data/app/{assets/javascripts/decidim/meetings/admin/meetings_form.js.es6 → packs/src/decidim/meetings/admin/meetings_form.js} +7 -4
- data/app/{assets/javascripts/decidim/meetings/admin/registrations_form.js.es6 → packs/src/decidim/meetings/admin/registrations_form.js} +0 -0
- data/app/{assets/javascripts/decidim/meetings/admin/registrations_invite_form.es6 → packs/src/decidim/meetings/admin/registrations_invite_form.js} +3 -3
- data/app/packs/src/decidim/meetings/meetings_form.js +54 -0
- data/app/packs/src/decidim/meetings/meetings_polls.js +41 -0
- data/app/packs/src/decidim/meetings/poll.component.js +166 -0
- data/app/packs/stylesheets/decidim/meetings/_header.scss +52 -0
- data/app/packs/stylesheets/decidim/meetings/_main.scss +178 -0
- data/app/packs/stylesheets/decidim/meetings/_meetings.scss +2 -0
- data/app/permissions/decidim/meetings/admin/permissions.rb +16 -8
- data/app/permissions/decidim/meetings/permissions.rb +42 -17
- data/app/presenters/decidim/meetings/admin_log/meeting_presenter.rb +5 -1
- data/app/presenters/decidim/meetings/meeting_presenter.rb +22 -1
- data/app/queries/decidim/meetings/filtered_meetings.rb +1 -1
- data/app/queries/decidim/meetings/metrics/meetings_metric_manage.rb +1 -1
- data/app/queries/decidim/meetings/questionnaire_user_answers.rb +29 -0
- data/app/serializers/decidim/meetings/data_portability_invite_serializer.rb +2 -1
- data/app/serializers/decidim/meetings/data_portability_registration_serializer.rb +2 -1
- data/app/serializers/decidim/meetings/registration_serializer.rb +3 -12
- data/app/services/decidim/meetings/calendar/component_calendar.rb +2 -2
- data/app/services/decidim/meetings/calendar/meeting_calendar.rb +33 -0
- data/app/services/decidim/meetings/calendar_renderer.rb +2 -0
- data/app/services/decidim/meetings/meeting_iframe_embedder.rb +86 -0
- data/app/services/decidim/meetings/meeting_search.rb +2 -2
- data/app/views/decidim/meetings/admin/agenda/_form.html.erb +1 -1
- data/app/views/decidim/meetings/admin/invite_join_meeting_mailer/invite.html.erb +4 -4
- data/app/views/decidim/meetings/admin/invites/_form.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meeting_closes/_form.html.erb +16 -1
- data/app/views/decidim/meetings/admin/meeting_copies/_form.html.erb +1 -1
- data/app/views/decidim/meetings/admin/meetings/_form.html.erb +16 -1
- data/app/views/decidim/meetings/admin/meetings/index.html.erb +39 -11
- data/app/views/decidim/meetings/admin/poll/_answer_option.html.erb +34 -0
- data/app/views/decidim/meetings/admin/poll/_answer_option_template.html.erb +7 -0
- data/app/views/decidim/meetings/admin/poll/_form.html.erb +63 -0
- data/app/views/decidim/meetings/admin/poll/_question.html.erb +96 -0
- data/app/views/decidim/meetings/admin/poll/edit.html.erb +9 -0
- data/app/views/decidim/meetings/admin/registrations/_form.html.erb +1 -1
- data/app/views/decidim/meetings/directory/meetings/index.html.erb +4 -4
- data/app/views/decidim/meetings/directory/meetings/index.js.erb +2 -0
- data/app/views/decidim/meetings/layouts/live_event.html.erb +50 -0
- data/app/views/decidim/meetings/live_events/show.html.erb +12 -0
- data/app/views/decidim/meetings/meeting_closes/_form.html.erb +8 -1
- data/app/views/decidim/meetings/meeting_closes/edit.html.erb +1 -1
- data/app/views/decidim/meetings/meetings/_calendar_modal.html.erb +26 -0
- data/app/views/decidim/meetings/meetings/_filters.html.erb +1 -1
- data/app/views/decidim/meetings/meetings/_form.html.erb +6 -1
- data/app/views/decidim/meetings/meetings/_meeting_minutes.html.erb +7 -18
- data/app/views/decidim/meetings/meetings/edit.html.erb +1 -1
- data/app/views/decidim/meetings/meetings/index.html.erb +4 -4
- data/app/views/decidim/meetings/meetings/new.html.erb +1 -1
- data/app/views/decidim/meetings/meetings/show.html.erb +12 -13
- data/app/views/decidim/meetings/polls/answers/_multiple_option.html.erb +13 -0
- data/app/views/decidim/meetings/polls/answers/_single_option.html.erb +19 -0
- data/app/views/decidim/meetings/polls/answers/create.js.erb +5 -0
- data/app/views/decidim/meetings/polls/questions/_closed_question.html.erb +7 -0
- data/app/views/decidim/meetings/polls/questions/_index.html.erb +5 -0
- data/app/views/decidim/meetings/polls/questions/_index_admin.html.erb +43 -0
- data/app/views/decidim/meetings/polls/questions/_published_question.html.erb +29 -0
- data/app/views/decidim/meetings/polls/questions/_question.html.erb +7 -0
- data/app/views/decidim/meetings/polls/questions/index.js.erb +5 -0
- data/app/views/decidim/meetings/polls/questions/index_admin.js.erb +5 -0
- data/app/views/decidim/meetings/registration_mailer/confirmation.html.erb +5 -2
- data/app/views/devise/mailer/join_meeting.html.erb +6 -6
- data/config/assets.rb +11 -0
- data/config/locales/ar.yml +3 -24
- data/config/locales/ca.yml +36 -27
- data/config/locales/cs.yml +72 -26
- data/config/locales/de.yml +22 -27
- data/config/locales/el.yml +3 -24
- data/config/locales/en.yml +112 -26
- data/config/locales/es-MX.yml +13 -27
- data/config/locales/es-PY.yml +13 -27
- data/config/locales/es.yml +13 -27
- data/config/locales/eu.yml +3 -24
- data/config/locales/fi-plain.yml +70 -26
- data/config/locales/fi.yml +70 -26
- data/config/locales/fr-CA.yml +19 -26
- data/config/locales/fr-LU.yml +534 -0
- data/config/locales/fr.yml +19 -26
- data/config/locales/gl.yml +46 -24
- data/config/locales/hu.yml +5 -24
- data/config/locales/id-ID.yml +3 -24
- data/config/locales/is-IS.yml +2 -22
- data/config/locales/it.yml +117 -23
- data/config/locales/ja.yml +148 -58
- data/config/locales/lb-LU.yml +1 -0
- data/config/locales/lv.yml +3 -24
- data/config/locales/nl.yml +70 -25
- data/config/locales/no.yml +5 -26
- data/config/locales/pl.yml +22 -33
- data/config/locales/pt-BR.yml +178 -23
- data/config/locales/pt.yml +3 -24
- data/config/locales/ro-RO.yml +38 -27
- data/config/locales/ru.yml +3 -24
- data/config/locales/sk.yml +3 -24
- data/config/locales/sv.yml +36 -27
- data/config/locales/tr-TR.yml +5 -27
- data/config/locales/uk.yml +3 -24
- data/config/locales/zh-CN.yml +3 -24
- data/db/migrate/20210217124802_add_registration_custom_content_to_meetings.rb +8 -0
- data/db/migrate/20210413050756_add_published_at_to_meetings.rb +7 -0
- data/db/migrate/20210413050917_update_published_at_to_existing_meetings.rb +20 -0
- data/db/migrate/20210430123416_add_public_participation_to_decidim_meetings_registrations.rb +7 -0
- data/db/migrate/20210506180226_merge_meetings_minutes_into_meetings_table.rb +48 -0
- data/db/migrate/20210512055802_create_decidim_meetings_polls.rb +10 -0
- data/db/migrate/20210512100333_drop_decidim_meetings_minutes_table.rb +77 -0
- data/db/migrate/20210518133236_merge_minutes_with_closing_report_in_meetings_table.rb +57 -0
- data/db/migrate/20210520084247_create_decidim_meetings_questionnaires.rb +11 -0
- data/db/migrate/20210520084253_create_decidim_meetings_questions.rb +15 -0
- data/db/migrate/20210520084321_create_decidim_meetings_answers.rb +13 -0
- data/db/migrate/20210520084330_create_decidim_meetings_answer_options.rb +10 -0
- data/db/migrate/20210520084337_create_decidim_meetings_answer_choices.rb +13 -0
- data/db/migrate/20210520134834_add_status_to_meetings_questions.rb +7 -0
- data/db/migrate/20210602040614_add_setting_embed_iframe_to_meetings.rb +7 -0
- data/lib/decidim/api/linked_resources_interface.rb +8 -1
- data/lib/decidim/api/meeting_type.rb +19 -4
- data/lib/decidim/api/meetings_type.rb +2 -2
- data/lib/decidim/meetings.rb +10 -0
- data/lib/decidim/meetings/admin_engine.rb +5 -1
- data/lib/decidim/meetings/api.rb +0 -1
- data/lib/decidim/meetings/component.rb +41 -6
- data/lib/decidim/meetings/data_portability_user_answers_serializer.rb +33 -0
- data/lib/decidim/meetings/engine.rb +10 -11
- data/lib/decidim/meetings/meeting_serializer.rb +1 -0
- data/lib/decidim/meetings/polls.rb +10 -0
- data/lib/decidim/meetings/test/factories.rb +85 -9
- data/lib/decidim/meetings/user_answers_serializer.rb +47 -0
- data/lib/decidim/meetings/version.rb +1 -1
- metadata +104 -114
- data/app/assets/config/decidim_meetings_manifest.js +0 -9
- data/app/assets/javascripts/decidim/meetings/admin/agendas.js.es6 +0 -158
- data/app/assets/javascripts/decidim/meetings/meetings_form.js.es6 +0 -54
- data/app/commands/decidim/meetings/admin/create_minutes.rb +0 -55
- data/app/commands/decidim/meetings/admin/update_minutes.rb +0 -63
- data/app/controllers/decidim/meetings/admin/minutes_controller.rb +0 -69
- data/app/forms/decidim/meetings/admin/minutes_form.rb +0 -20
- data/app/models/decidim/meetings/minutes.rb +0 -22
- data/app/presenters/decidim/meetings/admin_log/minutes_presenter.rb +0 -42
- data/app/views/decidim/meetings/admin/minutes/_form.html.erb +0 -23
- data/app/views/decidim/meetings/admin/minutes/edit.html.erb +0 -7
- data/app/views/decidim/meetings/admin/minutes/new.html.erb +0 -7
- data/app/views/decidim/meetings/meetings/_online_meeting_link.html.erb +0 -11
- data/config/locales/ja-JP.yml +0 -494
- data/lib/decidim/api/minutes_type.rb +0 -20
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Meetings
|
5
|
+
class Poll < Meetings::ApplicationRecord
|
6
|
+
has_one :questionnaire,
|
7
|
+
class_name: "Decidim::Meetings::Questionnaire",
|
8
|
+
dependent: :destroy,
|
9
|
+
inverse_of: :questionnaire_for,
|
10
|
+
as: :questionnaire_for
|
11
|
+
|
12
|
+
belongs_to :meeting, foreign_key: "decidim_meeting_id", class_name: "Decidim::Meetings::Meeting"
|
13
|
+
|
14
|
+
delegate :organization, to: :meeting
|
15
|
+
|
16
|
+
QUESTION_TYPES = %w(single_option multiple_option).freeze
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Meetings
|
5
|
+
# The data store for a Question in the Decidim::Meetings component.
|
6
|
+
class Question < Meetings::ApplicationRecord
|
7
|
+
include Decidim::TranslatableResource
|
8
|
+
|
9
|
+
QUESTION_TYPES = %w(single_option multiple_option).freeze
|
10
|
+
|
11
|
+
translatable_fields :body
|
12
|
+
enum status: { unpublished: 0, published: 1, closed: 2 }
|
13
|
+
|
14
|
+
belongs_to :questionnaire, class_name: "Decidim::Meetings::Questionnaire", foreign_key: "decidim_questionnaire_id"
|
15
|
+
|
16
|
+
has_many :answers,
|
17
|
+
class_name: "Decidim::Meetings::Answer",
|
18
|
+
foreign_key: "decidim_question_id",
|
19
|
+
dependent: :destroy,
|
20
|
+
inverse_of: :question
|
21
|
+
|
22
|
+
has_many :answer_options,
|
23
|
+
class_name: "Decidim::Meetings::AnswerOption",
|
24
|
+
foreign_key: "decidim_question_id",
|
25
|
+
dependent: :destroy,
|
26
|
+
inverse_of: :question
|
27
|
+
|
28
|
+
validates :question_type, inclusion: { in: QUESTION_TYPES }
|
29
|
+
|
30
|
+
scope :visible, -> { where(status: [:published, :closed]) }
|
31
|
+
|
32
|
+
def multiple_choice?
|
33
|
+
%w(single_option multiple_option).include?(question_type)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Public: returns whether the questionnaire is answered by the user or not.
|
37
|
+
def answered_by?(user)
|
38
|
+
questionnaire.answers.where({ user: user, question: self }).any? if questionnaire.questions.present? && user.present?
|
39
|
+
end
|
40
|
+
|
41
|
+
def number_of_options
|
42
|
+
answer_options.size
|
43
|
+
end
|
44
|
+
|
45
|
+
def translated_body
|
46
|
+
Decidim::Forms::QuestionPresenter.new(self).translated_body
|
47
|
+
end
|
48
|
+
|
49
|
+
def answers_count
|
50
|
+
questionnaire.answers.where(question: self).count
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Meetings
|
5
|
+
# The data store for a Questionnaire in the Decidim::Meetings component.
|
6
|
+
class Questionnaire < Meetings::ApplicationRecord
|
7
|
+
belongs_to :questionnaire_for, polymorphic: true
|
8
|
+
|
9
|
+
has_many :questions, -> { order(:position) }, class_name: "Question", foreign_key: "decidim_questionnaire_id", dependent: :destroy
|
10
|
+
has_many :answers, class_name: "Answer", foreign_key: "decidim_questionnaire_id", dependent: :destroy
|
11
|
+
|
12
|
+
# Public: returns whether the questionnaire questions can be modified or not.
|
13
|
+
def questions_editable?
|
14
|
+
has_component = questionnaire_for.meeting.respond_to? :component
|
15
|
+
(has_component && !questionnaire_for.meeting.component.published?) || answers.empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
def all_questions_unpublished?
|
19
|
+
questions.all?(&:unpublished?)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
import "src/decidim/meetings/admin/agendas"
|
2
|
+
import "src/decidim/meetings/admin/destroy_meeting_alert"
|
3
|
+
import "src/decidim/meetings/admin/meetings_form"
|
4
|
+
import "src/decidim/meetings/admin/registrations_form"
|
5
|
+
import "src/decidim/meetings/admin/registrations_invite_form"
|
File without changes
|
File without changes
|
@@ -0,0 +1,159 @@
|
|
1
|
+
import AutoButtonsByPositionComponent from "src/decidim/admin/auto_buttons_by_position.component"
|
2
|
+
import AutoLabelByPositionComponent from "src/decidim/admin/auto_label_by_position.component"
|
3
|
+
import createSortList from "src/decidim/admin/sort_list.component"
|
4
|
+
import createDynamicFields from "src/decidim/admin/dynamic_fields.component"
|
5
|
+
import createQuillEditor from "src/decidim/editor"
|
6
|
+
|
7
|
+
const wrapperSelector = ".meeting-agenda-items";
|
8
|
+
const fieldSelector = ".meeting-agenda-item";
|
9
|
+
const childsWrapperSelector = ".meeting-agenda-item-childs";
|
10
|
+
const childFieldSelector = ".meeting-agenda-item-child";
|
11
|
+
|
12
|
+
const autoLabelByPosition = new AutoLabelByPositionComponent({
|
13
|
+
listSelector: ".meeting-agenda-item:not(.hidden)",
|
14
|
+
labelSelector: ".card-title span:first",
|
15
|
+
onPositionComputed: (el, idx) => {
|
16
|
+
$(el).find("input[name$=\\[position\\]]").val(idx);
|
17
|
+
}
|
18
|
+
});
|
19
|
+
|
20
|
+
const autoButtonsByPosition = new AutoButtonsByPositionComponent({
|
21
|
+
listSelector: ".meeting-agenda-item:not(.hidden)",
|
22
|
+
hideOnFirstSelector: ".move-up-agenda-item",
|
23
|
+
hideOnLastSelector: ".move-down-agenda-item"
|
24
|
+
});
|
25
|
+
|
26
|
+
const createSortableList = () => {
|
27
|
+
createSortList(".meeting-agenda-items-list:not(.published)", {
|
28
|
+
handle: ".agenda-item-divider",
|
29
|
+
placeholder: '<div style="border-style: dashed; border-color: #000"></div>',
|
30
|
+
forcePlaceholderSize: true,
|
31
|
+
onSortUpdate: () => { autoLabelByPosition.run() }
|
32
|
+
});
|
33
|
+
};
|
34
|
+
|
35
|
+
const createSortableListChild = () => {
|
36
|
+
createSortList(".meeting-agenda-item-childs-list:not(.published)", {
|
37
|
+
handle: ".agenda-item-child-divider",
|
38
|
+
placeholder: '<div style="border-style: dashed; border-color: #000"></div>',
|
39
|
+
forcePlaceholderSize: true,
|
40
|
+
onSortUpdate: () => { autoLabelByPosition.run() }
|
41
|
+
});
|
42
|
+
};
|
43
|
+
|
44
|
+
const autoLabelByPositionChild = new AutoLabelByPositionComponent({
|
45
|
+
listSelector: ".meeting-agenda-item-child:not(.hidden)",
|
46
|
+
labelSelector: ".card-title span:first",
|
47
|
+
onPositionComputed: (el, idx) => {
|
48
|
+
$(el).find("input[name$=\\[position\\]]").val(idx);
|
49
|
+
}
|
50
|
+
});
|
51
|
+
|
52
|
+
const autoButtonsByPositionChild = new AutoButtonsByPositionComponent({
|
53
|
+
listSelector: ".meeting-agenda-item-child:not(.hidden)",
|
54
|
+
hideOnFirstSelector: ".move-up-agenda-item-child",
|
55
|
+
hideOnLastSelector: ".move-down-agenda-item-child"
|
56
|
+
});
|
57
|
+
|
58
|
+
const createDynamicFieldsForAgendaItemChilds = (fieldId) => {
|
59
|
+
return createDynamicFields({
|
60
|
+
placeholderId: "meeting-agenda-item-child-id",
|
61
|
+
wrapperSelector: `#${fieldId} ${childsWrapperSelector}`,
|
62
|
+
containerSelector: ".meeting-agenda-item-childs-list",
|
63
|
+
fieldSelector: childFieldSelector,
|
64
|
+
addFieldButtonSelector: ".add-agenda-item-child",
|
65
|
+
removeFieldButtonSelector: ".remove-agenda-item-child",
|
66
|
+
moveUpFieldButtonSelector: ".move-up-agenda-item-child",
|
67
|
+
moveDownFieldButtonSelector: ".move-down-agenda-item-child",
|
68
|
+
|
69
|
+
onAddField: ($field) => {
|
70
|
+
createSortableListChild();
|
71
|
+
|
72
|
+
$field.find(".editor-container").each((idx, el) => {
|
73
|
+
createQuillEditor(el);
|
74
|
+
});
|
75
|
+
|
76
|
+
autoLabelByPositionChild.run();
|
77
|
+
autoButtonsByPositionChild.run();
|
78
|
+
},
|
79
|
+
onRemoveField: () => {
|
80
|
+
autoLabelByPositionChild.run();
|
81
|
+
autoButtonsByPositionChild.run();
|
82
|
+
},
|
83
|
+
onMoveUpField: () => {
|
84
|
+
autoLabelByPositionChild.run();
|
85
|
+
autoButtonsByPositionChild.run();
|
86
|
+
},
|
87
|
+
onMoveDownField: () => {
|
88
|
+
autoLabelByPositionChild.run();
|
89
|
+
autoButtonsByPositionChild.run();
|
90
|
+
}
|
91
|
+
});
|
92
|
+
};
|
93
|
+
|
94
|
+
const dynamicFieldsForAgendaItemChilds = {};
|
95
|
+
|
96
|
+
const setupInitialAgendaItemChildAttributes = ($target) => {
|
97
|
+
const fieldId = $target.attr("id");
|
98
|
+
|
99
|
+
dynamicFieldsForAgendaItemChilds[fieldId] = createDynamicFieldsForAgendaItemChilds(fieldId);
|
100
|
+
|
101
|
+
}
|
102
|
+
|
103
|
+
const hideDeletedAgendaItem = ($target) => {
|
104
|
+
const inputDeleted = $target.find("input[name$=\\[deleted\\]]").val();
|
105
|
+
|
106
|
+
if (inputDeleted === "true") {
|
107
|
+
$target.addClass("hidden");
|
108
|
+
$target.hide();
|
109
|
+
}
|
110
|
+
};
|
111
|
+
|
112
|
+
createDynamicFields({
|
113
|
+
placeholderId: "meeting-agenda-item-id",
|
114
|
+
wrapperSelector: wrapperSelector,
|
115
|
+
containerSelector: ".meeting-agenda-items-list",
|
116
|
+
fieldSelector: fieldSelector,
|
117
|
+
addFieldButtonSelector: ".add-agenda-item",
|
118
|
+
removeFieldButtonSelector: ".remove-agenda-item",
|
119
|
+
moveUpFieldButtonSelector: ".move-up-agenda-item",
|
120
|
+
moveDownFieldButtonSelector: ".move-down-agenda-item",
|
121
|
+
onAddField: ($field) => {
|
122
|
+
// createDynamicFieldsForAgendaItemChilds($field);
|
123
|
+
setupInitialAgendaItemChildAttributes($field);
|
124
|
+
createSortableList();
|
125
|
+
|
126
|
+
$field.find(".editor-container").each((idx, el) => {
|
127
|
+
createQuillEditor(el);
|
128
|
+
});
|
129
|
+
|
130
|
+
autoLabelByPosition.run();
|
131
|
+
autoButtonsByPosition.run();
|
132
|
+
},
|
133
|
+
onRemoveField: () => {
|
134
|
+
autoLabelByPosition.run();
|
135
|
+
autoButtonsByPosition.run();
|
136
|
+
},
|
137
|
+
onMoveUpField: () => {
|
138
|
+
autoLabelByPosition.run();
|
139
|
+
autoButtonsByPosition.run();
|
140
|
+
},
|
141
|
+
onMoveDownField: () => {
|
142
|
+
autoLabelByPosition.run();
|
143
|
+
autoButtonsByPosition.run();
|
144
|
+
}
|
145
|
+
});
|
146
|
+
|
147
|
+
createSortableList();
|
148
|
+
|
149
|
+
$(fieldSelector).each((idx, el) => {
|
150
|
+
const $target = $(el);
|
151
|
+
|
152
|
+
hideDeletedAgendaItem($target);
|
153
|
+
setupInitialAgendaItemChildAttributes($target);
|
154
|
+
});
|
155
|
+
|
156
|
+
autoLabelByPosition.run();
|
157
|
+
autoButtonsByPosition.run();
|
158
|
+
autoLabelByPositionChild.run();
|
159
|
+
autoButtonsByPositionChild.run();
|
File without changes
|
@@ -1,7 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
import AutoButtonsByPositionComponent from "src/decidim/admin/auto_buttons_by_position.component"
|
2
|
+
import AutoLabelByPositionComponent from "src/decidim/admin/auto_label_by_position.component"
|
3
|
+
import createSortList from "src/decidim/admin/sort_list.component"
|
4
|
+
import createDynamicFields from "src/decidim/admin/dynamic_fields.component"
|
5
|
+
import attachGeocoding from "src/decidim/geocoding/attach_input"
|
4
6
|
|
7
|
+
$(() => {
|
5
8
|
const wrapperSelector = ".meeting-services";
|
6
9
|
const fieldSelector = ".meeting-service";
|
7
10
|
|
@@ -144,4 +147,4 @@
|
|
144
147
|
toggleDependsOnSelect($meetingTypeOfMeeting, $meetingOnlineFields, "online");
|
145
148
|
toggleDependsOnSelect($meetingTypeOfMeeting, $meetingInPersonFields, "in_person");
|
146
149
|
}
|
147
|
-
})
|
150
|
+
})
|
File without changes
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
2
|
-
const { createFieldDependentInputs } = exports.DecidimAdmin;
|
1
|
+
import createFieldDependentInputs from "src/decidim/admin/field_dependent_inputs.component"
|
3
2
|
|
3
|
+
$(() => {
|
4
4
|
const $attendeeType = $('[name="meeting_registration_invite[existing_user]"');
|
5
5
|
|
6
6
|
createFieldDependentInputs({
|
@@ -22,4 +22,4 @@
|
|
22
22
|
return $("#meeting_registration_invite_existing_user_true").is(":checked")
|
23
23
|
}
|
24
24
|
});
|
25
|
-
})
|
25
|
+
})
|
@@ -0,0 +1,54 @@
|
|
1
|
+
import attachGeocoding from "src/decidim/geocoding/attach_input"
|
2
|
+
|
3
|
+
$(() => {
|
4
|
+
// Adds the latitude/longitude inputs after the geocoding is done
|
5
|
+
const $meetingAddress = $("#meeting_address");
|
6
|
+
if ($meetingAddress.length > 0) {
|
7
|
+
attachGeocoding($meetingAddress);
|
8
|
+
}
|
9
|
+
|
10
|
+
const $form = $(".meetings_form");
|
11
|
+
if ($form.length > 0) {
|
12
|
+
const $meetingTypeOfMeeting = $form.find("#meeting_type_of_meeting");
|
13
|
+
const $meetingOnlineFields = $form.find(".field[data-meeting-type='online']");
|
14
|
+
const $meetingInPersonFields = $form.find(".field[data-meeting-type='in_person']");
|
15
|
+
|
16
|
+
const toggleDependsOnSelect = ($target, $showDiv, type) => {
|
17
|
+
const value = $target.val();
|
18
|
+
if (value === "hybrid") {
|
19
|
+
$showDiv.show();
|
20
|
+
} else {
|
21
|
+
$showDiv.hide();
|
22
|
+
if (value === type) {
|
23
|
+
$showDiv.show();
|
24
|
+
}
|
25
|
+
}
|
26
|
+
};
|
27
|
+
|
28
|
+
$meetingTypeOfMeeting.on("change", (ev) => {
|
29
|
+
const $target = $(ev.target);
|
30
|
+
toggleDependsOnSelect($target, $meetingOnlineFields, "online");
|
31
|
+
toggleDependsOnSelect($target, $meetingInPersonFields, "in_person");
|
32
|
+
});
|
33
|
+
|
34
|
+
toggleDependsOnSelect($meetingTypeOfMeeting, $meetingOnlineFields, "online");
|
35
|
+
toggleDependsOnSelect($meetingTypeOfMeeting, $meetingInPersonFields, "in_person");
|
36
|
+
|
37
|
+
|
38
|
+
const $meetingRegistrationType = $form.find("#meeting_registration_type");
|
39
|
+
const $meetingRegistrationTerms = $form.find("#meeting_registration_terms");
|
40
|
+
const $meetingRegistrationUrl = $form.find("#meeting_registration_url");
|
41
|
+
const $meetingAvailableSlots = $form.find("#meeting_available_slots");
|
42
|
+
|
43
|
+
$meetingRegistrationType.on("change", (ev) => {
|
44
|
+
const $target = $(ev.target);
|
45
|
+
toggleDependsOnSelect($target, $meetingAvailableSlots, "on_this_platform");
|
46
|
+
toggleDependsOnSelect($target, $meetingRegistrationTerms, "on_this_platform");
|
47
|
+
toggleDependsOnSelect($target, $meetingRegistrationUrl, "on_different_platform");
|
48
|
+
});
|
49
|
+
|
50
|
+
toggleDependsOnSelect($meetingRegistrationType, $meetingAvailableSlots, "on_this_platform");
|
51
|
+
toggleDependsOnSelect($meetingRegistrationType, $meetingRegistrationTerms, "on_this_platform");
|
52
|
+
toggleDependsOnSelect($meetingRegistrationType, $meetingRegistrationUrl, "on_different_platform");
|
53
|
+
}
|
54
|
+
});
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import MeetingsPollComponent from "src/decidim/meetings/poll.component"
|
2
|
+
const OPEN_CLASS = "is-open";
|
3
|
+
|
4
|
+
$(() => {
|
5
|
+
// Mount polls component for users
|
6
|
+
const $container = $("[data-decidim-meetings-poll]");
|
7
|
+
const $counter = $("#visible-questions-count");
|
8
|
+
const poll = new MeetingsPollComponent($container, $container.data("decidim-meetings-poll"), $counter);
|
9
|
+
|
10
|
+
$(".meeting-polls__action-list").on("click", (event) => {
|
11
|
+
event.preventDefault();
|
12
|
+
|
13
|
+
if (poll.isMounted()) {
|
14
|
+
$(event.target).removeClass(OPEN_CLASS);
|
15
|
+
$container.removeClass(OPEN_CLASS);
|
16
|
+
poll.unmountComponent();
|
17
|
+
} else {
|
18
|
+
$(event.target).addClass(OPEN_CLASS);
|
19
|
+
$container.addClass(OPEN_CLASS);
|
20
|
+
poll.mountComponent();
|
21
|
+
}
|
22
|
+
});
|
23
|
+
|
24
|
+
// Mount polls component for admins
|
25
|
+
const $adminContainer = $("[data-decidim-admin-meetings-poll]");
|
26
|
+
const adminPoll = new MeetingsPollComponent($adminContainer, $adminContainer.data("decidim-admin-meetings-poll"));
|
27
|
+
|
28
|
+
$(".meeting-polls__action-administrate").on("click", (event) => {
|
29
|
+
event.preventDefault();
|
30
|
+
|
31
|
+
if (adminPoll.isMounted()) {
|
32
|
+
$(event.target).removeClass(OPEN_CLASS);
|
33
|
+
$adminContainer.removeClass(OPEN_CLASS);
|
34
|
+
adminPoll.unmountComponent();
|
35
|
+
} else {
|
36
|
+
$(event.target).addClass(OPEN_CLASS);
|
37
|
+
$adminContainer.addClass(OPEN_CLASS);
|
38
|
+
adminPoll.mountComponent();
|
39
|
+
}
|
40
|
+
});
|
41
|
+
});
|
@@ -0,0 +1,166 @@
|
|
1
|
+
/* eslint id-length: ["error", { "exceptions": ["$"] }] */
|
2
|
+
|
3
|
+
/**
|
4
|
+
* A plain Javascript component that handles questions from polls in meetings:
|
5
|
+
* - fetches them via Ajax
|
6
|
+
* - enables a polling to automatically update them
|
7
|
+
*
|
8
|
+
* @class
|
9
|
+
* @augments Component
|
10
|
+
*/
|
11
|
+
|
12
|
+
// This is necessary for testing purposes
|
13
|
+
const $ = window.$;
|
14
|
+
|
15
|
+
// Default question states
|
16
|
+
const OPEN = "open";
|
17
|
+
const CLOSED = "closed";
|
18
|
+
|
19
|
+
export default class PollComponent {
|
20
|
+
constructor($element, config, $counter = null) {
|
21
|
+
this.$element = $element;
|
22
|
+
this.$counter = $counter;
|
23
|
+
this.questionsUrl = config.questionsUrl;
|
24
|
+
this.pollingInterval = config.pollingInterval || 5000;
|
25
|
+
this.mounted = false;
|
26
|
+
this.questions = {};
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Returns if the component is mounted or not
|
31
|
+
* @public
|
32
|
+
* @returns {Void} - Returns nothing
|
33
|
+
*/
|
34
|
+
isMounted() {
|
35
|
+
return this.mounted;
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Handles the logic for mounting the component
|
40
|
+
* @public
|
41
|
+
* @returns {Void} - Returns nothing
|
42
|
+
*/
|
43
|
+
mountComponent() {
|
44
|
+
if (this.$element.length > 0 && !this.mounted) {
|
45
|
+
this.mounted = true;
|
46
|
+
this._fetchQuestions();
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
unmountComponent() {
|
51
|
+
if (this.mounted) {
|
52
|
+
this.mounted = false;
|
53
|
+
this._stopPolling();
|
54
|
+
this.$element.html("");
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
/**
|
59
|
+
* Performs the ajax call that updates the list of questions
|
60
|
+
* Before, stores the current questions states to apply them after the ajax call has
|
61
|
+
* been completed
|
62
|
+
* @private
|
63
|
+
* @returns {Void} - Returns nothing
|
64
|
+
*/
|
65
|
+
_fetchQuestions() {
|
66
|
+
// Store current questions state (open / closed) before overwritting them with the Ajax call
|
67
|
+
// response.
|
68
|
+
this._storeQuestionState(this.$element);
|
69
|
+
|
70
|
+
$.ajax({
|
71
|
+
url: this.questionsUrl,
|
72
|
+
method: "GET",
|
73
|
+
contentType: "application/javascript"
|
74
|
+
}).done(() => {
|
75
|
+
this._updateCounter();
|
76
|
+
this._setQuestionsState(this.$element);
|
77
|
+
this._pollQuestions();
|
78
|
+
});
|
79
|
+
}
|
80
|
+
|
81
|
+
/**
|
82
|
+
* Iterates over all existing questions and stores the state in an internal attribute.
|
83
|
+
* @private
|
84
|
+
* @param {jQuery} $parent - The HTML content for the questionnaire.
|
85
|
+
* @returns {Void} - Returns nothing
|
86
|
+
*/
|
87
|
+
_storeQuestionState($parent) {
|
88
|
+
$("[data-question]", $parent).each((_i, el) => {
|
89
|
+
const $el = $(el);
|
90
|
+
const questionId = $el.data("question");
|
91
|
+
if ($el[0].open === true) {
|
92
|
+
this.questions[questionId] = OPEN;
|
93
|
+
} else {
|
94
|
+
this.questions[questionId] = CLOSED;
|
95
|
+
}
|
96
|
+
});
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* Initializes the states of all the questions.
|
101
|
+
* @private
|
102
|
+
* @param {jQuery} $parent - The HTML container for the questionnaire.
|
103
|
+
* @returns {Void} - Returns nothing
|
104
|
+
*/
|
105
|
+
_setQuestionsState($parent) {
|
106
|
+
$("[data-question]", $parent).each((_i, el) => {
|
107
|
+
this._setQuestionState($(el));
|
108
|
+
});
|
109
|
+
}
|
110
|
+
|
111
|
+
/**
|
112
|
+
* Initializes the state of a single question with two types of modifications:
|
113
|
+
* - sets the is-new class if the question is new (doesn't exist in the internal list)
|
114
|
+
* - sets the state to open if it was open in the internal list
|
115
|
+
* @private
|
116
|
+
* @param {jQuery} $el - The HTML container for the questionnaire.
|
117
|
+
* @returns {Void} - Returns nothing
|
118
|
+
*/
|
119
|
+
_setQuestionState($el) {
|
120
|
+
const questionId = $el.data("question");
|
121
|
+
// Current question state
|
122
|
+
const state = this.questions[questionId];
|
123
|
+
// New questions have a special class
|
124
|
+
if (!state) {
|
125
|
+
$el.addClass("is-new");
|
126
|
+
} else if (state === OPEN) {
|
127
|
+
$el.prop(OPEN, true);
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
/**
|
132
|
+
* Sets a timeout to poll new questions.
|
133
|
+
* @private
|
134
|
+
* @returns {Void} - Returns nothing
|
135
|
+
*/
|
136
|
+
_pollQuestions() {
|
137
|
+
this._stopPolling();
|
138
|
+
|
139
|
+
this.pollTimeout = setTimeout(() => {
|
140
|
+
this._fetchQuestions();
|
141
|
+
}, this.pollingInterval);
|
142
|
+
}
|
143
|
+
|
144
|
+
/**
|
145
|
+
* Stops polling for new questions.
|
146
|
+
* @private
|
147
|
+
* @returns {Void} - Returns nothing
|
148
|
+
*/
|
149
|
+
_stopPolling() {
|
150
|
+
if (this.pollTimeout) {
|
151
|
+
clearTimeout(this.pollTimeout);
|
152
|
+
}
|
153
|
+
}
|
154
|
+
|
155
|
+
/**
|
156
|
+
* Updates the counter with the number of questions returned in the Ajax call
|
157
|
+
* @private
|
158
|
+
* @returns {Void} - Returns nothing
|
159
|
+
*/
|
160
|
+
_updateCounter() {
|
161
|
+
if (this.$counter) {
|
162
|
+
const questionsCount = this.$element.find("details").length;
|
163
|
+
this.$counter.html(`(${questionsCount})`);
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}
|