Add sdg manager section to admin
Allow a user to become an sdg manager
This commit is contained in:
13
app/components/admin/header.rb
Normal file
13
app/components/admin/header.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
module Admin::Header
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def header(options: {})
|
||||
provide(:title) do
|
||||
title
|
||||
end
|
||||
|
||||
tag.h2 options do
|
||||
title
|
||||
end
|
||||
end
|
||||
end
|
||||
38
app/components/admin/sdg/managers/index_component.html.erb
Normal file
38
app/components/admin/sdg/managers/index_component.html.erb
Normal file
@@ -0,0 +1,38 @@
|
||||
<%= header %>
|
||||
|
||||
<%= render "admin/shared/user_search", url: admin_sdg_managers_path %>
|
||||
|
||||
<div id="sdg_managers">
|
||||
<% if users.any? %>
|
||||
<h3 class="margin"><%= page_entries_info users %></h3>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<th scope="col"><%= SDG::Manager.human_attribute_name(:name) %></th>
|
||||
<th scope="col"><%= SDG::Manager.human_attribute_name(:email) %></th>
|
||||
<th scope="col"><%= t("admin.shared.actions") %></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% users.each do |user| %>
|
||||
<tr>
|
||||
<td>
|
||||
<%= user.name %>
|
||||
</td>
|
||||
<td>
|
||||
<%= user.email %>
|
||||
</td>
|
||||
<td>
|
||||
<%= render Admin::Roles::TableActionsComponent.new(user.sdg_manager || user.build_sdg_manager) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= paginate users %>
|
||||
<% else %>
|
||||
<div class="callout primary">
|
||||
<%= t("admin.sdg_managers.index.no_sdg_managers") %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
15
app/components/admin/sdg/managers/index_component.rb
Normal file
15
app/components/admin/sdg/managers/index_component.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
class Admin::SDG::Managers::IndexComponent < ApplicationComponent
|
||||
include Admin::Header
|
||||
|
||||
attr_reader :users
|
||||
|
||||
def initialize(users)
|
||||
@users = users
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def title
|
||||
SDG::Manager.model_name.human(count: 2).upcase_first
|
||||
end
|
||||
end
|
||||
23
app/controllers/admin/sdg/managers_controller.rb
Normal file
23
app/controllers/admin/sdg/managers_controller.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
class Admin::SDG::ManagersController < Admin::BaseController
|
||||
load_and_authorize_resource instance_name: :sdg_manager, class: "SDG::Manager"
|
||||
|
||||
def index
|
||||
if params[:search]
|
||||
@users = User.accessible_by(current_ability).search(params[:search]).page(params[:page])
|
||||
else
|
||||
@users = User.accessible_by(current_ability).sdg_managers.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@sdg_manager.user_id = params[:user_id]
|
||||
@sdg_manager.save!
|
||||
|
||||
redirect_to admin_sdg_managers_path
|
||||
end
|
||||
|
||||
def destroy
|
||||
@sdg_manager.destroy!
|
||||
redirect_to admin_sdg_managers_path
|
||||
end
|
||||
end
|
||||
@@ -56,6 +56,7 @@ module Abilities
|
||||
can [:search, :create, :index, :destroy], ::Moderator
|
||||
can [:search, :show, :edit, :update, :create, :index, :destroy, :summary], ::Valuator
|
||||
can [:search, :create, :index, :destroy], ::Manager
|
||||
can [:create, :read, :destroy], ::SDG::Manager
|
||||
can [:search, :index], ::User
|
||||
|
||||
can :manage, Dashboard::Action
|
||||
|
||||
@@ -95,6 +95,7 @@ class User < ApplicationRecord
|
||||
scope :administrators, -> { joins(:administrator) }
|
||||
scope :moderators, -> { joins(:moderator) }
|
||||
scope :organizations, -> { joins(:organization) }
|
||||
scope :sdg_managers, -> { joins(:sdg_manager) }
|
||||
scope :officials, -> { where("official_level > 0") }
|
||||
scope :male, -> { where(gender: "male") }
|
||||
scope :female, -> { where(gender: "female") }
|
||||
|
||||
1
app/views/admin/sdg/managers/index.html.erb
Normal file
1
app/views/admin/sdg/managers/index.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
<%= render Admin::SDG::Managers::IndexComponent.new(@users) %>
|
||||
@@ -4,6 +4,9 @@ en:
|
||||
results_enabled: "Show results"
|
||||
stats_enabled: "Show stats"
|
||||
advanced_stats_enabled: "Show advanced stats"
|
||||
name: Name
|
||||
email: Email
|
||||
description: Description
|
||||
activerecord:
|
||||
models:
|
||||
activity:
|
||||
@@ -78,6 +81,9 @@ en:
|
||||
sdg/local_target:
|
||||
one: "local target"
|
||||
other: "local targets"
|
||||
sdg/manager:
|
||||
one: "SDG manager"
|
||||
other: "SDG managers"
|
||||
sdg/target:
|
||||
one: "target"
|
||||
other: "targets"
|
||||
|
||||
@@ -621,6 +621,12 @@ en:
|
||||
add: Add
|
||||
search:
|
||||
title: "Managers: User search"
|
||||
sdg_managers:
|
||||
index:
|
||||
no_sdg_managers: There are no users.
|
||||
sdg/managers:
|
||||
sdg/manager:
|
||||
add: Add
|
||||
menu:
|
||||
activity: Moderator activity
|
||||
admin: Admin menu
|
||||
@@ -637,6 +643,7 @@ en:
|
||||
hidden_users: Hidden users
|
||||
administrators: Administrators
|
||||
managers: Managers
|
||||
sdg_managers: SDG Managers
|
||||
moderators: Moderators
|
||||
messaging_users: Messages to users
|
||||
newsletters: Newsletters
|
||||
|
||||
@@ -4,6 +4,9 @@ es:
|
||||
results_enabled: "Mostrar resultados"
|
||||
stats_enabled: "Mostrar estadísticas"
|
||||
advanced_stats_enabled: "Mostrar estadísticas avanzadas"
|
||||
name: Nombre
|
||||
email: Email
|
||||
description: Descripción
|
||||
activerecord:
|
||||
models:
|
||||
activity:
|
||||
@@ -78,6 +81,9 @@ es:
|
||||
sdg/local_target:
|
||||
one: "meta localizada"
|
||||
other: "metas localizadas"
|
||||
sdg/manager:
|
||||
one: "gestor ODS"
|
||||
other: "gestores ODS"
|
||||
sdg/target:
|
||||
one: "meta"
|
||||
other: "metas"
|
||||
|
||||
@@ -620,6 +620,12 @@ es:
|
||||
add: Añadir como gestor
|
||||
search:
|
||||
title: "Gestores: Búsqueda de usuarios"
|
||||
sdg_managers:
|
||||
index:
|
||||
no_sdg_managers: No hay usuarios.
|
||||
sdg/managers:
|
||||
sdg/manager:
|
||||
add: Añadir como gestor ODS
|
||||
menu:
|
||||
activity: Actividad de moderadores
|
||||
admin: Menú de administración
|
||||
@@ -636,6 +642,7 @@ es:
|
||||
hidden_users: Usuarios bloqueados
|
||||
administrators: Administradores
|
||||
managers: Gestores
|
||||
sdg_managers: Gestores ODS
|
||||
moderators: Moderadores
|
||||
messaging_users: Mensajes a usuarios
|
||||
newsletters: Newsletters
|
||||
|
||||
@@ -113,6 +113,10 @@ namespace :admin do
|
||||
get :search, on: :collection
|
||||
end
|
||||
|
||||
namespace :sdg do
|
||||
resources :managers, only: [:index, :create, :destroy]
|
||||
end
|
||||
|
||||
resources :administrators, only: [:index, :create, :destroy, :edit, :update] do
|
||||
get :search, on: :collection
|
||||
end
|
||||
|
||||
@@ -109,4 +109,8 @@ describe Abilities::Administrator do
|
||||
|
||||
it { should be_able_to(:read, SDG::Goal) }
|
||||
it { should be_able_to(:read, SDG::Target) }
|
||||
|
||||
it { should be_able_to(:read, SDG::Manager) }
|
||||
it { should be_able_to(:create, SDG::Manager) }
|
||||
it { should be_able_to(:destroy, SDG::Manager) }
|
||||
end
|
||||
|
||||
@@ -307,4 +307,8 @@ describe Abilities::Common do
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Goal) }
|
||||
it { should_not be_able_to(:read, SDG::Target) }
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Manager) }
|
||||
it { should_not be_able_to(:create, SDG::Manager) }
|
||||
it { should_not be_able_to(:delete, SDG::Manager) }
|
||||
end
|
||||
|
||||
@@ -55,4 +55,8 @@ describe Abilities::Everyone do
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Goal) }
|
||||
it { should_not be_able_to(:read, SDG::Target) }
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Manager) }
|
||||
it { should_not be_able_to(:create, SDG::Manager) }
|
||||
it { should_not be_able_to(:delete, SDG::Manager) }
|
||||
end
|
||||
|
||||
@@ -111,4 +111,8 @@ describe Abilities::Moderator do
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Goal) }
|
||||
it { should_not be_able_to(:read, SDG::Target) }
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Manager) }
|
||||
it { should_not be_able_to(:create, SDG::Manager) }
|
||||
it { should_not be_able_to(:delete, SDG::Manager) }
|
||||
end
|
||||
|
||||
@@ -25,4 +25,8 @@ describe "Abilities::Organization" do
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Goal) }
|
||||
it { should_not be_able_to(:read, SDG::Target) }
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Manager) }
|
||||
it { should_not be_able_to(:create, SDG::Manager) }
|
||||
it { should_not be_able_to(:delete, SDG::Manager) }
|
||||
end
|
||||
|
||||
@@ -9,4 +9,8 @@ describe "Abilities::SDG::Manager" do
|
||||
|
||||
it { should be_able_to(:read, SDG::Goal) }
|
||||
it { should be_able_to(:read, SDG::Target) }
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Manager) }
|
||||
it { should_not be_able_to(:create, SDG::Manager) }
|
||||
it { should_not be_able_to(:delete, SDG::Manager) }
|
||||
end
|
||||
|
||||
@@ -42,4 +42,8 @@ describe Abilities::Valuator do
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Goal) }
|
||||
it { should_not be_able_to(:read, SDG::Target) }
|
||||
|
||||
it { should_not be_able_to(:read, SDG::Manager) }
|
||||
it { should_not be_able_to(:create, SDG::Manager) }
|
||||
it { should_not be_able_to(:delete, SDG::Manager) }
|
||||
end
|
||||
|
||||
96
spec/system/admin/sdg/managers_spec.rb
Normal file
96
spec/system/admin/sdg/managers_spec.rb
Normal file
@@ -0,0 +1,96 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe "Admin SDG managers", :js do
|
||||
let!(:user) { create(:user) }
|
||||
let!(:sdg_manager) { create(:sdg_manager) }
|
||||
|
||||
before do
|
||||
login_as(create(:administrator).user)
|
||||
visit admin_sdg_managers_path
|
||||
end
|
||||
|
||||
scenario "Index" do
|
||||
expect(page).to have_content sdg_manager.name
|
||||
expect(page).to have_content sdg_manager.email
|
||||
expect(page).not_to have_content user.name
|
||||
end
|
||||
|
||||
scenario "Create SDG Manager" do
|
||||
fill_in "search", with: user.email
|
||||
click_button "Search"
|
||||
|
||||
expect(page).to have_content user.name
|
||||
|
||||
click_link "Add"
|
||||
|
||||
within("#sdg_managers") do
|
||||
expect(page).to have_content user.name
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Delete SDG Manager" do
|
||||
accept_confirm { click_link "Delete" }
|
||||
|
||||
within("#sdg_managers") do
|
||||
expect(page).not_to have_content sdg_manager.name
|
||||
end
|
||||
end
|
||||
|
||||
context "Search" do
|
||||
let(:user) { create(:user, username: "Taylor Swift", email: "taylor@swift.com") }
|
||||
let(:user2) { create(:user, username: "Stephanie Corneliussen", email: "steph@mrrobot.com") }
|
||||
let!(:sdg_manager1) { create(:sdg_manager, user: user) }
|
||||
let!(:sdg_manager2) { create(:sdg_manager, user: user2) }
|
||||
|
||||
before do
|
||||
visit admin_sdg_managers_path
|
||||
end
|
||||
|
||||
scenario "returns no results if search term is empty" do
|
||||
expect(page).to have_content(sdg_manager1.name)
|
||||
expect(page).to have_content(sdg_manager2.name)
|
||||
|
||||
fill_in "search", with: " "
|
||||
click_button "Search"
|
||||
|
||||
expect(page).to have_content("SDG managers")
|
||||
expect(page).to have_content("There are no users.")
|
||||
expect(page).not_to have_content(sdg_manager1.name)
|
||||
expect(page).not_to have_content(sdg_manager2.name)
|
||||
end
|
||||
|
||||
scenario "search by name" do
|
||||
expect(page).to have_content(sdg_manager1.name)
|
||||
expect(page).to have_content(sdg_manager2.name)
|
||||
|
||||
fill_in "search", with: "Taylor"
|
||||
click_button "Search"
|
||||
|
||||
expect(page).to have_content("SDG managers")
|
||||
expect(page).to have_content(sdg_manager1.name)
|
||||
expect(page).not_to have_content(sdg_manager2.name)
|
||||
end
|
||||
|
||||
scenario "search by email" do
|
||||
expect(page).to have_content(sdg_manager1.email)
|
||||
expect(page).to have_content(sdg_manager2.email)
|
||||
|
||||
fill_in "search", with: sdg_manager2.email
|
||||
click_button "Search"
|
||||
|
||||
expect(page).to have_content("SDG managers")
|
||||
expect(page).to have_content(sdg_manager2.email)
|
||||
expect(page).not_to have_content(sdg_manager1.email)
|
||||
end
|
||||
|
||||
scenario "Delete after searching" do
|
||||
fill_in "Search user by name or email", with: sdg_manager2.email
|
||||
click_button "Search"
|
||||
|
||||
accept_confirm { click_link "Delete" }
|
||||
|
||||
expect(page).to have_content(sdg_manager1.email)
|
||||
expect(page).not_to have_content(sdg_manager2.email)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -42,6 +42,16 @@ describe "Admin" do
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario "Access as SDG manager is not authorized", :js do
|
||||
create(:sdg_manager, user: user)
|
||||
login_as(user)
|
||||
visit admin_root_path
|
||||
|
||||
expect(page).not_to have_current_path(admin_root_path)
|
||||
expect(page).to have_current_path(root_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario "Access as poll officer is not authorized" do
|
||||
login_as(create(:poll_officer).user)
|
||||
visit admin_root_path
|
||||
@@ -59,12 +69,15 @@ describe "Admin" do
|
||||
end
|
||||
|
||||
scenario "Admin access links", :admin do
|
||||
Setting["feature.sdg"] = true
|
||||
|
||||
visit root_path
|
||||
|
||||
expect(page).to have_link("Administration")
|
||||
expect(page).to have_link("Moderation")
|
||||
expect(page).to have_link("Valuation")
|
||||
expect(page).to have_link("Management")
|
||||
expect(page).to have_link("SDG content")
|
||||
end
|
||||
|
||||
scenario "Admin dashboard", :admin do
|
||||
|
||||
@@ -43,6 +43,21 @@ describe "Moderation" do
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario "Access as SDG manager is not authorized", :js do
|
||||
create(:sdg_manager, user: user)
|
||||
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).not_to have_link("Moderation")
|
||||
|
||||
visit moderation_root_path
|
||||
|
||||
expect(page).not_to have_current_path(moderation_root_path)
|
||||
expect(page).to have_current_path(root_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario "Access as poll officer is not authorized" do
|
||||
create(:poll_officer, user: user)
|
||||
|
||||
|
||||
@@ -42,6 +42,20 @@ describe "Poll Officing" do
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario "Access as SDG manager is not authorized", :js do
|
||||
create(:sdg_manager, user: user)
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).not_to have_link("Polling officers")
|
||||
|
||||
visit officing_root_path
|
||||
|
||||
expect(page).not_to have_current_path(officing_root_path)
|
||||
expect(page).to have_current_path(root_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario "Access as a valuator is not authorized" do
|
||||
create(:valuator, user: user)
|
||||
login_as(user)
|
||||
|
||||
@@ -42,6 +42,19 @@ describe "Valuation" do
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario "Access as SDG manager is not authorized" do
|
||||
create(:sdg_manager, user: user)
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
expect(page).not_to have_link("Valuation")
|
||||
visit valuation_root_path
|
||||
|
||||
expect(page).not_to have_current_path(valuation_root_path)
|
||||
expect(page).to have_current_path(root_path)
|
||||
expect(page).to have_content "You do not have permission to access this page"
|
||||
end
|
||||
|
||||
scenario "Access as poll officer is not authorized" do
|
||||
create(:poll_officer, user: user)
|
||||
login_as(user)
|
||||
|
||||
Reference in New Issue
Block a user