Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfixing #5376

Merged
merged 12 commits into from Sep 30, 2019
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -69,6 +69,7 @@
- **decidim-core**: Fix rendering when custom colors exist [#5347](https://github.com/decidim/decidim/pull/5347)
- **decidim-core**: Fix component generator [#5348](https://github.com/decidim/decidim/pull/5348)
- **decidim-core**: Fix email notifications [#5370](https://github.com/decidim/decidim/pull/5370)
- **decidim-assemblies**, **decidim-core**, **decidim-generators**, **decidim-initiatives**, **decidim-meetings**, **decidim-system** [\#5329](https://github.com/decidim/decidim/pull/5329)

**Removed**:

Expand Down
2 changes: 1 addition & 1 deletion decidim-assemblies/app/models/decidim/assembly.rb
Expand Up @@ -85,7 +85,7 @@ def self.visible_for(user)

# Overwriting existing method Decidim::HasPrivateUsers.public_spaces
def self.public_spaces
where(private_space: false).or(where(private_space: true).where(is_transparent: true))
where(private_space: false).or(where(private_space: true).where(is_transparent: true)).published
end

# Scope to return only the promoted assemblies.
Expand Down
2 changes: 1 addition & 1 deletion decidim-assemblies/config/locales/en.yml
Expand Up @@ -264,7 +264,7 @@ en:
others: Others
public: Public
filter:
all: All types of assemblies
all: All types
commission: Commission
consultative_advisory: Consultative/Advisory
executive: Executive
Expand Down
4 changes: 2 additions & 2 deletions decidim-assemblies/spec/system/filter_assemblies_spec.rb
Expand Up @@ -20,11 +20,11 @@

before do
visit decidim_assemblies.assemblies_path
click_button "All types of assemblies"
click_button "All types"
end

it "filters by All types" do
click_link "All types of assemblies"
click_link "All types"
expect(page).to have_selector("article.card.card--assembly", count: 7)
end

Expand Down
Expand Up @@ -6,21 +6,18 @@ module Budgets
class ProjectsController < Decidim::Budgets::ApplicationController
include FilterResource
include NeedsCurrentOrder
include Orderable

helper_method :projects, :random_seed, :project
helper_method :projects, :project

private

def projects
@projects ||= search.results.page(params[:page]).per(current_component.settings.projects_per_page)
end

def random_seed
@random_seed ||= search.random_seed
@projects ||= search.results.order_randomly(random_seed).page(params[:page]).per(current_component.settings.projects_per_page)
end

def project
@project ||= projects.find(params[:id])
@project ||= search.results.find(params[:id])
end

def search_klass
Expand All @@ -31,8 +28,7 @@ def default_filter_params
{
search_text: "",
scope_id: "",
category_id: "",
random_seed: params[:random_seed]
category_id: ""
}
end

Expand Down
1 change: 1 addition & 0 deletions decidim-budgets/app/models/decidim/budgets/project.rb
Expand Up @@ -16,6 +16,7 @@ class Project < Budgets::ApplicationRecord
include Decidim::Comments::Commentable
include Decidim::Traceable
include Decidim::Loggable
include Decidim::Randomable

component_manifest_name "budgets"
has_many :line_items, class_name: "Decidim::Budgets::LineItem", foreign_key: "decidim_project_id", dependent: :destroy
Expand Down
12 changes: 1 addition & 11 deletions decidim-budgets/app/services/decidim/budgets/project_search.rb
Expand Up @@ -10,7 +10,6 @@ class ProjectSearch < ResourceSearch
# component - A Decidim::Component to get the projects from.
def initialize(options = {})
super(Project.all, options)
@random_seed = options[:random_seed].to_f
end

# Handle the search_text filter
Expand All @@ -22,16 +21,7 @@ def search_search_text

# Returns the random projects for the current page.
def results
@results ||= Project.transaction do
Project.connection.execute("SELECT setseed(#{Project.connection.quote(random_seed)})")
super.reorder(Arel.sql("RANDOM()")).load
end
end

# Returns the random seed used to randomize the proposals.
def random_seed
@random_seed = (rand * 2 - 1) if @random_seed == 0.0 || @random_seed > 1 || @random_seed < -1
@random_seed
Project.where(id: super.pluck(:id))
end

private
Expand Down
Expand Up @@ -19,6 +19,4 @@
<% if current_component.categories.any? %>
<%= form.categories_select :category_id, current_component.categories, legend_title: t(".category"), disable_parents: false, label: false, prompt: t(".category_prompt") %>
<% end %>

<%= form.hidden_field :random_seed %>
<% end %>
Expand Up @@ -3,4 +3,4 @@
<%= render partial: "project", locals: { project: project } %>
<% end %>
</div>
<%= decidim_paginate projects, random_seed: random_seed %>
<%= decidim_paginate projects %>
Expand Up @@ -9,29 +9,15 @@ module Orderable
extend ActiveSupport::Concern

included do
helper_method :order, :available_orders, :random_seed
include Decidim::Orderable

private

# Gets how the proposals should be ordered based on the choice
# made by the user.
def order
@order ||= detect_order(params[:order]) || default_order
end

def detect_order(candidate)
available_orders.detect { |order| order == candidate }
end

# Available orders based on enabled settings
def available_orders
%w(random recent)
end

def default_order
"random"
end

def reorder(consultations)
case order
when "recent"
Expand All @@ -40,12 +26,6 @@ def reorder(consultations)
consultations.order_randomly(random_seed)
end
end

# Returns: A random float number between -1 and 1 to be used as a
# random seed at the database.
def random_seed
@random_seed ||= (params[:random_seed] ? params[:random_seed].to_f : (rand * 2 - 1))
end
end
end
end
Expand Down
Expand Up @@ -10,7 +10,7 @@ class ConsultationsController < Decidim::Consultations::ApplicationController
include NeedsConsultation
include FilterResource
include Paginable
include Orderable
include Decidim::Consultations::Orderable
include ParticipatorySpaceContext

helper_method :collection, :consultations, :finished_consultations, :active_consultations, :filter
Expand Down
Expand Up @@ -13,4 +13,4 @@
<%= card_for consultation %>
<% end %>
</div>
<%= decidim_paginate consultations, random_seed: random_seed %>
<%= decidim_paginate consultations %>
3 changes: 1 addition & 2 deletions decidim-core/app/cells/decidim/activities_cell.rb
Expand Up @@ -28,8 +28,7 @@ def activity_cell_for(activity)

def activities
@activities ||= last_activities.select do |activity|
!activity.resource_lazy.respond_to?(:can_participate?) ||
activity.resource_lazy.can_participate?(current_user)
activity.visible_for?(current_user)
end
end

Expand Down
Expand Up @@ -33,7 +33,7 @@ def valid_activities
activities.each do |activity|
break if valid_activities_count == activities_to_show

if activity.resource_lazy.present? && activity.participatory_space_lazy.present? && visible_for_user?(activity)
if activity.visible_for?(current_user)
@valid_activities << activity
valid_activities_count += 1
end
Expand All @@ -44,12 +44,6 @@ def valid_activities

private

def visible_for_user?(activity)
return true unless activity.resource_lazy.respond_to?(:can_participate?)

activity.resource_lazy.can_participate?(current_user)
end

def activities
@activities ||= HomeActivitySearch.new(
organization: current_organization,
Expand Down
36 changes: 36 additions & 0 deletions decidim-core/app/controllers/concerns/decidim/orderable.rb
@@ -0,0 +1,36 @@
# frozen_string_literal: true

require "active_support/concern"

module Decidim
# Common logic to ordering resources
module Orderable
extend ActiveSupport::Concern

included do
helper_method :order, :available_orders, :random_seed

private

# Gets how the proposals should be ordered based on the choice
# made by the user.
def order
@order ||= detect_order(params[:order]) || default_order
end

def detect_order(candidate)
available_orders.detect { |order| order == candidate }
end

def default_order
"random"
end

# Returns: A random float number between -1 and 1 to be used as a
# random seed at the database.
def random_seed
@random_seed ||= session.fetch(:random_seed, (rand * 2 - 1)).to_f
end
end
end
end
12 changes: 12 additions & 0 deletions decidim-core/app/models/decidim/action_log.rb
Expand Up @@ -128,5 +128,17 @@ def self.lazy_relation(id_method, klass_name, cache)
scope.each { |relation| loader.call(relation.id, relation) }
end
end

# Whether this activity or log is visible for a given user (can also be nil)
#
# Returns a True/False.
def visible_for?(user)
return false if resource_lazy.blank?
return false if participatory_space_lazy.blank?
return false if resource_lazy.respond_to?(:hidden?) && resource_lazy.hidden?
return false if resource_lazy.respond_to?(:can_participate?) && !resource_lazy.can_participate?(user)

true
end
end
end
4 changes: 2 additions & 2 deletions decidim-core/config/locales/en.yml
Expand Up @@ -365,7 +365,7 @@ en:
email_already_exists: Another account is using the same email address
new:
complete_profile: Complete profile
nickname_help: Your alias (@nickname) in %{organization}
nickname_help: Your alias in %{organization}
sign_up: Please complete your profile
subtitle: Please fill in the following form in order to complete the sign up
username_help: Public name that appears on your posts. With the aim of guaranteeing the anonymity, can be any name.
Expand All @@ -374,7 +374,7 @@ en:
already_have_an_account?: Already have an account?
newsletter: Receive an occasional newsletter with relevant information
newsletter_title: Contact permission
nickname_help: Your alias (@nickname) in %{organization}
nickname_help: Your alias in %{organization}
password_help: "%{minimun_characters} characters minimum, must not be too common (e.g. 123456) and must be different from your nickname and your email."
sign_in: Log in
sign_up: Sign up
Expand Down
8 changes: 8 additions & 0 deletions decidim-core/lib/decidim/followable.rb
Expand Up @@ -9,5 +9,13 @@ module Followable
has_many :follows, as: :followable, foreign_key: "decidim_followable_id", foreign_type: "decidim_followable_type", class_name: "Decidim::Follow"
has_many :followers, through: :follows, source: :user
end

def followers
if respond_to?(:participatory_space) && participatory_space.present? && participatory_space.respond_to?(:followers)
super.or(participatory_space.followers).distinct
else
super
end
end
end
end
2 changes: 1 addition & 1 deletion decidim-core/lib/decidim/has_private_users.rb
Expand Up @@ -38,7 +38,7 @@ def can_participate?(user)
end

def self.public_spaces
where(private_space: false)
where(private_space: false).published
end

def self.private_spaces
Expand Down
Expand Up @@ -53,6 +53,14 @@ def resource_types
it { is_expected.not_to include(action_log) }
end

context "when the resource has been hidden" do
before do
create(:moderation, :hidden, reportable: action_log.resource)
end

it { is_expected.not_to include(action_log) }
end

context "with a lot of activities" do
before do
5.times do
Expand Down
46 changes: 46 additions & 0 deletions decidim-core/spec/lib/followable_spec.rb
@@ -0,0 +1,46 @@
# frozen_string_literal: true

require "spec_helper"

module Decidim
describe Followable do
subject { resource }

let(:resource) { create(:dummy_resource) }

describe "followers" do
let!(:follow) { create(:follow, followable: resource) }

it "returns the users following the resource" do
expect(subject.followers).to include(follow.user)
end

context "when the resource doesn't have a participatory space" do
let(:resource) { create(:user) }

it "returns their followers" do
expect(subject.followers).to include(follow.user)
end
end

context "when the participatory space has also followers" do
let!(:space_follow) { create(:follow, followable: resource.participatory_space) }

it "includes them too" do
expect(subject.followers.count).to eq(2)
expect(subject.followers).to include(follow.user)
expect(subject.followers).to include(space_follow.user)
end

context "when the user follows the space and resource" do
let!(:space_follow) { create(:follow, followable: resource.participatory_space, user: follow.user) }

it "is included only once" do
expect(subject.followers.count).to eq(1)
expect(subject.followers).to include(follow.user)
end
end
end
end
end
end