decidim-meetings 0.29.2 → 0.30.0.rc2

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.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/meetings/cancel_registration_meeting_button/cancelation_modal.erb +1 -1
  3. data/app/cells/decidim/meetings/cancel_registration_meeting_button/show.erb +3 -1
  4. data/app/cells/decidim/meetings/cancel_registration_meeting_button_cell.rb +1 -1
  5. data/app/cells/decidim/meetings/dates_and_map/show.erb +1 -1
  6. data/app/cells/decidim/meetings/highlighted_meetings_for_component/show.erb +1 -1
  7. data/app/cells/decidim/meetings/join_meeting_button/show.erb +5 -2
  8. data/app/cells/decidim/meetings/meeting_card_metadata_cell.rb +3 -3
  9. data/app/cells/decidim/meetings/meeting_l_cell.rb +12 -0
  10. data/app/commands/decidim/meetings/admin/copy_meeting.rb +1 -2
  11. data/app/commands/decidim/meetings/admin/create_meeting.rb +8 -2
  12. data/app/commands/decidim/meetings/admin/update_meeting.rb +8 -2
  13. data/app/commands/decidim/meetings/create_meeting.rb +2 -2
  14. data/app/commands/decidim/meetings/update_meeting.rb +2 -3
  15. data/app/controllers/concerns/decidim/meetings/admin/filterable.rb +9 -5
  16. data/app/controllers/concerns/decidim/meetings/component_filterable.rb +1 -2
  17. data/app/controllers/decidim/meetings/admin/meetings_controller.rb +14 -22
  18. data/app/controllers/decidim/meetings/admin/registration_form_controller.rb +8 -0
  19. data/app/controllers/decidim/meetings/directory/meetings_controller.rb +2 -4
  20. data/app/controllers/decidim/meetings/meetings_controller.rb +40 -6
  21. data/app/forms/decidim/meetings/admin/meeting_form.rb +16 -30
  22. data/app/forms/decidim/meetings/base_meeting_form.rb +6 -0
  23. data/app/forms/decidim/meetings/meeting_form.rb +2 -30
  24. data/app/helpers/decidim/meetings/admin/application_helper.rb +11 -1
  25. data/app/helpers/decidim/meetings/application_helper.rb +35 -1
  26. data/app/helpers/decidim/meetings/directory/application_helper.rb +9 -48
  27. data/app/helpers/decidim/meetings/meetings_helper.rb +5 -0
  28. data/app/models/decidim/meetings/invite.rb +10 -0
  29. data/app/models/decidim/meetings/meeting.rb +23 -1
  30. data/app/models/decidim/meetings/meeting_link.rb +25 -0
  31. data/app/packs/entrypoints/decidim_meetings_admin.js +1 -0
  32. data/app/packs/src/decidim/meetings/admin/meetings_components_form.js +77 -0
  33. data/app/packs/src/decidim/meetings/admin/meetings_form.js +8 -0
  34. data/app/permissions/decidim/meetings/admin/permissions.rb +1 -1
  35. data/app/permissions/decidim/meetings/permissions.rb +13 -9
  36. data/app/presenters/decidim/meetings/admin_log/meeting_presenter.rb +1 -1
  37. data/app/presenters/decidim/meetings/meeting_presenter.rb +13 -1
  38. data/app/queries/decidim/meetings/filtered_meetings.rb +2 -2
  39. data/app/queries/decidim/meetings/metrics/meeting_followers_metric_measure.rb +2 -2
  40. data/app/queries/decidim/meetings/metrics/meetings_metric_manage.rb +6 -6
  41. data/app/serializers/decidim/meetings/base_download_your_data_serializer.rb +32 -0
  42. data/app/serializers/decidim/meetings/download_your_data_invite_serializer.rb +6 -26
  43. data/app/serializers/decidim/meetings/download_your_data_meeting_serializer.rb +15 -0
  44. data/app/serializers/decidim/meetings/download_your_data_registration_serializer.rb +6 -24
  45. data/app/views/decidim/meetings/admin/meetings/_component.html.erb +15 -0
  46. data/app/views/decidim/meetings/admin/meetings/_form.html.erb +7 -9
  47. data/app/views/decidim/meetings/admin/meetings/_linked_spaces.html.erb +53 -0
  48. data/app/views/decidim/meetings/admin/meetings/_meeting-tr.html.erb +42 -0
  49. data/app/views/decidim/meetings/admin/meetings/_meeting_actions.html.erb +70 -0
  50. data/app/views/decidim/meetings/admin/meetings/_meetings-thead.html.erb +26 -0
  51. data/app/views/decidim/meetings/admin/meetings/index.html.erb +16 -142
  52. data/app/views/decidim/meetings/admin/meetings/manage_trash.html.erb +23 -0
  53. data/app/views/decidim/meetings/admin/registration_form/edit_questions.html.erb +44 -0
  54. data/app/views/decidim/meetings/admin/registrations/edit.html.erb +1 -0
  55. data/app/views/decidim/meetings/directory/meetings/index.html.erb +1 -2
  56. data/app/views/decidim/meetings/live_events/show.html.erb +5 -5
  57. data/app/views/decidim/meetings/meetings/_form.html.erb +4 -8
  58. data/app/views/decidim/meetings/meetings/_meeting.html.erb +51 -26
  59. data/app/views/decidim/meetings/meetings/_meeting_actions.html.erb +34 -0
  60. data/app/views/decidim/meetings/meetings/_meeting_aside.html.erb +20 -59
  61. data/app/views/decidim/meetings/meetings/_meeting_poll_actions.html.erb +2 -5
  62. data/app/views/decidim/meetings/meetings/_schema_org_event_meeting.html.erb +3 -0
  63. data/app/views/decidim/meetings/meetings/index.html.erb +10 -2
  64. data/app/views/decidim/meetings/meetings/show.html.erb +5 -5
  65. data/app/views/decidim/meetings/polls/answers/index.html.erb +5 -5
  66. data/app/views/decidim/meetings/shared/_filters.html.erb +1 -13
  67. data/app/views/decidim/meetings/shared/_index.html.erb +1 -1
  68. data/app/views/decidim/meetings/shared/_index.js.erb +3 -2
  69. data/app/views/decidim/meetings/shared/_meetings_aside.html.erb +2 -2
  70. data/app/views/decidim/participatory_spaces/_conference_venues.html.erb +1 -1
  71. data/config/locales/ar.yml +17 -17
  72. data/config/locales/bg.yml +5 -25
  73. data/config/locales/ca.yml +137 -25
  74. data/config/locales/cs.yml +138 -28
  75. data/config/locales/de.yml +138 -26
  76. data/config/locales/el.yml +1 -22
  77. data/config/locales/en.yml +133 -21
  78. data/config/locales/es-MX.yml +137 -25
  79. data/config/locales/es-PY.yml +137 -25
  80. data/config/locales/es.yml +137 -25
  81. data/config/locales/eu.yml +138 -26
  82. data/config/locales/fi-plain.yml +138 -26
  83. data/config/locales/fi.yml +138 -26
  84. data/config/locales/fr-CA.yml +79 -26
  85. data/config/locales/fr.yml +79 -26
  86. data/config/locales/ga-IE.yml +0 -13
  87. data/config/locales/gl.yml +1 -12
  88. data/config/locales/hu.yml +1 -19
  89. data/config/locales/id-ID.yml +1 -13
  90. data/config/locales/is-IS.yml +0 -12
  91. data/config/locales/it.yml +1 -17
  92. data/config/locales/ja.yml +95 -25
  93. data/config/locales/lb.yml +0 -11
  94. data/config/locales/lt.yml +1 -23
  95. data/config/locales/lv.yml +1 -13
  96. data/config/locales/nl.yml +1 -17
  97. data/config/locales/no.yml +1 -16
  98. data/config/locales/pl.yml +5 -21
  99. data/config/locales/pt-BR.yml +1 -21
  100. data/config/locales/pt.yml +1 -17
  101. data/config/locales/ro-RO.yml +30 -17
  102. data/config/locales/ru.yml +1 -13
  103. data/config/locales/sk.yml +1 -13
  104. data/config/locales/sv.yml +74 -26
  105. data/config/locales/tr-TR.yml +1 -19
  106. data/config/locales/uk.yml +0 -12
  107. data/config/locales/zh-CN.yml +1 -18
  108. data/config/locales/zh-TW.yml +1 -21
  109. data/db/migrate/20181107175558_add_questionnaire_to_existing_meetings.rb +1 -1
  110. data/db/migrate/20200827153856_add_commentable_counter_cache_to_meetings.rb +1 -1
  111. data/db/migrate/20201016065302_fix_meetings_registration_terms.rb +1 -1
  112. data/db/migrate/20210310120731_add_followable_counter_cache_to_meetings.rb +1 -1
  113. data/db/migrate/20240712104245_create_decidim_meetings_meeting_link.rb +12 -0
  114. data/db/migrate/20240828103603_add_deleted_at_to_decidim_meetings_meetings.rb +8 -0
  115. data/decidim-meetings.gemspec +1 -1
  116. data/lib/decidim/api/agenda_item_type.rb +6 -7
  117. data/lib/decidim/api/agenda_type.rb +3 -4
  118. data/lib/decidim/api/meeting_type.rb +33 -41
  119. data/lib/decidim/api/meetings_type.rb +4 -5
  120. data/lib/decidim/api/service_type.rb +1 -1
  121. data/lib/decidim/meetings/admin_engine.rb +9 -1
  122. data/lib/decidim/meetings/component.rb +14 -4
  123. data/lib/decidim/meetings/download_your_data_user_answers_serializer.rb +13 -7
  124. data/lib/decidim/meetings/meeting_serializer.rb +70 -59
  125. data/lib/decidim/meetings/schema_org_event_meeting_serializer.rb +151 -0
  126. data/lib/decidim/meetings/seeds.rb +2 -4
  127. data/lib/decidim/meetings/test/factories.rb +8 -0
  128. data/lib/decidim/meetings/test/translated_event.rb +3 -3
  129. data/lib/decidim/meetings/version.rb +1 -1
  130. data/lib/decidim/meetings.rb +1 -0
  131. metadata +32 -21
  132. data/app/cells/decidim/meetings/meetings_map/show.erb +0 -16
  133. data/app/cells/decidim/meetings/meetings_map_cell.rb +0 -32
  134. data/app/commands/decidim/meetings/admin/destroy_meeting.rb +0 -21
  135. data/app/helpers/decidim/meetings/map_helper.rb +0 -21
  136. data/app/views/decidim/meetings/meetings/_actions.html.erb +0 -6
@@ -7,7 +7,6 @@ module Decidim
7
7
  module ApplicationHelper
8
8
  include PaginateHelper
9
9
  include Decidim::MapHelper
10
- include Decidim::Meetings::MapHelper
11
10
  include Decidim::Comments::CommentsHelper
12
11
  include Decidim::SanitizeHelper
13
12
  include Decidim::CheckBoxesTreeHelper
@@ -39,6 +38,41 @@ module Decidim
39
38
  flat_filter_values(:all, :upcoming, :past, scope: "decidim.meetings.meetings.filters.date_values")
40
39
  end
41
40
 
41
+ # rubocop:disable Metrics/ParameterLists
42
+ # rubocop:disable Metrics/CyclomaticComplexity
43
+ def filter_sections(date: false, type: false, origin: false, taxonomies: false, space_type: false, activity: false)
44
+ @filter_sections ||= begin
45
+ items = []
46
+ if date
47
+ items.append(method: :with_any_date, collection: filter_date_values, label: t("decidim.meetings.meetings.filters.date"), id: "date",
48
+ type: :radio_buttons)
49
+ end
50
+ items.append(method: :with_any_type, collection: filter_type_values, label: t("decidim.meetings.meetings.filters.type"), id: "type") if type
51
+ if taxonomies
52
+ available_taxonomy_filters.each do |taxonomy_filter|
53
+ items.append(method: "with_any_taxonomies[#{taxonomy_filter.root_taxonomy_id}]",
54
+ collection: filter_taxonomy_values_for(taxonomy_filter),
55
+ label: decidim_sanitize_translated(taxonomy_filter.name),
56
+ id: "taxonomy-#{taxonomy_filter.root_taxonomy_id}")
57
+ end
58
+ end
59
+ items.append(method: :with_any_origin, collection: filter_origin_values, label: t("decidim.meetings.meetings.filters.origin"), id: "origin") if origin
60
+ if space_type
61
+ items.append(method: :with_any_space, collection: directory_meeting_spaces_values, label: t("decidim.meetings.directory.meetings.index.space_type"),
62
+ id: "space_type")
63
+ end
64
+ if activity
65
+ items.append(method: :activity, collection: activity_filter_values, label: t("decidim.meetings.meetings.filters.activity"), id: "activity",
66
+ type: :radio_buttons)
67
+ end
68
+ items.reject { |item| item[:collection].blank? }
69
+ end
70
+ end
71
+ # rubocop:enable Metrics/ParameterLists
72
+ # rubocop:enable Metrics/CyclomaticComplexity
73
+
74
+ delegate :available_taxonomy_filters, to: :current_component
75
+
42
76
  # Options to filter meetings by activity.
43
77
  def activity_filter_values
44
78
  flat_filter_values(:all, :my_meetings, scope: "decidim.meetings.meetings.filters")
@@ -8,7 +8,6 @@ module Decidim
8
8
  module ApplicationHelper
9
9
  include PaginateHelper
10
10
  include Decidim::MapHelper
11
- include Decidim::Meetings::MapHelper
12
11
  include Decidim::Meetings::MeetingsHelper
13
12
  include Decidim::Comments::CommentsHelper
14
13
  include Decidim::SanitizeHelper
@@ -27,6 +26,15 @@ module Decidim
27
26
  )
28
27
  end
29
28
 
29
+ def available_taxonomy_filters
30
+ @available_taxonomy_filters ||= begin
31
+ participatory_spaces = current_organization.public_participatory_spaces
32
+ components = Decidim::Component.where(manifest_name: "meetings", participatory_space: participatory_spaces)
33
+ filter_ids = components.map(&:settings).pluck(:taxonomy_filters).flatten.compact
34
+ Decidim::TaxonomyFilter.for(current_organization).where(id: filter_ids)
35
+ end
36
+ end
37
+
30
38
  def filter_date_values
31
39
  %w(all upcoming past).map { |k| [k, t(k, scope: "decidim.meetings.meetings.filters.date_values")] }
32
40
  end
@@ -43,57 +51,10 @@ module Decidim
43
51
  filter_tree_from_array(spaces)
44
52
  end
45
53
 
46
- def directory_filter_categories_values
47
- participatory_spaces = current_organization.public_participatory_spaces
48
- list_of_ps = participatory_spaces.flat_map do |current_participatory_space|
49
- next unless current_participatory_space.respond_to?(:categories)
50
-
51
- sorted_main_categories = current_participatory_space.categories.first_class.includes(:subcategories).sort_by do |category|
52
- [category.weight, translated_attribute(category.name, current_organization)]
53
- end
54
-
55
- categories_values = categories_values(sorted_main_categories)
56
-
57
- next if categories_values.empty?
58
-
59
- key_point = current_participatory_space.class.name.gsub("::", "__") + current_participatory_space.id.to_s
60
-
61
- TreeNode.new(
62
- TreePoint.new(key_point, translated_attribute(current_participatory_space.title, current_organization)),
63
- categories_values
64
- )
65
- end
66
-
67
- list_of_ps.compact!
68
- TreeNode.new(
69
- TreePoint.new("", t("decidim.meetings.application_helper.filter_category_values.all")),
70
- list_of_ps
71
- )
72
- end
73
-
74
54
  # Options to filter meetings by activity.
75
55
  def activity_filter_values
76
56
  %w(all my_meetings).map { |k| [k, t(k, scope: "decidim.meetings.meetings.filters")] }
77
57
  end
78
-
79
- protected
80
-
81
- def categories_values(sorted_main_categories)
82
- sorted_main_categories.flat_map do |category|
83
- sorted_descendant_categories = category.descendants.includes(:subcategories).sort_by do |subcategory|
84
- [subcategory.weight, translated_attribute(subcategory.name, current_organization)]
85
- end
86
-
87
- subcategories = sorted_descendant_categories.flat_map do |subcategory|
88
- TreePoint.new(subcategory.id.to_s, translated_attribute(subcategory.name, current_organization))
89
- end
90
-
91
- TreeNode.new(
92
- TreePoint.new(category.id.to_s, translated_attribute(category.name, current_organization)),
93
- subcategories
94
- )
95
- end
96
- end
97
58
  end
98
59
  end
99
60
  end
@@ -142,6 +142,11 @@ module Decidim
142
142
  base_url = "https://calendar.google.com/calendar/u/0/r/eventedit"
143
143
  "#{base_url}?#{params.to_param}"
144
144
  end
145
+
146
+ def render_schema_org_event_meeting(meeting)
147
+ exported_meeting = Decidim::Exporters::JSON.new([meeting], Decidim::Meetings::SchemaOrgEventMeetingSerializer).export.read
148
+ JSON.pretty_generate(JSON.parse(exported_meeting).first)
149
+ end
145
150
  end
146
151
  end
147
152
  end
@@ -33,6 +33,16 @@ module Decidim
33
33
  update!(rejected_at: Time.current, accepted_at: nil)
34
34
  end
35
35
  alias decline! reject!
36
+
37
+ def self.ransackable_attributes(auth_object = nil)
38
+ return [] unless auth_object&.admin?
39
+
40
+ %w(accepted_at rejected_at sent_at)
41
+ end
42
+
43
+ def self.ransackable_associations(_auth_object = nil)
44
+ %w(user)
45
+ end
36
46
  end
37
47
  end
38
48
  end
@@ -12,12 +12,14 @@ module Decidim
12
12
  include Decidim::HasReference
13
13
  include Decidim::ScopableResource
14
14
  include Decidim::HasCategory
15
+ include Decidim::Taxonomizable
15
16
  include Decidim::Followable
16
17
  include Decidim::Comments::CommentableWithComponent
17
18
  include Decidim::Comments::HasAvailabilityAttributes
18
19
  include Decidim::Searchable
19
20
  include Decidim::Traceable
20
21
  include Decidim::Loggable
22
+ include Decidim::DownloadYourData
21
23
  include Decidim::Forms::HasQuestionnaire
22
24
  include Decidim::Paddable
23
25
  include Decidim::ActsAsAuthor
@@ -26,6 +28,7 @@ module Decidim
26
28
  include Decidim::TranslatableResource
27
29
  include Decidim::Publicable
28
30
  include Decidim::FilterableResource
31
+ include Decidim::SoftDeletable
29
32
 
30
33
  TYPE_OF_MEETING = { in_person: 0, online: 10, hybrid: 20 }.freeze
31
34
  REGISTRATION_TYPES = { registration_disabled: 0, on_this_platform: 10, on_different_platform: 20 }.freeze
@@ -45,6 +48,8 @@ module Decidim
45
48
  foreign_key: :decidim_user_id,
46
49
  source: :user
47
50
  )
51
+ has_many :meeting_links, dependent: :destroy, class_name: "Decidim::Meetings::MeetingLink", foreign_key: "decidim_meeting_id"
52
+ has_many :components, through: :meeting_links, class_name: "Decidim::Component", foreign_key: "decidim_component_id"
48
53
 
49
54
  enum iframe_access_level: [:all, :signed_in, :registered], _prefix: true
50
55
  enum iframe_embed_type: [:none, :embed_in_meeting_page, :open_in_live_event_page, :open_in_new_tab], _prefix: true
@@ -57,6 +62,7 @@ module Decidim
57
62
 
58
63
  geocoded_by :address
59
64
 
65
+ scope :closed, -> { where.not(closed_at: nil) }
60
66
  scope :published, -> { where.not(published_at: nil) }
61
67
  scope :past, -> { where(arel_table[:end_time].lteq(Time.current)) }
62
68
  scope :upcoming, -> { where(arel_table[:end_time].gteq(Time.current)) }
@@ -151,6 +157,10 @@ module Decidim
151
157
  # we create a salt for the meeting only on new meetings to prevent changing old IDs for existing (Ether)PADs
152
158
  before_create :set_default_salt
153
159
 
160
+ def self.export_serializer
161
+ Decidim::Meetings::DownloadYourDataMeetingSerializer
162
+ end
163
+
154
164
  def self.participants_iframe_embed_types
155
165
  iframe_embed_types.except(:open_in_live_event_page)
156
166
  end
@@ -370,7 +380,19 @@ module Decidim
370
380
  end
371
381
 
372
382
  def self.ransackable_scopes(_auth_object = nil)
373
- [:with_any_type, :with_any_date, :with_any_space, :with_any_origin, :with_any_scope, :with_any_category, :with_any_global_category]
383
+ [:with_any_type, :with_any_date, :with_any_space, :with_any_origin, :with_any_taxonomies, :with_any_global_category]
384
+ end
385
+
386
+ def self.ransackable_attributes(auth_object = nil)
387
+ base = %w(description id_string search_text title)
388
+
389
+ return base unless auth_object&.admin?
390
+
391
+ base + %w(is_upcoming closed_at)
392
+ end
393
+
394
+ def self.ransackable_associations(_auth_object = nil)
395
+ %w(taxonomies)
374
396
  end
375
397
 
376
398
  def self.ransack(params = {}, options = {})
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ class MeetingLink < Meetings::ApplicationRecord
6
+ include Decidim::HasComponent
7
+
8
+ belongs_to :meeting, foreign_key: "decidim_meeting_id", class_name: "Decidim::Meetings::Meeting"
9
+ belongs_to :component, foreign_key: "decidim_component_id", class_name: "Decidim::Component"
10
+
11
+ # Finds all the meetings linked to the given component
12
+ # filtering out meetings that belong to private not transparent spaces.
13
+ def self.find_meetings(component:)
14
+ meetings = Meeting
15
+ .joins(:meeting_links)
16
+ .where("decidim_meetings_meeting_links.component": component)
17
+ .filter do |meeting|
18
+ !meeting.component.private_non_transparent_space?
19
+ end
20
+
21
+ Meeting.where(id: meetings.map(&:id))
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,5 +1,6 @@
1
1
  import "src/decidim/meetings/admin/agendas"
2
2
  import "src/decidim/meetings/admin/destroy_meeting_alert"
3
3
  import "src/decidim/meetings/admin/meetings_form"
4
+ import "src/decidim/meetings/admin/meetings_components_form"
4
5
  import "src/decidim/meetings/admin/registrations_form"
5
6
  import "src/decidim/meetings/admin/registrations_invite_form"
@@ -0,0 +1,77 @@
1
+ import TomSelect from "tom-select/dist/cjs/tom-select.popular";
2
+ import createTooltip from "src/decidim/tooltips"
3
+
4
+ /**
5
+ * This module manages the Linked Spaces section from the
6
+ * admin meeting edit form.
7
+ *
8
+ * It allows to add and remove components to the meeting and
9
+ * setup a TomSelect for the components selector.
10
+ */
11
+
12
+ const handleRemoveButton = (button) => {
13
+ button.addEventListener("click", function() {
14
+ button.closest("tr").remove();
15
+ });
16
+ };
17
+
18
+ const handleAddButton = () => {
19
+ const select = document.querySelector("select[name='add_component_select']");
20
+ const componentId = select.value;
21
+ const componentTitle = select.options[select.selectedIndex].text;
22
+
23
+ if (!componentId) {
24
+ return;
25
+ }
26
+
27
+ const table = document.querySelector(".js-components");
28
+ const body = document.querySelector(".js-components tbody");
29
+ const template = document.querySelector("#meeting_component_template");
30
+ const clone = template.content.cloneNode(true);
31
+ const title = clone.querySelector(".js-component-title");
32
+ const id = clone.querySelector("input");
33
+ const button = clone.querySelector(".js-remove-component");
34
+
35
+ title.textContent = componentTitle;
36
+ id.value = componentId;
37
+ if (button) {
38
+ handleRemoveButton(button);
39
+ }
40
+
41
+ body.appendChild(clone);
42
+
43
+ const tooltips = body.querySelectorAll("[data-tooltip]")
44
+
45
+ if (tooltips.length) {
46
+ createTooltip(tooltips[tooltips.length - 1]);
47
+ }
48
+
49
+ select.value = "";
50
+ table.classList.remove("hidden");
51
+ };
52
+
53
+ const setupTomSelect = () => {
54
+ const componentsSelect = document.querySelector(
55
+ "#add_component_select"
56
+ );
57
+
58
+ const config = {
59
+ plugins: ["dropdown_input"]
60
+ };
61
+
62
+ if (componentsSelect) {
63
+ return new TomSelect(componentsSelect, config);
64
+ }
65
+ return null;
66
+ }
67
+
68
+ document.addEventListener("DOMContentLoaded", () => {
69
+ document.querySelectorAll(".js-remove-component").forEach(handleRemoveButton);
70
+ const addButton = document.querySelector(".js-add-component")
71
+
72
+ if (addButton) {
73
+ addButton.addEventListener("click", handleAddButton);
74
+ }
75
+
76
+ setupTomSelect();
77
+ });
@@ -86,10 +86,16 @@ $(() => {
86
86
  if ($form.length > 0) {
87
87
  const $privateMeeting = $form.find("#private_meeting");
88
88
  const $transparent = $form.find("#transparent");
89
+ const $warning = $form.find(".js-private-warning");
90
+ const $assign = $form.find(".js-add-component");
89
91
 
90
92
  const toggleDisabledHiddenFields = () => {
91
93
  const enabledPrivateSpace = $privateMeeting.find("input[type='checkbox']").prop("checked");
94
+ const enabledTransparent = $transparent.find("input[type='checkbox']").prop("checked");
95
+
92
96
  $transparent.find("input[type='checkbox']").attr("disabled", "disabled");
97
+ $warning?.toggleClass("hidden", !enabledPrivateSpace || enabledTransparent);
98
+ $assign?.attr("disabled", enabledPrivateSpace && !enabledTransparent);
93
99
 
94
100
  if (enabledPrivateSpace) {
95
101
  $transparent.find("input[type='checkbox']").attr("disabled", !enabledPrivateSpace);
@@ -97,6 +103,8 @@ $(() => {
97
103
  };
98
104
 
99
105
  $privateMeeting.on("change", toggleDisabledHiddenFields);
106
+ $transparent.on("change", toggleDisabledHiddenFields);
107
+
100
108
  toggleDisabledHiddenFields();
101
109
 
102
110
  attachGeocoding($form.find("#meeting_address"));
@@ -41,7 +41,7 @@ module Decidim
41
41
  return disallow! if meeting && !meeting.official?
42
42
 
43
43
  case permission_action.action
44
- when :close, :copy, :destroy, :export_registrations, :update, :read_invites
44
+ when :close, :copy, :export_registrations, :update, :read_invites
45
45
  toggle_allow(meeting.present?)
46
46
  when :invite_attendee
47
47
  toggle_allow(meeting.present? && meeting.registrations_enabled?)
@@ -84,13 +84,20 @@ module Decidim
84
84
  end
85
85
 
86
86
  def can_create_meetings?
87
- component_settings&.creation_enabled_for_participants? && public_space_or_member?
87
+ (component_settings&.creation_enabled_for_participants? && can_participate?) || initiative_authorship?
88
88
  end
89
89
 
90
- def public_space_or_member?
90
+ def can_participate?
91
+ context[:current_component].participatory_space.can_participate?(user)
92
+ end
93
+
94
+ def initiative_authorship?
95
+ return false unless Decidim.module_installed?("initiatives")
96
+
91
97
  participatory_space = context[:current_component].participatory_space
92
98
 
93
- participatory_space.private_space? ? space_member?(participatory_space, user) : true
99
+ participatory_space.is_a?(Decidim::Initiative) &&
100
+ participatory_space.has_authorship?(user)
94
101
  end
95
102
 
96
103
  # Neither platform admins, nor space admins should be able to create meetings from the public side.
@@ -101,21 +108,18 @@ module Decidim
101
108
  end
102
109
 
103
110
  def can_update_meeting?
104
- component_settings&.creation_enabled_for_participants? &&
105
- meeting.authored_by?(user) &&
111
+ meeting.authored_by?(user) &&
106
112
  !meeting.closed?
107
113
  end
108
114
 
109
115
  def can_withdraw_meeting?
110
- component_settings&.creation_enabled_for_participants? &&
111
- meeting.authored_by?(user) &&
116
+ meeting.authored_by?(user) &&
112
117
  !meeting.withdrawn? &&
113
118
  !meeting.past?
114
119
  end
115
120
 
116
121
  def can_close_meeting?
117
- component_settings&.creation_enabled_for_participants? &&
118
- meeting.authored_by?(user) &&
122
+ meeting.authored_by?(user) &&
119
123
  meeting.past?
120
124
  end
121
125
 
@@ -39,7 +39,7 @@ module Decidim
39
39
 
40
40
  def action_string
41
41
  case action
42
- when "close", "create", "delete", "export_registrations", "update"
42
+ when "close", "create", "delete", "export_registrations", "update", "soft_delete", "restore"
43
43
  "decidim.meetings.admin_log.meeting.#{action}"
44
44
  else
45
45
  super
@@ -10,6 +10,8 @@ module Decidim
10
10
  include ActionView::Helpers::UrlHelper
11
11
  include Decidim::SanitizeHelper
12
12
 
13
+ alias super_title title
14
+
13
15
  def meeting
14
16
  __getobj__
15
17
  end
@@ -18,6 +20,12 @@ module Decidim
18
20
  Decidim::ResourceLocatorPresenter.new(meeting).path
19
21
  end
20
22
 
23
+ def taxonomy_names(html_escape: false, all_locales: false)
24
+ meeting.taxonomies.map do |taxonomy|
25
+ super_title(taxonomy.name, false, html_escape, all_locales)
26
+ end
27
+ end
28
+
21
29
  def display_mention
22
30
  link_to title, meeting_path
23
31
  end
@@ -25,7 +33,7 @@ module Decidim
25
33
  def title(links: false, html_escape: false, all_locales: false)
26
34
  return unless meeting
27
35
 
28
- super meeting.title, links, html_escape, all_locales
36
+ super(meeting.title, links, html_escape, all_locales)
29
37
  end
30
38
 
31
39
  def description(links: false, extras: true, strip_tags: false, all_locales: false)
@@ -103,6 +111,10 @@ module Decidim
103
111
  ""
104
112
  end
105
113
 
114
+ def space_title
115
+ translated_attribute component.participatory_space.title
116
+ end
117
+
106
118
  def profile_path
107
119
  resource_locator(meeting).path
108
120
  end
@@ -28,8 +28,8 @@ module Decidim
28
28
  # by a range of dates.
29
29
  def query
30
30
  meetings = Decidim::Meetings::Meeting.not_hidden.published.where(component: @components)
31
- meetings = meetings.where("created_at >= ?", @start_at) if @start_at.present?
32
- meetings = meetings.where("created_at <= ?", @end_at) if @end_at.present?
31
+ meetings = meetings.where(created_at: @start_at..) if @start_at.present?
32
+ meetings = meetings.where(created_at: ..@end_at) if @end_at.present?
33
33
  meetings
34
34
  end
35
35
  end
@@ -14,10 +14,10 @@ module Decidim
14
14
  meetings = Decidim::Meetings::Meeting.where(component: @resource).joins(:component)
15
15
 
16
16
  meetings_followers = Decidim::Follow.where(followable: meetings).joins(:user)
17
- .where("decidim_follows.created_at <= ?", end_time)
17
+ .where(decidim_follows: { created_at: ..end_time })
18
18
  cumulative_users = meetings_followers.pluck(:decidim_user_id)
19
19
 
20
- meetings_followers = meetings_followers.where("decidim_follows.created_at >= ?", start_time)
20
+ meetings_followers = meetings_followers.where(decidim_follows: { created_at: start_time.. })
21
21
  quantity_users = meetings_followers.pluck(:decidim_user_id)
22
22
 
23
23
  {
@@ -13,9 +13,9 @@ module Decidim
13
13
  next if cumulative_value.zero?
14
14
 
15
15
  quantity_value = quantity[key] || 0
16
- category_id, space_type, space_id = key
16
+ taxonomy_id, space_type, space_id = key
17
17
  record = Decidim::Metric.find_or_initialize_by(day: @day.to_s, metric_type: @metric_name,
18
- organization: @organization, decidim_category_id: category_id,
18
+ organization: @organization, decidim_taxonomy_id: taxonomy_id,
19
19
  participatory_space_type: space_type, participatory_space_id: space_id)
20
20
  record.assign_attributes(cumulative: cumulative_value, quantity: quantity_value)
21
21
  record.save!
@@ -31,16 +31,16 @@ module Decidim
31
31
  manifest.participatory_spaces.call(@organization).public_spaces
32
32
  end
33
33
  @query = Decidim::Meetings::Meeting.where(component: visible_components_from_spaces(spaces)).joins(:component)
34
- .left_outer_joins(:category).visible
35
- @query = @query.where("decidim_meetings_meetings.created_at <= ?", end_time)
36
- @query = @query.group("decidim_categorizations.decidim_category_id",
34
+ .left_outer_joins(:taxonomizations).visible
35
+ @query = @query.where(decidim_meetings_meetings: { created_at: ..end_time })
36
+ @query = @query.group("decidim_taxonomizations.taxonomy_id",
37
37
  :participatory_space_type,
38
38
  :participatory_space_id)
39
39
  @query
40
40
  end
41
41
 
42
42
  def quantity
43
- @quantity ||= query.where("decidim_meetings_meetings.created_at >= ?", start_time).count
43
+ @quantity ||= query.where(decidim_meetings_meetings: { created_at: start_time.. }).count
44
44
  end
45
45
  end
46
46
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ class BaseDownloadYourDataSerializer < Decidim::Exporters::Serializer
6
+ # This is the Base class for Invite and Registrations models for the download your data feature
7
+ def serialize
8
+ {
9
+ id: resource.id,
10
+ created_at: resource.created_at,
11
+ updated_at: resource.updated_at,
12
+ meeting: {
13
+ title: resource.meeting.title,
14
+ url: Decidim::ResourceLocatorPresenter.new(resource.meeting).url,
15
+ description: resource.meeting.description,
16
+ start_time: resource.meeting.start_time,
17
+ end_time: resource.meeting.end_time,
18
+ address: resource.meeting.address,
19
+ location: resource.meeting.location,
20
+ location_hints: resource.meeting.location_hints,
21
+ reference: resource.meeting.reference,
22
+ attendees_count: resource.meeting.attendees_count,
23
+ attending_organizations: resource.meeting.attending_organizations,
24
+ closed_at: resource.meeting.closed_at,
25
+ closing_report: resource.meeting.closing_report,
26
+ published_at: resource.meeting.published_at
27
+ }
28
+ }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -2,34 +2,14 @@
2
2
 
3
3
  module Decidim
4
4
  module Meetings
5
- class DownloadYourDataInviteSerializer < Decidim::Exporters::Serializer
5
+ class DownloadYourDataInviteSerializer < BaseDownloadYourDataSerializer
6
6
  # Serializes an invite for download your data
7
7
  def serialize
8
- {
9
- id: resource.id,
10
- sent_at: resource.sent_at,
11
- accepted_at: resource.accepted_at,
12
- rejected_at: resource.rejected_at,
13
- user: {
14
- name: resource.user.name,
15
- email: resource.user.email
16
- },
17
- meeting: {
18
- title: resource.meeting.title,
19
- description: resource.meeting.description,
20
- start_time: resource.meeting.start_time,
21
- end_time: resource.meeting.end_time,
22
- address: resource.meeting.address,
23
- location: resource.meeting.location,
24
- location_hints: resource.meeting.location_hints,
25
- reference: resource.meeting.reference,
26
- attendees_count: resource.meeting.attendees_count,
27
- attending_organizations: resource.meeting.attending_organizations,
28
- closed_at: resource.meeting.closed_at,
29
- closing_report: resource.meeting.closing_report,
30
- published_at: resource.meeting.published_at
31
- }
32
- }
8
+ super.merge({
9
+ sent_at: resource.sent_at,
10
+ accepted_at: resource.accepted_at,
11
+ rejected_at: resource.rejected_at
12
+ })
33
13
  end
34
14
  end
35
15
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ class DownloadYourDataMeetingSerializer < Decidim::Meetings::MeetingSerializer
6
+ # Serializes a Meeting for download your data feature
7
+ #
8
+ # Remove the author information as it is the same of the user that
9
+ # requested the data
10
+ def serialize
11
+ super.except!(:author)
12
+ end
13
+ end
14
+ end
15
+ end