decidim-proposals 0.27.5 → 0.27.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/proposals/highlighted_proposals_for_component/show.erb +1 -1
  3. data/app/cells/decidim/proposals/participatory_text_proposal/buttons.erb +2 -2
  4. data/app/cells/decidim/proposals/proposal_tags/show.erb +2 -2
  5. data/app/controllers/decidim/proposals/widgets_controller.rb +11 -1
  6. data/app/helpers/decidim/proposals/application_helper.rb +1 -1
  7. data/app/models/decidim/proposals/proposal.rb +2 -14
  8. data/app/models/decidim/proposals/valuation_assignment.rb +2 -1
  9. data/app/packs/src/decidim/proposals/admin/proposals.js +7 -0
  10. data/app/permissions/decidim/proposals/permissions.rb +9 -0
  11. data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +1 -5
  12. data/app/presenters/decidim/proposals/admin_log/value_types/proposal_title_body_presenter.rb +1 -3
  13. data/app/presenters/decidim/proposals/log/valuation_assignment_presenter.rb +1 -1
  14. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +1 -1
  15. data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +1 -1
  16. data/app/views/decidim/proposals/admin/proposals/show.html.erb +1 -1
  17. data/app/views/decidim/proposals/admin/proposals/update_attribute.js.erb +2 -1
  18. data/app/views/decidim/proposals/proposals/show.html.erb +3 -1
  19. data/config/locales/ar.yml +2 -6
  20. data/config/locales/bg.yml +748 -1
  21. data/config/locales/ca.yml +35 -33
  22. data/config/locales/cs.yml +5 -4
  23. data/config/locales/de.yml +9 -7
  24. data/config/locales/el.yml +0 -4
  25. data/config/locales/en.yml +2 -0
  26. data/config/locales/es-MX.yml +9 -7
  27. data/config/locales/es-PY.yml +9 -7
  28. data/config/locales/es.yml +22 -20
  29. data/config/locales/eu.yml +6 -4
  30. data/config/locales/fi-plain.yml +7 -5
  31. data/config/locales/fi.yml +6 -4
  32. data/config/locales/fr-CA.yml +9 -7
  33. data/config/locales/fr.yml +9 -7
  34. data/config/locales/ga-IE.yml +13 -0
  35. data/config/locales/gl.yml +2 -5
  36. data/config/locales/he-IL.yml +1 -0
  37. data/config/locales/hu.yml +16 -11
  38. data/config/locales/id-ID.yml +1 -4
  39. data/config/locales/is-IS.yml +4 -5
  40. data/config/locales/it.yml +4 -7
  41. data/config/locales/ja.yml +19 -17
  42. data/config/locales/lt.yml +0 -4
  43. data/config/locales/lv.yml +1 -4
  44. data/config/locales/nl.yml +5 -8
  45. data/config/locales/no.yml +1 -4
  46. data/config/locales/pl.yml +91 -5
  47. data/config/locales/pt-BR.yml +34 -5
  48. data/config/locales/pt.yml +1 -4
  49. data/config/locales/ro-RO.yml +1 -3
  50. data/config/locales/ru.yml +7 -5
  51. data/config/locales/sk.yml +5 -8
  52. data/config/locales/sv.yml +3 -7
  53. data/config/locales/tr-TR.yml +9 -8
  54. data/config/locales/uk.yml +7 -5
  55. data/config/locales/zh-CN.yml +1 -4
  56. data/config/locales/zh-TW.yml +0 -4
  57. data/db/migrate/20240404202756_add_valuation_assignments_count_to_decidim_proposals_proposals.rb +16 -0
  58. data/decidim-proposals.gemspec +40 -0
  59. data/lib/decidim/proposals/proposal_serializer.rb +52 -0
  60. data/lib/decidim/proposals/test/factories.rb +76 -57
  61. data/lib/decidim/proposals/valuatable.rb +2 -1
  62. data/lib/decidim/proposals/version.rb +1 -1
  63. metadata +26 -25
  64. data/app/presenters/decidim/proposals/log/resource_presenter.rb +0 -22
  65. data/config/environment.rb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d86dedc7c769a8efba7a3e155139f0e0668e31ffe54edafb51a49485479fef8
4
- data.tar.gz: 1e8ea8f759a82484b1b1b93513c77d55d06b780e033f3cb13862cb46c6085b6b
3
+ metadata.gz: 1e291f2f0b2cac7faf278350614fa4d8eea1f12c514787a1102bc34f033c6c20
4
+ data.tar.gz: 26de14643cc5d736985bd35684628cd38b21618d5bfc065fa789f282d9fff8f5
5
5
  SHA512:
6
- metadata.gz: 69f4c89eeea8892cb2906d9b87895615c79d47de2865391f661b79be144b9ad59a49f1532110c82ba4ac78dc7fc88f3317be07f94a30fcc814f9511a9285e94b
7
- data.tar.gz: 06d799b876315ba91c6e97f73297f663e393094718122d7cb5c5677e2033d91a93c77797dcbe8a0e93a59d11796d6463d0013b281ad58ddef234e0546516e5bb
6
+ metadata.gz: c80f1d038c0c260680c3186cec61780b5d1cae0d66ed946014647b84cbb0ada6f8bf98cd478b65e78d1bf059495cf0fc66eeba76f80066025451d948f45d434b
7
+ data.tar.gz: 4187a7c435fda93c5212bdcb8e7feae60c826b72b0fd5be1bda96078f94c63c538f3371b6ef5a21c89771d51d8d728fa7bb3c872b2c9ed1968c298c7e237862c
@@ -1,6 +1,6 @@
1
1
  <section class="section row collapse highlighted_proposals">
2
2
  <h3 class="section-heading">
3
- <%= translated_attribute(model.name) %> <a href="<%= main_component_path(model) %>" class="text-small"><%= t("decidim.participatory_spaces.highlighted_proposals.see_all", count: proposals_count) %></a>
3
+ <%= decidim_escape_translated(model.name) %> <a href="<%= main_component_path(model) %>" class="text-small"><%= t("decidim.participatory_spaces.highlighted_proposals.see_all", count: proposals_count) %></a>
4
4
  </h3>
5
5
 
6
6
  <%= cell(
@@ -6,7 +6,7 @@
6
6
  <%= link_to resource_amendments_path, class: "column medium-4 button light secondary" do %>
7
7
  <%= visible_emendations.count %>
8
8
  <% end %>
9
- <%= link_to amend_resource_path, class: "column button hollow secondary button--sc", disabled: amend_button_disabled? do %>
9
+ <%= action_authorized_link_to :amend, amend_resource_path, resource: model, data: { "redirect_url" => amend_resource_path }, class: "column button hollow secondary button--sc", disabled: amend_button_disabled? do %>
10
10
  <%= t("amend", scope: "decidim.proposals.participatory_text_proposal.buttons") %>
11
11
  <% end %>
12
12
  </div>
@@ -23,7 +23,7 @@
23
23
  <%= link_to resource_comments_path, class: "column medium-4 button light secondary" do %>
24
24
  <%= icon "comment-square", class: "icon--small", aria_label: t("comments", scope: "decidim.proposals.participatory_text_proposal.buttons"), role: "img" %> <%= model.comments_count %>
25
25
  <% end %>
26
- <%= link_to resource_comments_path, class: "column button hollow secondary button--sc" do %>
26
+ <%= action_authorized_link_to :comment, resource_comments_path, resource: model, class: "column button hollow secondary button--sc" do %>
27
27
  <%= t("comment", scope: "decidim.proposals.participatory_text_proposal.buttons") %>
28
28
  <% end %>
29
29
  <% end %>
@@ -3,8 +3,8 @@
3
3
  <% if category.present? %>
4
4
  <li>
5
5
  <%= link_to resource_locator(model).index(filter: { with_any_category: [category.id.to_s] }), title: t("decidim.tags.filter_results_for_category", resource: translated_attribute(category.name)) do %>
6
- <span class="show-for-sr"><%= t "decidim.tags.filter_results_for_category", resource: translated_attribute(category.name) %></span>
7
- <span aria-hidden="true"><%= translated_attribute(category.name) %></span>
6
+ <span class="show-for-sr"><%= t "decidim.tags.filter_results_for_category", resource: decidim_html_escape(translated_attribute(category.name)) %></span>
7
+ <span aria-hidden="true"><%= decidim_html_escape(translated_attribute(category.name)) %></span>
8
8
  <% end %>
9
9
  <% if previous_category.present? && show_previous_category? %>
10
10
  &nbsp;
@@ -5,15 +5,25 @@ module Decidim
5
5
  class WidgetsController < Decidim::WidgetsController
6
6
  helper Proposals::ApplicationHelper
7
7
 
8
+ def show
9
+ enforce_permission_to :embed, :proposal, proposal: model if model
10
+
11
+ super
12
+ end
13
+
8
14
  private
9
15
 
10
16
  def model
11
- @model ||= Proposal.where(component: params[:component_id]).find(params[:proposal_id])
17
+ @model ||= Proposal.not_hidden.except_withdrawn.where(component: current_component).find(params[:proposal_id])
12
18
  end
13
19
 
14
20
  def iframe_url
15
21
  @iframe_url ||= proposal_widget_url(model)
16
22
  end
23
+
24
+ def permission_class_chain
25
+ [Decidim::Proposals::Permissions]
26
+ end
17
27
  end
18
28
  end
19
29
  end
@@ -151,7 +151,7 @@ module Decidim
151
151
  end
152
152
 
153
153
  def show_voting_rules?
154
- return false unless votes_enabled?
154
+ return false if !votes_enabled? || current_settings.votes_blocked?
155
155
 
156
156
  return true if vote_limit_enabled?
157
157
  return true if threshold_per_proposal_enabled?
@@ -96,11 +96,11 @@ module Decidim
96
96
  }
97
97
 
98
98
  scope :sort_by_valuation_assignments_count_asc, lambda {
99
- order(Arel.sql("#{sort_by_valuation_assignments_count_nulls_last_query} ASC NULLS FIRST").to_s)
99
+ order(valuation_assignments_count: :asc)
100
100
  }
101
101
 
102
102
  scope :sort_by_valuation_assignments_count_desc, lambda {
103
- order(Arel.sql("#{sort_by_valuation_assignments_count_nulls_last_query} DESC NULLS LAST").to_s)
103
+ order(valuation_assignments_count: :desc)
104
104
  }
105
105
 
106
106
  scope_search_multi :with_any_state, [:accepted, :rejected, :evaluating, :state_not_published]
@@ -333,18 +333,6 @@ module Decidim
333
333
  ProposalSearch.new(self, params, options)
334
334
  end
335
335
 
336
- # Defines the base query so that ransack can actually sort by this value
337
- def self.sort_by_valuation_assignments_count_nulls_last_query
338
- <<-SQL.squish
339
- (
340
- SELECT COUNT(decidim_proposals_valuation_assignments.id)
341
- FROM decidim_proposals_valuation_assignments
342
- WHERE decidim_proposals_valuation_assignments.decidim_proposal_id = decidim_proposals_proposals.id
343
- GROUP BY decidim_proposals_valuation_assignments.decidim_proposal_id
344
- )
345
- SQL
346
- end
347
-
348
336
  # method to filter by assigned valuator role ID
349
337
  def self.valuator_role_ids_has(value)
350
338
  query = <<-SQL.squish
@@ -9,7 +9,8 @@ module Decidim
9
9
  include Decidim::Traceable
10
10
  include Decidim::Loggable
11
11
 
12
- belongs_to :proposal, foreign_key: "decidim_proposal_id", class_name: "Decidim::Proposals::Proposal"
12
+ belongs_to :proposal, foreign_key: "decidim_proposal_id", class_name: "Decidim::Proposals::Proposal",
13
+ counter_cache: true
13
14
  belongs_to :valuator_role, polymorphic: true
14
15
 
15
16
  def self.log_presenter_class_for(_log)
@@ -47,6 +47,12 @@ $(() => {
47
47
  }
48
48
  }
49
49
 
50
+ const resetForms = function() {
51
+ $("#js-bulk-actions-dropdown button").each(function() {
52
+ $(`#js-form-${$(this).data("action")}`)[0].reset();
53
+ })
54
+ }
55
+
50
56
  const showOtherActionsButtons = function() {
51
57
  $("#js-other-actions-wrapper").removeClass("hide");
52
58
  }
@@ -68,6 +74,7 @@ $(() => {
68
74
  window.showOtherActionsButtons = showOtherActionsButtons;
69
75
  window.hideOtherActionsButtons = hideOtherActionsButtons;
70
76
  window.hideBulkActionForms = hideBulkActionForms;
77
+ window.resetForms = resetForms;
71
78
 
72
79
  if ($(".js-bulk-action-form").length) {
73
80
  hideBulkActionForms();
@@ -4,6 +4,7 @@ module Decidim
4
4
  module Proposals
5
5
  class Permissions < Decidim::DefaultPermissions
6
6
  def permissions
7
+ allow_embed_proposal?
7
8
  return permission_action unless user
8
9
 
9
10
  # Delegate the admin permission checks to the admin permissions class
@@ -47,6 +48,14 @@ module Decidim
47
48
  @proposal ||= context.fetch(:proposal, nil) || context.fetch(:resource, nil)
48
49
  end
49
50
 
51
+ # As this is a public action, we need to run this before other checks
52
+ def allow_embed_proposal?
53
+ return unless permission_action.action == :embed && permission_action.subject == :proposal && proposal
54
+ return disallow! if proposal.withdrawn?
55
+
56
+ allow!
57
+ end
58
+
50
59
  def voting_enabled?
51
60
  return unless current_settings
52
61
 
@@ -15,13 +15,9 @@ module Decidim
15
15
  class ProposalPresenter < Decidim::Log::BasePresenter
16
16
  private
17
17
 
18
- def resource_presenter
19
- @resource_presenter ||= Decidim::Proposals::Log::ResourcePresenter.new(action_log.resource, h, action_log.extra["resource"])
20
- end
21
-
22
18
  def diff_fields_mapping
23
19
  {
24
- title: "Decidim::Proposals::AdminLog::ValueTypes::ProposalTitleBodyPresenter",
20
+ title: :i18n,
25
21
  body: "Decidim::Proposals::AdminLog::ValueTypes::ProposalTitleBodyPresenter",
26
22
  state: "Decidim::Proposals::AdminLog::ValueTypes::ProposalStatePresenter",
27
23
  answered_at: :date,
@@ -5,12 +5,10 @@ module Decidim
5
5
  module AdminLog
6
6
  module ValueTypes
7
7
  class ProposalTitleBodyPresenter < Decidim::Log::ValueTypes::DefaultPresenter
8
- include Decidim::TranslatableAttributes
9
-
10
8
  def present
11
9
  return unless value
12
10
 
13
- translated_value = translated_attribute(value)
11
+ translated_value = h.decidim_escape_translated(value)
14
12
  return if translated_value.blank?
15
13
 
16
14
  renderer = Decidim::ContentRenderers::HashtagRenderer.new(translated_value)
@@ -11,7 +11,7 @@ module Decidim
11
11
  # Returns an HTML-safe String.
12
12
  def present_resource_name
13
13
  if resource.present?
14
- Decidim::Proposals::ProposalPresenter.new(resource.proposal).title
14
+ resource.proposal.presenter.title(html_escape: true)
15
15
  else
16
16
  super
17
17
  end
@@ -44,7 +44,7 @@
44
44
 
45
45
  <div class="row column" id="proposal_meeting">
46
46
  <%= form.select :meeting_id,
47
- options_for_select(@form.meetings&.map { |meeting| [present(meeting).title, meeting.id] }, selected: meetings_as_authors_selected ),
47
+ options_for_select(@form.meetings&.map { |meeting| [present(meeting).title(html_escape: true), meeting.id] }, selected: meetings_as_authors_selected ),
48
48
  { include_blank: true, label: t(".select_a_meeting") },
49
49
  { multiple: false, class: "chosen-select" } %>
50
50
  </div>
@@ -53,7 +53,7 @@
53
53
  </td>
54
54
 
55
55
  <td class="valuators-count">
56
- <%= proposal.valuation_assignments.count %>
56
+ <%= proposal.valuation_assignments.size %>
57
57
  </td>
58
58
 
59
59
  <td>
@@ -107,7 +107,7 @@
107
107
  <% proposal_meetings.each do |meeting| %>
108
108
  <% presented_meeting = present(meeting) %>
109
109
  <li>
110
- <%= link_to presented_meeting.title, presented_meeting.profile_path %>
110
+ <%= link_to decidim_escape_translated(meeting.title).html_safe, presented_meeting.profile_path %>
111
111
  </li>
112
112
  <% end %>
113
113
  </ul>
@@ -22,5 +22,6 @@
22
22
  window.hideBulkActionsButton();
23
23
  window.hideBulkActionForms();
24
24
  window.showOtherActionsButtons();
25
- window.selectedResourcesCountUpdate();
25
+ window.selectedProposalsCountUpdate();
26
+ window.resetForms();
26
27
  <% end %>
@@ -129,7 +129,9 @@ extra_admin_link(
129
129
  <%= resource_version(proposal_presenter, versions_path: proposal_versions_path(@proposal)) %>
130
130
  <%= cell("decidim/fingerprint", @proposal) %>
131
131
  <%= render partial: "decidim/shared/share_modal", locals: { resource: @proposal } %>
132
- <%= embed_modal_for proposal_widget_url(@proposal, format: :js) %>
132
+ <% if allowed_to? :embed, :proposal, proposal: @proposal %>
133
+ <%= embed_modal_for proposal_widget_url(@proposal, format: :js) %>
134
+ <% end %>
133
135
  <%= cell "decidim/proposals/proposal_link_to_collaborative_draft", @proposal %>
134
136
  <%= cell "decidim/proposals/proposal_link_to_rejected_emendation", @proposal %>
135
137
  </div>
@@ -191,7 +191,6 @@ ar:
191
191
  proposal_wizard_step_1_help_text: اقتراح الاقتراح "إنشاء" نص مساعدة الخطوة
192
192
  proposal_wizard_step_2_help_text: اقتراح الاقتراح "قارن" نص خطوة المساعدة
193
193
  proposal_wizard_step_3_help_text: نص اقتراح "إكمال" تعليمات نص المعالج
194
- proposal_wizard_step_4_help_text: اقتراح الاقتراح "نشر" نص تعليمات الخطوة
195
194
  resources_permissions_enabled: يمكن تعيين أذونات الإجراءات لكل اقتراح
196
195
  scope_id: نطاق
197
196
  scopes_enabled: النطاقات مفعلة
@@ -291,7 +290,6 @@ ar:
291
290
  notification_title: تم قبول اقتراحك <a href="%{resource_path}">%{resource_title}</a>.
292
291
  follower:
293
292
  email_intro: 'تم قبول الاقتراح "%{resource_title}". يمكنك قراءة الإجابة على هذه الصفحة:'
294
- email_outro: لقد تلقيت هذا الإشعار لأنك تتابع %{resource_title}. يمكنك إلغاء المتابعة على الرابط السابق.
295
293
  email_subject: تم قبول اقتراح تتابعه
296
294
  notification_title: لقد تم قبول المُقتَرح <a href="%{resource_path}">%{resource_title}</a>.
297
295
  proposal_evaluating:
@@ -302,7 +300,6 @@ ar:
302
300
  notification_title: يتم تقييم الاقتراح الخاص بك <a href="%{resource_path}">%{resource_title}</a>.
303
301
  follower:
304
302
  email_intro: 'الاقتراح "%{resource_title}" قيد التقييم حاليا. يمكنك التحقق من وجود إجابة على هذه الصفحة:'
305
- email_outro: لقد تلقيت هذا الإشعار لأنك تتابع %{resource_title}. يمكنك إلغاء المتابعة على الرابط السابق.
306
303
  email_subject: واحد من الاقتراحات التي تتبعها قيد التقييم الآن
307
304
  notification_title: الاقتراح <a href="%{resource_path}">%{resource_title}</a> قيد التقييم الآن.
308
305
  proposal_mentioned:
@@ -329,7 +326,6 @@ ar:
329
326
  notification_title: تم رفض اقتراحك <a href="%{resource_path}">%{resource_title}</a>.
330
327
  follower:
331
328
  email_intro: 'تم رفض الاقتراح %{resource_title}. يمكنك قراءة الإجابة على ذلك على هذه الصفحة:'
332
- email_outro: لقد تلقيت هذا الإشعار لأنك تتابع %{resource_title}. يمكنك إلغاء المتابعة على الرابط السابق.
333
329
  email_subject: واحد من الاقتراحات التي تتبعها تم رفضها
334
330
  notification_title: تم رفض الاقتراح <a href="%{resource_path}">%{resource_title}</a>.
335
331
  proposal_update_category:
@@ -496,7 +492,7 @@ ar:
496
492
  accepted: وافقت
497
493
  answer_proposal: إجابة
498
494
  evaluating: تقييم
499
- not_answered: لم تتم الإجابة عليه
495
+ not_answered: بلا جواب
500
496
  rejected: مرفوض
501
497
  title: الإجابة على الاقتراح %{title}
502
498
  proposal_notes:
@@ -992,7 +988,7 @@ ar:
992
988
  step_1: إنشاء اقتراحك
993
989
  step_2: قارن
994
990
  step_3: إكمال
995
- step_4: انشر اقتراحك
991
+ step_4: نشر اقتراحك
996
992
  step_of: الخطوة %{current_step_num} من %{total_steps}
997
993
  title: خطوات إنشاء الاقتراحات
998
994
  proposals_picker: