From 30299c951786120aea4ecd444b101a0a6566ca5a Mon Sep 17 00:00:00 2001 From: stephanie rousset Date: Wed, 18 Jun 2025 12:35:10 +0200 Subject: [PATCH 01/12] fix: remove inappropriate roles menu and menuitem --- decidim-core/app/helpers/decidim/menu_helper.rb | 2 +- decidim-core/app/presenters/decidim/menu_item_presenter.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/decidim-core/app/helpers/decidim/menu_helper.rb b/decidim-core/app/helpers/decidim/menu_helper.rb index d2735bd43afb6..77213b63b64ef 100644 --- a/decidim-core/app/helpers/decidim/menu_helper.rb +++ b/decidim-core/app/helpers/decidim/menu_helper.rb @@ -57,7 +57,7 @@ def footer_menu self, element_class: "font-semibold underline", active_class: "is-active", - container_options: { class: "space-y-4 break-inside-avoid", role: :menu }, + container_options: { class: "space-y-4 break-inside-avoid" }, label: t("layouts.decidim.footer.decidim_title") ) end diff --git a/decidim-core/app/presenters/decidim/menu_item_presenter.rb b/decidim-core/app/presenters/decidim/menu_item_presenter.rb index 9354e88169528..da2454f00700a 100644 --- a/decidim-core/app/presenters/decidim/menu_item_presenter.rb +++ b/decidim-core/app/presenters/decidim/menu_item_presenter.rb @@ -29,7 +29,7 @@ def initialize(menu_item, view, options = {}) delegate :content_tag, :safe_join, :link_to, :active_link_to_class, :is_active_link?, :icon, to: :@view def render - content_tag :li, role: :menuitem, class: link_wrapper_classes do + content_tag :li, class: link_wrapper_classes do output = if url == "#" [content_tag(:span, composed_label, class: "sidebar-menu__item-disabled")] else From add5039ab805fe7a327831529925401bcd7b0910 Mon Sep 17 00:00:00 2001 From: stephanie rousset Date: Wed, 9 Jul 2025 09:44:26 +0200 Subject: [PATCH 02/12] fix: accessibility on ul menu on account page --- .../decidim/shared/_layout_user_profile.html.erb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb b/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb index b02f52413d3b0..f3941af7b2dee 100644 --- a/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb +++ b/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb @@ -29,3 +29,17 @@ <% end %> + From 15b9b1e67058ff0bd2971b3c861a18e1d88f0d62 Mon Sep 17 00:00:00 2001 From: stephanie rousset Date: Thu, 10 Jul 2025 16:58:59 +0200 Subject: [PATCH 03/12] fix: remove unwanted code --- .../decidim/shared/_layout_user_profile.html.erb | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb b/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb index f3941af7b2dee..b02f52413d3b0 100644 --- a/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb +++ b/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb @@ -29,17 +29,3 @@ <% end %> - From 2e10076f819c4bcfd4a570c94dc49f33c55df610 Mon Sep 17 00:00:00 2001 From: stephanie rousset Date: Mon, 28 Jul 2025 11:09:28 +0200 Subject: [PATCH 04/12] fix: add js again to fix account page accessibility --- .../decidim/shared/_layout_user_profile.html.erb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb b/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb index b02f52413d3b0..ae502686f207d 100644 --- a/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb +++ b/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb @@ -29,3 +29,17 @@ <% end %> + From e896ebc4ab9a51614661acf1e856fdf9df86a8fa Mon Sep 17 00:00:00 2001 From: stephanie rousset Date: Mon, 1 Sep 2025 13:45:50 +0200 Subject: [PATCH 05/12] fix: remove js added for account page accessibility --- .../decidim/shared/_layout_user_profile.html.erb | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb b/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb index ae502686f207d..b02f52413d3b0 100644 --- a/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb +++ b/decidim-core/app/views/layouts/decidim/shared/_layout_user_profile.html.erb @@ -29,17 +29,3 @@ <% end %> - From cbdec226f5f1f3b52d64760d11d44b7fc0ef43c6 Mon Sep 17 00:00:00 2001 From: stephanie rousset Date: Mon, 1 Sep 2025 16:06:48 +0200 Subject: [PATCH 06/12] test: try fixing election system test --- .../spec/system/admin/admin_manages_elections_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/decidim-elections/spec/system/admin/admin_manages_elections_spec.rb b/decidim-elections/spec/system/admin/admin_manages_elections_spec.rb index 4da6f96335bf8..b65dc37b1c834 100644 --- a/decidim-elections/spec/system/admin/admin_manages_elections_spec.rb +++ b/decidim-elections/spec/system/admin/admin_manages_elections_spec.rb @@ -19,7 +19,7 @@ let!(:published_results_election) { create(:election, :published, :published_results, component: current_component) } let(:attributes) { attributes_for(:election, component: current_component) } - let(:start_time) { Time.current.change(day: 10, hour: 12, min: 50) } + let(:start_time) { Time.current } let(:end_time) { Time.current.change(day: 12, hour: 12, min: 50) } before do @@ -72,6 +72,7 @@ end describe "updating an election" do + it "updates an election" do within "tr", text: translated(election.title) do find("button[data-controller='dropdown']").click From 9112eefe317cab0450c654f93dc2fa0da746ae84 Mon Sep 17 00:00:00 2001 From: stephanie rousset Date: Mon, 1 Sep 2025 16:23:46 +0200 Subject: [PATCH 07/12] style: update test with rubocop --- .../spec/system/admin/admin_manages_elections_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/decidim-elections/spec/system/admin/admin_manages_elections_spec.rb b/decidim-elections/spec/system/admin/admin_manages_elections_spec.rb index b65dc37b1c834..cb493c31e884a 100644 --- a/decidim-elections/spec/system/admin/admin_manages_elections_spec.rb +++ b/decidim-elections/spec/system/admin/admin_manages_elections_spec.rb @@ -72,7 +72,6 @@ end describe "updating an election" do - it "updates an election" do within "tr", text: translated(election.title) do find("button[data-controller='dropdown']").click From 042b0f38f50ee9afe06e093e36e635dea62fa737 Mon Sep 17 00:00:00 2001 From: stephanie rousset Date: Mon, 1 Sep 2025 16:59:05 +0200 Subject: [PATCH 08/12] test: try fixing download_your_data test --- decidim-core/spec/system/download_your_data_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/decidim-core/spec/system/download_your_data_spec.rb b/decidim-core/spec/system/download_your_data_spec.rb index f4061c8cab788..87bedc460cdcf 100644 --- a/decidim-core/spec/system/download_your_data_spec.rb +++ b/decidim-core/spec/system/download_your_data_spec.rb @@ -103,6 +103,7 @@ describe "Export data" do it "exports an archive with all user information" do expect(Decidim::PrivateExport.count).to eq(4) + sleep 2 perform_enqueued_jobs { click_on "Request" } within_flash_messages do From 27d5c84af04019b94e5e361da155f0f2b1fefd45 Mon Sep 17 00:00:00 2001 From: stephanie rousset Date: Tue, 2 Sep 2025 08:58:39 +0200 Subject: [PATCH 09/12] Trigger CI From 038862f3ded8894e5f0e700bb3b846e31ef476e1 Mon Sep 17 00:00:00 2001 From: Tom Greenwood <101816158+greenwoodt@users.noreply.github.com> Date: Mon, 8 Sep 2025 20:15:57 +0200 Subject: [PATCH 10/12] Update to democratic quality indicators (#15148) --- .../config/locales/en.yml | 105 +++++++----------- 1 file changed, 41 insertions(+), 64 deletions(-) diff --git a/decidim-participatory_processes/config/locales/en.yml b/decidim-participatory_processes/config/locales/en.yml index 4fe4ca6450126..19a1b7c60a4b8 100644 --- a/decidim-participatory_processes/config/locales/en.yml +++ b/decidim-participatory_processes/config/locales/en.yml @@ -429,7 +429,7 @@ en: three: 40 - 60% two: 20 - 40% citizen_influence_level: - legend: This indicator measures the degree of actual citizen power in a process, specifically quantifying the level of decisional and executive authority citizens hold, from simply receiving information to decisively influencing decisions and managing resources. + legend: To what extent do citizens hold decisional authority in this process, ranging from simply receiving information to decisively influencing decisions and managing resources? options: five: Participants were involved in the decision-making and the management of resources or the implementation four: Participants were involved decisively in the decision-making @@ -719,55 +719,23 @@ en:

The questions that make up the self-assessment form answered by the administrators, as well as the values associated with each answer, are set out below.

-

Inclusiveness

- -

Inclusivity according to cultural origin and functional diversity.

+

Informativeness

    -
  1. Have migrant groups been invited to participate? -
      -
    • Yes = 5
    • -
    • No = 0
    • -
    -
  2. -
  3. How many people from diverse cultural origins have participated out of the invited? -
      -
    • 0-20% = 1
    • -
    • 20-40% = 2
    • -
    • 40-60% = 3
    • -
    • 60-80% = 4
    • -
    • 80-100% = 5
    • -
    -
  4. -
  5. Have groups of people with functional diversity been invited to participate? +
  6. Does the published information provide clarity on the decision-making mechanisms (e.g., voting, consensus, direct negotiations)?
      -
    • Yes = 5
    • -
    • No = 0
    • +
    • No clarity = 0
    • +
    • Low clarity = 1
    • +
    • Sufficient clarity = 2,5
    • +
    • Full clarity = 5
  7. -
  8. How many people with functional diversity have participated out of the invited? +
  9. Has information been provided regarding the participants' capacity to influence the topic under discussion (both in the communication of the process and invitations, as well as at the beginning of each debate session)?
      -
    • 0-20% = 1
    • -
    • 20-40% = 2
    • -
    • 40-60% = 3
    • -
    • 60-80% = 4
    • -
    • 80-100% = 5
    • -
    -
  10. -
- -

Relevance

- -

Impact relevance, as the percentage of the organisation's budget, of the organisation's workforce, or of the total population, that will be affected by the process' result, and the time of such impact.

- -
    -
  1. Percentage of organisation's budget, workforce or of the total population affected by the process' result. -
      -
    • 0-20% = 1
    • -
    • 20-40% = 2
    • -
    • 40-60% = 3
    • -
    • 60-80% = 4
    • -
    • 80-100% = 5
    • +
    • Never = 0
    • +
    • Almost never = 1
    • +
    • Usually = 2,5
    • +
    • Always = 5
@@ -775,26 +743,13 @@ en:

Citizens influence

    -
  1. Level of influence of the process according to the participation mechanisms enabled, according to the ladder of participation defined by Sherry Arnstein (1969). +
  2. Assessment of the degree of participation in the process
      -
    • Informative = 0 -

      One-way flow of information—from officials to citizens—with no channel provided for feedback and no power for negotiation.

      -
    • -
    • Consultation = 1 -

      A participatory process where citizens are asked for their opinions, typically through surveys or meetings, but without assurance that their input will influence decisions.

      -
    • -
    • Placation = 2 -

      A participatory process where citizens are given limited influence, often in a tokenistic manner, such as inclusion in boards or committees, but without real power, as decision-making remains controlled by the traditional power elite.

      -
    • -
    • Partnership = 3 -

      A participatory process where citizens and organizations share decision-making power, allowing participants to negotiate, allocate resources, and influence planning, with rules that cannot be changed unilaterally. It often emerges from citizen mobilization and collective action.

      -
    • -
    • Delegated power = 4 -

      A participatory process where citizens gain authority, control, or funding to influence and manage an organization.

      -
    • -
    • Citizen control = 5 -

      A highest level of participation where citizens fully govern a program or institution, managing policies, resources, and decision-making without external interference.

      -
    • +
    • Participants received information from the organisation. = 1
    • +
    • Participants were asked in a consultative manner or gave feedback to the organisation. = 2
    • +
    • Participants were involved to share decision-making power. = 3
    • +
    • Participants were involved decisively in the decision-making. = 4
    • +
    • Participants were involved in the decision-making and the management of resources or the implementation. = 5
  3. Percentage of phases with 0-5 citizen decisional intervention. @@ -809,9 +764,17 @@ en:
-

Accessibility

+

Inclusiveness

    +
  1. How is the degree of diversity of the agents and participants assessed with respect to the population of reference in the process? +
      +
    • None = 0
    • +
    • Low = 1
    • +
    • Sufficient = 2,5
    • +
    • Good = 5
    • +
    +
  2. In how many languages has the process been communicated?
    • One language = 1
    • @@ -826,6 +789,20 @@ en:
    • Yes = 5
  3. +
  4. The participation sessions have been scheduled at varied times (morning, midday, afternoon, evening, and weekends). +
      +
    • No = 0
    • +
    • Partially = 2,5
    • +
    • Yes = 5
    • +
    +
  5. +
  6. Has digital support been offered to the participants? +
      +
    • No = 0
    • +
    • Partially = 2,5
    • +
    • Yes = 5
    • +
    +
title: Democratic quality indicators statistics: From d60d4105d60296754723f368fee45cf70e90fb1d Mon Sep 17 00:00:00 2001 From: Alexandru Emil Lupu Date: Tue, 9 Sep 2025 09:40:13 +0300 Subject: [PATCH 11/12] Fix proposal pipeline (#15154) --- .../spec/system/admin/admin_edits_proposal_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decidim-proposals/spec/system/admin/admin_edits_proposal_spec.rb b/decidim-proposals/spec/system/admin/admin_edits_proposal_spec.rb index fd0f398c544aa..5418552ded89a 100644 --- a/decidim-proposals/spec/system/admin/admin_edits_proposal_spec.rb +++ b/decidim-proposals/spec/system/admin/admin_edits_proposal_spec.rb @@ -59,7 +59,7 @@ visit_component_admin within "tr[data-id='#{proposal.id}']" do - find("button[data-component='dropdown']").click + find("button[data-controller='dropdown']").click click_on "Edit proposal" end From c523c61f678d4153c3ef6ce4537bddbba2692b1c Mon Sep 17 00:00:00 2001 From: Alexandru Emil Lupu Date: Tue, 9 Sep 2025 10:42:11 +0300 Subject: [PATCH 12/12] Fix `resource_hidden?` within decidim-ai (#15108) * Fix resource_hidden? within decidim-ai * Add specs * Fix specs * Make tests more readable --- .../ai/spam_detection/resource/base.rb | 2 +- .../spam_detection/importer/database_spec.rb | 71 ++++++++++++------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/decidim-ai/lib/decidim/ai/spam_detection/resource/base.rb b/decidim-ai/lib/decidim/ai/spam_detection/resource/base.rb index f2fee86815d85..3482f158bb86b 100644 --- a/decidim-ai/lib/decidim/ai/spam_detection/resource/base.rb +++ b/decidim-ai/lib/decidim/ai/spam_detection/resource/base.rb @@ -40,7 +40,7 @@ def error_message(klass, method_name) end def resource_hidden?(resource) - resource.class.included_modules.include?(Decidim::Reportable) && resource.hidden? && report_reasons.exclude?(resource.reports&.last&.reason) + resource.class.included_modules.include?(Decidim::Reportable) && resource.hidden? && report_reasons.include?(resource.reports&.last&.reason) end def report_reasons diff --git a/decidim-ai/spec/lib/decidim/ai/spam_detection/importer/database_spec.rb b/decidim-ai/spec/lib/decidim/ai/spam_detection/importer/database_spec.rb index 667abd5db0afa..0cb1ddaf4fd1a 100644 --- a/decidim-ai/spec/lib/decidim/ai/spam_detection/importer/database_spec.rb +++ b/decidim-ai/spec/lib/decidim/ai/spam_detection/importer/database_spec.rb @@ -11,6 +11,30 @@ Decidim::Ai::SpamDetection.resource_models = resources end + shared_examples "some resources are being spam" do + before do + Decidim::Ai::SpamDetection.resource_models = resource_models + allow(Decidim::Ai::SpamDetection).to receive(:resource_classifier).and_return(instance) + end + + let(:reporting_user) { author } + let(:spam_count) { 2 } + let!(:parent) { create(:report, reason: "parent_hidden", user: reporting_user, moderation: create(:moderation, :hidden, reportable: resources.last)) } + Decidim::Report::REASONS.excluding("parent_hidden").each do |reason| + let!(:report) { create(:report, reason:, user: reporting_user, moderation: create(:moderation, :hidden, reportable:)) } + + it "successfully loads the dataset when there are resources marked as #{reason}" do + allow(instance).to receive(:train) + + described_class.call + + expect(instance).to have_received(:train).with(:ham, anything).at_least(training - spam_count) + expect(instance).to have_received(:train).with(:spam, anything).at_least(spam_count) + expect(instance).to have_received(:train).with(:spam, "Hidden resource").at_least(1) + end + end + end + shared_examples "resource is being indexed" do let(:organization) { create(:organization) } let!(:author) { create(:user, organization:) } @@ -56,67 +80,64 @@ let(:manifest_name) { "meetings" } let(:training) { 20 } - let!(:meetings) do - create_list(:meeting, 4, component:, author:, - title: { en: "Some proposal that is not blocked" }, - description: { en: "The body for the meeting." }) - end + let!(:reportable) { create(:meeting, component:, author:, title: { en: "Hidden resource" }) } + let!(:resources) { create_list(:meeting, 3, component:, author:) } + let(:resource_models) { { "Decidim::Meetings::Meeting" => "Decidim::Ai::SpamDetection::Resource::Meeting" } } include_examples "resource is being indexed" + include_examples "some resources are being spam" do + let(:spam_count) { 5 } + end end context "when trained model is Decidim::Proposals::Proposal" do let(:manifest_name) { "proposals" } let(:training) { 8 } - let!(:proposals) do - create_list(:proposal, 4, - :published, - component:, - users: [author], - title: "Some proposal that is not blocked", - body: "The body for the proposal.") - end + let!(:reportable) { create(:proposal, :published, component:, users: [author], title: { en: "Hidden resource" }) } + let!(:resources) { create_list(:proposal, 3, :published, component:, users: [author]) } let(:resource_models) { { "Decidim::Proposals::Proposal" => "Decidim::Ai::SpamDetection::Resource::Proposal" } } include_examples "resource is being indexed" + include_examples "some resources are being spam" end context "when trained model is Decidim::Proposals::CollaborativeDraft" do let(:manifest_name) { "proposals" } let(:training) { 8 } - let!(:collaborative_drafts) do - create_list(:collaborative_draft, 4, - component:, - users: [author], - title: "Some draft that is not blocked", - body: "The body for the proposal.") - end + let!(:reportable) { create(:collaborative_draft, component:, users: [author], title: "Hidden resource") } + let!(:resources) { create_list(:collaborative_draft, 3, component:, users: [author]) } let(:resource_models) { { "Decidim::Proposals::CollaborativeDraft" => "Decidim::Ai::SpamDetection::Resource::CollaborativeDraft" } } include_examples "resource is being indexed" + include_examples "some resources are being spam" end context "when trained model is Decidim::Debates::Debate" do let(:manifest_name) { "debates" } let(:training) { 8 } - let!(:debates) do - create_list(:debate, 4, + let!(:reportable) do + create(:debate, + author:, component:, + title: { en: "Hidden resource" }) + end + let!(:resources) do + create_list(:debate, 3, author:, component:, - title: { en: "Some proposal that is not blocked" }, - description: { en: "The body for the meeting." }) + title: { en: "Some proposal that is not blocked" }) end let(:resource_models) { { "Decidim::Debates::Debate" => "Decidim::Ai::SpamDetection::Resource::Debate" } } include_examples "resource is being indexed" + include_examples "some resources are being spam" end context "when trained model is Decidim::User" do let(:tested) { 3 } - let(:training) { tested + 1 } # tested + author in shared example + let(:training) { 4 } # tested + author in shared example let!(:user) { create_list(:user, tested, organization:, about: "Something about me") } let(:resource_models) { { "Decidim::User" => "Decidim::Ai::SpamDetection::Resource::UserBaseEntity" } }