From cdef87b55c05ebb26a6e9f54d222b7f5f133fb07 Mon Sep 17 00:00:00 2001 From: Ana Ulin Date: Fri, 10 Dec 2021 17:07:41 -0800 Subject: [PATCH 1/4] Add pages to show existing door codes and input new ones. --- app/controllers/admin/door_code_controller.rb | 5 -- .../admin/door_codes_controller.rb | 31 ++++++++++ app/views/admin/door_codes/index.html.erb | 34 +++++++++++ app/views/admin/door_codes/new.html.erb | 34 +++++++++++ app/views/layouts/_member_nav.html.haml | 1 + config/routes.rb | 1 + .../admin/door_code_controller_spec.rb | 12 ---- .../admin/door_codes_controller_spec.rb | 60 +++++++++++++++++++ 8 files changed, 161 insertions(+), 17 deletions(-) delete mode 100644 app/controllers/admin/door_code_controller.rb create mode 100644 app/controllers/admin/door_codes_controller.rb create mode 100644 app/views/admin/door_codes/index.html.erb create mode 100644 app/views/admin/door_codes/new.html.erb delete mode 100644 spec/controllers/admin/door_code_controller_spec.rb create mode 100644 spec/controllers/admin/door_codes_controller_spec.rb diff --git a/app/controllers/admin/door_code_controller.rb b/app/controllers/admin/door_code_controller.rb deleted file mode 100644 index 95bac6be..00000000 --- a/app/controllers/admin/door_code_controller.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Admin::DoorCodeController < ApplicationController - before_action :ensure_admin - - # TODO: add actions for new door code administration workflow -end diff --git a/app/controllers/admin/door_codes_controller.rb b/app/controllers/admin/door_codes_controller.rb new file mode 100644 index 00000000..8c566546 --- /dev/null +++ b/app/controllers/admin/door_codes_controller.rb @@ -0,0 +1,31 @@ +class Admin::DoorCodesController < ApplicationController + before_action :ensure_admin + + def index + @door_codes = DoorCode.all.includes(:user) + end + + def new ; end + + def create + if door_code.save + flash[:notice] = "You have successfully created door code #{door_code.code}" + redirect_to action: :index + else + flash[:warning] = "Errors saving code. See details below." + render :new + end + end + + private + + def door_code_params + return {} unless params.key?(:door_code) + + params.require(:door_code).permit(:code, :status, :user_id) + end + + helper_method def door_code + @door_code ||= DoorCode.new(door_code_params) + end +end diff --git a/app/views/admin/door_codes/index.html.erb b/app/views/admin/door_codes/index.html.erb new file mode 100644 index 00000000..7027c9a5 --- /dev/null +++ b/app/views/admin/door_codes/index.html.erb @@ -0,0 +1,34 @@ +

Manage Door Codes

+ +<%= link_to 'Add New Codes', new_admin_door_code_path() , class: "btn btn-primary" %> + +

Existing Door Codes

+ +<% if @door_codes.empty? %> + There are no door codes in the database yet! +<% end %> + + + + + + + + + + + <% @door_codes.each do |door_code| %> + + + + + + <% end %> + +
CodeStatusAssigned To
+ <%= door_code.code %> + + <%= door_code.status %> + + <%= door_code.user_id.present? ? door_code.user.name : "unassigned" %> +
diff --git a/app/views/admin/door_codes/new.html.erb b/app/views/admin/door_codes/new.html.erb new file mode 100644 index 00000000..a405b17b --- /dev/null +++ b/app/views/admin/door_codes/new.html.erb @@ -0,0 +1,34 @@ +

Add New Door Codes

+ +<%# TODO: Add x new door codes link %> + +

Input New Door Code

+ +<%= form_with(model: [:admin, door_code], local: true) do |door_code_form| %> +

+ <% door_code.errors.messages.each do |field, msgs| %> + <%= field.to_s.humanize %>: + <%= msgs.join(', ') %> + <% end %> +

+ +
+ <%= door_code_form.label :code %> + <%= door_code_form.text_field :code %> +
+ +
+ <%= door_code_form.label :status %> + <%= door_code_form.select :status, DoorCode.statuses.keys.to_a %> +
+ +
+ <%= door_code_form.label :user_id %> + <%= door_code_form.select :user_id, User.all.collect { |u| [u.name, u.id] }, { include_blank: true} %> +

Optional. Use only if you want to assign this code to an existing user.

+
+ +
+ <%= door_code_form.submit %> +
+<% end %> diff --git a/app/views/layouts/_member_nav.html.haml b/app/views/layouts/_member_nav.html.haml index 015254a7..1a4b5f1c 100644 --- a/app/views/layouts/_member_nav.html.haml +++ b/app/views/layouts/_member_nav.html.haml @@ -20,6 +20,7 @@ %ul.dropdown-menu %li= link_to 'Manage Applications', admin_applications_path %li= link_to 'Manage Members', admin_memberships_path + %li= link_to 'Manage Door Codes', admin_door_codes_path %li= link_to 'Manage Dues', admin_dues_path %li= link_to 'New Members', admin_new_members_path %li= link_to 'Configure app', admin_configurable_path diff --git a/config/routes.rb b/config/routes.rb index 88f4cf90..dc52d320 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -29,6 +29,7 @@ end namespace :admin do + resources :door_codes, only: [:index, :new, :create] resource :exceptions, only: :show resources :memberships, only: [:index, :update] patch "memberships/:id/change_membership_state" => "memberships#change_membership_state", :as => "change_membership_state" diff --git a/spec/controllers/admin/door_code_controller_spec.rb b/spec/controllers/admin/door_code_controller_spec.rb deleted file mode 100644 index 9dd8a0b0..00000000 --- a/spec/controllers/admin/door_code_controller_spec.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Admin::DoorCodeController do - include AuthHelper - - let(:door_code) { create(:door_code) } - let(:params) { { id: door_code.id } } - - # TODO: add tests for new workflow actions, once they are added -end diff --git a/spec/controllers/admin/door_codes_controller_spec.rb b/spec/controllers/admin/door_codes_controller_spec.rb new file mode 100644 index 00000000..154ad51a --- /dev/null +++ b/spec/controllers/admin/door_codes_controller_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Admin::DoorCodesController do + include AuthHelper + + render_views + + let(:door_code) { create(:door_code) } + let(:params) { { id: door_code.id } } + + describe "GET :index" do + context "logged in as a non-admin member" do + before { login_as(:member) } + + it "redirects to root" do + get :index + expect(response).to redirect_to :root + end + end + + context "when logged in as an admin" do + let!(:door_codes) { create_list(:door_code, 5)} + + before { login_as(:voting_member, is_admin: true) } + + it "shows the index" do + get :index + + door_codes.each do |door_code| + expect(response.body).to include(door_code.code) + expect(response.body).to include(door_code.status.to_s) + end + end + end + end + + describe "POST :create" do + context "when logged in as an admin" do + let!(:existing_member) { create(:member) } + let!(:existing_door_code) { create(:door_code) } + + before { login_as(:voting_member, is_admin: true) } + + it "saves the new door code" do + expect { + post :create, params: { door_code: { code: "1234567", status: "in_lock", user_id: existing_member.id } } + }.to change(DoorCode, :count).from(1).to(2) + expect(existing_member.door_code.code).to eq("1234567") + end + + it "doesn't save a duplicated door code" do + expect { + post :create, params: { door_code: { code: existing_door_code.code, status: "in_lock" } } + }.to_not change(DoorCode, :count) + end + end + end +end From 7cac1bf69d02b680d8bffd6e3feb610b0f49175d Mon Sep 17 00:00:00 2001 From: Ana Ulin Date: Fri, 10 Dec 2021 17:42:01 -0800 Subject: [PATCH 2/4] Make it possible to edit existing codes. --- .../admin/door_codes_controller.rb | 19 ++++++++++-- app/views/admin/door_codes/_form.html.erb | 28 ++++++++++++++++++ app/views/admin/door_codes/edit.html.erb | 3 ++ app/views/admin/door_codes/index.html.erb | 4 +++ app/views/admin/door_codes/new.html.erb | 29 +------------------ config/routes.rb | 2 +- .../admin/door_codes_controller_spec.rb | 18 +++++++++++- 7 files changed, 70 insertions(+), 33 deletions(-) create mode 100644 app/views/admin/door_codes/_form.html.erb create mode 100644 app/views/admin/door_codes/edit.html.erb diff --git a/app/controllers/admin/door_codes_controller.rb b/app/controllers/admin/door_codes_controller.rb index 8c566546..df056fbb 100644 --- a/app/controllers/admin/door_codes_controller.rb +++ b/app/controllers/admin/door_codes_controller.rb @@ -2,7 +2,7 @@ class Admin::DoorCodesController < ApplicationController before_action :ensure_admin def index - @door_codes = DoorCode.all.includes(:user) + @door_codes = DoorCode.all.includes(:user).order(created_at: :asc) end def new ; end @@ -17,15 +17,28 @@ def create end end + def edit + end + + def update + if door_code.update(door_code_params) + flash[:notice] = "You have successfully updated door code #{door_code.code}" + redirect_to action: :index + else + flash[:warning] = "Errors saving code. See details below." + render :edit + end + end + private def door_code_params return {} unless params.key?(:door_code) - params.require(:door_code).permit(:code, :status, :user_id) + params.require(:door_code).permit(:code, :status, :user_id, :id) end helper_method def door_code - @door_code ||= DoorCode.new(door_code_params) + @door_code ||= params.key?(:id) ? DoorCode.find(params[:id]) : DoorCode.new(door_code_params) end end diff --git a/app/views/admin/door_codes/_form.html.erb b/app/views/admin/door_codes/_form.html.erb new file mode 100644 index 00000000..d67d38f7 --- /dev/null +++ b/app/views/admin/door_codes/_form.html.erb @@ -0,0 +1,28 @@ +<%= form_with(model: [:admin, door_code], local: true) do |door_code_form| %> +

+ <% door_code.errors.messages.each do |field, msgs| %> + <%= field.to_s.humanize %>: + <%= msgs.join(', ') %> + <% end %> +

+ +
+ <%= door_code_form.label :code %> + <%= door_code_form.text_field :code %> +
+ +
+ <%= door_code_form.label :status %> + <%= door_code_form.select :status, DoorCode.statuses.keys.to_a %> +
+ +
+ <%= door_code_form.label :user_id %> + <%= door_code_form.select :user_id, User.all.collect { |u| [u.name, u.id] }, { include_blank: true} %> +

Optional. Use only if you want to assign this code to an existing user.

+
+ +
+ <%= door_code_form.submit %> +
+<% end %> diff --git a/app/views/admin/door_codes/edit.html.erb b/app/views/admin/door_codes/edit.html.erb new file mode 100644 index 00000000..14c95286 --- /dev/null +++ b/app/views/admin/door_codes/edit.html.erb @@ -0,0 +1,3 @@ +

Edit Door Code

+ +<%= render partial: 'form', locals: { door_code: door_code} %> diff --git a/app/views/admin/door_codes/index.html.erb b/app/views/admin/door_codes/index.html.erb index 7027c9a5..90e123bc 100644 --- a/app/views/admin/door_codes/index.html.erb +++ b/app/views/admin/door_codes/index.html.erb @@ -14,6 +14,7 @@ Code Status Assigned To + @@ -28,6 +29,9 @@ <%= door_code.user_id.present? ? door_code.user.name : "unassigned" %> + + <%= link_to 'Edit', edit_admin_door_code_path(door_code), class: "btn btn-primary" %> + <% end %> diff --git a/app/views/admin/door_codes/new.html.erb b/app/views/admin/door_codes/new.html.erb index a405b17b..ee7fc466 100644 --- a/app/views/admin/door_codes/new.html.erb +++ b/app/views/admin/door_codes/new.html.erb @@ -4,31 +4,4 @@

Input New Door Code

-<%= form_with(model: [:admin, door_code], local: true) do |door_code_form| %> -

- <% door_code.errors.messages.each do |field, msgs| %> - <%= field.to_s.humanize %>: - <%= msgs.join(', ') %> - <% end %> -

- -
- <%= door_code_form.label :code %> - <%= door_code_form.text_field :code %> -
- -
- <%= door_code_form.label :status %> - <%= door_code_form.select :status, DoorCode.statuses.keys.to_a %> -
- -
- <%= door_code_form.label :user_id %> - <%= door_code_form.select :user_id, User.all.collect { |u| [u.name, u.id] }, { include_blank: true} %> -

Optional. Use only if you want to assign this code to an existing user.

-
- -
- <%= door_code_form.submit %> -
-<% end %> +<%= render partial: 'form', locals: { door_code: door_code} %> diff --git a/config/routes.rb b/config/routes.rb index dc52d320..e288d62b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -29,7 +29,7 @@ end namespace :admin do - resources :door_codes, only: [:index, :new, :create] + resources :door_codes, only: [:index, :new, :create, :edit, :update] resource :exceptions, only: :show resources :memberships, only: [:index, :update] patch "memberships/:id/change_membership_state" => "memberships#change_membership_state", :as => "change_membership_state" diff --git a/spec/controllers/admin/door_codes_controller_spec.rb b/spec/controllers/admin/door_codes_controller_spec.rb index 154ad51a..931328ee 100644 --- a/spec/controllers/admin/door_codes_controller_spec.rb +++ b/spec/controllers/admin/door_codes_controller_spec.rb @@ -53,7 +53,23 @@ it "doesn't save a duplicated door code" do expect { post :create, params: { door_code: { code: existing_door_code.code, status: "in_lock" } } - }.to_not change(DoorCode, :count) + }.not_to change(DoorCode, :count) + end + end + end + + describe "PATCH :update" do + context "when logged in as an admin" do + let!(:member) { create(:member) } + let!(:door_code) { create(:door_code) } + + before { login_as(:voting_member, is_admin: true) } + + it "updates the door code" do + expect { + patch :update, params: { id: door_code.id, door_code: { user_id: member.id } } + }.not_to change(DoorCode, :count) + expect(door_code.reload.user.id).to eq(member.id) end end end From fc078d433b2d7524fa809bd98efc8b0d051316b2 Mon Sep 17 00:00:00 2001 From: Ana Ulin Date: Fri, 10 Dec 2021 17:58:11 -0800 Subject: [PATCH 3/4] Add capability to autogenerate 10 new codes. --- app/controllers/admin/door_codes_controller.rb | 10 ++++++++++ app/views/admin/door_codes/index.html.erb | 6 +++++- config/routes.rb | 4 +++- spec/controllers/admin/door_codes_controller_spec.rb | 12 ++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/app/controllers/admin/door_codes_controller.rb b/app/controllers/admin/door_codes_controller.rb index df056fbb..e648bbb7 100644 --- a/app/controllers/admin/door_codes_controller.rb +++ b/app/controllers/admin/door_codes_controller.rb @@ -30,6 +30,16 @@ def update end end + def generate_new + num_codes_to_generate = 10 + num_codes_to_generate.times do + DoorCode.create!(code: DoorCode.make_random_code) + end + + flash[:notice] = "Autogenerated #{num_codes_to_generate} new codes (see table below for details)" + redirect_to action: :index + end + private def door_code_params diff --git a/app/views/admin/door_codes/index.html.erb b/app/views/admin/door_codes/index.html.erb index 90e123bc..84aaf96a 100644 --- a/app/views/admin/door_codes/index.html.erb +++ b/app/views/admin/door_codes/index.html.erb @@ -1,6 +1,10 @@

Manage Door Codes

-<%= link_to 'Add New Codes', new_admin_door_code_path() , class: "btn btn-primary" %> +<%= link_to 'Add New Codes', new_admin_door_code_path(), class: "btn btn-primary" %> + +<%= form_with url: generate_new_admin_door_codes_path(), method: :post, local: true do |form| %> + <%= form.submit "Autogenerate New Door Codes", class: "btn btn-primary" %> +<% end %>

Existing Door Codes

diff --git a/config/routes.rb b/config/routes.rb index e288d62b..80dafda9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -29,7 +29,9 @@ end namespace :admin do - resources :door_codes, only: [:index, :new, :create, :edit, :update] + resources :door_codes, only: [:index, :new, :create, :edit, :update] do + post :generate_new, on: :collection + end resource :exceptions, only: :show resources :memberships, only: [:index, :update] patch "memberships/:id/change_membership_state" => "memberships#change_membership_state", :as => "change_membership_state" diff --git a/spec/controllers/admin/door_codes_controller_spec.rb b/spec/controllers/admin/door_codes_controller_spec.rb index 931328ee..5c81102c 100644 --- a/spec/controllers/admin/door_codes_controller_spec.rb +++ b/spec/controllers/admin/door_codes_controller_spec.rb @@ -73,4 +73,16 @@ end end end + + describe "POST :generate_new" do + context "when logged in as an admin" do + before { login_as(:voting_member, is_admin: true) } + + it "updates the door code" do + expect { + post :generate_new + }.to change(DoorCode, :count).by(10) + end + end + end end From 9ccc54d2181a4586274c3bb97028635b33b5d179 Mon Sep 17 00:00:00 2001 From: Ana Ulin Date: Fri, 10 Dec 2021 18:05:51 -0800 Subject: [PATCH 4/4] Small improvements to the UI, code organization. --- app/controllers/admin/door_codes_controller.rb | 9 +++++---- app/views/admin/door_codes/index.html.erb | 2 +- app/views/admin/door_codes/new.html.erb | 6 +----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/app/controllers/admin/door_codes_controller.rb b/app/controllers/admin/door_codes_controller.rb index e648bbb7..2666b237 100644 --- a/app/controllers/admin/door_codes_controller.rb +++ b/app/controllers/admin/door_codes_controller.rb @@ -5,7 +5,11 @@ def index @door_codes = DoorCode.all.includes(:user).order(created_at: :asc) end - def new ; end + def new + end + + def edit + end def create if door_code.save @@ -17,9 +21,6 @@ def create end end - def edit - end - def update if door_code.update(door_code_params) flash[:notice] = "You have successfully updated door code #{door_code.code}" diff --git a/app/views/admin/door_codes/index.html.erb b/app/views/admin/door_codes/index.html.erb index 84aaf96a..15608b86 100644 --- a/app/views/admin/door_codes/index.html.erb +++ b/app/views/admin/door_codes/index.html.erb @@ -1,6 +1,6 @@

Manage Door Codes

-<%= link_to 'Add New Codes', new_admin_door_code_path(), class: "btn btn-primary" %> +<%= link_to 'Add New Door Code', new_admin_door_code_path(), class: "btn btn-primary" %> <%= form_with url: generate_new_admin_door_codes_path(), method: :post, local: true do |form| %> <%= form.submit "Autogenerate New Door Codes", class: "btn btn-primary" %> diff --git a/app/views/admin/door_codes/new.html.erb b/app/views/admin/door_codes/new.html.erb index ee7fc466..06898f99 100644 --- a/app/views/admin/door_codes/new.html.erb +++ b/app/views/admin/door_codes/new.html.erb @@ -1,7 +1,3 @@ -

Add New Door Codes

- -<%# TODO: Add x new door codes link %> - -

Input New Door Code

+

Add New Door Code

<%= render partial: 'form', locals: { door_code: door_code} %>