Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OSU-114] Service sanger admin tab #4931

Merged
merged 7 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/views/shared/nav/_manage_product.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
= content_for :h1 do
= current_facility
= content_for :sidebar do
= render "admin/shared/sidenav_product", sidenav_tab: @product.class.name.pluralize.underscore
= content_for :tabnav do
= render "admin/shared/tabnav_product", secondary_tab: local_assigns[:secondary_tab]
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2025_01_10_132703) do
ActiveRecord::Schema[7.0].define(version: 2025_01_13_205804) do
create_table "account_facility_joins", id: :integer, charset: "utf8mb3", force: :cascade do |t|
t.integer "facility_id", null: false
t.integer "account_id", null: false
Expand Down Expand Up @@ -735,6 +735,7 @@
t.string "group", null: false
t.datetime "created_at", precision: nil
t.datetime "updated_at", precision: nil
t.boolean "needs_primer", default: false, null: false
t.index ["product_id"], name: "index_sanger_seq_product_groups_on_product_id", unique: true
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class UploadError < StandardError

def validate_product_group
@product_group = params[:group].presence
raise ActiveRecord::RecordNotFound unless @product_group.blank? || ProductGroup::GROUPS.include?(@product_group)
raise ActiveRecord::RecordNotFound unless @product_group.blank? || SangerProduct::GROUPS.include?(@product_group)
end

def load_batch
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

module SangerSequencing

class SangerProductsController < BaseController
before_action :set_resources
before_action { @active_tab = "admin_products" }
before_action { authorize! :manage, current_facility }

layout "two_column"
admin_tab :all

def show
end

def edit
end

def update
if @sanger_product.update(sanger_product_params)
redirect_to [current_facility, @product, :sanger_sequencing, :sanger_product], notice: text(".update.success")
else
render :edit
end
end

private

def sanger_product_groups
SangerProduct::GROUPS.map do |group|
[SangerProduct.human_attribute_name("group.#{group}"), group]
end
end

helper_method :sanger_product_groups

def sanger_product_params
params.require(:sanger_sequencing_sanger_product).permit(
:needs_primer,
:group
)
end

def set_resources
@product = current_facility.products.find_by!(
url_name: params[:service_id]
)
@sanger_product = @product.sanger_product || @product.create_sanger_product
end
end

end
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

module SangerSequencing

module SangerEnabledProduct

extend ActiveSupport::Concern

included do
has_one :sanger_product, class_name: "SangerSequencing::SangerProduct", foreign_key: :product_id
end

end

end
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@

module SangerSequencing

class ProductGroup < ApplicationRecord
##
# Model that holds Sanger module configuration
# for a product
class SangerProduct < ApplicationRecord

# sanger_sequencing_product_groups is too long of a table name for Oracle
self.table_name = "sanger_seq_product_groups"
GROUPS = WellPlateConfiguration::CONFIGS.keys

belongs_to :product

attribute :group, default: 'default'

validates :group, presence: true, inclusion: { in: GROUPS }
validates :product, presence: true, uniqueness: { case_sensitive: false }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ class Submission < ApplicationRecord

def self.for_product_group(product_group)
if product_group.present?
where(order_details: { product_id: ProductGroup.where(group: product_group).pluck(:product_id) })
where(order_details: { product_id: SangerProduct.where(group: product_group).pluck(:product_id) })
else
where.not(order_details: { product_id: ProductGroup.pluck(:product_id) })
where.not(order_details: { product_id: SangerProduct.pluck(:product_id) })
end
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- if @product.sanger_sequencing_enabled? && can?(:manage, current_facility)
= tab t("sanger_sequencing.tabnav_product"),
facility_service_sanger_sequencing_sanger_product_path(current_facility, @product),
(secondary_tab == "sanger")
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
= render "shared/nav/manage_product", secondary_tab: "sanger"

%h2= text("title")

= simple_form_for @sanger_product, url: facility_service_sanger_sequencing_sanger_product_path(current_facility, @product) do |f|
= f.input :needs_primer,
as: :boolean,
label: false,
inline_label: SangerSequencing::SangerProduct.human_attribute_name(:needs_primer),
include_blank: false,
hint: text("needs_primer")

= f.input :group,
collection: sanger_product_groups,
hint: text("group")

= f.submit text("shared.save"), class: "btn btn-primary"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
= render "shared/nav/manage_product", secondary_tab: "sanger"

%h2= text("title")

= readonly_form_for @sanger_product.class.name.underscore, @sanger_product do |f|
= f.input :needs_primer, as: :boolean
= f.input :group,
input_html: { value: SangerSequencing::SangerProduct.human_attribute_name("group.#{@sanger_product.group}") }

- if can? :edit, @product
%ul.inline
%li= link_to "Edit", edit_facility_service_sanger_sequencing_sanger_product_path(current_facility, @product), class: "btn"

17 changes: 17 additions & 0 deletions vendor/engines/sanger_sequencing/config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,27 @@ en:
product_groups:
default: Sanger Sequencing
fragment: Fragment Analysis
tabnav_product: Sanger

controllers:
sanger_sequencing/admin/batches:
create:
success: "We have saved your batch"
destroy:
success: "Batch was successfully deleted"
sanger_sequencing/sanger_products:
update:
success: Sanger Configuration updated successfully

views:
sanger_sequencing:
sanger_products:
show:
title: Sanger Configuration
edit:
title: Sanger Configuration
needs_primer: Require submissions to include a primer
group: Submissions of the same type can be batched together
submissions:
form:
submit: "Save Submission"
Expand Down Expand Up @@ -52,6 +63,12 @@ en:
sanger_sequencing/batch:
created_at: Created
created_by: Created By
sanger_sequencing/sanger_product:
needs_primer: Needs a Primer
group: Plated Service Type
sanger_sequencing/sanger_product/group:
default: Sanger Sequencing
fragment: Fragment Analysis

models:
sanger_sequencing/submission:
Expand Down
5 changes: 5 additions & 0 deletions vendor/engines/sanger_sequencing/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
end

resources :facilities, only: [] do
resources :services, only: [] do
namespace :sanger_sequencing do
resource :sanger_product, only: [:show, :edit, :update]
end
end
namespace :sanger_sequencing do
namespace :admin do
resources :submissions, only: [:index, :show]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

class AddProductGroupPrimer < ActiveRecord::Migration[4.2]
LeticiaErrandonea marked this conversation as resolved.
Show resolved Hide resolved
def change
add_column(
:sanger_seq_product_groups,
:needs_primer,
:boolean,
default: false,
null: false
)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ class Engine < ::Rails::Engine

ViewHook.add_hook "orders.receipt", "after_note", "sanger_sequencing/orders/samples_on_receipt"
ViewHook.add_hook "purchase_notifier.order_receipt", "after_note", "sanger_sequencing/orders/samples_on_receipt"
ViewHook.add_hook(
"admin.shared.tabnav_product",
"additional_tabs",
"sanger_sequencing/admin/shared/tabnav_product/sanger"
)

Service.include SangerSequencing::SangerEnabledProduct
end

config.generators do |g|
Expand Down
2 changes: 0 additions & 2 deletions vendor/engines/sanger_sequencing/sanger_sequencing.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,4 @@ Gem::Specification.new do |s|

s.add_dependency "rails", ">= 4.0"
# s.add_dependency "jquery-rails"

s.add_development_dependency "rails-rspec"
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# frozen_string_literal: true

require "rails_helper"
require "controller_spec_helper"

RSpec.describe SangerSequencing::SangerProductsController do
let(:facility) { create(:setup_facility, sanger_sequencing_enabled: true) }
let(:service) { create(:setup_service, facility:, sanger_sequencing_enabled: true) }
let(:user) { create(:user, :facility_administrator, facility:) }

before do
sign_in user

@params = { facility_id: facility.url_name, service_id: service.url_name }
end

shared_examples "creates a sanger product if needed" do
it "creates a sanger product if needed" do
expect { do_request }.to(
change do
service.reload.sanger_product
end.from(nil).to(SangerSequencing::SangerProduct)
)
end
end

describe "show" do
before do
@method = :get
@action = :show
end

include_examples "creates a sanger product if needed"
end

describe "edit" do
before do
@method = :get
@action = :edit
end

include_examples "creates a sanger product if needed"
end

describe "update" do
before do
@method = :put
@action = :update
@params[:sanger_sequencing_sanger_product] = { group: "default" }
end

include_examples "creates a sanger product if needed"

it "updates the sanger product" do
sanger_product_json = {
"needs_primer" => true, "group" => "fragment"
}
@params[:sanger_sequencing_sanger_product] = sanger_product_json

service.create_sanger_product

expect { do_request }.to(
change do
service.reload.sanger_product.as_json(only: %i[needs_primer group])
end.from(
{ "needs_primer" => false, "group" => "default" }
).to(
sanger_product_json
)
)
end
end
end
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

FactoryBot.define do
factory :product_group, class: SangerSequencing::ProductGroup do
factory :product_group, class: SangerSequencing::SangerProduct do
product factory: :setup_service

trait :default do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def click_add(submission_id)

describe "when the service is mapped to the fragment group" do
before do
SangerSequencing::ProductGroup.create!(product: service, group: "fragment")
SangerSequencing::SangerProduct.create!(product: service, group: "fragment")
visit facility_sanger_sequencing_admin_batches_path(facility, group: "fragment")
click_link "Create New Batch"
end
Expand Down
Loading
Loading