Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion decidim-ai/lib/decidim/ai/spam_detection/resource/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:) }
Expand Down Expand Up @@ -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" } }
Expand Down
2 changes: 1 addition & 1 deletion decidim-core/app/helpers/decidim/menu_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion decidim-core/app/presenters/decidim/menu_item_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions decidim-core/spec/system/download_your_data_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
105 changes: 41 additions & 64 deletions decidim-participatory_processes/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -719,82 +719,37 @@ en:

<p>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.</p>

<h4>Inclusiveness</h4>

<p>Inclusivity according to cultural origin and functional diversity.</p>
<h4>Informativeness</h4>

<ol>
<li>Have migrant groups been invited to participate?
<ul>
<li>Yes = 5</li>
<li>No = 0</li>
</ul>
</li>
<li>How many people from diverse cultural origins have participated out of the invited?
<ul>
<li>0-20% = 1</li>
<li>20-40% = 2</li>
<li>40-60% = 3</li>
<li>60-80% = 4</li>
<li>80-100% = 5</li>
</ul>
</li>
<li>Have groups of people with functional diversity been invited to participate?
<li>Does the published information provide clarity on the decision-making mechanisms (e.g., voting, consensus, direct negotiations)?
<ul>
<li>Yes = 5</li>
<li>No = 0</li>
<li>No clarity = 0</li>
<li>Low clarity = 1</li>
<li>Sufficient clarity = 2,5</li>
<li>Full clarity = 5</li>
</ul>
</li>
<li>How many people with functional diversity have participated out of the invited?
<li>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)?
<ul>
<li>0-20% = 1</li>
<li>20-40% = 2</li>
<li>40-60% = 3</li>
<li>60-80% = 4</li>
<li>80-100% = 5</li>
</ul>
</li>
</ol>

<h4>Relevance</h4>

<p>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.</p>

<ol>
<li>Percentage of organisation's budget, workforce or of the total population affected by the process' result.
<ul>
<li>0-20% = 1</li>
<li>20-40% = 2</li>
<li>40-60% = 3</li>
<li>60-80% = 4</li>
<li>80-100% = 5</li>
<li>Never = 0</li>
<li>Almost never = 1</li>
<li>Usually = 2,5</li>
<li>Always = 5</li>
</ul>
</li>
</ol>

<h4>Citizens influence</h4>

<ol>
<li>Level of influence of the process according to the participation mechanisms enabled, according to the ladder of participation defined by Sherry Arnstein (1969).
<li>Assessment of the degree of participation in the process
<ul>
<li>Informative = 0
<p>One-way flow of information—from officials to citizens—with no channel provided for feedback and no power for negotiation.</p>
</li>
<li>Consultation = 1
<p>A participatory process where citizens are asked for their opinions, typically through surveys or meetings, but without assurance that their input will influence decisions.</p>
</li>
<li>Placation = 2
<p>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.</p>
</li>
<li>Partnership = 3
<p>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.</p>
</li>
<li>Delegated power = 4
<p>A participatory process where citizens gain authority, control, or funding to influence and manage an organization.</p>
</li>
<li>Citizen control = 5
<p>A highest level of participation where citizens fully govern a program or institution, managing policies, resources, and decision-making without external interference.</p>
</li>
<li>Participants received information from the organisation. = 1</li>
<li>Participants were asked in a consultative manner or gave feedback to the organisation. = 2</li>
<li>Participants were involved to share decision-making power. = 3</li>
<li>Participants were involved decisively in the decision-making. = 4</li>
<li>Participants were involved in the decision-making and the management of resources or the implementation. = 5</li>
</ul>
</li>
<li>Percentage of phases with 0-5 citizen decisional intervention.
Expand All @@ -809,9 +764,17 @@ en:
</li>
</ol>

<h4>Accessibility</h4>
<h4>Inclusiveness</h4>

<ol>
<li>How is the degree of diversity of the agents and participants assessed with respect to the population of reference in the process?
<ul>
<li>None = 0</li>
<li>Low = 1</li>
<li>Sufficient = 2,5</li>
<li>Good = 5</li>
</ul>
</li>
<li>In how many languages has the process been communicated?
<ul>
<li>One language = 1</li>
Expand All @@ -826,6 +789,20 @@ en:
<li>Yes = 5</li>
</ul>
</li>
<li>The participation sessions have been scheduled at varied times (morning, midday, afternoon, evening, and weekends).
<ul>
<li>No = 0</li>
<li>Partially = 2,5</li>
<li>Yes = 5</li>
</ul>
</li>
<li>Has digital support been offered to the participants?
<ul>
<li>No = 0</li>
<li>Partially = 2,5</li>
<li>Yes = 5</li>
</ul>
</li>
</ol>
title: Democratic quality indicators
statistics:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading