Skip to content

Commit

Permalink
Merge pull request #1001 from department-of-veterans-affairs/feature/…
Browse files Browse the repository at this point in the history
…dm-5105-ipm-integration

Feature: DM-5105 IPM Integration
  • Loading branch information
nuel247 authored Oct 23, 2024
2 parents 807956c + 5529931 commit 573a4a5
Show file tree
Hide file tree
Showing 185 changed files with 4,080 additions and 561 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ on:
branches:
[
"master",
"feature/dm-5105-ipm-integration",
"ci-migration",
"ci-migration-cv",
"ci-migration-en",
"ci-migration-pd",
"ci-migration-bj"
"ci-migration-bj",
]
pull_request:
branches: ["master"]
branches: ["master", "feature/dm-5105-ipm-integration"]
jobs:
build:
name: rspec
Expand Down
5 changes: 4 additions & 1 deletion app/admin/categories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@
end
row :related_terms
row "Innovations Tagged" do |c|
c.practices
c.innovable_practices
end
row "Products Tagged" do |c|
c.innovable_products
end
end
end
Expand Down
50 changes: 33 additions & 17 deletions app/admin/practice_partners.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
row('Practices') do |partner|
partner.practices.order(Arel.sql("lower(name) ASC"))
end
row('Products') do |partner|
partner.products.order(Arel.sql("lower(name) ASC"))
end
row('Major Practice Partner') { |partner| status_tag partner.is_major? }
end
active_admin_comments
Expand All @@ -49,6 +52,7 @@
f.input :icon
f.input :slug
f.input :practices, as: :select, multiple: true, include_blank: 'None', collection: Practice.published.order(Arel.sql("lower(name) ASC")).map { |p| ["#{p.name.capitalize}", p.id]}
f.input :products, as: :select, multiple: true, include_blank: 'None', collection: Product.published.order(Arel.sql("lower(name) ASC")).map { |p| ["#{p.name.capitalize}", p.id]}
f.input :is_major, label: 'Major practice partner?'
end
f.actions
Expand All @@ -61,7 +65,7 @@

controller do
before_action :set_selected_practices, only: :edit
after_action :update_partner_practices, only: [:create, :update]
after_action :update_partner_innovations, only: [:create, :update]

def find_resource
scoped_collection.friendly.find(params[:id])
Expand Down Expand Up @@ -120,23 +124,35 @@ def update
create_or_update_practice_partner
end

def update_partner_practices
practice_ids = params[:practice_partner][:practice_ids]
# if the 'None' option is selected, remove the first two practice partner ids -- first one is the hidden input, and the second is for the blank option. If not, just remove the first id for the hidden input
selected_practices = practice_ids === ['', ''] ? practice_ids.drop(2) : practice_ids.drop(1)
selected_practices.map! { |p| p.to_i }
practice_partner = PracticePartner.find_by(name: params[:practice_partner][:name])
current_partner_practices = PracticePartnerPractice.where(practice_partner_id: practice_partner[:id]) unless practice_partner.nil?

if selected_practices.length > 0 && practice_partner.present?
selected_practices.map { |p| PracticePartnerPractice.find_or_create_by!(practice_id: p, practice_partner_id: practice_partner[:id]) }
end
def update_partner_innovations
%w[practice product].each do |type|
ids_param = params[:practice_partner]["#{type}_ids"]
# if the 'None' option is selected, remove the first two practice partner ids -- first one is the hidden input, and the second is for the blank option. If not, just remove the first id for the hidden input
selected_ids = ids_param == ['', ''] ? ids_param.drop(2) : ids_param.drop(1)
selected_ids.map!(&:to_i)

practice_partner = PracticePartner.find_by(name: params[:practice_partner][:name])
current_partner_records = PracticePartnerPractice.where(
practice_partner_id: practice_partner[:id],
innovable_type: type.capitalize
) if practice_partner.present?

if selected_ids.any? && practice_partner.present?
selected_ids.each do |id|
PracticePartnerPractice.find_or_create_by!(
innovable_id: id,
practice_partner_id: practice_partner[:id],
innovable_type: type.capitalize
)
end
end

if params[:action] === 'update' && current_partner_practices.present?
if selected_practices.empty?
current_partner_practices.map { |p| p.destroy! }
else
current_partner_practices.map { |p| p.destroy! unless selected_practices.include? p.practice_id }
if params[:action] == 'update' && current_partner_records.present?
if selected_ids.empty?
current_partner_records.map(&:destroy!)
else
current_partner_records.each { |record| record.destroy! unless selected_ids.include?(record.innovable_id) }
end
end
end
end
Expand Down
10 changes: 5 additions & 5 deletions app/admin/practices.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include ApplicationHelper
include ActiveAdminHelpers
include PracticeEditorUtils
include InnovationEditorUtils
include UserUtils
include ActiveAdminUtils

Expand Down Expand Up @@ -334,7 +334,7 @@ def create_or_update_practice

set_practice_user(practice) if email.present?
practice.user = nil unless email.present?
if practice.user.present? && !is_user_an_editor_for_practice(practice, practice.user)
if practice.user.present? && !is_user_an_editor_for_innovation(practice, practice.user)
PracticeEditor.create_and_invite(practice, practice.user)
end
respond_to do |format|
Expand Down Expand Up @@ -395,7 +395,7 @@ def find_resource

def set_categories_view
@practice_categories = []
current_categories = CategoryPractice.where(practice_id: params[:id])
current_categories = CategoryPractice.where(innovable_id: params[:id])
unless current_categories.empty?
current_categories.map do |cp|
@practice_categories.push(cp[:category_id])
Expand All @@ -408,9 +408,9 @@ def update_categories
selected_categories = params[:practice][:category_ids].drop(1)
selected_categories.map! { |cat| cat.to_i }
practice = Practice.find_by(name: params[:practice][:name])
current_categories = CategoryPractice.where(practice_id: practice[:id]) unless practice.nil?
current_categories = CategoryPractice.where(innovable_id: practice[:id]) unless practice.nil?
if selected_categories.length > 0 && practice.present?
selected_categories.map { |cat| CategoryPractice.find_or_create_by!(category_id: cat, practice_id: practice[:id]) }
selected_categories.map { |cat| CategoryPractice.find_or_create_by!(category_id: cat, innovable_id: practice[:id], innovable_type: "Practice") }
end

if params[:action] == 'update' && current_categories.present?
Expand Down
170 changes: 170 additions & 0 deletions app/admin/products.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
include UserUtils

ActiveAdmin.register Product do
config.create_another = true
actions :all

# To do: set up index file export
index do
id_column
column 'Product Name', :name
column 'Owner Email', :user_email
column 'Published', :published
column 'Date Published', :date_published
column 'Created At', :created_at
column 'Last Updated', :updated_at
actions do |product|
product_retired_action_str = product.retired ? "Activate" : "Retire"
item product_retired_action_str, retire_product_admin_product_path(product), method: :post
product_published_action_str = product.published ? "Unpublish" : "Publish"
item product_published_action_str, publish_product_admin_product_path(product), method: :post
end
end

member_action :retire_product, method: :post do
resource.toggle!(:retired)
retired_state = resource.retired ? "retired" : "activated"
message = "\"#{resource.name}\" was #{retired_state}"
redirect_back fallback_location: root_path, notice: message
end

member_action :publish_product, method: :post do
resource.toggle!(:published)
published_state = resource.published ? "published" : "unpublished"
message = "\"#{resource.name}\" was #{published_state}"
redirect_back fallback_location: root_path, notice: message
end

filter :name
filter :user_email, label: "Owner Email"
filter :published

form do |f|
f.semantic_errors *f.object.errors.attribute_names# shows errors on :base
f.inputs do
f.input :name, label: 'Product name *Required*'
f.input :user, label: 'User email', as: :string, input_html: {name: 'user_email', value: f.object.user&.email || ''}
end
f.actions
end

show do
attributes_table do
row :id
row(:name, label: 'Product name') { |product| link_to(product.name, product_path(product)) }
row('Edit URL') { |product| link_to(product_description_path(product), product_description_path(product)) }
row(:user) {|product| link_to(product.user&.email, admin_user_path(product.user)) if product.user.present?}
row(:published, label: 'Published')
row(:date_published, label: 'Date Published')
row(:retired, label: 'Retired')
end
end

controller do
rescue_from ActiveRecord::RecordInvalid, with: :handle_error_redirect
def scoped_collection
super.left_joins(:user).includes(:user)
end

def find_resource
scoped_collection.friendly.find(params[:id])
end

def create
ActiveRecord::Base.transaction do
@product = Product.new(product_params)
handle_user_email(user_email_param)

if @product.save
add_user_as_editor
handle_redirect_after_save(@product, "created")
else
flash[:error] = @product.errors.map(&:message).join(', ')
redirect_to new_admin_product_path
end
end
end

def update
ActiveRecord::Base.transaction do
@product = Product.friendly.find(params[:id])
@product.assign_attributes(product_params)
handle_user_email(user_email_param)

if @product.save
add_user_as_editor
handle_redirect_after_save(@product, "updated")
else
flash[:error] = @product.errors.map(&:message).join(', ')
redirect_to edit_admin_product_path(@product)
end
end
end

private

def handle_user_email(email)
if email.present? && is_invalid_va_email(email)
@product.errors.add(:user_email, 'must be a valid @va.gov address')
raise ActiveRecord::RecordInvalid.new(@product)
end
set_product_user(email)
end

def handle_redirect_after_save(product, action)
if params[:create_another] == "on"
redirect_to new_admin_product_path, notice: "Product was successfully #{action}. You can create another one."
else
redirect_to admin_product_path(product), notice: "Product was successfully #{action}."
end
end

def handle_error_redirect(exception)
error_messages = exception.record.errors.map do |error|
error.options[:message] || "Email #{error.type}"
end
path = action_name == 'update' ? edit_admin_product_path(@product) : new_admin_product_path
redirect_to path, flash: { error: error_messages.join(', ') }
end

def set_product_user(email)
if email.blank?
@product.user = nil
return
end

return if @product.user_email == email

user = User.find_by(email: email)
if user.nil?
@product.errors.add(:user_email, 'does not match any registered users')
raise ActiveRecord::RecordInvalid.new(@product)
else
@product.user = user
end

# Uncomment and update for Product when show page / commontator functionality enabled:
# if the practice user is updated, remove the previous product user from the
# commontator_thread subscribers list if the following conditions are also true
# if previous_product_user.present? && previous_product_user != product.user &&
# product.commontator_thread.comments.where(creator_id: previous_product_user.id).empty?
# product.commontator_thread.unsubscribe(previous_product_user)
# end
# product.commontator_thread.subscribe(user)
end

def add_user_as_editor
if @product.user.present? && !is_user_an_editor_for_innovation(@product, @product.user)
PracticeEditor.create_and_invite(@product, @product.user)
end
end

def product_params
params.require(:product).permit(:name)
end

def user_email_param
params[:user_email].presence
end
end
end
7 changes: 6 additions & 1 deletion app/assets/javascripts/_introduction_image_editor.es6
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@
let $cancelEditBtn;
let $deleteInput;
let $imgsContainer;
let fileUploadHtml = `<input class="dm-cropper-upload-image usa-file-input" accept="image/*" type="file" name="practice[main_display_image]" id="practice_main_display_image">`;

function _clearUpload({ target }) {
let $imgImgsContainer = $(target).closest('.dm-cropper-boundary').find($imgsContainer)
$imgImgsContainer.empty();

let modelType = $(target).closest('.dm-cropper-boundary').data('model-type');

// Dynamically set the correct input HTML based on the model type
let fileUploadHtml = `<input class="dm-cropper-upload-image usa-file-input" accept="image/*" type="file" name="${modelType}[main_display_image]" id="${modelType}_main_display_image">`;

let fileUploadExists = $('.usa-file-input').length > 0;

if (fileUploadExists) {
Expand Down
Loading

0 comments on commit 573a4a5

Please sign in to comment.