diff --git a/app/components/admin/header.rb b/app/components/admin/header.rb
new file mode 100644
index 000000000..015af44b0
--- /dev/null
+++ b/app/components/admin/header.rb
@@ -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
diff --git a/app/components/admin/sdg/managers/index_component.html.erb b/app/components/admin/sdg/managers/index_component.html.erb
new file mode 100644
index 000000000..1abb68e4f
--- /dev/null
+++ b/app/components/admin/sdg/managers/index_component.html.erb
@@ -0,0 +1,38 @@
+<%= header %>
+
+<%= render "admin/shared/user_search", url: admin_sdg_managers_path %>
+
+
+ <% if users.any? %>
+
<%= page_entries_info users %>
+
+
+
+ | <%= SDG::Manager.human_attribute_name(:name) %> |
+ <%= SDG::Manager.human_attribute_name(:email) %> |
+ <%= t("admin.shared.actions") %> |
+
+
+ <% users.each do |user| %>
+
+ |
+ <%= user.name %>
+ |
+
+ <%= user.email %>
+ |
+
+ <%= render Admin::Roles::TableActionsComponent.new(user.sdg_manager || user.build_sdg_manager) %>
+ |
+
+ <% end %>
+
+
+
+ <%= paginate users %>
+ <% else %>
+
+ <%= t("admin.sdg_managers.index.no_sdg_managers") %>
+
+ <% end %>
+
diff --git a/app/components/admin/sdg/managers/index_component.rb b/app/components/admin/sdg/managers/index_component.rb
new file mode 100644
index 000000000..d935f43e8
--- /dev/null
+++ b/app/components/admin/sdg/managers/index_component.rb
@@ -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
diff --git a/app/controllers/admin/sdg/managers_controller.rb b/app/controllers/admin/sdg/managers_controller.rb
new file mode 100644
index 000000000..3310e47f0
--- /dev/null
+++ b/app/controllers/admin/sdg/managers_controller.rb
@@ -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
diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb
index 978672daf..e93e68e96 100644
--- a/app/models/abilities/administrator.rb
+++ b/app/models/abilities/administrator.rb
@@ -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
diff --git a/app/models/user.rb b/app/models/user.rb
index 083f21732..f20db4bea 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -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") }
diff --git a/app/views/admin/sdg/managers/index.html.erb b/app/views/admin/sdg/managers/index.html.erb
new file mode 100644
index 000000000..b884b74df
--- /dev/null
+++ b/app/views/admin/sdg/managers/index.html.erb
@@ -0,0 +1 @@
+<%= render Admin::SDG::Managers::IndexComponent.new(@users) %>
diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml
index 73edfc440..bc561d093 100644
--- a/config/locales/en/activerecord.yml
+++ b/config/locales/en/activerecord.yml
@@ -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"
diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml
index 6c05bf15c..8fe8c4236 100644
--- a/config/locales/en/admin.yml
+++ b/config/locales/en/admin.yml
@@ -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
diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml
index 070ec9aa4..96f7fcd63 100644
--- a/config/locales/es/activerecord.yml
+++ b/config/locales/es/activerecord.yml
@@ -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"
diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml
index f970c74f4..0c18e9209 100644
--- a/config/locales/es/admin.yml
+++ b/config/locales/es/admin.yml
@@ -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
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index 20300220c..632a91a64 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -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
diff --git a/spec/models/abilities/administrator_spec.rb b/spec/models/abilities/administrator_spec.rb
index 47534629e..f237964dc 100644
--- a/spec/models/abilities/administrator_spec.rb
+++ b/spec/models/abilities/administrator_spec.rb
@@ -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
diff --git a/spec/models/abilities/common_spec.rb b/spec/models/abilities/common_spec.rb
index f90960888..336116012 100644
--- a/spec/models/abilities/common_spec.rb
+++ b/spec/models/abilities/common_spec.rb
@@ -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
diff --git a/spec/models/abilities/everyone_spec.rb b/spec/models/abilities/everyone_spec.rb
index 0b27be818..a5399e25b 100644
--- a/spec/models/abilities/everyone_spec.rb
+++ b/spec/models/abilities/everyone_spec.rb
@@ -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
diff --git a/spec/models/abilities/moderator_spec.rb b/spec/models/abilities/moderator_spec.rb
index 55e39372e..762583534 100644
--- a/spec/models/abilities/moderator_spec.rb
+++ b/spec/models/abilities/moderator_spec.rb
@@ -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
diff --git a/spec/models/abilities/organization_spec.rb b/spec/models/abilities/organization_spec.rb
index d10ac4507..2553b3f18 100644
--- a/spec/models/abilities/organization_spec.rb
+++ b/spec/models/abilities/organization_spec.rb
@@ -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
diff --git a/spec/models/abilities/sdg/manager.rb b/spec/models/abilities/sdg/manager.rb
index 910b886e2..004ad0ada 100644
--- a/spec/models/abilities/sdg/manager.rb
+++ b/spec/models/abilities/sdg/manager.rb
@@ -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
diff --git a/spec/models/abilities/valuator_spec.rb b/spec/models/abilities/valuator_spec.rb
index a8eeeb236..634dd7e92 100644
--- a/spec/models/abilities/valuator_spec.rb
+++ b/spec/models/abilities/valuator_spec.rb
@@ -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
diff --git a/spec/system/admin/sdg/managers_spec.rb b/spec/system/admin/sdg/managers_spec.rb
new file mode 100644
index 000000000..0f893e79b
--- /dev/null
+++ b/spec/system/admin/sdg/managers_spec.rb
@@ -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
diff --git a/spec/system/admin_spec.rb b/spec/system/admin_spec.rb
index e6949140d..169205b7f 100644
--- a/spec/system/admin_spec.rb
+++ b/spec/system/admin_spec.rb
@@ -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
diff --git a/spec/system/moderation_spec.rb b/spec/system/moderation_spec.rb
index 42199fcca..46923e1a1 100644
--- a/spec/system/moderation_spec.rb
+++ b/spec/system/moderation_spec.rb
@@ -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)
diff --git a/spec/system/officing_spec.rb b/spec/system/officing_spec.rb
index a2298d8fd..79301f8b3 100644
--- a/spec/system/officing_spec.rb
+++ b/spec/system/officing_spec.rb
@@ -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)
diff --git a/spec/system/valuation_spec.rb b/spec/system/valuation_spec.rb
index b14dbcc25..68c5f8285 100644
--- a/spec/system/valuation_spec.rb
+++ b/spec/system/valuation_spec.rb
@@ -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)