+
+ <% end %>
<% cache [locale_and_user_status(proposal), 'index', proposal, proposal.author] do %>
<%= link_to proposal.title, namespaced_proposal_path(proposal) %>
@@ -60,7 +62,9 @@
-
+
>
<% if proposal.successful? %>
diff --git a/app/views/proposals/show.html.erb b/app/views/proposals/show.html.erb
index ade0972d8..aa8b0aee3 100644
--- a/app/views/proposals/show.html.erb
+++ b/app/views/proposals/show.html.erb
@@ -69,7 +69,9 @@
<%= safe_html_with_links @proposal.description %>
<% if feature?(:map) && map_location_available?(@proposal.map_location) %>
- <%= render_map(@proposal.map_location, "proposal", false, nil) %>
+
+ <%= render_map(@proposal.map_location, "proposal", false, nil) %>
+
<% end %>
<% if @proposal.external_url.present? %>
@@ -180,6 +182,9 @@
} %>
<% if current_user %>
+
+
+
<%= render 'follows/follow_button', follow: find_or_build_follow(current_user, @proposal) %>
<% end %>
diff --git a/app/views/users/_budget_investment_follow.html.erb b/app/views/users/_budget_investment_follow.html.erb
new file mode 100644
index 000000000..be6555ed7
--- /dev/null
+++ b/app/views/users/_budget_investment_follow.html.erb
@@ -0,0 +1,3 @@
+
+ <%= link_to budget_investment.title, budget_investment_path(budget_investment.budget, budget_investment) %>
+
diff --git a/app/views/users/_following.html.erb b/app/views/users/_following.html.erb
index a5e78a3b6..1ee5c412a 100644
--- a/app/views/users/_following.html.erb
+++ b/app/views/users/_following.html.erb
@@ -1,30 +1,27 @@
-
+
+
+
- <% @follows.each do |followable_type, follows| %>
+ <% @follows.each do |followable_type, follows| %>
-
-
+
+
+ <%= followable_type_title(followable_type) %>
+
-
-
-
-
-
- <%= followable_type_title(followable_type) %>
-
-
+
+ <% follows.each do |follow| %>
+ <%= render_follow(follow) %>
+ <% end %>
+
+ <% end %>
+
-
-
-
- <% follows.each do |follow| %>
- <%= render_follow(follow) %>
- <% end %>
-
-
-
-
-
-
- <% end %>
-
-
+
+ <%= render 'interests', user: @user if valid_interests_access? %>
+
+
diff --git a/app/views/users/_interests.html.erb b/app/views/users/_interests.html.erb
index a0d110346..3b830e1ac 100644
--- a/app/views/users/_interests.html.erb
+++ b/app/views/users/_interests.html.erb
@@ -2,18 +2,10 @@
<%= interests_title_text(user) %>
<% if user.interests.any? %>
-
-
- <% else %>
-
-
- <%= empty_interests_message_text(user) %>
-
-
<% end %>
diff --git a/app/views/users/_proposal_follow.html.erb b/app/views/users/_proposal_follow.html.erb
new file mode 100644
index 000000000..1df5cfa72
--- /dev/null
+++ b/app/views/users/_proposal_follow.html.erb
@@ -0,0 +1,6 @@
+
+ <%= link_to proposal.title, proposal, proposal.retired? ? { class: 'retired' } : {} %>
+ <% if proposal.retired? %>
+ <%= t('users.proposals.retired') %>
+ <% end %>
+
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index 4e6b6f0e5..a4f739a28 100644
--- a/app/views/users/show.html.erb
+++ b/app/views/users/show.html.erb
@@ -38,18 +38,20 @@
<% end %>
<% end %>
<% end %>
- <%= t("users.show.no_activity") if @activity_counts.values.inject(&:+) == 0 %>
+ <% if @activity_counts.values.inject(&:+) == 0 %>
+
+ <%= t("users.show.no_activity") %>
+
+ <% end %>
+
<%= render "activity_page" %>
<% else %>
<%= t('users.show.private_activity') %>
<% end %>
-
- <%= render 'interests', user: @user if valid_interests_access? %>
-
diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml
index 9d1ad1560..ad5cc30e3 100644
--- a/config/locales/en/general.yml
+++ b/config/locales/en/general.yml
@@ -13,10 +13,8 @@ en:
phone_number_label: Phone number
public_activity_label: Keep my list of activities public
public_interests_label: Keep my interests public
- public_interests_my_title_list: List of interests (tags of elements you follow)
- public_interests_user_title_list: List of interests (tags of elements this user follows)
- public_interests_my_empty_list: You do not follow any elements yet.
- public_interests_user_empty_list: This user does not follow any elements yet.
+ public_interests_my_title_list: Tags of elements you follow
+ public_interests_user_title_list: Tags of elements this user follows
save_changes_submit: Save changes
subscription_to_website_newsletter_label: Receive by email website relevant information
email_on_direct_message_label: Receive emails about direct messages
@@ -570,6 +568,7 @@ en:
collective: Collective
flag: Flag as inappropriate
follow: "Follow"
+ following: "Following"
follow_entity: "Follow %{entity}"
followable:
budget_investment:
@@ -614,7 +613,6 @@ en:
target_blank_html: " (link opens in new window)"
you_are_in: "You are in"
unflag: Unflag
- unfollow: "Unfollow"
unfollow_entity: "Unfollow %{entity}"
outline:
budget: Participatory budget
diff --git a/config/locales/en/settings.yml b/config/locales/en/settings.yml
index 59452bbe6..531393e65 100644
--- a/config/locales/en/settings.yml
+++ b/config/locales/en/settings.yml
@@ -44,6 +44,7 @@ en:
recommendations: Recommendeds
community: Community on proposals and investments
map: Proposals and budget investments geolocation
+ allow_images: Allow upload and show images
map_latitude: Latitude
map_longitude: Longitude
map_zoom: Zoom
diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml
index a90d6837e..e455e1770 100644
--- a/config/locales/es/general.yml
+++ b/config/locales/es/general.yml
@@ -13,10 +13,8 @@ es:
phone_number_label: Teléfono
public_activity_label: Mostrar públicamente mi lista de actividades
public_interests_label: Mostrar públicamente mis intereses
- public_interests_my_title_list: Lista de intereses (etiquetas de los elementos que sigues)
- public_interests_user_title_list: Lista de intereses (etiquetas de los elementos seguidos este usuario)
- public_interests_my_empty_list: Aún no sigues ningún elemento.
- public_interests_user_empty_list: Este usuario no sigue ningún elemento todavía.
+ public_interests_my_title_list: Etiquetas de los elementos que sigues
+ public_interests_user_title_list: Etiquetas de los elementos que sigue este usuario
save_changes_submit: Guardar cambios
subscription_to_website_newsletter_label: Recibir emails con información interesante sobre la web
email_on_direct_message_label: Recibir emails con mensajes privados
@@ -567,6 +565,7 @@ es:
collective: Colectivo
flag: Denunciar como inapropiado
follow: "Seguir"
+ following: "Siguiendo"
follow_entity: "Seguir %{entity}"
followable:
budget_investment:
@@ -611,7 +610,6 @@ es:
target_blank_html: " (se abre en ventana nueva)"
you_are_in: "Estás en"
unflag: Deshacer denuncia
- unfollow: "Dejar de seguir"
unfollow_entity: "Dejar de seguir %{entity}"
outline:
budget: Presupuestos participativos
diff --git a/config/locales/es/settings.yml b/config/locales/es/settings.yml
index bf8e112ac..3473a99dd 100644
--- a/config/locales/es/settings.yml
+++ b/config/locales/es/settings.yml
@@ -44,6 +44,7 @@ es:
recommendations: Recomendaciones
community: Comunidad en propuestas y proyectos de inversión
map: Geolocalización de propuestas y proyectos de inversión
+ allow_images: Permitir subir y mostrar imágenes
map_latitude: Latitud
map_longitude: Longitud
map_zoom: Zoom
diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb
index af3e602e6..3c4462e85 100644
--- a/db/dev_seeds.rb
+++ b/db/dev_seeds.rb
@@ -51,6 +51,7 @@ section "Creating Settings" do
Setting.create(key: 'feature.user.recommendations', value: "true")
Setting.create(key: 'feature.community', value: "true")
Setting.create(key: 'feature.map', value: "true")
+ Setting.create(key: 'feature.allow_images', value: "true")
Setting.create(key: 'feature.public_stats', value: "true")
Setting.create(key: 'per_page_code_head', value: "")
Setting.create(key: 'per_page_code_body', value: "")
diff --git a/db/seeds.rb b/db/seeds.rb
index 6758bf75c..e06b5d07d 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -84,6 +84,7 @@ Setting['feature.legislation'] = true
Setting['feature.user.recommendations'] = true
Setting['feature.community'] = true
Setting['feature.map'] = nil
+Setting['feature.allow_images'] = true
# Spending proposals feature flags
Setting['feature.spending_proposal_features.voting_allowed'] = nil
diff --git a/spec/controllers/installation_controller_spec.rb b/spec/controllers/installation_controller_spec.rb
index 7cb9a3af1..4ad446cd4 100644
--- a/spec/controllers/installation_controller_spec.rb
+++ b/spec/controllers/installation_controller_spec.rb
@@ -19,7 +19,8 @@ describe InstallationController, type: :request do
'user.recommendations' => nil,
'community' => nil,
'map' => 't',
- 'spending_proposal_features.voting_allowed' => 't'
+ 'spending_proposal_features.voting_allowed' => 't',
+ 'allow_images' => 't'
}
end
@@ -42,6 +43,7 @@ describe InstallationController, type: :request do
Setting['feature.community'] = true
Setting['feature.map'] = nil
Setting['feature.spending_proposal_features.voting_allowed'] = nil
+ Setting['feature.allow_images'] = true
end
specify "with query string inside query params" do
diff --git a/spec/features/budgets/investments_spec.rb b/spec/features/budgets/investments_spec.rb
index 9cb1326b1..fa1f3d9f6 100644
--- a/spec/features/budgets/investments_spec.rb
+++ b/spec/features/budgets/investments_spec.rb
@@ -9,6 +9,14 @@ feature 'Budget Investments' do
let(:group) { create(:budget_group, name: "Health", budget: budget) }
let!(:heading) { create(:budget_heading, name: "More hospitals", group: group) }
+ before do
+ Setting['feature.allow_images'] = true
+ end
+
+ after do
+ Setting['feature.allow_images'] = nil
+ end
+
scenario 'Index' do
investments = [create(:budget_investment, heading: heading),
create(:budget_investment, heading: heading),
@@ -37,7 +45,7 @@ feature 'Budget Investments' do
visit budget_investments_path(budget, heading_id: heading.id)
within("#budget_investment_#{investment.id}") do
- expect(page).to have_css("div.no-image")
+ expect(page).to_not have_css("div.with-image")
end
within("#budget_investment_#{investment_with_image.id}") do
expect(page).to have_css("img[alt='#{investment_with_image.image.title}']")
diff --git a/spec/features/proposals_spec.rb b/spec/features/proposals_spec.rb
index 886459c38..e2fd8edbb 100644
--- a/spec/features/proposals_spec.rb
+++ b/spec/features/proposals_spec.rb
@@ -10,6 +10,15 @@ feature 'Proposals' do
end
context 'Index' do
+
+ before do
+ Setting['feature.allow_images'] = true
+ end
+
+ after do
+ Setting['feature.allow_images'] = nil
+ end
+
scenario 'Lists featured and regular proposals' do
featured_proposals = create_featured_proposals
proposals = [create(:proposal), create(:proposal), create(:proposal)]
@@ -61,7 +70,7 @@ feature 'Proposals' do
visit proposals_path(proposal)
within("#proposal_#{proposal.id}") do
- expect(page).to have_css("div.no-image")
+ expect(page).to_not have_css("div.with-image")
end
within("#proposal_#{proposal_with_image.id}") do
expect(page).to have_css("img[alt='#{proposal_with_image.image.title}']")
diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb
index 5a73209df..0ca1f0266 100644
--- a/spec/features/users_spec.rb
+++ b/spec/features/users_spec.rb
@@ -259,6 +259,9 @@ feature 'Users' do
end
scenario 'User can display public page' do
+ proposal = create(:proposal, tag_list: "Sport")
+ create(:follow, :followed_proposal, followable: proposal, user: @user)
+
login_as(@user)
visit account_path
@@ -267,22 +270,29 @@ feature 'Users' do
logout
- visit user_path(@user)
+ visit user_path(@user, filter: 'follows', page: '1')
+
expect(page).to have_css('#public_interests')
end
scenario 'Is always visible for the owner' do
+ proposal = create(:proposal, tag_list: "Sport")
+ create(:follow, :followed_proposal, followable: proposal, user: @user)
+
login_as(@user)
visit account_path
uncheck 'account_public_interests'
click_button 'Save changes'
- visit user_path(@user)
+ visit user_path(@user, filter: 'follows', page: '1')
expect(page).to have_css('#public_interests')
end
scenario 'Is always visible for admins' do
+ proposal = create(:proposal, tag_list: "Sport")
+ create(:follow, :followed_proposal, followable: proposal, user: @user)
+
login_as(@user)
visit account_path
@@ -292,11 +302,14 @@ feature 'Users' do
logout
login_as(create(:administrator).user)
- visit user_path(@user)
+ visit user_path(@user, filter: 'follows', page: '1')
expect(page).to have_css('#public_interests')
end
scenario 'Is always visible for moderators' do
+ proposal = create(:proposal, tag_list: "Sport")
+ create(:follow, :followed_proposal, followable: proposal, user: @user)
+
login_as(@user)
visit account_path
@@ -306,38 +319,29 @@ feature 'Users' do
logout
login_as(create(:moderator).user)
- visit user_path(@user)
+ visit user_path(@user, filter: 'follows', page: '1')
expect(page).to have_css('#public_interests')
end
scenario 'Should display generic interests title' do
- @user.update(public_interests: true)
- visit user_path(@user)
+ proposal = create(:proposal, tag_list: "Sport")
+ create(:follow, :followed_proposal, followable: proposal, user: @user)
- expect(page).to have_content("List of interests (tags of elements this user follows)")
+ @user.update(public_interests: true)
+ visit user_path(@user, filter: 'follows', page: '1')
+
+ expect(page).to have_content("Tags of elements this user follows")
end
scenario 'Should display custom interests title when user is visiting own user page' do
+ proposal = create(:proposal, tag_list: "Sport")
+ create(:follow, :followed_proposal, followable: proposal, user: @user)
+
@user.update(public_interests: true)
login_as(@user)
- visit user_path(@user)
+ visit user_path(@user, filter: 'follows', page: '1')
- expect(page).to have_content("List of interests (tags of elements you follow)")
- end
-
- scenario 'Should display generic empty interests list message when visited user has not interests defined' do
- @user.update(public_interests: true)
- visit user_path(@user)
-
- expect(page).to have_content("This user does not follow any elements yet.")
- end
-
- scenario 'Should display custom empty interests list message when user has not interests defined and user is visiting own user page' do
- @user.update(public_interests: true)
- login_as(@user)
- visit user_path(@user)
-
- expect(page).to have_content("You do not follow any elements yet.")
+ expect(page).to have_content("Tags of elements you follow")
end
end
@@ -418,22 +422,22 @@ feature 'Users' do
expect(page).to have_content('1 Following')
end
- scenario 'Display accordion proposal tab when user is following one proposal at least' do
+ scenario 'Display proposal tab when user is following one proposal at least' do
proposal = create(:proposal)
create(:follow, followable: proposal, user: @user)
visit user_path(@user, filter: "follows")
- expect(page).to have_link('Citizen proposals', href: "#")
+ expect(page).to have_link('Citizen proposals', href: "#citizen_proposals")
end
- scenario 'Not display accordion proposal tab when user is not following any proposal' do
+ scenario 'Not display proposal tab when user is not following any proposal' do
visit user_path(@user, filter: "follows")
- expect(page).not_to have_link('Citizen proposals', href: "#")
+ expect(page).not_to have_link('Citizen proposals', href: "#citizen_proposals")
end
- scenario 'Display proposal with action buttons inside accordion proposal tab when current user is proposal author', :js do
+ scenario 'Display proposals with link to proposal' do
proposal = create(:proposal, author: @user)
create(:follow, followable: proposal, user: @user)
login_as @user
@@ -442,35 +446,7 @@ feature 'Users' do
click_link 'Citizen proposals'
expect(page).to have_content proposal.title
- expect(page).to have_link "Send notification"
- expect(page).to have_link "Retire"
end
-
- scenario 'Display proposal with action buttons inside accordion proposal tab when there is no logged user', :js do
- proposal = create(:proposal, author: @user)
- create(:follow, followable: proposal, user: @user)
-
- visit user_path(@user, filter: "follows")
- click_link 'Citizen proposals'
-
- expect(page).to have_content proposal.title
- expect(page).not_to have_link "Send notification"
- expect(page).not_to have_link "Retire"
- end
-
- scenario 'Display proposal without action buttons inside accordion proposal tab when current user is not proposal author', :js do
- proposal = create(:proposal)
- create(:follow, followable: proposal, user: @user)
- login_as @user
-
- visit user_path(@user, filter: "follows")
- click_link 'Citizen proposals'
-
- expect(page).to have_content proposal.title
- expect(page).not_to have_link "Send notification"
- expect(page).not_to have_link "Retire"
- end
-
end
describe 'Budget Investments' do
@@ -484,35 +460,22 @@ feature 'Users' do
expect(page).to have_content('1 Following')
end
- scenario 'Display accordion budget investment tab when user is following one budget investment at least' do
+ scenario 'Display budget investment tab when user is following one budget investment at least' do
budget_investment = create(:budget_investment)
create(:follow, followable: budget_investment, user: @user)
- visit user_path(@user, filter: "follow")
+ visit user_path(@user, filter: "follows")
- expect(page).to have_link('Investments', href: "#")
+ expect(page).to have_link('Investments', href: "#investments")
end
- scenario 'Not display accordion budget investment tab when user is not following any budget investment' do
- visit user_path(@user, filter: "follow")
+ scenario 'Not display budget investment tab when user is not following any budget investment' do
+ visit user_path(@user, filter: "follows")
- expect(page).not_to have_link('Investments', href: "#")
+ expect(page).not_to have_link('Investments', href: "#investments")
end
- scenario 'Display budget investment with action buttons inside accordion budget investment tab when current user is a verified user and author', :js do
- user = create(:user, :level_two)
- budget_investment = create(:budget_investment, author: user)
- create(:follow, followable: budget_investment, user: user)
- login_as user
-
- visit user_path(user, filter: "follows")
- click_link 'Investments'
-
- expect(page).to have_link budget_investment.title
- expect(page).to have_link "Delete"
- end
-
- scenario 'Display budget investment with action buttons inside accordion budget investment tab when there is no logged user', :js do
+ scenario 'Display budget investment with link to budget investment' do
user = create(:user, :level_two)
budget_investment = create(:budget_investment, author: user)
create(:follow, followable: budget_investment, user: user)
@@ -521,22 +484,7 @@ feature 'Users' do
click_link 'Investments'
expect(page).to have_link budget_investment.title
- expect(page).not_to have_link "Delete"
end
-
- scenario 'Display budget investment without action buttons inside accordion budget investment tab when current user is not budget investment author', :js do
- user = create(:user, :level_two)
- budget_investment = create(:budget_investment)
- create(:follow, followable: budget_investment, user: user)
- login_as user
-
- visit user_path(user, filter: "follows")
- click_link 'Investments'
-
- expect(page).to have_link budget_investment.title
- expect(page).not_to have_link "Delete"
- end
-
end
end
diff --git a/spec/shared/features/followable.rb b/spec/shared/features/followable.rb
index fc42a3ce7..55d47e53c 100644
--- a/spec/shared/features/followable.rb
+++ b/spec/shared/features/followable.rb
@@ -28,7 +28,7 @@ shared_examples "followable" do |followable_class_name, followable_path, followa
visit send(followable_path, arguments)
within "##{dom_id(followable)}" do
- expect(page).to have_link("Follow")
+ expect(page).to have_link("Follow #{followable.model_name.human.downcase}")
end
end
@@ -37,8 +37,7 @@ shared_examples "followable" do |followable_class_name, followable_path, followa
login_as(user)
visit send(followable_path, arguments)
-
- expect(page).to have_link("Follow")
+ expect(page).to have_link("Follow #{followable.model_name.human.downcase}")
end
scenario "Should display unfollow after user clicks on follow button", :js do
@@ -47,10 +46,10 @@ shared_examples "followable" do |followable_class_name, followable_path, followa
visit send(followable_path, arguments)
within "##{dom_id(followable)}" do
- click_link "Follow"
+ click_link("Follow #{followable.model_name.human.downcase}")
- expect(page).not_to have_link "Follow"
- expect(page).to have_link "Unfollow"
+ expect(page).not_to have_link("Follow")
+ expect(page).to have_link("Following")
end
end
@@ -60,7 +59,7 @@ shared_examples "followable" do |followable_class_name, followable_path, followa
visit send(followable_path, arguments)
within "##{dom_id(followable)}" do
- click_link "Follow"
+ click_link("Follow #{followable.model_name.human.downcase}")
end
expect(page).to have_content strip_tags(t("shared.followable.#{followable_class_name}.create.notice_html"))
@@ -73,7 +72,7 @@ shared_examples "followable" do |followable_class_name, followable_path, followa
visit send(followable_path, arguments)
- expect(page).to have_link("Unfollow")
+ expect(page).to have_link("Following")
end
scenario "Should update follow button and show destroy notice after user clicks on unfollow button", :js do
@@ -83,10 +82,10 @@ shared_examples "followable" do |followable_class_name, followable_path, followa
visit send(followable_path, arguments)
within "##{dom_id(followable)}" do
- click_link "Unfollow"
+ click_link("Unfollow #{followable.model_name.human.downcase}")
- expect(page).not_to have_link "Unfollow"
- expect(page).to have_link "Follow"
+ expect(page).not_to have_link("Unfollow")
+ expect(page).to have_link("Follow #{followable.model_name.human.downcase}")
end
end
@@ -97,7 +96,7 @@ shared_examples "followable" do |followable_class_name, followable_path, followa
visit send(followable_path, arguments)
within "##{dom_id(followable)}" do
- click_link "Unfollow"
+ click_link("Unfollow #{followable.model_name.human.downcase}")
end
expect(page).to have_content strip_tags(t("shared.followable.#{followable_class_name}.destroy.notice_html"))
diff --git a/spec/shared/features/nested_imageable.rb b/spec/shared/features/nested_imageable.rb
index 947887afa..721c7e694 100644
--- a/spec/shared/features/nested_imageable.rb
+++ b/spec/shared/features/nested_imageable.rb
@@ -9,6 +9,9 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
let!(:imageable) { create(imageable_factory_name) }
before do
+
+ Setting['feature.allow_images'] = true
+
imageable_path_arguments&.each do |argument_name, path_to_value|
arguments.merge!("#{argument_name}": imageable.send(path_to_value))
end
@@ -16,6 +19,10 @@ shared_examples "nested imageable" do |imageable_factory_name, path, imageable_p
imageable.update(author: user) if imageable.respond_to?(:author)
end
+ after do
+ Setting['feature.allow_images'] = nil
+ end
+
describe "at #{path}" do
scenario "Should show new image link when imageable has not an associated image defined" do