Merge pull request #2183 from consul/related-content

Related contents functionalities
This commit is contained in:
Raimond Garcia
2017-12-15 10:00:43 +01:00
committed by GitHub
13 changed files with 253 additions and 1 deletions

View File

@@ -20,6 +20,7 @@
// 18. Banners
// 19. Recommended Section Home
// 20. Documents
// 21. Related content
//
// 01. Global styles
@@ -2391,3 +2392,56 @@ table {
background: #fafafa;
border-bottom: 1px solid #eee;
}
// 21. Related content
// -------------------
.related-content {
border-top: 1px solid $border;
h2 {
font-size: rem-calc(24);
span {
color: #4f4f4f;
font-weight: normal;
}
}
}
.add-related-content {
display: block;
@include breakpoint(medium) {
float: right;
}
}
.related-content-list {
list-style-type: none;
margin-left: 0;
li {
border-bottom: 1px solid $border;
padding: $line-height / 4;
&:first-child {
border-top: 1px solid $border;
}
}
h3 {
font-size: $base-font-size;
font-weight: normal;
}
span {
color: #4f4f4f;
font-size: rem-calc(12);
text-transform: uppercase;
}
.flag {
margin-top: $line-height / 2;
}
}

View File

@@ -14,6 +14,8 @@ class Management::ProposalsController < Management::BaseController
def show
super
@notifications = @proposal.notifications
@related_contents = Kaminari.paginate_array(@proposal.relationed_contents).page(params[:page]).per(5)
redirect_to management_proposal_path(@proposal), status: :moved_permanently if request.path != management_proposal_path(@proposal)
end

View File

@@ -22,6 +22,8 @@ class ProposalsController < ApplicationController
def show
super
@notifications = @proposal.notifications
@related_contents = Kaminari.paginate_array(@proposal.relationed_contents).page(params[:page]).per(5)
redirect_to proposal_path(@proposal), status: :moved_permanently if request.path != proposal_path(@proposal)
end

View File

@@ -0,0 +1,42 @@
class RelatedContentsController < ApplicationController
VALID_URL = /#{Setting['url']}\/.*\/.*/
skip_authorization_check
def create
if relationable_object && related_object
@relationable.relate_content(@related)
flash[:success] = t('related_content.success')
else
flash[:error] = t('related_content.error', url: Setting['url'])
end
redirect_to @relationable
end
private
def valid_url?
params[:url].match(VALID_URL)
end
def relationable_object
@relationable = (params[:relationable_klass].singularize.camelize.constantize).find_by_id(params[:relationable_id])
end
def related_object
begin
if valid_url?
url = params[:url]
related_klass = url.match(/\/(#{RelatedContent::RELATIONABLE_MODELS.join("|")})\//)[0].gsub("/", "")
related_id = url.match(/\/[0-9]+/)[0].gsub("/", "")
@related = (related_klass.singularize.camelize.constantize).find_by_id(related_id)
end
rescue
nil
end
end
end

View File

@@ -1,5 +1,6 @@
class RelatedContent < ActiveRecord::Base
RELATED_CONTENTS_REPORT_THRESHOLD = Setting['related_contents_report_threshold'].to_i
RELATIONABLE_MODELS = %w{proposals debates}
belongs_to :parent_relationable, polymorphic: true
belongs_to :child_relationable, polymorphic: true

View File

@@ -108,6 +108,8 @@
<%= render 'shared/geozone', geozonable: @proposal %>
<%= render 'relationable/related_content', relationable: @proposal %>
<div class="js-moderator-proposal-actions margin">
<%= render 'proposals/actions', proposal: @proposal %>
</div>

View File

@@ -0,0 +1,22 @@
<%= form_tag related_contents_path, method: :post, id: "related_content", class: "hide", "data-toggler": ".hide" do %>
<label><%= t("related_content.label") %></label>
<p class="help-text" id="related_content_help_text">
<%= t("related_content.help", models: t('related_content.content_title').values.to_sentence, org: setting['org_name']) %>
</p>
<div class="input-group">
<div class="input-group-field">
<%= text_field_tag :url, '',
"aria-describedby": "related_content_help_text",
placeholder: t("related_content.placeholder", url: setting['url']) %>
<%= hidden_field_tag :relationable_klass, relationable.class.name %>
<%= hidden_field_tag :relationable_id, relationable.id %>
</div>
<div class="input-group-button">
<%= submit_tag t("related_content.submit"), class: "button" %>
</div>
</div>
<% end %>

View File

@@ -0,0 +1,18 @@
<div class="related-content padding">
<div class="margin-bottom">
<h2 class="inline-block">
<%= t("related_content.title") %>&nbsp;<span>(<%= relationable.relationed_contents.count %>)</span>
</h2>
<a>
<button type="button" data-toggle="related_content" class="add-related-content" id="add-related-content">
<%= t("related_content.add") %>
</button>
</a>
</div>
<%= render 'relationable/form', relationable: relationable %>
<%= render 'relationable/related_list', relationable: relationable %>
</div>

View File

@@ -0,0 +1,16 @@
<ul class="related-content-list" id="related-content-list">
<% @related_contents.each do |related| %>
<li>
<a href="#" class="float-right flag">
<span class="icon-flag"></span> <!-- This should be similar to comments/flag_actions -->
</a>
<span><%= t("related_content.content_title.#{related.class.name.downcase}") %></span><br>
<h3 class="inline-block">
<%= link_to related.title, eval("#{related.class.name.downcase}_path(related)") %>
</h3>
</li>
<% end %>
</ul>
<%= paginate @related_contents %>

View File

@@ -811,3 +811,15 @@ en:
invisible_captcha:
sentence_for_humans: "If you are human, ignore this field"
timestamp_error_message: "Sorry, that was too quick! Please resubmit."
related_content:
title: "Related content"
add: "Add related content"
label: "Link to related content"
placeholder: "%{url}"
help: "You can add links of %{models} inside of %{org}."
submit: "Add"
error: "Link not valid. Remember to start with %{url}."
success: "You added a new related content"
content_title:
proposal: "Proposal"
debate: "Debate"

View File

@@ -808,3 +808,15 @@ es:
invisible_captcha:
sentence_for_humans: "Si eres humano, por favor ignora este campo"
timestamp_error_message: "Eso ha sido demasiado rápido. Por favor, reenvía el formulario."
related_content:
title: "Contenido relacionado"
add: "Añadir contenido relacionado"
label: "Enlace a contenido relacionado"
placeholder: "%{url}"
help: "Puedes introducir cualquier enlace de %{models} que esté dentro de %{org}."
submit: "Añadir"
error: "Enlace no válido. Recuerda que debe empezar por %{url}."
success: "Has añadido un nuevo contenido relacionado"
content_title:
proposal: "Propuesta"
debate: "Debate"

View File

@@ -462,6 +462,8 @@ Rails.application.routes.draw do
root to: "dashboard#index"
end
resources :related_contents, only: [:create]
# GraphQL
get '/graphql', to: 'graphql#query'
post '/graphql', to: 'graphql#query'

View File

@@ -142,6 +142,73 @@ feature 'Proposals' do
visit proposal_path(proposal)
expect(page).not_to have_content "Access the community"
end
scenario 'related contents are listed' do
proposal1 = create(:proposal)
proposal2 = create(:proposal)
related_content = create(:related_content, parent_relationable: proposal1, child_relationable: proposal2)
visit proposal_path(proposal1)
within("#related-content-list") do
expect(page).to have_content(proposal2.title)
end
visit proposal_path(proposal2)
within("#related-content-list") do
expect(page).to have_content(proposal1.title)
end
end
scenario 'related contents can be added' do
proposal1 = create(:proposal)
proposal2 = create(:proposal)
debate1 = create(:debate)
visit proposal_path(proposal1)
expect(page).to have_selector('#related_content', visible: false)
click_on("Add related content")
expect(page).to have_selector('#related_content', visible: true)
within("#related_content") do
fill_in 'url', with: "#{Setting['url']}/proposals/#{proposal2.to_param}"
click_button "Add"
end
within("#related-content-list") do
expect(page).to have_content(proposal2.title)
end
visit proposal_path(proposal2)
within("#related-content-list") do
expect(page).to have_content(proposal1.title)
end
within("#related_content") do
fill_in 'url', with: "#{Setting['url']}/debates/#{debate1.to_param}"
click_button "Add"
end
within("#related-content-list") do
expect(page).to have_content(debate1.title)
end
end
scenario 'if related content URL is invalid returns error' do
proposal1 = create(:proposal)
visit proposal_path(proposal1)
click_on("Add related content")
within("#related_content") do
fill_in 'url', with: "http://invalidurl.com"
click_button "Add"
end
expect(page).to have_content("Link not valid. Remember to start with #{Setting[:url]}.")
end
end
context "Embedded video" do