diff --git a/app/controllers/casa_orgs_controller.rb b/app/controllers/casa_orgs_controller.rb index 222cd22ec8..abf9d668d3 100644 --- a/app/controllers/casa_orgs_controller.rb +++ b/app/controllers/casa_orgs_controller.rb @@ -3,6 +3,7 @@ class CasaOrgsController < ApplicationController before_action :set_casa_org, only: %i[edit update] before_action :set_contact_type_data, only: %i[edit update] before_action :set_hearing_types, only: %i[edit update] + before_action :set_judges, only: %i[edit update] before_action :must_be_admin before_action :require_organization! @@ -42,4 +43,8 @@ def set_contact_type_data def set_hearing_types @hearing_types = HearingType.for_organization(@casa_org) end + + def set_judges + @judges = Judge.for_organization(@casa_org) + end end diff --git a/app/controllers/judges_controller.rb b/app/controllers/judges_controller.rb new file mode 100644 index 0000000000..5d04c17cb6 --- /dev/null +++ b/app/controllers/judges_controller.rb @@ -0,0 +1,43 @@ +class JudgesController < ApplicationController + before_action :authenticate_user!, :must_be_admin + before_action :set_judge, except: [:new, :create] + + def new + @judge = Judge.new + end + + def create + @judge = Judge.new(judge_params) + + respond_to do |format| + if @judge.save + format.html { redirect_to edit_casa_org_path(current_organization), notice: "Judge was successfully created." } + else + format.html { render :new } + end + end + end + + def edit + end + + def update + if @judge.update(judge_params) + redirect_to edit_casa_org_path(current_organization), notice: "Judge was successfully updated." + else + render :edit + end + end + + private + + def set_judge + @judge = Judge.find(params[:id]) + end + + def judge_params + params.require(:judge).permit(:name, :active).merge( + casa_org: current_organization + ) + end +end diff --git a/app/models/judge.rb b/app/models/judge.rb new file mode 100644 index 0000000000..5ea4f03bc7 --- /dev/null +++ b/app/models/judge.rb @@ -0,0 +1,30 @@ +class Judge < ApplicationRecord + has_paper_trail + + belongs_to :casa_org + + validates :name, presence: true, uniqueness: {scope: %i[casa_org]} + + scope :for_organization, ->(org) { where(casa_org: org) } + scope :active, -> { where(active: true) } +end + +# == Schema Information +# +# Table name: judges +# +# id :bigint not null, primary key +# active :boolean default(TRUE) +# name :string +# created_at :datetime not null +# updated_at :datetime not null +# casa_org_id :bigint not null +# +# Indexes +# +# index_judges_on_casa_org_id (casa_org_id) +# +# Foreign Keys +# +# fk_rails_... (casa_org_id => casa_orgs.id) +# diff --git a/app/views/casa_orgs/_hearing_types.html.erb b/app/views/casa_orgs/_hearing_types.html.erb index 4edd081108..bfff894157 100644 --- a/app/views/casa_orgs/_hearing_types.html.erb +++ b/app/views/casa_orgs/_hearing_types.html.erb @@ -9,7 +9,7 @@ Name - Active + Active? Actions diff --git a/app/views/casa_orgs/_judges.html.erb b/app/views/casa_orgs/_judges.html.erb new file mode 100644 index 0000000000..f5283ea785 --- /dev/null +++ b/app/views/casa_orgs/_judges.html.erb @@ -0,0 +1,32 @@ +
+
+

Judge

+ <%= link_to "New Judge", new_judge_path, class: "btn btn-primary" %> +
+
+ + + + + + + + + + + + <% @judges.each do |judge| %> + + + + + + <% end %> + +
NameActive?Actions
+ <%= judge.name %> + + <%= judge.active ? "Yes" : "No" %> + + <%= link_to "Edit", edit_judge_path(judge) %> +
diff --git a/app/views/casa_orgs/edit.html.erb b/app/views/casa_orgs/edit.html.erb index 0a198613ea..18ea8853bc 100644 --- a/app/views/casa_orgs/edit.html.erb +++ b/app/views/casa_orgs/edit.html.erb @@ -47,5 +47,6 @@
<%= render "hearing_types" %> + <%= render "judges" %>
diff --git a/app/views/judges/_form.html.erb b/app/views/judges/_form.html.erb new file mode 100644 index 0000000000..1c7c541d57 --- /dev/null +++ b/app/views/judges/_form.html.erb @@ -0,0 +1,22 @@ +<%= link_to 'Back', :back %> + +

<%= title %>

+ +
+
+ <%= form_with(model: judge, local: true) do |form| %> + <%= render "/shared/error_messages", resource: judge %> +
+ <%= form.label :name %> + <%= form.text_field :name, class: "form-control" %> +
+
+ <%= form.check_box :active %> + <%= form.label :active %> +
+
+ <%= form.submit "Submit", class: "btn btn-primary" %> +
+ <% end %> +
+
diff --git a/app/views/judges/edit.html.erb b/app/views/judges/edit.html.erb new file mode 100644 index 0000000000..24b6af80eb --- /dev/null +++ b/app/views/judges/edit.html.erb @@ -0,0 +1 @@ +<%= render partial: "form", locals: { title: "Edit Judge", judge: @judge } %> diff --git a/app/views/judges/new.html.erb b/app/views/judges/new.html.erb new file mode 100644 index 0000000000..2872eef56d --- /dev/null +++ b/app/views/judges/new.html.erb @@ -0,0 +1 @@ +<%= render partial: "form", locals: { title: "New Judge", judge: @judge } %> diff --git a/config/routes.rb b/config/routes.rb index dd4aaa6570..b76a1351a9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -46,6 +46,7 @@ resources :contact_type_groups, only: %i[new create edit update] resources :contact_types, only: %i[new create edit update] resources :hearing_types, only: %i[new create edit update] + resources :judges, only: %i[new create edit update] resources :supervisors, except: %i[destroy] resources :supervisor_volunteers, only: %i[create] do diff --git a/db/migrate/20201023233638_create_judges.rb b/db/migrate/20201023233638_create_judges.rb new file mode 100644 index 0000000000..3690482862 --- /dev/null +++ b/db/migrate/20201023233638_create_judges.rb @@ -0,0 +1,9 @@ +class CreateJudges < ActiveRecord::Migration[6.0] + def change + create_table :judges do |t| + t.references :casa_org, null: false, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/migrate/20201023234325_add_active_to_judge.rb b/db/migrate/20201023234325_add_active_to_judge.rb new file mode 100644 index 0000000000..8e884bbc3d --- /dev/null +++ b/db/migrate/20201023234325_add_active_to_judge.rb @@ -0,0 +1,5 @@ +class AddActiveToJudge < ActiveRecord::Migration[6.0] + def change + add_column :judges, :active, :boolean, default: true + end +end diff --git a/db/migrate/20201024003821_add_name_to_judge.rb b/db/migrate/20201024003821_add_name_to_judge.rb new file mode 100644 index 0000000000..4c466a4b8e --- /dev/null +++ b/db/migrate/20201024003821_add_name_to_judge.rb @@ -0,0 +1,5 @@ +class AddNameToJudge < ActiveRecord::Migration[6.0] + def change + add_column :judges, :name, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index c6b989e823..0f0444fcec 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_10_20_095451) do +ActiveRecord::Schema.define(version: 2020_10_24_003821) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -153,6 +153,15 @@ t.index ["casa_org_id"], name: "index_hearing_types_on_casa_org_id" end + create_table "judges", force: :cascade do |t| + t.bigint "casa_org_id", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.boolean "active", default: true + t.string "name" + t.index ["casa_org_id"], name: "index_judges_on_casa_org_id" + end + create_table "supervisor_volunteers", force: :cascade do |t| t.bigint "supervisor_id", null: false t.bigint "volunteer_id", null: false @@ -213,6 +222,7 @@ add_foreign_key "case_assignments", "users", column: "volunteer_id" add_foreign_key "case_contacts", "casa_cases" add_foreign_key "case_contacts", "users", column: "creator_id" + add_foreign_key "judges", "casa_orgs" add_foreign_key "supervisor_volunteers", "users", column: "supervisor_id" add_foreign_key "supervisor_volunteers", "users", column: "volunteer_id" add_foreign_key "users", "casa_orgs" diff --git a/spec/factories/judges.rb b/spec/factories/judges.rb new file mode 100644 index 0000000000..c685f5de94 --- /dev/null +++ b/spec/factories/judges.rb @@ -0,0 +1,7 @@ +FactoryBot.define do + factory :judge do + casa_org { create(:casa_org) } + name { Faker::Name.name } + active { true } + end +end diff --git a/spec/models/judge_spec.rb b/spec/models/judge_spec.rb new file mode 100644 index 0000000000..3f503a7090 --- /dev/null +++ b/spec/models/judge_spec.rb @@ -0,0 +1,11 @@ +require "rails_helper" + +RSpec.describe Judge, type: :model do + it { is_expected.to belong_to(:casa_org) } + it { is_expected.to validate_presence_of(:name) } + + it "has a valid factory" do + judge = build(:judge) + expect(judge.valid?).to be true + end +end diff --git a/spec/requests/judges_spec.rb b/spec/requests/judges_spec.rb new file mode 100644 index 0000000000..c2b1e00455 --- /dev/null +++ b/spec/requests/judges_spec.rb @@ -0,0 +1,147 @@ +require "rails_helper" + +RSpec.describe "/judges", type: :request do + describe "GET /judges/new" do + context "logged in as admin user" do + it "can successfully access a judge create page" do + sign_in_as_admin + + get new_judge_path + + expect(response).to be_successful + end + end + + context "logged in as a non-admin user" do + it "cannot access a judge create page" do + sign_in_as_volunteer + + get new_judge_path + + expect(response).to redirect_to root_path + expect(response.request.flash[:notice]).to eq "Sorry, you are not authorized to perform this action." + end + end + + context "unauthenticated request" do + it "cannot access a judge create page" do + get new_judge_path + + expect(response).to redirect_to new_user_session_path + end + end + end + + describe "POST /judges" do + let(:params) { {judge: {name: "Joe Judge", active: true}} } + context "logged in as admin user" do + it "can successfully create a judge" do + casa_org = create(:casa_org) + sign_in create(:casa_admin, casa_org: casa_org) + + expect { + post judges_path, params: params + }.to change(Judge, :count).by(1) + + judge = Judge.last + + expect(judge.name).to eql "Joe Judge" + expect(judge.casa_org).to eql casa_org + expect(judge.active).to be_truthy + expect(response).to redirect_to edit_casa_org_path(casa_org) + expect(response.request.flash[:notice]).to eq "Judge was successfully created." + end + end + + context "logged in as a non-admin user" do + it "cannot create a judge" do + sign_in_as_volunteer + + post judges_path, params: params + + expect(response).to redirect_to root_path + expect(response.request.flash[:notice]).to eq "Sorry, you are not authorized to perform this action." + end + end + + context "unauthenticated request" do + it "cannot create a judge" do + post judges_path, params: params + + expect(response).to redirect_to new_user_session_path + end + end + end + + describe "GET /judges/:id/edit" do + let(:judge) { create(:judge) } + + context "logged in as admin user" do + it "can successfully access a judge edit page" do + sign_in_as_admin + + get edit_judge_path(judge) + + expect(response).to be_successful + end + end + + context "logged in as a non-admin user" do + it "cannot access a judge edit page" do + sign_in_as_volunteer + + get edit_judge_path(judge) + + expect(response).to redirect_to root_path + expect(response.request.flash[:notice]).to eq "Sorry, you are not authorized to perform this action." + end + end + + context "unauthenticated request" do + it "cannot access a judge edit page" do + get edit_judge_path(judge) + + expect(response).to redirect_to new_user_session_path + end + end + end + + describe "PUT /judges/:id" do + let(:judge) { create(:judge) } + let(:params) { {judge: {name: "New Name", judge_id: judge.id, active: false}} } + context "logged in as admin user" do + it "can successfully update a judge" do + casa_org = create(:casa_org) + sign_in create(:casa_admin, casa_org: casa_org) + + put judge_path(judge), params: params + + judge.reload + expect(judge.name).to eq "New Name" + expect(judge.active).to be_falsey + + expect(response).to redirect_to edit_casa_org_path(casa_org) + expect(response.request.flash[:notice]).to eq "Judge was successfully updated." + end + end + + context "logged in as a non-admin user" do + it "cannot update a judge" do + sign_in_as_volunteer + + put judge_path(judge), params: params + + expect(response).to redirect_to root_path + expect(response.request.flash[:notice]).to eq "Sorry, you are not authorized to perform this action." + end + end + + context "unauthenticated request" do + it "cannot update a judge" do + put judge_path(judge), params: params + + expect(response).to redirect_to new_user_session_path + end + end + end +end diff --git a/spec/system/create_judge_spec.rb b/spec/system/create_judge_spec.rb new file mode 100644 index 0000000000..5cf2bbf724 --- /dev/null +++ b/spec/system/create_judge_spec.rb @@ -0,0 +1,25 @@ +require "rails_helper" + +RSpec.describe "Create Judge Spec", type: :system do + let(:organization) { create(:casa_org) } + let(:admin) { create(:casa_admin, casa_org_id: organization.id) } + + before do + sign_in admin + + visit new_judge_path + end + + it "adds new judge" do + fill_in "Name", with: "" + click_on "Submit" + + expect(page).to have_text("Name can't be blank") + + fill_in "Name", with: "Joey Shmoey" + click_on "Submit" + + expect(page).to have_text("Judge was successfully created.") + expect(page).to have_text("Joey Shmoey") + end +end diff --git a/spec/system/edit_casa_org_spec.rb b/spec/system/edit_casa_org_spec.rb index 9becd76cba..26956105ab 100644 --- a/spec/system/edit_casa_org_spec.rb +++ b/spec/system/edit_casa_org_spec.rb @@ -4,6 +4,7 @@ let(:organization) { create(:casa_org) } let(:admin) { create(:casa_admin, casa_org_id: organization.id) } let!(:hearing_type) { create(:hearing_type, casa_org: organization, name: "Spec Test Hearing Type") } + let!(:judge) { create(:judge, casa_org: organization, name: "Joey Tom") } before do sign_in admin @@ -31,4 +32,8 @@ ] ) end + + it "has judge content" do + expect(page).to have_text(judge.name) + end end