decidim-debates 0.31.5 → 0.32.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -3
  3. data/app/cells/decidim/debates/debate_l_cell.rb +1 -0
  4. data/app/commands/decidim/debates/close_debate.rb +2 -0
  5. data/app/controllers/decidim/debates/admin/debate_closes_controller.rb +1 -1
  6. data/app/controllers/decidim/debates/admin/debates_controller.rb +3 -2
  7. data/app/controllers/decidim/debates/debates_controller.rb +14 -4
  8. data/app/controllers/decidim/debates/orderable.rb +16 -2
  9. data/app/controllers/decidim/debates/versions_controller.rb +11 -1
  10. data/app/helpers/decidim/debates/application_helper.rb +15 -3
  11. data/app/models/decidim/debates/debate.rb +10 -1
  12. data/app/permissions/decidim/debates/permissions.rb +2 -0
  13. data/app/views/decidim/debates/admin/debates/_debate-tr.html.erb +2 -2
  14. data/app/views/decidim/debates/debates/index.html.erb +1 -1
  15. data/config/locales/ca-IT.yml +2 -1
  16. data/config/locales/ca.yml +2 -1
  17. data/config/locales/cs.yml +1 -1
  18. data/config/locales/en.yml +2 -1
  19. data/config/locales/es-MX.yml +2 -1
  20. data/config/locales/es-PY.yml +2 -1
  21. data/config/locales/es.yml +2 -1
  22. data/config/locales/eu.yml +2 -1
  23. data/config/locales/fi-plain.yml +2 -1
  24. data/config/locales/fi.yml +2 -1
  25. data/config/locales/fr-CA.yml +2 -1
  26. data/config/locales/fr.yml +2 -1
  27. data/config/locales/ja.yml +2 -1
  28. data/config/locales/pt-BR.yml +2 -1
  29. data/config/locales/sk.yml +2 -1
  30. data/config/locales/sv.yml +2 -1
  31. data/db/migrate/20200902133452_add_cached_comment_metadata_to_debates.rb +1 -1
  32. data/db/migrate/20251114092453_remove_legacy_images_from_debates_module.rb +7 -0
  33. data/db/migrate/20260208201402_remove_user_group_debates.rb +13 -0
  34. data/decidim-debates.gemspec +8 -10
  35. data/lib/decidim/api/debate_type.rb +0 -1
  36. data/lib/decidim/api/debates_type.rb +2 -2
  37. data/lib/decidim/api/mutations/close_debate_attributes.rb +12 -0
  38. data/lib/decidim/api/mutations/close_debate_type.rb +47 -0
  39. data/lib/decidim/api/mutations/create_debate_type.rb +44 -0
  40. data/lib/decidim/api/mutations/debate_attributes.rb +14 -0
  41. data/lib/decidim/api/mutations/debate_mutation_type.rb +15 -0
  42. data/lib/decidim/api/mutations/debates_mutation_type.rb +24 -0
  43. data/lib/decidim/api/mutations/update_debate_type.rb +57 -0
  44. data/lib/decidim/debates/api.rb +8 -0
  45. data/lib/decidim/debates/component.rb +2 -6
  46. data/lib/decidim/debates/engine.rb +6 -0
  47. data/lib/decidim/debates/version.rb +1 -1
  48. metadata +23 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c0d82b7ee202c93e0fe2af99737c57943467a0c873c3aaad7f53a1e4d8a0080
4
- data.tar.gz: 9685a4bf32bf4d594e1900d1a83bd531fb4dfc153f83f689d44bef9d96815462
3
+ metadata.gz: b891ad6b7f5d46c7da8c4650490cbf0be1839fb86b4495d5f49ec3df495eeec5
4
+ data.tar.gz: b8007bb033fcb5bf06f765e7c90e499de0e171df8ad480c9162ae722d674f326
5
5
  SHA512:
6
- metadata.gz: 16cad6f7b7150ea61159012bed52e0e209fb5ebd58dfe6d74e016090a95e21a11cb0f7ca660d0d9c6e30755c9700d8b7f9040d6c573a0c78d8a56a1f12e1dc95
7
- data.tar.gz: 229c5fcc58c3e881a0a245df0b72862d8a7f8c4cafbd25f04c50aea9291ab7319f48ab3678012b2a2832fe4bf2df49ff516f36eca446bd7162050e9e99c81c73
6
+ metadata.gz: a6d9e91554ad0bbc58c42e3760e0fe8d05b34bc0f0713c7b560875e09f601b8bd5f68705d8ec445077b0f817440af41a3d74a8d95c284d67137ea6be9221afe9
7
+ data.tar.gz: '00807e921467c822897f93edcf1cef0b16102ba28f7217fcab9cc47cda929cf4476f8458f92e8e1428f79c7554666305fa502d17447786d03e027be02ef02b49'
data/README.md CHANGED
@@ -1,10 +1,14 @@
1
- # Decidim::Debates
1
+ # decidim-debates
2
2
 
3
- The Debates module adds debate to any participatory process. It adds a CRUD engine to the admin and public view scoped inside the participatory process.
3
+ The Debates module adds debate to any participatory space. It adds a CRUD engine to the admin and public view scoped inside the participatory space.
4
4
 
5
5
  ## Usage
6
6
 
7
- Debates will be available as a Component for any participatory space.
7
+ Debates will be available as a Component for any Participatory Space.
8
+
9
+ ## Installation
10
+
11
+ This is on the default Decidim installation so you should not change anything to use this component.
8
12
 
9
13
  ## Contributing
10
14
 
@@ -8,6 +8,7 @@ module Decidim
8
8
  # for a given instance of a Debate
9
9
  class DebateLCell < Decidim::CardLCell
10
10
  include Decidim::SanitizeHelper
11
+
11
12
  delegate :component_settings, to: :controller
12
13
 
13
14
  alias debate model
@@ -28,6 +28,8 @@ module Decidim
28
28
 
29
29
  attr_reader :form
30
30
 
31
+ delegate :debate, to: :form
32
+
31
33
  def close_debate
32
34
  @debate = Decidim.traceability.perform_action!(
33
35
  :close,
@@ -26,7 +26,7 @@ module Decidim
26
26
 
27
27
  on(:invalid) do
28
28
  flash.now[:alert] = I18n.t("debates.close.invalid", scope: "decidim.debates")
29
- render action: "edit", status: :unprocessable_entity
29
+ render action: "edit", status: :unprocessable_content
30
30
  end
31
31
  end
32
32
  end
@@ -6,6 +6,7 @@ module Decidim
6
6
  # This controller allows an admin to manage debates from a Participatory Space
7
7
  class DebatesController < Decidim::Debates::Admin::ApplicationController
8
8
  include Decidim::Admin::HasTrashableResources
9
+
9
10
  helper Decidim::ApplicationHelper
10
11
 
11
12
  helper_method :debates
@@ -34,7 +35,7 @@ module Decidim
34
35
 
35
36
  on(:invalid) do
36
37
  flash.now[:alert] = I18n.t("debates.create.invalid", scope: "decidim.debates.admin")
37
- render action: "new", status: :unprocessable_entity
38
+ render action: "new", status: :unprocessable_content
38
39
  end
39
40
  end
40
41
  end
@@ -57,7 +58,7 @@ module Decidim
57
58
 
58
59
  on(:invalid) do
59
60
  flash.now[:alert] = I18n.t("debates.update.invalid", scope: "decidim.debates.admin")
60
- render action: "edit", status: :unprocessable_entity
61
+ render action: "edit", status: :unprocessable_content
61
62
  end
62
63
  end
63
64
  end
@@ -35,7 +35,7 @@ module Decidim
35
35
 
36
36
  on(:invalid) do
37
37
  flash.now[:alert] = I18n.t("debates.create.invalid", scope: "decidim.debates")
38
- render action: "new", status: :unprocessable_entity
38
+ render action: "new", status: :unprocessable_content
39
39
  end
40
40
  end
41
41
  end
@@ -63,7 +63,7 @@ module Decidim
63
63
 
64
64
  on(:invalid) do
65
65
  flash.now[:alert] = I18n.t("debates.update.invalid", scope: "decidim.debates")
66
- render :edit, status: :unprocessable_entity
66
+ render :edit, status: :unprocessable_content
67
67
  end
68
68
  end
69
69
  end
@@ -76,12 +76,12 @@ module Decidim
76
76
  CloseDebate.call(@form) do
77
77
  on(:ok) do |debate|
78
78
  flash[:notice] = I18n.t("debates.close.success", scope: "decidim.debates")
79
- redirect_back fallback_location: Decidim::ResourceLocatorPresenter.new(debate).path
79
+ redirect_back_or_to(Decidim::ResourceLocatorPresenter.new(debate).path)
80
80
  end
81
81
 
82
82
  on(:invalid) do
83
83
  flash[:alert] = I18n.t("debates.close.invalid", scope: "decidim.debates")
84
- redirect_back fallback_location: Decidim::ResourceLocatorPresenter.new(debate).path
84
+ redirect_back_or_to(Decidim::ResourceLocatorPresenter.new(debate).path)
85
85
  end
86
86
  end
87
87
  end
@@ -125,6 +125,16 @@ module Decidim
125
125
  def tab_panel_items
126
126
  @tab_panel_items ||= attachments_tab_panel_items(debate)
127
127
  end
128
+
129
+ def add_breadcrumb_item
130
+ return {} if debate.blank?
131
+
132
+ {
133
+ label: translated_attribute(debate.title),
134
+ url: Decidim::EngineRouter.main_proxy(current_component).debate_path(debate),
135
+ active: false
136
+ }
137
+ end
128
138
  end
129
139
  end
130
140
  end
@@ -14,18 +14,32 @@ module Decidim
14
14
  private
15
15
 
16
16
  def available_orders
17
- @available_orders ||= %w(random recent commented updated)
17
+ @available_orders ||= possible_orders
18
+ end
19
+
20
+ def possible_orders
21
+ @possible_orders ||= begin
22
+ possible_orders = %w(random recent updated)
23
+ possible_orders << "most_commented" if most_commented_order_available?
24
+ possible_orders
25
+ end
18
26
  end
19
27
 
20
28
  def default_order
21
29
  "updated"
22
30
  end
23
31
 
32
+ def most_commented_order_available?
33
+ return @most_commented_order_available if defined?(@most_commented_order_available)
34
+
35
+ @most_commented_order_available = Decidim::Debates::Debate.most_commented_available?(current_component)
36
+ end
37
+
24
38
  def reorder(debates)
25
39
  case order
26
40
  when "recent"
27
41
  debates.order(created_at: :desc)
28
- when "commented"
42
+ when "most_commented"
29
43
  debates.order(comments_count: :desc)
30
44
  when "updated"
31
45
  debates.order(updated_at: :desc)
@@ -9,7 +9,17 @@ module Decidim
9
9
  include Decidim::ResourceVersionsConcern
10
10
 
11
11
  def versioned_resource
12
- @versioned_resource ||= present(Debate.where(component: current_component).not_hidden.find(params[:debate_id]))
12
+ @versioned_resource ||= Debate.where(component: current_component).not_hidden.find(params[:debate_id])
13
+ end
14
+
15
+ def add_breadcrumb_item
16
+ return {} if versioned_resource.blank?
17
+
18
+ {
19
+ label: translated_attribute(versioned_resource.title),
20
+ url: Decidim::EngineRouter.main_proxy(current_component).debate_path(versioned_resource),
21
+ active: false
22
+ }
13
23
  end
14
24
  end
15
25
  end
@@ -72,19 +72,31 @@ module Decidim
72
72
  @filter_sections ||= begin
73
73
  items = [{
74
74
  method: :with_any_state,
75
+ name: "[with_any_state]",
75
76
  collection: filter_debates_state_values,
76
77
  label: t("decidim.debates.debates.filters.state"),
77
78
  id: "date",
78
79
  type: :radio_buttons
79
80
  }]
80
81
  current_component.available_taxonomy_filters.each do |taxonomy_filter|
81
- items.append(method: "with_any_taxonomies[#{taxonomy_filter.root_taxonomy_id}]",
82
+ items.append(method: :with_any_taxonomies,
83
+ name: "[with_any_taxonomies][#{taxonomy_filter.root_taxonomy_id}]",
82
84
  collection: filter_taxonomy_values_for(taxonomy_filter),
83
85
  label: decidim_sanitize_translated(taxonomy_filter.name),
84
86
  id: "taxonomy-#{taxonomy_filter.root_taxonomy_id}")
85
87
  end
86
- items.append(method: :with_any_origin, collection: filter_origin_values, label: t("decidim.debates.debates.filters.origin"), id: "origin")
87
- items.append(method: :activity, collection: activity_filter_values, label: t("decidim.debates.debates.filters.activity"), id: "activity") if current_user
88
+ items.append(method: :with_any_origin,
89
+ name: "[with_any_origin]",
90
+ collection: filter_origin_values,
91
+ label: t("decidim.debates.debates.filters.origin"),
92
+ id: "origin")
93
+ if current_user
94
+ items.append(method: :activity,
95
+ name: "[activity]",
96
+ collection: activity_filter_values,
97
+ label: t("decidim.debates.debates.filters.activity"),
98
+ id: "activity")
99
+ end
88
100
 
89
101
  items.reject { |item| item[:collection].blank? }
90
102
  end
@@ -220,7 +220,7 @@ module Decidim
220
220
  # rubocop:disable Rails/SkipsModelValidations
221
221
  def update_comments_count
222
222
  comments_count = comments.not_hidden.not_deleted.count
223
- last_comment = comments.not_hidden.not_deleted.order("created_at DESC").first
223
+ last_comment = comments.not_hidden.not_deleted.order(created_at: :desc).first
224
224
 
225
225
  update_columns(
226
226
  last_comment_at: last_comment&.created_at,
@@ -236,6 +236,15 @@ module Decidim
236
236
  # Create the :search_text ransacker alias for searching from both of these.
237
237
  ransacker_i18n_multi :search_text, [:title, :description]
238
238
 
239
+ def self.most_commented_available?(component)
240
+ return false unless component.settings.comments_enabled?
241
+
242
+ where(component:)
243
+ .not_hidden
244
+ .where("comments_count > 0")
245
+ .exists?
246
+ end
247
+
239
248
  def self.ransackable_scopes(_auth_object = nil)
240
249
  [:with_any_state, :with_any_origin, :with_any_taxonomies]
241
250
  end
@@ -31,6 +31,8 @@ module Decidim
31
31
  private
32
32
 
33
33
  def can_create_debate?
34
+ return false unless user
35
+
34
36
  authorized?(:create) &&
35
37
  current_settings&.creation_enabled? && component.participatory_space.can_participate?(user)
36
38
  end
@@ -8,12 +8,12 @@
8
8
  </td>
9
9
  <td data-label="<%= t("models.debate.fields.start_time", scope: "decidim.debates") %>">
10
10
  <% if debate.start_time %>
11
- <%= l debate.start_time, format: :long %>
11
+ <%= l debate.start_time, format: :decidim_short %>
12
12
  <% end %>
13
13
  </td>
14
14
  <td data-label="<%= t("models.debate.fields.end_time", scope: "decidim.debates") %>">
15
15
  <% if debate.end_time %>
16
- <%= l debate.end_time, format: :long %>
16
+ <%= l debate.end_time, format: :decidim_short %>
17
17
  <% end %>
18
18
  </td>
19
19
  <td data-label="<%= t("models.debate.fields.taxonomies", scope: "decidim.debates") %>">
@@ -1,7 +1,7 @@
1
1
  <% add_decidim_meta_tags(
2
2
  description: translated_attribute(current_participatory_space.try(:short_description) || current_participatory_space.description),
3
3
  title: t("decidim.components.pagination.page_title",
4
- component_name: component_name,
4
+ component_name:,
5
5
  current_page: paginated_debates.current_page,
6
6
  total_pages: paginated_debates.total_pages ),
7
7
  url: debates_url,
@@ -34,6 +34,7 @@ ca-IT:
34
34
  comment: Comentar
35
35
  create: Crear un debat
36
36
  like: M'agrada
37
+ vote_comment: Votar el comentari
37
38
  name: Debats
38
39
  settings:
39
40
  global:
@@ -156,8 +157,8 @@ ca-IT:
156
157
  create: Crear
157
158
  title: Crear un debat
158
159
  orders:
159
- commented: Més comentats
160
160
  label: Ordenar debats per
161
+ most_commented: Més comentats
161
162
  random: Ordre aleatori
162
163
  recent: Més recents
163
164
  updated: Recentment actualitzats
@@ -34,6 +34,7 @@ ca:
34
34
  comment: Comentar
35
35
  create: Crear un debat
36
36
  like: M'agrada
37
+ vote_comment: Votar el comentari
37
38
  name: Debats
38
39
  settings:
39
40
  global:
@@ -156,8 +157,8 @@ ca:
156
157
  create: Crear
157
158
  title: Crear un debat
158
159
  orders:
159
- commented: Més comentats
160
160
  label: Ordenar debats per
161
+ most_commented: Més comentats
161
162
  random: Ordre aleatori
162
163
  recent: Més recents
163
164
  updated: Recentment actualitzats
@@ -160,8 +160,8 @@ cs:
160
160
  create: Vytvořit
161
161
  title: Vytvořit novou debatu
162
162
  orders:
163
- commented: Nejvíce komentované
164
163
  label: Řazení debat podle
164
+ most_commented: Nejvíce komentované
165
165
  random: Náhodné pořadí
166
166
  recent: Nejnovější
167
167
  updated: Naposledy aktualizované
@@ -34,6 +34,7 @@ en:
34
34
  comment: Comment
35
35
  create: Create a debate
36
36
  like: Like
37
+ vote_comment: Vote comment
37
38
  name: Debates
38
39
  settings:
39
40
  global:
@@ -156,8 +157,8 @@ en:
156
157
  create: Create
157
158
  title: Create new debate
158
159
  orders:
159
- commented: Most commented
160
160
  label: Order debates by
161
+ most_commented: Most commented
161
162
  random: Random order
162
163
  recent: Most recent
163
164
  updated: Recently updated
@@ -34,6 +34,7 @@ es-MX:
34
34
  comment: Comentar
35
35
  create: Crear un debate
36
36
  like: Me gusta
37
+ vote_comment: Votar el comentario
37
38
  name: Debates
38
39
  settings:
39
40
  global:
@@ -156,8 +157,8 @@ es-MX:
156
157
  create: Crear
157
158
  title: Crear un debate
158
159
  orders:
159
- commented: Más comentados
160
160
  label: Ordenar debates por
161
+ most_commented: Más comentados
161
162
  random: Orden aleatorio
162
163
  recent: Más recientes
163
164
  updated: Actualizados recientemente
@@ -34,6 +34,7 @@ es-PY:
34
34
  comment: Comentar
35
35
  create: Crear un debate
36
36
  like: Me gusta
37
+ vote_comment: Votar el comentario
37
38
  name: Debates
38
39
  settings:
39
40
  global:
@@ -152,8 +153,8 @@ es-PY:
152
153
  create: Crear
153
154
  title: Crear un debate
154
155
  orders:
155
- commented: Más comentados
156
156
  label: Ordenar debates por
157
+ most_commented: Más comentados
157
158
  random: Orden aleatorio
158
159
  recent: Más recientes
159
160
  updated: Actualizados recientemente
@@ -34,6 +34,7 @@ es:
34
34
  comment: Comentar
35
35
  create: Crear un debate
36
36
  like: Me gusta
37
+ vote_comment: Votar el comentario
37
38
  name: Debates
38
39
  settings:
39
40
  global:
@@ -156,8 +157,8 @@ es:
156
157
  create: Crear
157
158
  title: Crear un debate
158
159
  orders:
159
- commented: Más comentados
160
160
  label: Ordenar debates por
161
+ most_commented: Más comentados
161
162
  random: Orden aleatorio
162
163
  recent: Más recientes
163
164
  updated: Actualizados recientemente
@@ -34,6 +34,7 @@ eu:
34
34
  comment: Iruzkina
35
35
  create: Sortu eztabaida bat
36
36
  like: Atsegin dut
37
+ vote_comment: Bozkatu iruzkina
37
38
  name: Eztabaidak
38
39
  settings:
39
40
  global:
@@ -156,8 +157,8 @@ eu:
156
157
  create: Sortu
157
158
  title: Sortu eztabaida berri bat
158
159
  orders:
159
- commented: Iruzkin gehien dutenak
160
160
  label: Ordenatu eztabaidak honen arabera
161
+ most_commented: Iruzkin gehien dutenak
161
162
  random: Ausazko ordena
162
163
  recent: Berrienetatik zaharrenetara
163
164
  updated: Orain dela gutxi eguneratuak
@@ -34,6 +34,7 @@ fi-pl:
34
34
  comment: Kommentoi
35
35
  create: Luo keskustelu
36
36
  like: Tykkää
37
+ vote_comment: Äänestä kommenttia
37
38
  name: Keskustelut
38
39
  settings:
39
40
  global:
@@ -156,8 +157,8 @@ fi-pl:
156
157
  create: Luo
157
158
  title: Luo uusi keskustelu
158
159
  orders:
159
- commented: Eniten kommentoidut
160
160
  label: Järjestä keskustelut
161
+ most_commented: Eniten kommentoidut
161
162
  random: Satunnainen järjestys
162
163
  recent: Viimeisimmät
163
164
  updated: Viimeksi päivitetyt
@@ -34,6 +34,7 @@ fi:
34
34
  comment: Kommentoi
35
35
  create: Luo keskustelu
36
36
  like: Tykkää
37
+ vote_comment: Äänestä kommenttia
37
38
  name: Keskustelut
38
39
  settings:
39
40
  global:
@@ -156,8 +157,8 @@ fi:
156
157
  create: Luo
157
158
  title: Luo uusi keskustelu
158
159
  orders:
159
- commented: Eniten kommentoidut
160
160
  label: Järjestä keskustelut
161
+ most_commented: Eniten kommentoidut
161
162
  random: Satunnainen järjestys
162
163
  recent: Viimeisimmät
163
164
  updated: Viimeksi päivitetyt
@@ -33,6 +33,7 @@ fr-CA:
33
33
  actions:
34
34
  comment: Commenter
35
35
  create: Créer un débat
36
+ vote_comment: Vote sur le commentaire
36
37
  name: Débats
37
38
  settings:
38
39
  global:
@@ -144,8 +145,8 @@ fr-CA:
144
145
  create: Créer
145
146
  title: Créer un nouveau débat
146
147
  orders:
147
- commented: Les plus commentés
148
148
  label: Trier les débats par
149
+ most_commented: Les plus commentés
149
150
  random: Ordre aléatoire
150
151
  recent: Les plus récents
151
152
  updated: Mis à jour récemment
@@ -33,6 +33,7 @@ fr:
33
33
  actions:
34
34
  comment: Commenter
35
35
  create: Créer un débat
36
+ vote_comment: Vote sur le commentaire
36
37
  name: Débats
37
38
  settings:
38
39
  global:
@@ -144,8 +145,8 @@ fr:
144
145
  create: Créer
145
146
  title: Créer un nouveau débat
146
147
  orders:
147
- commented: Les plus commentés
148
148
  label: Trier les débats par
149
+ most_commented: Les plus commentés
149
150
  random: Ordre aléatoire
150
151
  recent: Les plus récents
151
152
  updated: Mis à jour récemment
@@ -33,6 +33,7 @@ ja:
33
33
  comment: コメント
34
34
  create: ディベートを作成
35
35
  like: いいね
36
+ vote_comment: コメントに投票
36
37
  name: ディベート
37
38
  settings:
38
39
  global:
@@ -154,8 +155,8 @@ ja:
154
155
  create: 作成
155
156
  title: 新しいディベートを作成
156
157
  orders:
157
- commented: コメントの多い順
158
158
  label: '議論の並び替え:'
159
+ most_commented: コメントの多い順
159
160
  random: ランダムに並び替え
160
161
  recent: 新着順
161
162
  updated: 更新が新しい順
@@ -34,6 +34,7 @@ pt-BR:
34
34
  comment: Comentário
35
35
  create: Criar um debate
36
36
  like: Curtir
37
+ vote_comment: Votar comentário
37
38
  name: Debates
38
39
  settings:
39
40
  global:
@@ -156,8 +157,8 @@ pt-BR:
156
157
  create: Criar
157
158
  title: Criar novo debate
158
159
  orders:
159
- commented: Mais comentado
160
160
  label: Ordenar debates por
161
+ most_commented: Mais comentado
161
162
  random: Ordem aleatória
162
163
  recent: Mais recente
163
164
  updated: Atualizado recentemente
@@ -36,6 +36,7 @@ sk:
36
36
  comment: Komentovať
37
37
  create: Vytvoriť debatu
38
38
  like: Páči sa mi to
39
+ vote_comment: Hlasovať za komentár
39
40
  name: Debaty
40
41
  settings:
41
42
  global:
@@ -160,8 +161,8 @@ sk:
160
161
  create: Vytvoriť
161
162
  title: Vytvoriť novú debatu
162
163
  orders:
163
- commented: Najviac komentované
164
164
  label: Zoradiť debaty podľa
165
+ most_commented: Najviac komentované
165
166
  random: Náhodné poradie
166
167
  recent: Najnovšie
167
168
  updated: Nedávno aktualizované
@@ -34,6 +34,7 @@ sv:
34
34
  comment: Kommentera
35
35
  create: Skapa en debatt
36
36
  like: Gilla
37
+ vote_comment: Rösta på kommentar
37
38
  name: Debatter
38
39
  settings:
39
40
  global:
@@ -156,8 +157,8 @@ sv:
156
157
  create: Skapa
157
158
  title: Skapa ny debatt
158
159
  orders:
159
- commented: Mest kommenterad
160
160
  label: Sortera debatter efter
161
+ most_commented: Mest kommenterad
161
162
  random: Slumpmässig ordning
162
163
  recent: Senaste
163
164
  updated: Senast uppdaterade
@@ -9,7 +9,7 @@ class AddCachedCommentMetadataToDebates < ActiveRecord::Migration[5.2]
9
9
  # rubocop:disable Rails/SkipsModelValidations
10
10
  Decidim::Debates::Debate.reset_column_information
11
11
  Decidim::Debates::Debate.unscoped.includes(comments: [:author, :user_group]).find_each do |debate|
12
- last_comment = debate.comments.order("created_at DESC").first
12
+ last_comment = debate.comments.order(created_at: :desc).first
13
13
  next unless last_comment
14
14
 
15
15
  debate.update_columns(
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RemoveLegacyImagesFromDebatesModule < ActiveRecord::Migration[7.2]
4
+ def change
5
+ remove_column :decidim_debates_debates, :image, :string
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RemoveUserGroupDebates < ActiveRecord::Migration[7.0]
4
+ def up
5
+ remove_index :decidim_debates_debates, :decidim_user_group_id
6
+ remove_column :decidim_debates_debates, :decidim_user_group_id
7
+ end
8
+
9
+ def down
10
+ add_column :decidim_debates_debates, :decidim_user_group_id, :integer
11
+ add_index :decidim_debates_debates, :decidim_user_group_id
12
+ end
13
+ end
@@ -2,11 +2,9 @@
2
2
 
3
3
  $LOAD_PATH.push File.expand_path("lib", __dir__)
4
4
 
5
- require "decidim/debates/version"
6
-
7
- # Describe your gem and declare its dependencies:
8
5
  Gem::Specification.new do |s|
9
- s.version = Decidim::Debates.version
6
+ version = "0.32.0.rc2"
7
+ s.version = version
10
8
  s.authors = ["Josep Jaume Rey Peroy", "Marc Riera Casals", "Oriol Gual Oliva", "Genis Matutes Pujol"]
11
9
  s.email = ["josepjaume@gmail.com", "mrc2407@gmail.com", "oriolgual@gmail.com", "genis.matutes@gmail.com"]
12
10
  s.license = "AGPL-3.0-or-later"
@@ -18,7 +16,7 @@ Gem::Specification.new do |s|
18
16
  "homepage_uri" => "https://decidim.org",
19
17
  "source_code_uri" => "https://github.com/decidim/decidim"
20
18
  }
21
- s.required_ruby_version = "~> 3.3.0"
19
+ s.required_ruby_version = "~> 3.4.0"
22
20
 
23
21
  s.name = "decidim-debates"
24
22
  s.summary = "Decidim debates module"
@@ -31,10 +29,10 @@ Gem::Specification.new do |s|
31
29
  end
32
30
  end
33
31
 
34
- s.add_dependency "decidim-comments", Decidim::Debates.version
35
- s.add_dependency "decidim-core", Decidim::Debates.version
32
+ s.add_dependency "decidim-comments", version
33
+ s.add_dependency "decidim-core", version
36
34
 
37
- s.add_development_dependency "decidim-admin", Decidim::Debates.version
38
- s.add_development_dependency "decidim-assemblies", Decidim::Debates.version
39
- s.add_development_dependency "decidim-dev", Decidim::Debates.version
35
+ s.add_development_dependency "decidim-admin", version
36
+ s.add_development_dependency "decidim-assemblies", version
37
+ s.add_development_dependency "decidim-dev", version
40
38
  end
@@ -21,7 +21,6 @@ module Decidim
21
21
  field :description, Decidim::Core::TranslatedFieldType, "The description for this debate", null: true
22
22
  field :end_time, Decidim::Core::DateTimeType, "The end time for this debate", null: true
23
23
  field :id, GraphQL::Types::ID, "The internal ID for this debate", null: false
24
- field :image, GraphQL::Types::String, "The image of this debate", null: true
25
24
  field :information_updates, Decidim::Core::TranslatedFieldType, "The information updates for this debate", null: true
26
25
  field :instructions, Decidim::Core::TranslatedFieldType, "The instructions for this debate", null: true
27
26
  field :last_comment_at, Decidim::Core::DateTimeType, "The last comment time for this debate", null: true
@@ -15,8 +15,8 @@ module Decidim
15
15
  Debate.where(component: object).includes(:component)
16
16
  end
17
17
 
18
- def debate(**args)
19
- Debate.where(component: object).find_by(id: args[:id])
18
+ def debate(id:)
19
+ Decidim::Core::ComponentFinderBase.new(model_class: Debate).call(object, { id: }, context)
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Debates
5
+ class CloseDebateAttributes < Decidim::Api::Types::BaseInputObject
6
+ graphql_name "CloseDebateAttributes"
7
+ description "Attributes for closing a debate"
8
+
9
+ argument :conclusions, GraphQL::Types::String, description: "The conclusions for closing the debate", required: true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Debates
5
+ class CloseDebateType < Decidim::Api::Types::BaseMutation
6
+ graphql_name "CloseDebate"
7
+
8
+ description "Closes a debate"
9
+ type Decidim::Debates::DebateType
10
+
11
+ argument :attributes, CloseDebateAttributes, description: "Input attributes for closing a debate", required: true
12
+ argument :locale, GraphQL::Types::String, "The locale to use for the mutation", required: true
13
+ argument :toggle_translations, GraphQL::Types::Boolean, "Whether the user asked to toggle the machine translations or not", required: false, default_value: false
14
+
15
+ def resolve(attributes:, locale:, toggle_translations:)
16
+ set_locale(locale:, toggle_translations:)
17
+
18
+ params = {
19
+ id: object.id,
20
+ conclusions: attributes.to_h.fetch(:conclusions, "")
21
+ }
22
+
23
+ form = form(Decidim::Debates::CloseDebateForm).from_params(params)
24
+
25
+ Decidim::Debates::CloseDebate.call(form) do
26
+ on(:ok) do |debate|
27
+ return debate.reload
28
+ end
29
+
30
+ on(:invalid) do
31
+ raise Decidim::Api::Errors::AttributeValidationError, form.errors
32
+ end
33
+ end
34
+ end
35
+
36
+ def authorized?(attributes:, locale:, toggle_translations:)
37
+ raise Decidim::Api::Errors::MutationNotAuthorizedError, I18n.t("decidim.api.errors.unauthorized_mutation") unless [
38
+ super,
39
+ allowed_to?(:close, :debate, object, context),
40
+ !object.closed?
41
+ ].all?
42
+
43
+ true
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Debates
5
+ class CreateDebateType < Decidim::Api::Types::BaseMutation
6
+ graphql_name "CreateDebate"
7
+
8
+ description "Creates a debate"
9
+ type Decidim::Debates::DebateType
10
+
11
+ argument :attributes, DebateAttributes, description: "Input attributes of a debate", required: true
12
+ argument :locale, GraphQL::Types::String, "The locale for which to set the debate texts", required: true
13
+ argument :toggle_translations, GraphQL::Types::Boolean, "Whether the user asked to toggle the machine translations or not.", required: false, default_value: false
14
+
15
+ def resolve(attributes:, locale:, toggle_translations:)
16
+ set_locale(locale:, toggle_translations:)
17
+
18
+ params = attributes.to_h.slice(:title, :description)
19
+
20
+ params[:taxonomies] = Decidim::Taxonomy.where(organization: current_organization, id: attributes.to_h.fetch(:taxonomies, [])).pluck(:id)
21
+
22
+ form = form(Decidim::Debates::DebateForm).from_params(params)
23
+
24
+ Decidim::Debates::CreateDebate.call(form) do
25
+ on(:ok) do |debate|
26
+ return debate.reload
27
+ end
28
+
29
+ on(:invalid) do
30
+ raise Decidim::Api::Errors::AttributeValidationError, form.errors
31
+ end
32
+ end
33
+ end
34
+
35
+ def authorized?(attributes:, locale:, toggle_translations:)
36
+ unless super && allowed_to?(:create, :debate, Debate.new(component: current_component), { current_user:, current_component: })
37
+ raise Decidim::Api::Errors::MutationNotAuthorizedError, I18n.t("decidim.api.errors.unauthorized_mutation")
38
+ end
39
+
40
+ true
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Debates
5
+ class DebateAttributes < Decidim::Api::Types::BaseInputObject
6
+ graphql_name "DebateAttributes"
7
+ description "Attributes of a debate"
8
+
9
+ argument :description, GraphQL::Types::String, description: "The description of the debate", required: true
10
+ argument :taxonomies, [GraphQL::Types::ID], description: "Array of taxonomy IDs", required: false
11
+ argument :title, GraphQL::Types::String, description: "The title of the debate", required: true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Debates
5
+ class DebateMutationType < Decidim::Api::Types::BaseObject
6
+ include Decidim::ApiResponseHelper
7
+
8
+ graphql_name "DebateMutation"
9
+ description "A debate which includes its available mutations"
10
+
11
+ field :close, mutation: Decidim::Debates::CloseDebateType, description: "Closes a debate"
12
+ field :update, mutation: Decidim::Debates::UpdateDebateType, description: "Updates a debate"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Debates
5
+ class DebatesMutationType < Decidim::Core::ComponentType
6
+ description "Debates mutations for a component."
7
+
8
+ field :create_debate, mutation: Decidim::Debates::CreateDebateType, description: "Creates a debate"
9
+ field :debate, type: Decidim::Debates::DebateMutationType, description: "Mutates a debate", null: true do
10
+ argument :id, GraphQL::Types::ID, "The ID of the debate", required: true
11
+ end
12
+
13
+ def debate(id:)
14
+ collection.find(id)
15
+ end
16
+
17
+ private
18
+
19
+ def collection
20
+ Debate.where(component: object).not_hidden
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Debates
5
+ class UpdateDebateType < Decidim::Api::Types::BaseMutation
6
+ graphql_name "UpdateDebate"
7
+
8
+ description "Updates a debate"
9
+ type Decidim::Debates::DebateType
10
+
11
+ argument :attributes, DebateAttributes, description: "input attributes of a debate", required: true
12
+ argument :locale, GraphQL::Types::String, "The locale for which to set the debate texts", required: true
13
+ argument :toggle_translations, GraphQL::Types::Boolean, "Whether the user asked to toggle the machine translations or not.", required: false, default_value: false
14
+
15
+ def resolve(attributes:, locale:, toggle_translations:)
16
+ set_locale(locale:, toggle_translations:)
17
+
18
+ params = extract_from(attributes)
19
+ params[:taxonomies] = Decidim::Taxonomy.where(organization: current_organization, id: params[:taxonomies]).pluck(:id) if params[:taxonomies]
20
+
21
+ form = form(Decidim::Debates::DebateForm).from_params(params)
22
+
23
+ UpdateDebate.call(form, object) do
24
+ on(:ok) do
25
+ return object.reload
26
+ end
27
+
28
+ on(:invalid) do
29
+ raise Decidim::Api::Errors::AttributeValidationError, form.errors
30
+ end
31
+ end
32
+ end
33
+
34
+ def authorized?(attributes:, locale:, toggle_translations:)
35
+ raise Decidim::Api::Errors::MutationNotAuthorizedError, I18n.t("decidim.api.errors.unauthorized_mutation") unless super && allowed_to?(:edit, :debate, object, context)
36
+
37
+ true
38
+ end
39
+
40
+ private
41
+
42
+ def extract_from(attributes)
43
+ attributes = attributes.to_h.compact
44
+
45
+ title = attributes.fetch(:title, translated_attribute(object.title))
46
+ description = attributes.fetch(:description, translated_attribute(object.description))
47
+ taxonomies = attributes.fetch(:taxonomies, object.taxonomies.pluck(:id))
48
+
49
+ {
50
+ title:,
51
+ description:,
52
+ taxonomies:
53
+ }
54
+ end
55
+ end
56
+ end
57
+ end
@@ -4,5 +4,13 @@ module Decidim
4
4
  module Debates
5
5
  autoload :DebateType, "decidim/api/debate_type"
6
6
  autoload :DebatesType, "decidim/api/debates_type"
7
+
8
+ autoload :DebatesMutationType, "decidim/api/mutations/debates_mutation_type"
9
+ autoload :DebateMutationType, "decidim/api/mutations/debate_mutation_type"
10
+ autoload :CloseDebateType, "decidim/api/mutations/close_debate_type"
11
+ autoload :CloseDebateAttributes, "decidim/api/mutations/close_debate_attributes"
12
+ autoload :CreateDebateType, "decidim/api/mutations/create_debate_type"
13
+ autoload :DebateAttributes, "decidim/api/mutations/debate_attributes"
14
+ autoload :UpdateDebateType, "decidim/api/mutations/update_debate_type"
7
15
  end
8
16
  end
@@ -12,10 +12,6 @@ Decidim.register_component(:debates) do |component|
12
12
 
13
13
  component.newsletter_participant_entities = ["Decidim::Debates::Debate"]
14
14
 
15
- component.on(:before_destroy) do |instance|
16
- raise StandardError, "Cannot remove this component" if Decidim::Debates::Debate.where(component: instance).any?
17
- end
18
-
19
15
  component.on(:publish) do |instance|
20
16
  Decidim::Debates::Debate.where(component: instance).find_in_batches(batch_size: 100) do |batch|
21
17
  Decidim::UpdateSearchIndexesJob.perform_later(batch)
@@ -79,10 +75,10 @@ Decidim.register_component(:debates) do |component|
79
75
  resource.card = "decidim/debates/debate"
80
76
  resource.reported_content_cell = "decidim/debates/reported_content"
81
77
  resource.searchable = true
82
- resource.actions = %w(create like comment)
78
+ resource.actions = %w(create like comment vote_comment)
83
79
  end
84
80
 
85
- component.actions = %w(create like comment)
81
+ component.actions = %w(create like comment vote_comment)
86
82
 
87
83
  component.exports :debates do |exports|
88
84
  exports.collection do |component_instance|
@@ -98,6 +98,12 @@ module Decidim
98
98
  end
99
99
  end
100
100
  end
101
+
102
+ initializer "decidim_debates.register_mutations", before: "decidim_api.graphiql" do
103
+ Decidim::MutationRegistry.instance.register(
104
+ Decidim::Debates::DebatesMutationType
105
+ )
106
+ end
101
107
  end
102
108
  end
103
109
  end
@@ -4,7 +4,7 @@ module Decidim
4
4
  # This holds the decidim-debates version.
5
5
  module Debates
6
6
  def self.version
7
- "0.31.5"
7
+ "0.32.0.rc2"
8
8
  end
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,17 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-debates
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.31.5
4
+ version: 0.32.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josep Jaume Rey Peroy
8
8
  - Marc Riera Casals
9
9
  - Oriol Gual Oliva
10
10
  - Genis Matutes Pujol
11
- autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2026-05-12 00:00:00.000000000 Z
13
+ date: 1980-01-02 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: decidim-comments
@@ -19,70 +18,70 @@ dependencies:
19
18
  requirements:
20
19
  - - '='
21
20
  - !ruby/object:Gem::Version
22
- version: 0.31.5
21
+ version: 0.32.0.rc2
23
22
  type: :runtime
24
23
  prerelease: false
25
24
  version_requirements: !ruby/object:Gem::Requirement
26
25
  requirements:
27
26
  - - '='
28
27
  - !ruby/object:Gem::Version
29
- version: 0.31.5
28
+ version: 0.32.0.rc2
30
29
  - !ruby/object:Gem::Dependency
31
30
  name: decidim-core
32
31
  requirement: !ruby/object:Gem::Requirement
33
32
  requirements:
34
33
  - - '='
35
34
  - !ruby/object:Gem::Version
36
- version: 0.31.5
35
+ version: 0.32.0.rc2
37
36
  type: :runtime
38
37
  prerelease: false
39
38
  version_requirements: !ruby/object:Gem::Requirement
40
39
  requirements:
41
40
  - - '='
42
41
  - !ruby/object:Gem::Version
43
- version: 0.31.5
42
+ version: 0.32.0.rc2
44
43
  - !ruby/object:Gem::Dependency
45
44
  name: decidim-admin
46
45
  requirement: !ruby/object:Gem::Requirement
47
46
  requirements:
48
47
  - - '='
49
48
  - !ruby/object:Gem::Version
50
- version: 0.31.5
49
+ version: 0.32.0.rc2
51
50
  type: :development
52
51
  prerelease: false
53
52
  version_requirements: !ruby/object:Gem::Requirement
54
53
  requirements:
55
54
  - - '='
56
55
  - !ruby/object:Gem::Version
57
- version: 0.31.5
56
+ version: 0.32.0.rc2
58
57
  - !ruby/object:Gem::Dependency
59
58
  name: decidim-assemblies
60
59
  requirement: !ruby/object:Gem::Requirement
61
60
  requirements:
62
61
  - - '='
63
62
  - !ruby/object:Gem::Version
64
- version: 0.31.5
63
+ version: 0.32.0.rc2
65
64
  type: :development
66
65
  prerelease: false
67
66
  version_requirements: !ruby/object:Gem::Requirement
68
67
  requirements:
69
68
  - - '='
70
69
  - !ruby/object:Gem::Version
71
- version: 0.31.5
70
+ version: 0.32.0.rc2
72
71
  - !ruby/object:Gem::Dependency
73
72
  name: decidim-dev
74
73
  requirement: !ruby/object:Gem::Requirement
75
74
  requirements:
76
75
  - - '='
77
76
  - !ruby/object:Gem::Version
78
- version: 0.31.5
77
+ version: 0.32.0.rc2
79
78
  type: :development
80
79
  prerelease: false
81
80
  version_requirements: !ruby/object:Gem::Requirement
82
81
  requirements:
83
82
  - - '='
84
83
  - !ruby/object:Gem::Version
85
- version: 0.31.5
84
+ version: 0.32.0.rc2
86
85
  description: A debates component for decidim's participatory spaces.
87
86
  email:
88
87
  - josepjaume@gmail.com
@@ -277,9 +276,18 @@ files:
277
276
  - db/migrate/20240828103648_add_deleted_at_to_decidim_debates_debates.rb
278
277
  - db/migrate/20241017153555_add_comments_layout_to_debates.rb
279
278
  - db/migrate/20250515115545_rename_debates_endorsements_count_to_likes.rb
279
+ - db/migrate/20251114092453_remove_legacy_images_from_debates_module.rb
280
+ - db/migrate/20260208201402_remove_user_group_debates.rb
280
281
  - decidim-debates.gemspec
281
282
  - lib/decidim/api/debate_type.rb
282
283
  - lib/decidim/api/debates_type.rb
284
+ - lib/decidim/api/mutations/close_debate_attributes.rb
285
+ - lib/decidim/api/mutations/close_debate_type.rb
286
+ - lib/decidim/api/mutations/create_debate_type.rb
287
+ - lib/decidim/api/mutations/debate_attributes.rb
288
+ - lib/decidim/api/mutations/debate_mutation_type.rb
289
+ - lib/decidim/api/mutations/debates_mutation_type.rb
290
+ - lib/decidim/api/mutations/update_debate_type.rb
283
291
  - lib/decidim/debates.rb
284
292
  - lib/decidim/debates/admin.rb
285
293
  - lib/decidim/debates/admin_engine.rb
@@ -299,7 +307,6 @@ metadata:
299
307
  funding_uri: https://opencollective.com/decidim
300
308
  homepage_uri: https://decidim.org
301
309
  source_code_uri: https://github.com/decidim/decidim
302
- post_install_message:
303
310
  rdoc_options: []
304
311
  require_paths:
305
312
  - lib
@@ -307,15 +314,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
307
314
  requirements:
308
315
  - - "~>"
309
316
  - !ruby/object:Gem::Version
310
- version: 3.3.0
317
+ version: 3.4.0
311
318
  required_rubygems_version: !ruby/object:Gem::Requirement
312
319
  requirements:
313
320
  - - ">="
314
321
  - !ruby/object:Gem::Version
315
322
  version: '0'
316
323
  requirements: []
317
- rubygems_version: 3.5.11
318
- signing_key:
324
+ rubygems_version: 3.6.9
319
325
  specification_version: 4
320
326
  summary: Decidim debates module
321
327
  test_files: []