Merge pull request #1833 from rockandror/improve-community
Improve community
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
App.EmbedVideo =
|
||||
|
||||
|
||||
initialize: ->
|
||||
$('#js-embedded-video').each ->
|
||||
code = $(this).data("video-code")
|
||||
code = $(this).data("video-code")
|
||||
$('#js-embedded-video').html(code)
|
||||
|
||||
@@ -48,7 +48,7 @@ class Admin::BudgetInvestmentMilestonesController < Admin::BaseController
|
||||
end
|
||||
|
||||
def load_budget_investment_milestone
|
||||
@milestone = Budget::Investment::Milestone.find params[:id]
|
||||
@milestone = Budget::Investment::Milestone.find params[:id]
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
class CommunitiesController < ApplicationController
|
||||
TOPIC_ORDERS = %w{newest most_commented oldest}.freeze
|
||||
before_action :set_order, :set_community, :load_topics, :load_participants
|
||||
|
||||
before_action :set_order, :set_community, :load_topics, :load_participants, only: :show
|
||||
|
||||
has_orders %w{newest most_commented oldest}, only: :show
|
||||
has_orders TOPIC_ORDERS
|
||||
|
||||
skip_authorization_check
|
||||
|
||||
@@ -13,7 +13,7 @@ class CommunitiesController < ApplicationController
|
||||
private
|
||||
|
||||
def set_order
|
||||
@order = params[:order].present? ? params[:order] : "newest"
|
||||
@order = valid_order? ? params[:order] : "newest"
|
||||
end
|
||||
|
||||
def set_community
|
||||
@@ -27,4 +27,8 @@ class CommunitiesController < ApplicationController
|
||||
def load_participants
|
||||
@participants = @community.participants
|
||||
end
|
||||
|
||||
def valid_order?
|
||||
params[:order].present? && TOPIC_ORDERS.include?(params[:order])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ class Management::SessionsController < ActionController::Base
|
||||
|
||||
def destroy_session
|
||||
session[:manager] = nil
|
||||
session[:document_type] = nil
|
||||
session[:document_type] = nil
|
||||
session[:document_number] = nil
|
||||
end
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
class TopicsController < ApplicationController
|
||||
include CommentableActions
|
||||
include FlagActions
|
||||
|
||||
before_action :load_community
|
||||
before_action :load_topic, only: [:show, :edit, :update]
|
||||
before_action :load_topic, only: [:show, :edit, :update, :destroy]
|
||||
|
||||
has_orders %w{most_voted newest oldest}, only: :show
|
||||
|
||||
skip_authorization_check
|
||||
skip_authorization_check only: :show
|
||||
load_and_authorize_resource except: :show
|
||||
|
||||
def new
|
||||
@topic = Topic.new
|
||||
@@ -39,6 +39,11 @@ class TopicsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@topic.destroy
|
||||
redirect_to community_path(@community), notice: I18n.t('flash.actions.destroy.topic')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def topic_params
|
||||
|
||||
@@ -42,7 +42,7 @@ module CommentsHelper
|
||||
|
||||
def commentable_path(comment)
|
||||
commentable = comment.commentable
|
||||
|
||||
|
||||
case comment.commentable_type
|
||||
when "Budget::Investment"
|
||||
budget_investment_path(commentable.budget_id, commentable)
|
||||
@@ -51,7 +51,7 @@ module CommentsHelper
|
||||
when "Legislation::Annotation"
|
||||
legislation_process_draft_version_annotation_path(commentable.draft_version.process, commentable.draft_version, commentable)
|
||||
when "Topic"
|
||||
community_topic_path(comment.commentable.community, comment.commentable)
|
||||
community_topic_path(commentable.community, commentable)
|
||||
else
|
||||
commentable
|
||||
end
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
module CommunitiesHelper
|
||||
|
||||
def community_title(community)
|
||||
if community.from_proposal?
|
||||
community.proposal.title
|
||||
else
|
||||
investment = Budget::Investment.where(community_id: community.id).first
|
||||
investment.title
|
||||
end
|
||||
community.from_proposal? ? community.proposal.title : community.investment.title
|
||||
end
|
||||
|
||||
def community_text(community)
|
||||
@@ -21,8 +16,7 @@ module CommunitiesHelper
|
||||
if community.from_proposal?
|
||||
community.proposal.author_id == participant.id
|
||||
else
|
||||
investment = Budget::Investment.where(community_id: community.id).first
|
||||
investment.author_id == participant.id
|
||||
community.investment.author_id == participant.id
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,8 +24,7 @@ module CommunitiesHelper
|
||||
if community.from_proposal?
|
||||
proposal_path(community.proposal)
|
||||
else
|
||||
investment = Budget::Investment.where(community_id: community.id).first
|
||||
budget_investment_path(investment.budget_id, investment)
|
||||
budget_investment_path(community.investment.budget_id, community.investment)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -71,6 +71,9 @@ module Abilities
|
||||
|
||||
can :create, Annotation
|
||||
can [:update, :destroy], Annotation, user_id: user.id
|
||||
|
||||
can [:create], Topic
|
||||
can [:update, :destroy], Topic, author_id: user.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
class Community < ActiveRecord::Base
|
||||
has_one :proposal
|
||||
has_one :investment
|
||||
has_one :investment, class_name: Budget::Investment
|
||||
has_many :topics
|
||||
|
||||
def participants
|
||||
users_participants = users_who_commented_by +
|
||||
users_who_topics_author_by +
|
||||
users_participants = users_who_commented +
|
||||
users_who_topics_author +
|
||||
author_from_community
|
||||
users_participants.uniq
|
||||
end
|
||||
@@ -16,24 +16,19 @@ class Community < ActiveRecord::Base
|
||||
|
||||
private
|
||||
|
||||
def users_who_commented_by
|
||||
def users_who_commented
|
||||
topics_ids = topics.pluck(:id)
|
||||
query = "comments.commentable_id IN (?)and comments.commentable_type = 'Topic'"
|
||||
User.by_comments(query, topics_ids)
|
||||
end
|
||||
|
||||
def users_who_topics_author_by
|
||||
def users_who_topics_author
|
||||
author_ids = topics.pluck(:author_id)
|
||||
User.by_authors(author_ids)
|
||||
end
|
||||
|
||||
def author_from_community
|
||||
if from_proposal?
|
||||
User.where(id: proposal.author_id)
|
||||
else
|
||||
investment = Budget::Investment.where(community_id: id).first
|
||||
User.where(id: investment.author_id)
|
||||
end
|
||||
from_proposal? ? User.where(id: proposal.author_id) : User.where(id: investment.author_id)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -7,8 +7,8 @@ module Communitable
|
||||
end
|
||||
|
||||
def associate_community
|
||||
community = Community.create
|
||||
self.community_id = community.id
|
||||
community = Community.create
|
||||
self.community_id = community.id
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
class Topic < ActiveRecord::Base
|
||||
include Flaggable
|
||||
|
||||
acts_as_paranoid column: :hidden_at
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<% if page.status == "published" %>
|
||||
<%= link_to t("admin.site_customization.pages.index.see_page"), page.url, target: "_blank" %>
|
||||
<% else %>
|
||||
<%= t("admin.site_customization.pages.index.see_page") %>
|
||||
<%= t("admin.site_customization.pages.index.see_page") %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="small delete">
|
||||
|
||||
22
app/views/communities/_participant.html.erb
Normal file
22
app/views/communities/_participant.html.erb
Normal file
@@ -0,0 +1,22 @@
|
||||
<div class="comment-body">
|
||||
<div class="comment-info">
|
||||
|
||||
<%= avatar_image( participant, seed: participant.id, size: 32, class: 'author-photo') %>
|
||||
|
||||
<div class="comment-info">
|
||||
|
||||
<span class="user-name">
|
||||
<%= link_to participant.name, user_path(participant)%>
|
||||
</span>
|
||||
|
||||
<% if is_author?(@community, participant) %>
|
||||
•
|
||||
<span class="label round is-author">
|
||||
<%= t("comments.comment.author") %>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -14,28 +14,7 @@
|
||||
</ul>
|
||||
|
||||
<% @participants.each do |participant| %>
|
||||
<div class="comment-body">
|
||||
<div class="comment-info">
|
||||
|
||||
<%= avatar_image( participant, seed: participant.id, size: 32, class: 'author-photo') %>
|
||||
|
||||
<div class="comment-info">
|
||||
|
||||
<span class="user-name">
|
||||
<%= link_to participant.name, user_path(participant)%>
|
||||
</span>
|
||||
|
||||
<% if is_author?(@community, participant) %>
|
||||
•
|
||||
<span class="label round is-author">
|
||||
<%= t("comments.comment.author") %>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<%= render 'participant', participant: participant %>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<% if poll.expired? %>
|
||||
<%= t("polls.index.participate_button_expired") %>
|
||||
<% elsif poll.incoming? %>
|
||||
<%= t("polls.index.participate_button_incoming") %>
|
||||
<%= t("polls.index.participate_button_incoming") %>
|
||||
<% else %>
|
||||
<%= t("polls.index.participate_button") %>
|
||||
<% end %>
|
||||
|
||||
11
app/views/topics/_informative_text.html.erb
Normal file
11
app/views/topics/_informative_text.html.erb
Normal file
@@ -0,0 +1,11 @@
|
||||
<h3><%= t("community.show.create_first_community_topic.first_theme") %></h3>
|
||||
|
||||
<% if user_signed_in? %>
|
||||
<%= t("community.show.create_first_community_topic.first_theme_not_logged_in") %>
|
||||
<% else %>
|
||||
<div class="callout primary">
|
||||
<%= t("community.show.create_first_community_topic.sub_first_theme",
|
||||
link: link_to(t("community.show.create_first_community_topic.sign_link",
|
||||
org_name: setting['org_name']), new_user_session_path)).html_safe %>
|
||||
</div>
|
||||
<% end %>
|
||||
25
app/views/topics/_topic.html.erb
Normal file
25
app/views/topics/_topic.html.erb
Normal file
@@ -0,0 +1,25 @@
|
||||
<div id="<%= dom_id(topic) %>" class="panel column">
|
||||
|
||||
<div class="small-8 column">
|
||||
|
||||
<h3><%= link_to topic.title, community_topic_path(@community, topic) %></h3>
|
||||
|
||||
<p class="topic-info">
|
||||
<span class="icon-comments"></span>
|
||||
<%= link_to t("community.show.topic.comments", count: topic.comments_count), community_topic_path(@community, topic, anchor: "comments") %>
|
||||
<span class="bullet"> • </span>
|
||||
<%= I18n.l topic.created_at.to_date %>
|
||||
<span class="bullet"> • </span>
|
||||
<%= topic.author.name %>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="small-4 column text-right">
|
||||
<% if topic.author == current_user %>
|
||||
<%= link_to t("community.show.topic.edit_button"), edit_community_topic_path(@community.id, topic), class: 'button small hollow' %>
|
||||
<%= link_to t("community.show.topic.destroy_button"), community_topic_path(@community.id, topic), method: :delete, class: 'button hollow alert small' %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -1,48 +1,13 @@
|
||||
<% if topics.any? %>
|
||||
|
||||
<div class="row column">
|
||||
<div class="order">
|
||||
<%= render 'shared/wide_order_selector', i18n_namespace: "comments" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% topics.each do |topic| %>
|
||||
|
||||
<div id="<%= dom_id(topic) %>" class="panel column">
|
||||
<div class="small-10 column">
|
||||
|
||||
<h3><%= link_to topic.title, community_topic_path(@community, topic) %></h3>
|
||||
|
||||
<p class="topic-info">
|
||||
<span class="icon-comments"></span>
|
||||
<%= link_to t("community.show.topic.comments", count: topic.comments_count), community_topic_path(@community, topic, anchor: "comments") %>
|
||||
<span class="bullet"> • </span>
|
||||
<%= I18n.l topic.created_at.to_date %>
|
||||
<span class="bullet"> • </span>
|
||||
<%= topic.author.name %>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="small-2 column text-right">
|
||||
<% if topic.author == current_user %>
|
||||
<%= link_to t("community.show.topic.edit_button"), edit_community_topic_path(@community.id, topic), class: 'button small hollow' %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<% end %>
|
||||
|
||||
<% else %>
|
||||
<h3><%= t("community.show.create_first_community_topic.first_theme") %></h3>
|
||||
<% if user_signed_in? %>
|
||||
<%= t("community.show.create_first_community_topic.first_theme_not_logged_in") %>
|
||||
<% else %>
|
||||
<div class="callout primary">
|
||||
<%= t("community.show.create_first_community_topic.sub_first_theme",
|
||||
link: link_to(t("community.show.create_first_community_topic.sign_link",
|
||||
org_name: setting['org_name']), new_user_session_path)).html_safe %>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= render 'topics/informative_text', topics: topics %>
|
||||
<% end %>
|
||||
|
||||
<% topics.each do |topic| %>
|
||||
<%= render 'topics/topic', topic: topic %>
|
||||
<% end %>
|
||||
|
||||
@@ -26,6 +26,7 @@ en:
|
||||
disabled_info_title: You need to be logged to create a new topic
|
||||
topic:
|
||||
edit_button: Edit
|
||||
destroy_button: Destroy
|
||||
comments:
|
||||
one: 1 comment
|
||||
other: "%{count} comments"
|
||||
|
||||
@@ -29,3 +29,4 @@ en:
|
||||
spending_proposal: "Spending proposal deleted succesfully."
|
||||
budget_investment: "Investment project deleted succesfully."
|
||||
error: "Could not delete"
|
||||
topic: "Topic deleted successfully."
|
||||
|
||||
@@ -26,6 +26,7 @@ es:
|
||||
disabled_info_title: Necesitas estar logueado para crear un nuevo tema
|
||||
topic:
|
||||
edit_button: Editar
|
||||
destroy_button: Eliminar
|
||||
comments:
|
||||
one: 1 Comentario
|
||||
other: "%{count} Comentarios"
|
||||
|
||||
@@ -29,3 +29,4 @@ es:
|
||||
spending_proposal: "Propuesta de inversión eliminada."
|
||||
budget_investment: "Propuesta de inversión eliminada."
|
||||
error: "No se pudo borrar"
|
||||
topic: "Tema eliminado."
|
||||
|
||||
@@ -39,10 +39,10 @@ Setting["months_to_archive_proposals"] = 12
|
||||
Setting["email_domain_for_officials"] = ''
|
||||
|
||||
# Code to be included at the top (inside <head>) of every page (useful for tracking)
|
||||
Setting['per_page_code_head'] = ''
|
||||
Setting['per_page_code_head'] = ''
|
||||
|
||||
# Code to be included at the top (inside <body>) of every page
|
||||
Setting['per_page_code_body'] = ''
|
||||
Setting['per_page_code_body'] = ''
|
||||
|
||||
# Social settings
|
||||
Setting["twitter_handle"] = nil
|
||||
@@ -79,7 +79,7 @@ Setting['feature.public_stats'] = true
|
||||
Setting['feature.budgets'] = true
|
||||
Setting['feature.signature_sheets'] = true
|
||||
Setting['feature.legislation'] = true
|
||||
Setting['feature.community'] = nil
|
||||
Setting['feature.community'] = true
|
||||
|
||||
# Spending proposals feature flags
|
||||
Setting['feature.spending_proposal_features.voting_allowed'] = nil
|
||||
|
||||
@@ -5,14 +5,14 @@ namespace :communities do
|
||||
|
||||
Proposal.all.each do |proposal|
|
||||
if proposal.community.blank?
|
||||
community = Community.create
|
||||
community = Community.create
|
||||
proposal.update(community_id: community.id)
|
||||
end
|
||||
end
|
||||
|
||||
Budget::Investment.all.each do |investment|
|
||||
if investment.community.blank?
|
||||
community = Community.create
|
||||
community = Community.create
|
||||
investment.update(community_id: community.id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -340,6 +340,8 @@ feature 'Budget Investments' do
|
||||
end
|
||||
|
||||
scenario 'Can not access the community' do
|
||||
Setting['feature.community'] = false
|
||||
|
||||
investment = create(:budget_investment, heading: heading)
|
||||
visit budget_investment_path(budget_id: budget.id, id: investment.id)
|
||||
expect(page).not_to have_content "Access the community"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require 'rails_helper'
|
||||
include ActionView::Helpers::DateHelper
|
||||
|
||||
feature 'Commenting topics' do
|
||||
feature 'Commenting topics from proposals' do
|
||||
let(:user) { create :user }
|
||||
let(:proposal) { create :proposal }
|
||||
|
||||
@@ -319,7 +319,7 @@ feature 'Commenting topics' do
|
||||
page.find("#flag-expand-comment-#{comment.id}").click
|
||||
expect(page).to have_selector("#flag-comment-#{comment.id}")
|
||||
end
|
||||
|
||||
|
||||
Setting['feature.community'] = nil
|
||||
end
|
||||
|
||||
@@ -550,3 +550,553 @@ feature 'Commenting topics' do
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
feature 'Commenting topics from budget investments' do
|
||||
let(:user) { create :user }
|
||||
let(:investment) { create :budget_investment }
|
||||
|
||||
scenario 'Index', :js do
|
||||
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
3.times { create(:comment, commentable: topic) }
|
||||
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
expect(page).to have_css('.comment', count: 3)
|
||||
|
||||
comment = Comment.last
|
||||
within first('.comment') do
|
||||
expect(page).to have_content comment.user.name
|
||||
expect(page).to have_content I18n.l(comment.created_at, format: :datetime)
|
||||
expect(page).to have_content comment.body
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Show', :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
parent_comment = create(:comment, commentable: topic)
|
||||
first_child = create(:comment, commentable: topic, parent: parent_comment)
|
||||
second_child = create(:comment, commentable: topic, parent: parent_comment)
|
||||
|
||||
visit comment_path(parent_comment)
|
||||
|
||||
expect(page).to have_css(".comment", count: 3)
|
||||
expect(page).to have_content parent_comment.body
|
||||
expect(page).to have_content first_child.body
|
||||
expect(page).to have_content second_child.body
|
||||
|
||||
expect(page).to have_link "Go back to #{topic.title}", href: community_topic_path(community, topic)
|
||||
end
|
||||
|
||||
scenario 'Collapsable comments', :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
parent_comment = create(:comment, body: "Main comment", commentable: topic)
|
||||
child_comment = create(:comment, body: "First subcomment", commentable: topic, parent: parent_comment)
|
||||
grandchild_comment = create(:comment, body: "Last subcomment", commentable: topic, parent: child_comment)
|
||||
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
expect(page).to have_css('.comment', count: 3)
|
||||
|
||||
find("#comment_#{child_comment.id}_children_arrow").trigger('click')
|
||||
|
||||
expect(page).to have_css('.comment', count: 2)
|
||||
expect(page).to_not have_content grandchild_comment.body
|
||||
|
||||
find("#comment_#{child_comment.id}_children_arrow").trigger('click')
|
||||
|
||||
expect(page).to have_css('.comment', count: 3)
|
||||
expect(page).to have_content grandchild_comment.body
|
||||
|
||||
find("#comment_#{parent_comment.id}_children_arrow").trigger('click')
|
||||
|
||||
expect(page).to have_css('.comment', count: 1)
|
||||
expect(page).to_not have_content child_comment.body
|
||||
expect(page).to_not have_content grandchild_comment.body
|
||||
end
|
||||
|
||||
scenario 'Comment order' do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
c1 = create(:comment, :with_confidence_score, commentable: topic, cached_votes_up: 100,
|
||||
cached_votes_total: 120, created_at: Time.current - 2)
|
||||
c2 = create(:comment, :with_confidence_score, commentable: topic, cached_votes_up: 10,
|
||||
cached_votes_total: 12, created_at: Time.current - 1)
|
||||
c3 = create(:comment, :with_confidence_score, commentable: topic, cached_votes_up: 1,
|
||||
cached_votes_total: 2, created_at: Time.current)
|
||||
|
||||
visit community_topic_path(community, topic, order: :most_voted)
|
||||
|
||||
expect(c1.body).to appear_before(c2.body)
|
||||
expect(c2.body).to appear_before(c3.body)
|
||||
|
||||
visit community_topic_path(community, topic, order: :newest)
|
||||
|
||||
expect(c3.body).to appear_before(c2.body)
|
||||
expect(c2.body).to appear_before(c1.body)
|
||||
|
||||
visit community_topic_path(community, topic, order: :oldest)
|
||||
|
||||
expect(c1.body).to appear_before(c2.body)
|
||||
expect(c2.body).to appear_before(c3.body)
|
||||
end
|
||||
|
||||
scenario 'Creation date works differently in roots and in child comments, when sorting by confidence_score' do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
old_root = create(:comment, commentable: topic, created_at: Time.current - 10)
|
||||
new_root = create(:comment, commentable: topic, created_at: Time.current)
|
||||
old_child = create(:comment, commentable: topic, parent_id: new_root.id, created_at: Time.current - 10)
|
||||
new_child = create(:comment, commentable: topic, parent_id: new_root.id, created_at: Time.current)
|
||||
|
||||
visit community_topic_path(community, topic, order: :most_voted)
|
||||
|
||||
expect(new_root.body).to appear_before(old_root.body)
|
||||
expect(old_child.body).to appear_before(new_child.body)
|
||||
|
||||
visit community_topic_path(community, topic, order: :newest)
|
||||
|
||||
expect(new_root.body).to appear_before(old_root.body)
|
||||
expect(new_child.body).to appear_before(old_child.body)
|
||||
|
||||
visit community_topic_path(community, topic, order: :oldest)
|
||||
|
||||
expect(old_root.body).to appear_before(new_root.body)
|
||||
expect(old_child.body).to appear_before(new_child.body)
|
||||
end
|
||||
|
||||
scenario 'Turns links into html links' do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
create :comment, commentable: topic, body: 'Built with http://rubyonrails.org/'
|
||||
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
within first('.comment') do
|
||||
expect(page).to have_content 'Built with http://rubyonrails.org/'
|
||||
expect(page).to have_link('http://rubyonrails.org/', href: 'http://rubyonrails.org/')
|
||||
expect(find_link('http://rubyonrails.org/')[:rel]).to eq('nofollow')
|
||||
expect(find_link('http://rubyonrails.org/')[:target]).to eq('_blank')
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Sanitizes comment body for security' do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
create :comment, commentable: topic,
|
||||
body: "<script>alert('hola')</script> <a href=\"javascript:alert('sorpresa!')\">click me<a/> http://www.url.com"
|
||||
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
within first('.comment') do
|
||||
expect(page).to have_content "click me http://www.url.com"
|
||||
expect(page).to have_link('http://www.url.com', href: 'http://www.url.com')
|
||||
expect(page).not_to have_link('click me')
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Paginated comments' do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
per_page = 10
|
||||
(per_page + 2).times { create(:comment, commentable: topic)}
|
||||
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
expect(page).to have_css('.comment', count: per_page)
|
||||
within("ul.pagination") do
|
||||
expect(page).to have_content("1")
|
||||
expect(page).to have_content("2")
|
||||
expect(page).to_not have_content("3")
|
||||
click_link "Next", exact: false
|
||||
end
|
||||
|
||||
expect(page).to have_css('.comment', count: 2)
|
||||
end
|
||||
|
||||
feature 'Not logged user' do
|
||||
scenario 'can not see comments forms' do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
create(:comment, commentable: topic)
|
||||
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
expect(page).to have_content 'You must Sign in or Sign up to leave a comment'
|
||||
within('#comments') do
|
||||
expect(page).to_not have_content 'Write a comment'
|
||||
expect(page).to_not have_content 'Reply'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Create', :js do
|
||||
login_as(user)
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
fill_in "comment-body-topic_#{topic.id}", with: 'Have you thought about...?'
|
||||
click_button 'Publish comment'
|
||||
|
||||
within "#comments" do
|
||||
expect(page).to have_content 'Have you thought about...?'
|
||||
end
|
||||
|
||||
within "#tab-comments-label" do
|
||||
expect(page).to have_content 'Comments (1)'
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Errors on create', :js do
|
||||
login_as(user)
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
click_button 'Publish comment'
|
||||
|
||||
expect(page).to have_content "Can't be blank"
|
||||
end
|
||||
|
||||
scenario 'Reply', :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
citizen = create(:user, username: 'Ana')
|
||||
manuela = create(:user, username: 'Manuela')
|
||||
comment = create(:comment, commentable: topic, user: citizen)
|
||||
|
||||
login_as(manuela)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
click_link "Reply"
|
||||
|
||||
within "#js-comment-form-comment_#{comment.id}" do
|
||||
fill_in "comment-body-comment_#{comment.id}", with: 'It will be done next week.'
|
||||
click_button 'Publish reply'
|
||||
end
|
||||
|
||||
within "#comment_#{comment.id}" do
|
||||
expect(page).to have_content 'It will be done next week.'
|
||||
end
|
||||
|
||||
expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true)
|
||||
end
|
||||
|
||||
scenario 'Errors on reply', :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
comment = create(:comment, commentable: topic, user: user)
|
||||
|
||||
login_as(user)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
click_link "Reply"
|
||||
|
||||
within "#js-comment-form-comment_#{comment.id}" do
|
||||
click_button 'Publish reply'
|
||||
expect(page).to have_content "Can't be blank"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
scenario "N replies", :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
parent = create(:comment, commentable: topic)
|
||||
|
||||
7.times do
|
||||
create(:comment, commentable: topic, parent: parent)
|
||||
parent = parent.children.first
|
||||
end
|
||||
|
||||
visit community_topic_path(community, topic)
|
||||
expect(page).to have_css(".comment.comment.comment.comment.comment.comment.comment.comment")
|
||||
end
|
||||
|
||||
scenario "Flagging as inappropriate", :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
comment = create(:comment, commentable: topic)
|
||||
|
||||
login_as(user)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
within "#comment_#{comment.id}" do
|
||||
page.find("#flag-expand-comment-#{comment.id}").click
|
||||
page.find("#flag-comment-#{comment.id}").click
|
||||
|
||||
expect(page).to have_css("#unflag-expand-comment-#{comment.id}")
|
||||
end
|
||||
|
||||
expect(Flag.flagged?(user, comment)).to be
|
||||
end
|
||||
|
||||
scenario "Undoing flagging as inappropriate", :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
comment = create(:comment, commentable: topic)
|
||||
Flag.flag(user, comment)
|
||||
|
||||
login_as(user)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
within "#comment_#{comment.id}" do
|
||||
page.find("#unflag-expand-comment-#{comment.id}").click
|
||||
page.find("#unflag-comment-#{comment.id}").click
|
||||
|
||||
expect(page).to have_css("#flag-expand-comment-#{comment.id}")
|
||||
end
|
||||
|
||||
expect(Flag.flagged?(user, comment)).to_not be
|
||||
end
|
||||
|
||||
scenario "Flagging turbolinks sanity check", :js do
|
||||
Setting['feature.community'] = true
|
||||
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community, title: "Should we change the world?")
|
||||
comment = create(:comment, commentable: topic)
|
||||
|
||||
login_as(user)
|
||||
visit community_path(community)
|
||||
click_link "Should we change the world?"
|
||||
|
||||
within "#comment_#{comment.id}" do
|
||||
page.find("#flag-expand-comment-#{comment.id}").click
|
||||
expect(page).to have_selector("#flag-comment-#{comment.id}")
|
||||
end
|
||||
|
||||
Setting['feature.community'] = nil
|
||||
end
|
||||
|
||||
scenario "Erasing a comment's author" do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
comment = create(:comment, commentable: topic, body: "this should be visible")
|
||||
comment.user.erase
|
||||
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
within "#comment_#{comment.id}" do
|
||||
expect(page).to have_content('User deleted')
|
||||
expect(page).to have_content('this should be visible')
|
||||
end
|
||||
end
|
||||
|
||||
feature "Moderators" do
|
||||
scenario "can create comment as a moderator", :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
moderator = create(:moderator)
|
||||
|
||||
login_as(moderator.user)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
fill_in "comment-body-topic_#{topic.id}", with: "I am moderating!"
|
||||
check "comment-as-moderator-topic_#{topic.id}"
|
||||
click_button "Publish comment"
|
||||
|
||||
within "#comments" do
|
||||
expect(page).to have_content "I am moderating!"
|
||||
expect(page).to have_content "Moderator ##{moderator.id}"
|
||||
expect(page).to have_css "div.is-moderator"
|
||||
expect(page).to have_css "img.moderator-avatar"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "can create reply as a moderator", :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
citizen = create(:user, username: "Ana")
|
||||
manuela = create(:user, username: "Manuela")
|
||||
moderator = create(:moderator, user: manuela)
|
||||
comment = create(:comment, commentable: topic, user: citizen)
|
||||
|
||||
login_as(manuela)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
click_link "Reply"
|
||||
|
||||
within "#js-comment-form-comment_#{comment.id}" do
|
||||
fill_in "comment-body-comment_#{comment.id}", with: "I am moderating!"
|
||||
check "comment-as-moderator-comment_#{comment.id}"
|
||||
click_button 'Publish reply'
|
||||
end
|
||||
|
||||
within "#comment_#{comment.id}" do
|
||||
expect(page).to have_content "I am moderating!"
|
||||
expect(page).to have_content "Moderator ##{moderator.id}"
|
||||
expect(page).to have_css "div.is-moderator"
|
||||
expect(page).to have_css "img.moderator-avatar"
|
||||
end
|
||||
|
||||
expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true)
|
||||
end
|
||||
|
||||
scenario "can not comment as an administrator" do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
moderator = create(:moderator)
|
||||
|
||||
login_as(moderator.user)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
expect(page).to_not have_content "Comment as administrator"
|
||||
end
|
||||
end
|
||||
|
||||
feature "Administrators" do
|
||||
scenario "can create comment as an administrator", :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
admin = create(:administrator)
|
||||
|
||||
login_as(admin.user)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
fill_in "comment-body-topic_#{topic.id}", with: "I am your Admin!"
|
||||
check "comment-as-administrator-topic_#{topic.id}"
|
||||
click_button "Publish comment"
|
||||
|
||||
within "#comments" do
|
||||
expect(page).to have_content "I am your Admin!"
|
||||
expect(page).to have_content "Administrator ##{admin.id}"
|
||||
expect(page).to have_css "div.is-admin"
|
||||
expect(page).to have_css "img.admin-avatar"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "can create reply as an administrator", :js do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
citizen = create(:user, username: "Ana")
|
||||
manuela = create(:user, username: "Manuela")
|
||||
admin = create(:administrator, user: manuela)
|
||||
comment = create(:comment, commentable: topic, user: citizen)
|
||||
|
||||
login_as(manuela)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
click_link "Reply"
|
||||
|
||||
within "#js-comment-form-comment_#{comment.id}" do
|
||||
fill_in "comment-body-comment_#{comment.id}", with: "Top of the world!"
|
||||
check "comment-as-administrator-comment_#{comment.id}"
|
||||
click_button 'Publish reply'
|
||||
end
|
||||
|
||||
within "#comment_#{comment.id}" do
|
||||
expect(page).to have_content "Top of the world!"
|
||||
expect(page).to have_content "Administrator ##{admin.id}"
|
||||
expect(page).to have_css "div.is-admin"
|
||||
expect(page).to have_css "img.admin-avatar"
|
||||
end
|
||||
|
||||
expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true)
|
||||
end
|
||||
|
||||
scenario "can not comment as a moderator" do
|
||||
community = investment.community
|
||||
topic = create(:topic, community: community)
|
||||
admin = create(:administrator)
|
||||
|
||||
login_as(admin.user)
|
||||
visit community_topic_path(community, topic)
|
||||
|
||||
expect(page).to_not have_content "Comment as moderator"
|
||||
end
|
||||
end
|
||||
|
||||
feature 'Voting comments' do
|
||||
|
||||
background do
|
||||
@manuela = create(:user, verified_at: Time.current)
|
||||
@pablo = create(:user)
|
||||
@investment = create(:budget_investment)
|
||||
@topic = create(:topic, community: @investment.community)
|
||||
@comment = create(:comment, commentable: @topic)
|
||||
|
||||
login_as(@manuela)
|
||||
end
|
||||
|
||||
scenario 'Show' do
|
||||
create(:vote, voter: @manuela, votable: @comment, vote_flag: true)
|
||||
create(:vote, voter: @pablo, votable: @comment, vote_flag: false)
|
||||
|
||||
visit community_topic_path(@investment.community, @topic)
|
||||
|
||||
within("#comment_#{@comment.id}_votes") do
|
||||
within(".in_favor") do
|
||||
expect(page).to have_content "1"
|
||||
end
|
||||
|
||||
within(".against") do
|
||||
expect(page).to have_content "1"
|
||||
end
|
||||
|
||||
expect(page).to have_content "2 votes"
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Create', :js do
|
||||
visit community_topic_path(@investment.community, @topic)
|
||||
|
||||
within("#comment_#{@comment.id}_votes") do
|
||||
find(".in_favor a").click
|
||||
|
||||
within(".in_favor") do
|
||||
expect(page).to have_content "1"
|
||||
end
|
||||
|
||||
within(".against") do
|
||||
expect(page).to have_content "0"
|
||||
end
|
||||
|
||||
expect(page).to have_content "1 vote"
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Update', :js do
|
||||
visit community_topic_path(@investment.community, @topic)
|
||||
|
||||
within("#comment_#{@comment.id}_votes") do
|
||||
find('.in_favor a').click
|
||||
find('.against a').click
|
||||
|
||||
within('.in_favor') do
|
||||
expect(page).to have_content "0"
|
||||
end
|
||||
|
||||
within('.against') do
|
||||
expect(page).to have_content "1"
|
||||
end
|
||||
|
||||
expect(page).to have_content "1 vote"
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Trying to vote multiple times', :js do
|
||||
visit community_topic_path(@investment.community, @topic)
|
||||
|
||||
within("#comment_#{@comment.id}_votes") do
|
||||
find('.in_favor a').click
|
||||
find('.in_favor a').click
|
||||
|
||||
within('.in_favor') do
|
||||
expect(page).to have_content "1"
|
||||
end
|
||||
|
||||
within('.against') do
|
||||
expect(page).to have_content "0"
|
||||
end
|
||||
|
||||
expect(page).to have_content "1 vote"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -15,7 +15,7 @@ feature 'Communities' do
|
||||
scenario 'Should display default content' do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
user = create(:user)
|
||||
user = create(:user)
|
||||
login_as(user)
|
||||
|
||||
visit community_path(community)
|
||||
@@ -63,10 +63,47 @@ feature 'Communities' do
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Topic order" do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
topic1 = create(:topic, community: community)
|
||||
topic2 = create(:topic, community: community)
|
||||
topic2_comment = create(:comment, :with_confidence_score, commentable: topic2)
|
||||
topic3 = create(:topic, community: community)
|
||||
topic3_comment = create(:comment, :with_confidence_score, commentable: topic3)
|
||||
topic3_comment = create(:comment, :with_confidence_score, commentable: topic3)
|
||||
|
||||
visit community_path(community, order: :most_commented)
|
||||
|
||||
expect(topic3.title).to appear_before(topic2.title)
|
||||
expect(topic2.title).to appear_before(topic1.title)
|
||||
|
||||
visit community_path(community, order: :oldest)
|
||||
|
||||
expect(topic1.title).to appear_before(topic2.title)
|
||||
expect(topic2.title).to appear_before(topic3.title)
|
||||
|
||||
visit community_path(community, order: :newest)
|
||||
|
||||
expect(topic3.title).to appear_before(topic2.title)
|
||||
expect(topic2.title).to appear_before(topic1.title)
|
||||
end
|
||||
|
||||
scenario "Should order by newest when order param is invalid" do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
topic1 = create(:topic, community: community)
|
||||
topic2 = create(:topic, community: community)
|
||||
|
||||
visit community_path(community, order: "invalid_param")
|
||||
|
||||
expect(topic2.title).to appear_before(topic1.title)
|
||||
end
|
||||
|
||||
scenario 'Should display topic edit button when author is logged' do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
user = create(:user)
|
||||
user = create(:user)
|
||||
topic1 = create(:topic, community: community, author: user)
|
||||
topic2 = create(:topic, community: community)
|
||||
login_as(user)
|
||||
|
||||
@@ -101,6 +101,8 @@ feature 'Proposals' do
|
||||
end
|
||||
|
||||
scenario 'Can not access the community' do
|
||||
Setting['feature.community'] = false
|
||||
|
||||
proposal = create(:proposal)
|
||||
visit proposal_path(proposal)
|
||||
expect(page).not_to have_content "Access the community"
|
||||
|
||||
@@ -13,10 +13,10 @@ feature 'Topics' do
|
||||
expect(page).to have_selector(".button.expanded.disabled")
|
||||
end
|
||||
|
||||
scenario 'Should can access to new topic page with user logged', :js do
|
||||
scenario 'Can access to new topic page with user logged', :js do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
user = create(:user)
|
||||
user = create(:user)
|
||||
login_as(user)
|
||||
visit community_path(community)
|
||||
|
||||
@@ -28,7 +28,7 @@ feature 'Topics' do
|
||||
scenario 'Should have content on new topic page', :js do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
user = create(:user)
|
||||
user = create(:user)
|
||||
login_as(user)
|
||||
visit community_path(community)
|
||||
|
||||
@@ -47,10 +47,10 @@ feature 'Topics' do
|
||||
|
||||
context 'Create' do
|
||||
|
||||
scenario 'Should can create a new topic', :js do
|
||||
scenario 'Can create a new topic', :js do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
user = create(:user)
|
||||
user = create(:user)
|
||||
login_as(user)
|
||||
|
||||
visit new_community_topic_path(community)
|
||||
@@ -62,14 +62,23 @@ feature 'Topics' do
|
||||
expect(current_path).to eq(community_path(community))
|
||||
end
|
||||
|
||||
scenario 'Can not create a new topic when user not logged', :js do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
|
||||
visit new_community_topic_path(community)
|
||||
|
||||
expect(page).to have_content "You do not have permission to carry out the action 'new' on topic."
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'Edit' do
|
||||
|
||||
scenario 'Should can edit a topic' do
|
||||
scenario 'Can edit a topic' do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
user = create(:user)
|
||||
user = create(:user)
|
||||
topic = create(:topic, community: community, author: user)
|
||||
login_as(user)
|
||||
visit edit_community_topic_path(community, topic)
|
||||
@@ -82,11 +91,23 @@ feature 'Topics' do
|
||||
expect(current_path).to eq(community_path(community))
|
||||
end
|
||||
|
||||
scenario 'Can not edit a topic when user logged is not an author' do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
topic = create(:topic, community: community)
|
||||
user = create(:user)
|
||||
login_as(user)
|
||||
|
||||
visit edit_community_topic_path(community, topic)
|
||||
|
||||
expect(page).to have_content "You do not have permission to carry out the action 'edit' on topic."
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'Show' do
|
||||
|
||||
scenario 'Should can show topic' do
|
||||
scenario 'Can show topic' do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
topic = create(:topic, community: community)
|
||||
@@ -99,4 +120,35 @@ feature 'Topics' do
|
||||
|
||||
end
|
||||
|
||||
context 'Destroy' do
|
||||
|
||||
scenario 'Can destroy a topic' do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
user = create(:user)
|
||||
topic = create(:topic, community: community, author: user)
|
||||
login_as(user)
|
||||
visit community_path(community)
|
||||
|
||||
click_link "Destroy"
|
||||
|
||||
expect(page).to have_content "Topic deleted successfully."
|
||||
expect(page).not_to have_content topic.title
|
||||
expect(current_path).to eq(community_path(community))
|
||||
end
|
||||
|
||||
scenario 'Can not destroy a topic when user logged is not an author' do
|
||||
proposal = create(:proposal)
|
||||
community = proposal.community
|
||||
topic = create(:topic, community: community)
|
||||
user = create(:user)
|
||||
login_as(user)
|
||||
|
||||
visit community_path(community)
|
||||
|
||||
expect(page).not_to have_link "Destroy"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -235,7 +235,7 @@ feature 'Users' do
|
||||
end
|
||||
|
||||
scenario 'Not display interests when proposal has been destroyed' do
|
||||
proposal = create(:proposal, tag_list: "Sport")
|
||||
proposal = create(:proposal, tag_list: "Sport")
|
||||
create(:follow, :followed_proposal, followable: proposal, user: @user)
|
||||
proposal.destroy
|
||||
|
||||
|
||||
@@ -668,8 +668,8 @@ describe User do
|
||||
end
|
||||
|
||||
it "should discard followed objects duplicated tags" do
|
||||
proposal1 = create(:proposal, tag_list: "Sport")
|
||||
proposal2 = create(:proposal, tag_list: "Sport")
|
||||
proposal1 = create(:proposal, tag_list: "Sport")
|
||||
proposal2 = create(:proposal, tag_list: "Sport")
|
||||
budget_investment = create(:budget_investment, tag_list: "Sport")
|
||||
|
||||
create(:follow, followable: proposal1, user: user)
|
||||
|
||||
2
vendor/assets/javascripts/annotator.js
vendored
2
vendor/assets/javascripts/annotator.js
vendored
@@ -2054,7 +2054,7 @@ setDocument = Sizzle.setDocument = function( node ) {
|
||||
// getElementById is not reliable as a find shortcut
|
||||
delete Expr.find["ID"];
|
||||
|
||||
Expr.filter["ID"] = function( id ) {
|
||||
Expr.filter["ID"] = function( id ) {
|
||||
var attrId = id.replace( runescape, funescape );
|
||||
return function( elem ) {
|
||||
var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
|
||||
|
||||
Reference in New Issue
Block a user