Skip to content

Commit

Permalink
Add collaborator actions to Admin::Users#edit
Browse files Browse the repository at this point in the history
  • Loading branch information
phil-l-brockwell committed Dec 9, 2024
1 parent 9a806a0 commit 55385ef
Show file tree
Hide file tree
Showing 14 changed files with 313 additions and 3 deletions.
5 changes: 5 additions & 0 deletions app/controllers/admin/admins_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
class Admin::AdminsController < Admin::UsersController
before_action :find_resource, except: [:index, :new, :create, :login_as_assessor, :login_as_user]

expose(:collaborators) do
nil
end

def index
params[:search] ||= AdminSearch::DEFAULT_SEARCH
params[:search].permit!
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/admin/assessors_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ class Admin::AssessorsController < Admin::UsersController
:bulk_deactivate_dt,
]

expose(:collaborators) do
nil
end

def index
params[:search] ||= AssessorSearch::DEFAULT_SEARCH
params[:search].permit!
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/admin/judges_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
class Admin::JudgesController < Admin::UsersController
expose(:collaborators) do
nil
end

def index
params[:search] ||= JudgeSearch::DEFAULT_SEARCH
params[:search].permit!
Expand Down
52 changes: 52 additions & 0 deletions app/controllers/admin/users/collaborators_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
class Admin::Users::CollaboratorsController < Admin::BaseController
expose(:user) do
User.find(params[:user_id])
end

expose(:collaborator) do
User.find(params[:collaborator_id])
end

expose(:search_users) do
AdminActions::SearchCollaboratorCandidates.new(existing_collaborators: user.account.users, params: search_params)
end

expose(:add_collaborator_interactor) do
AdminActions::AddCollaborator.new(account: user.account, collaborator:, params: create_params)
end

expose(:candidates) do
search_users.candidates
end

def search
authorize user, :can_add_collaborators_to_account?
search_users.run if search_users.valid?
end

def create
authorize user, :can_add_collaborators_to_account?

add_collaborator_interactor.run.tap do |result|
if result.success?
redirect_to edit_admin_user_path(user), notice: "#{collaborator.email} successfully added to Collaborators!"
else
redirect_to edit_admin_user_path(user), notice: "#{collaborator.email} could not be added to Collaborators: #{result.error_messages}"
end
end
end

private

def create_params
params.require(:user).permit(:transfer_form_answers, :new_owner_id, :role).tap do |p|
p[:transfer_form_answers] = ActiveModel::Type::Boolean.new.cast(p[:transfer_form_answers])
end
end

def search_params
return if params[:search].blank?

params.require(:search).permit(:query)
end
end
4 changes: 4 additions & 0 deletions app/controllers/admin/users_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
class Admin::UsersController < Admin::BaseController
before_action :find_resource, except: [:index, :new, :create]

expose(:collaborators) do
@resource.account.collaborators_without(@resource)
end

def index
params[:search] ||= UserSearch::DEFAULT_SEARCH
params[:search].permit!
Expand Down
2 changes: 1 addition & 1 deletion app/policies/user_policy.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class UserPolicy < ApplicationPolicy
%w[index? update? create? show? new?].each do |method|
%w[index? update? create? show? new? can_add_collaborators_to_account?].each do |method|
define_method method do
admin?
end
Expand Down
5 changes: 3 additions & 2 deletions app/views/admin/users/_fields_collaborators.html.slim
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/ TODO collaborators new/delete, also the collaborators variable
- if action_name == "edit"
- collaborators = resource.account.collaborators_without(resource)
- if collaborators.any?
= render "admin/collaborators/list", collaborators: collaborators
- else
Expand All @@ -11,3 +9,6 @@
br
p.p-empty This user has not added any collaborators.
br

- if policy(resource).can_add_collaborators_to_account?
= render "admin/users/collaborators/search_form", resource: resource
27 changes: 27 additions & 0 deletions app/views/admin/users/collaborators/_search_form.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
= simple_form_for :search,
url: search_admin_user_collaborators_url(resource),
remote: true,
method: :get,
as: nil,
html: { class: "admin-search-collaborators-form" } do |f|

.form-container
label.form-label for="admin-search-collaborators-query" Add collaborator

.alert.alert-danger.hidden.js-admin-search-collaborators-error-box role="alert"

.form-block
.row
.col-md-12
= f.input :query,
as: :string,
label: false,
input_html: { class: "form-control", id: "admin-search-collaborators-query" },
wrapper_html: { class: 'pull-left col-md-10 admin-search-collaborators-query' },
placeholder: "Type part of email, first name or last name"

.text-right
= f.submit "Search", class: "btn btn-primary pull-right"
.clear

ul.list-unstyled.list-actions.hidden.js-admin-search-collaborators-results-box
9 changes: 9 additions & 0 deletions app/views/admin/users/collaborators/_search_results.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- if candidates.present?
- candidates.each do |candidate|
li.list-group-item id="user_#{candidate.id}"
p.pull-right
= link_to "#{candidate.full_name} (#{candidate.email})", edit_admin_user_path(candidate)

br

p= render "admin/users/collaborators/transfer_form", collaborator: candidate
29 changes: 29 additions & 0 deletions app/views/admin/users/collaborators/_transfer_form.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
= simple_form_for :user, url: admin_user_collaborators_url(collaborator_id: collaborator.id), method: :post do |f|
- if collaborator&.account.collaborators_without(collaborator).any? && collaborator.account.owner == collaborator
.question-group
h3 = f.label :new_owner_id, label: "Owner"
.row
.col-sm-6
= f.select :new_owner_id,
collaborator.account.collaborators_without(collaborator).map { |u| [u.email, u.id] },
{ include_blank: 'Select New Owner…' },
{ class: "form-control" }

.question-group
h3 = f.label :role, label: "Role"
.row
.col-sm-4
= f.select :role,
User::POSSIBLE_ROLES.map { |r| [r.humanize, r] },
{ selected: collaborator.role },
{ class: "form-control" }

- if collaborator.form_answers.any?
.question-group
h3 = f.label :transfer_form_answers, label: "Transfer existing Application/s"
.row
.col-sm-2
= f.check_box :transfer_form_answers, value: true

br
= f.submit "Transfer", class: "btn btn-secondary"
6 changes: 6 additions & 0 deletions app/views/admin/users/collaborators/search.js.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- if search_users.valid?
| $('.js-admin-search-collaborators-results-box').html("#{j render("search_results")}").removeClass("hidden");
| $(".js-admin-search-collaborators-error-box").addClass("hidden");
- else
| $('.js-admin-search-collaborators-results-box').addClass("hidden");
| $(".js-admin-search-collaborators-error-box").text("#{search_users.error.html_safe}").removeClass("hidden");
10 changes: 10 additions & 0 deletions app/views/admin/users/edit.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,13 @@
= "Edit #{controller_name == "users" ? "applicant" : controller_name.singularize}"

= render 'form', resource: @resource

- if collaborators
.panel.panel-default[data-controller="element-focus"]
.panel-heading id="section-collaborators-header"
h2.panel-title
a.collapsed data-toggle="collapse" data-parent="#user-form-panel" href="#section-collaborators" aria-expanded="false" aria-controls="section-collaborators" data-element-focus-target="reveal"
' Collaborators
#section-collaborators.section-collaborators.panel-collapse.collapse[aria-labelledby="section-collaborators-header" data-element-scroll-target="accordion"]
.panel-body
= render "fields_collaborators", resource: @resource
4 changes: 4 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,10 @@
patch :unlock
post :scan_via_debounce_api
end

resources :collaborators, only: [:create], module: :users do
get :search, on: :collection
end
end

resources :collaborator_deletion, only: [:destroy]
Expand Down
155 changes: 155 additions & 0 deletions spec/features/admin/users/collaborators_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
require "rails_helper"

describe "Collaborators", '
As a an Admin
I want to be able to add collaborators to any account
So that they can collaborate applications
', js: true do
include ActiveJob::TestHelper

let!(:admin) { create(:admin) }
let(:existing_user) { create(:user, :completed_profile) }

before do
login_admin admin
visit edit_admin_user_path(existing_user)
end

def search_for_user(email)
find("a[aria-controls='section-collaborators']").click

within(".admin-search-collaborators-form") do
fill_in "search[query]", with: email.to_s[2..-2]
first("input[type='submit']").click
end
end

describe "Add Collaborator" do
let(:email) { generate(:email) }
let!(:user) { create(:user, email: email) }
let(:form_answers) { [] }

context "with the Account Admin role" do
let(:role) { "Account admin" }

before do
search_for_user(email)
transfer_user(role)
end

it "should transfer the user with the correct role" do
expect(page).to have_content("#{email} successfully added to Collaborators!")
expect(page).to have_content("#{email} successfully added to Collaborators!")
login_as existing_user
click_link "Collaborators"
expect_to_see_user(user, role: "Admin and collaborator")
end
end

context "with the regular role" do
let(:role) { "Regular" }

before do
search_for_user(email)
transfer_user(role)
end

it "should transfer the user with the correct role" do
expect(page).to have_content("#{email} successfully added to Collaborators!")
expect(page).to have_content("#{email} successfully added to Collaborators!")
login_as existing_user
click_link "Collaborators"
expect_to_see_user(user, role: "Collaborator only")
end
end

context "with form_answers" do
let!(:form_answers) { create_list(:form_answer, 3, user: user, account: user.account) }
let(:role) { "Account admin" }
context "when transferring form_answers" do
before do
search_for_user(email)
transfer_user(role, transfer_form_answers: true)
end

it "should transfer the form_answers and user with the correct role" do
expect(page).to have_content("#{email} successfully added to Collaborators!")
login_as existing_user, scope: :user
click_link "Collaborators"
expect_to_see_user(user, role: "Admin and collaborator")
expect(existing_user.account.reload.form_answers).to eq(form_answers)
expect(user.reload.form_answers).to eq(form_answers)
end
end

context "when not transferring form_answers" do
context "with no other users" do
before do
search_for_user(email)
transfer_user(role, transfer_form_answers: false)
end

it "should transfer the user with the correct role" do
expect(page).to have_content("#{email} successfully added to Collaborators!")
login_as existing_user
click_link "Collaborators"
expect_to_see_user(user, role: "Admin and collaborator")
expect(existing_user.account.reload.form_answers).to eq([])
expect(user.reload.form_answers).to eq([])
end
end

context "with other users" do
let!(:other_user) { create(:user, :completed_profile, account: user.account) }

before do
search_for_user(email)
transfer_user(role, transfer_form_answers: false, new_owner: other_user)
end

it "should transfer the user with the correct role" do
expect(page).to have_content("#{email} successfully added to Collaborators!")
login_as existing_user
click_link "Collaborators"
expect_to_see_user(user, role: "Admin and collaborator")
expect(existing_user.account.reload.form_answers).to eq([])
expect(user.reload.form_answers).to eq([])
expect(other_user.reload.form_answers).to eq(form_answers)
end
end

context "when the form_answers are in progress" do
let!(:form_answers) { create_list(:form_answer, 3, :development, user: user, account: user.account) }

before do
search_for_user(email)
transfer_user(role, transfer_form_answers: false)
end

it "should display an error" do
expect(page).to have_content(
"#{user.email} could not be added to Collaborators: User has applications in progress, and there are no other users on the account to transfer them to",
)
end
end
end
end
end

def expect_to_see_user(user, role:)
within "#user_#{user.id}" do
expect(page).to have_content(user.full_name)
expect(page).to have_content(role)
end
end

def transfer_user(role, transfer_form_answers: false, new_owner: nil)
within(".js-admin-search-collaborators-results-box") do
select role, from: "user[role]"
select new_owner.email, from: "user[new_owner_id]" if new_owner
check "user[transfer_form_answers]" if transfer_form_answers

click_button "Transfer"
end
end
end

0 comments on commit 55385ef

Please sign in to comment.