Skip to content

Commit

Permalink
Add 'Primary Option' for each contact type on Matches (#859)
Browse files Browse the repository at this point in the history
* Add Primary Contact concept to match contacts

* rubocop

* async primary ling to remove jumpiness from modal postback

* contact order script cleanup

* Add primary contact filter to MAtches by Contacts dashboard report

* contact order filter - rename to be more clear what it is filtering

* setting contact order - include transaction adn update_all

* centralize and clean up match lists

* Only display primary contact icons when more than one contact is available.

* rerender tooltips after ajax call

* Add some padding to the primary checkbox when not in the modal

* fix for tooltips when new contact is added

* remove arel where not needed

* clean up additional contact lists

* Update migration to set contacts that are the only contact of that type on a match as the primary contact

---------

Co-authored-by: Elliot Anders <[email protected]>
  • Loading branch information
dtgreiner and eanders authored Sep 17, 2024
1 parent 4e7bf57 commit 362a97f
Show file tree
Hide file tree
Showing 24 changed files with 404 additions and 198 deletions.
156 changes: 101 additions & 55 deletions app/controllers/match_contacts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,72 +22,118 @@ def edit
def update
update_params = match_contacts_params
saved = @match_contacts.update(update_params)
unless request.xhr?
if saved
flash[:notice] = "Match Contacts updated"
redirect_to match_path(@match)
else
raise @match_contacts.errors.full_messages.inspect
flash[:error] = "Please review the form problems below."
redirect_to :edit
end
return if request.xhr?

if saved
flash[:notice] = 'Match Contacts updated'
redirect_to match_path(@match)
else
raise @match_contacts.errors.full_messages.inspect
flash[:error] = 'Please review the form problems below.' # rubocop:disable Lint/UnreachableCode
redirect_to :edit
end
end

def reorder
return unless params[:join_contact]

order_number = 1 # Default to setting the contact as primary
order_number = params[:order_number].to_i if params[:order_number]
set_contact_order(params[:join_contact], order_number)
set_match
set_match_contacts
# byebug
return if request.xhr?

redirect_to match_path(@match)
end

private

def match_scope
ClientOpportunityMatch.all
end
def set_contact_order(update_contact, order_number = 1)
ClientOpportunityMatchContact.transaction do
join_contact = match.client_opportunity_match_contacts.find(update_contact)
contact_type = nil
match_contact_methods.each do |type, _|
contact_type = type if join_contact.send(type)
end

def set_match
@match = match_scope.find params[:match_id]
end
# We currently only want one contact per order number, so strip order status for any other contacts in the group
@match.client_opportunity_match_contacts.where(contact_type => true, contact_order: order_number).update_all(contact_order: nil)

def set_current_contact
@current_contact = current_contact
# Set the selected contact as ordered contact
join_contact.contact_order = order_number
join_contact.save!
end
end

def set_match_contacts
@match_contacts = @match.match_contacts
end
def match_contact_methods
@match_contact_methods ||= {
shelter_agency: :shelter_agency_contacts,
client: :client_contacts,
dnd_staff: :dnd_staff_contacts,
housing_subsidy_admin: :housing_subsidy_admin_contacts,
ssp: :ssp_contacts,
hsp: :hsp_contacts,
do: :do_contacts,
}
end

def match_contacts_params
base_params = params[:match_contacts] || ActionController::Parameters.new
base_params.permit(
shelter_agency_contact_ids: [],
housing_subsidy_admin_contact_ids: [],
dnd_staff_contact_ids: [],
client_contact_ids: [],
ssp_contact_ids: [],
hsp_contact_ids: [],
do_contact_ids: [],
).tap do |result|
if current_contact.user_can_edit_match_contacts?
result[:shelter_agency_contact_ids] ||= []
result[:client_contact_ids] ||= []
result[:dnd_staff_contact_ids] ||= []
result[:housing_subsidy_admin_contact_ids] ||= []
result[:ssp_contact_ids] ||= []
result[:hsp_contact_ids] ||= []
result[:do_contact_ids] ||= []
elsif hsa_can_edit_contacts?
# only allow editing of the hsa contacts
result[:shelter_agency_contact_ids] = @match.shelter_agency_contact_ids
result[:client_contact_ids] = @match.client_contact_ids
result[:dnd_staff_contact_ids] = @match.dnd_staff_contact_ids
result[:housing_subsidy_admin_contact_ids] ||= []
result[:ssp_contact_ids] = @match.ssp_contact_ids
result[:hsp_contact_ids] = @match.hsp_contact_ids
result[:do_contact_ids] = @match.do_contact_ids
# always add self
result[:housing_subsidy_admin_contact_ids] << current_contact.id unless result[:housing_subsidy_admin_contact_ids].map(&:to_i).include? current_contact.id
end
end
end
def match_contacts_method_for input_name
match_contact_methods[input_name] || input_name
end

def match_scope
ClientOpportunityMatch.all
end

def require_current_contact_can_edit_match_contacts!
not_authorized! unless current_contact.user_can_edit_match_contacts? || hsa_can_edit_contacts?
def set_match
@match = match_scope.find params[:match_id]
end

def set_current_contact
@current_contact = current_contact
end

def set_match_contacts
@match_contacts = @match.match_contacts
end

def match_contacts_params
base_params = params[:match_contacts] || ActionController::Parameters.new
base_params.permit(
shelter_agency_contact_ids: [],
housing_subsidy_admin_contact_ids: [],
dnd_staff_contact_ids: [],
client_contact_ids: [],
ssp_contact_ids: [],
hsp_contact_ids: [],
do_contact_ids: [],
).tap do |result|
if current_contact.user_can_edit_match_contacts?
result[:shelter_agency_contact_ids] ||= []
result[:client_contact_ids] ||= []
result[:dnd_staff_contact_ids] ||= []
result[:housing_subsidy_admin_contact_ids] ||= []
result[:ssp_contact_ids] ||= []
result[:hsp_contact_ids] ||= []
result[:do_contact_ids] ||= []
elsif hsa_can_edit_contacts?
# only allow editing of the hsa contacts
result[:shelter_agency_contact_ids] = @match.shelter_agency_contact_ids
result[:client_contact_ids] = @match.client_contact_ids
result[:dnd_staff_contact_ids] = @match.dnd_staff_contact_ids
result[:housing_subsidy_admin_contact_ids] ||= []
result[:ssp_contact_ids] = @match.ssp_contact_ids
result[:hsp_contact_ids] = @match.hsp_contact_ids
result[:do_contact_ids] = @match.do_contact_ids
# always add self
result[:housing_subsidy_admin_contact_ids] << current_contact.id unless result[:housing_subsidy_admin_contact_ids].map(&:to_i).include? current_contact.id
end
end
end

def require_current_contact_can_edit_match_contacts!
not_authorized! unless current_contact.user_can_edit_match_contacts? || hsa_can_edit_contacts?
end
end
32 changes: 31 additions & 1 deletion app/models/client_contact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,41 @@
###

class ClientContact < ApplicationRecord

belongs_to :client, inverse_of: :client_contacts
belongs_to :contact, inverse_of: :client_contacts

acts_as_paranoid
has_paper_trail

def self.contact_types
[
:regular,
:shelter_agency,
:dnd_staff,
:housing_subsidy_admin,
:ssp,
:hsp,
:do,
].freeze
end

def self.contact_type_columns
contact_types.map { |t| ["#{t}_contacts".to_sym, t] }.to_h
end

def self.available_contact_methods
contact_types.map { |t| ["#{t}_contacts".to_sym, "available_#{t}_contacts".to_sym] }.to_h
end

def self.available_contact_method_for(contact_type)
available_contact_methods[contact_type] || contact_type
end

def self.selected_contact_methods
contact_types.map { |t| ["#{t}_contacts".to_sym, "#{t}_contacts".to_sym] }.to_h
end

def self.selected_contact_method_for(contact_type)
selected_contact_methods[contact_type] || contact_type
end
end
32 changes: 3 additions & 29 deletions app/models/client_contacts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,44 +101,18 @@ def progress_update_contact_ids
end

def self.input_names
[
:regular_contacts,
:shelter_agency_contacts,
:dnd_staff_contacts,
:housing_subsidy_admin_contacts,
:ssp_contacts,
:hsp_contacts,
:do_contacts,
]
ClientContact.contact_type_columns.keys
end

def input_names
self.class.input_names
end

def available_contacts_method_for input_name
@available_contacts_methods ||= {
shelter_agency_contacts: :available_shelter_agency_contacts,
regular_contacts: :available_regular_contacts,
dnd_staff_contacts: :available_dnd_staff_contacts,
housing_subsidy_admin_contacts: :available_housing_subsidy_admin_contacts,
ssp_contacts: :available_ssp_contacts,
hsp_contacts: :available_hsp_contacts,
do_contacts: :available_do_contacts,
}
@available_contacts_methods[input_name] || input_name
ClientContact.available_contact_method_for(input_name)
end

def selected_contacts_method_for input_name
@selected_contacts_methods ||= {
shelter_agency_contacts: :shelter_agency_contacts,
regular_contacts: :regular_contacts,
dnd_staff_contacts: :dnd_staff_contacts,
housing_subsidy_admin_contacts: :housing_subsidy_admin_contacts,
ssp_contacts: :ssp_contacts,
hsp_contacts: :hsp_contacts,
do_contacts: :do_contacts,
}
@selected_contacts_methods[input_name] || input_name
ClientContact.selected_contact_method_for(input_name)
end
end
50 changes: 49 additions & 1 deletion app/models/client_opportunity_match_contact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,62 @@ class ClientOpportunityMatchContact < ApplicationRecord

acts_as_paranoid

scope :for_contact_type, ->(contact_type) do
contact_type_column = ClientOpportunityMatchContact.column_for(contact_type)
where(contact_type_column => true)
end

def self.text_search(text)
return none unless text.present?

contact_matches = Contact.where(
Contact.arel_table[:id].eq(arel_table[:contact_id])
Contact.arel_table[:id].eq(arel_table[:contact_id]),
).text_search(text).arel.exists

where(contact_matches)
end

def self.contact_types
[
:shelter_agency,
:client,
:dnd_staff,
:housing_subsidy_admin,
:ssp,
:hsp,
:do,
].freeze
end

def self.contact_type_columns
contact_types.map { |t| ["#{t}_contacts".to_sym, t] }.to_h
end

def self.column_for(contact_type)
contact_type_columns[contact_type] || contact_type
end

def self.join_contact_methods
contact_types.map { |t| ["#{t}_contacts".to_sym, "#{t}_join_contacts".to_sym] }.to_h
end

def self.join_method_for(contact_type)
join_contact_methods[contact_type] || contact_type
end

def self.available_contact_methods
contact_types.map { |t| ["#{t}_contacts".to_sym, "available_#{t}_contacts".to_sym] }.to_h
end

def self.available_contact_method_for(contact_type)
available_contact_methods[contact_type] || contact_type
end

def self.selected_contact_methods
contact_types.map { |t| ["#{t}_contacts".to_sym, "#{t}_contacts".to_sym] }.to_h
end

def self.selected_contact_method_for(contact_type)
selected_contact_methods[contact_type] || contact_type
end
end
6 changes: 3 additions & 3 deletions app/models/concerns/contact_join_model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ module ContactJoinModel
extend ActiveSupport::Concern

included do
delegate :full_name, :email, :phone, :role,
to: :contact, allow_nil: true, prefix: true
delegate :full_name, :email, :phone, :role, :contact_order,
to: :contact, allow_nil: true, prefix: true

accepts_nested_attributes_for :contact

def self.model_name
# really just needed for route_key
# keeps standard naming but uses 'contact' for routes
@_model_name ||= ActiveModel::Name.new(self, nil, to_s.demodulize.underscore).tap do |model_name|
@model_name ||= ActiveModel::Name.new(self, nil, to_s.demodulize.underscore).tap do |model_name|
model_name.instance_variable_set(:@route_key, 'contacts')
model_name.instance_variable_set(:@singular_route_key, 'contact')
end
Expand Down
3 changes: 3 additions & 0 deletions app/models/concerns/related_default_contacts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ def contact_scope
Contact.active_contacts
end

def contact_order
end

def available_shelter_agency_contacts
contact_scope.where.not(id: shelter_agency_contact_ids)
end
Expand Down
6 changes: 6 additions & 0 deletions app/models/concerns/reporting/filter_scopes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,11 @@ module Reporting::FilterScopes

scope.contacts_in_type(@filter.contacts.map(&:to_s), @filter.contact_type)
end

private def filter_for_contact_order(scope)
return scope if @filter.contact_order.blank? || @filter.contact_order.zero?

scope.contacts_with_order_value(@filter.contacts.map(&:to_s), @filter.contact_order)
end
end
end
1 change: 0 additions & 1 deletion app/models/concerns/updateable_attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,4 @@ def update attrs = {}
assign_attributes attrs
save
end

end
Loading

0 comments on commit 362a97f

Please sign in to comment.