Skip to content

Commit

Permalink
Merge pull request #498 from rubyforgood/326-admins-controller
Browse files Browse the repository at this point in the history
Fixes #326, Fixes #593: AdminsController finishing
  • Loading branch information
seanmarcia committed Nov 14, 2018
2 parents 6f484b3 + 042c070 commit fa57dbd
Show file tree
Hide file tree
Showing 32 changed files with 628 additions and 54 deletions.
7 changes: 6 additions & 1 deletion app/assets/javascripts/barcode_items.js.erb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ $(document).ready(function() {
// Preserve this for reference of where we came from.
data['src'] = src;
data['value'] = value;
// We're setting this here because if it's looked up as a global, we need to find the first local
// item that matches.
data['item_id'] = data['item']['id'];
data['quantity'] = data['barcode_item']['quantity'];
console.log(data);
// Pass it all along to the .done() method
return data;
})
Expand Down Expand Up @@ -69,7 +74,7 @@ $(document).ready(function() {
}
})
$(line_item).find('input[type=number]').val(line_item_quantity);
$(line_item).find('[value="' + data['barcodeable_id'] + '"]').attr("selected", true);
$(line_item).find('[value="' + data['item_id'] + '"]').attr("selected", true);

if (data['src'] != $(line_item).closest('.__barcode_item_lookup').context) {
$(data['src']).closest('.nested-fields').remove();
Expand Down
40 changes: 27 additions & 13 deletions app/controllers/admin/barcode_items_controller.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
class Admin::BarcodeItemsController < AdminController
def edit
@barcode_item = BarcodeItem.find(params[:id])
end
before_action :load_canonical_items, only: %i(edit index new)
before_action :load_barcode_item, only: %i(edit update show destroy)

def edit; end

def update
@barcode_item = BarcodeItem.find(params[:id])
if @barcode_item.update(barcode_item_params)
redirect_to admin_barcode_items_path, notice: "Updated Barcode Item!"
else
Expand All @@ -14,30 +14,30 @@ def update
end

def index
@barcode_items = BarcodeItem.all
@barcode_items = BarcodeItem.global
end

def new
@barcode_item = BarcodeItem.new
end

def create
@barcode_item = BarcodeItem.create(barcode_item_params)
@barcode_item = BarcodeItem.create(barcode_item_params.merge(global: true, barcodeable_type: "CanonicalItem"))
if @barcode_item.save
redirect_to admin_barcode_items_path, notice: "Barcode Item added!"
respond_to do |format|
format.html { redirect_to admin_barcode_items_path, notice: "Barcode Item added!" }
format.js
end
else
load_canonical_items
flash[:error] = "Failed to create Barcode Item."
render :new
end
end

def show
@barcode_item = BarcodeItem.includes(items: [:organization]).find(params[:id])
@items = @barcode_item.items
end
def show; end

def destroy
@barcode_item = BarcodeItem.find(params[:id])
if @barcode_item.destroy
redirect_to admin_barcode_items_path, notice: "Barcode Item deleted!"
else
Expand All @@ -47,7 +47,21 @@ def destroy

private

def load_canonical_items
@canonical_items = CanonicalItem.order(:name).all
end

def barcode_item_params
params.require(:barcode_item).permit(:name, :key, :category)
params.require(:barcode_item).permit(:value, :barcodeable_id, :quantity)
end

def filter_params
return {} unless params.key?(:filters)

params.require(:filters).slice(:barcodeable_id, :less_than_quantity, :greater_than_quantity, :equal_to_quantity, :include_global, :canonical_item_id)
end

def load_barcode_item
@barcode_item = BarcodeItem.include_global(true).find(params[:id])
end
end
2 changes: 1 addition & 1 deletion app/controllers/admin/canonical_items_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def update
end

def index
@canonical_items = CanonicalItem.all
@canonical_items = CanonicalItem.order(:name).all
end

def new
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/admin/organizations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def update
end

def index
@organizations = Organization.all
@organizations = Organization.order(:name).all
end

def new
Expand Down
11 changes: 10 additions & 1 deletion app/controllers/admin_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,14 @@ def require_admin
verboten! unless current_user.super_admin?
end

def dashboard; end
def dashboard
@recent_organizations = Organization.where('created_at > ?', 1.week.ago)
@recent_users = User.where('created_at > ?', 1.week.ago)
@active_users = User.where('last_request_at > ?', 1.week.ago.utc)
@top_10_other = Item.by_partner_key('other').where.not(name: "Other").group(:name).limit(10).order('count_name DESC').count(:name)
@donation_count = Donation.where('created_at > ?', 1.week.ago).count
@distribution_count = Distribution.where('created_at > ?', 1.week.ago).count
@request_count = Request.where('created_at > ?', 1.week.ago).count
@organization_count = Organization.all.count
end
end
18 changes: 18 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
before_action :authorize_user
before_action :log_active_user
before_action :swaddled
before_action :configure_permitted_parameters, if: :devise_controller?

Expand Down Expand Up @@ -35,6 +36,23 @@ def authorize_user
verboten! unless params[:controller].include?("devise") || current_user.super_admin? || current_organization.id == current_user.organization_id
end

def log_active_user
if current_user && should_update_last_request_at?
# rubocop:disable Rails/SkipsModelValidations
# we don't want the user record to validate or run callbacks when we're tracking activity
current_user.update_columns(last_request_at: Time.now.utc)
# rubocop:enable Rails/SkipsModelValidations
end
end

def should_update_last_request_at?
current_user.last_request_at.nil? || last_request_logged_more_than_10_minutes_ago?
end

def last_request_logged_more_than_10_minutes_ago?
current_user.last_request_at.utc < 10.minutes.ago.utc
end

def not_found!
respond_to do |format|
format.html { render template: "errors/404", layout: "layouts/application", status: :not_found }
Expand Down
16 changes: 14 additions & 2 deletions app/controllers/barcode_items_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,21 @@ def show
end

def find
@barcode_item = current_organization.barcode_items.includes(:barcodeable).include_global(true).find_by!(value: barcode_item_params[:value])
# First, we do a naive lookup
@barcode_item = BarcodeItem.includes(:barcodeable).organization_barcodes_with_globals(@organization).find_by!(value: barcode_item_params[:value])
# Depending on whether or not the result is solely a global barcode, we may need additional queries
# Global barcodes don't explicitly map to organization items, so we can do a lookup to clarify that
if @barcode_item.global?
# So in this case, we need to do an item lookup. #593 clarifies that we should fall through to the
# *oldest* item that the organization has that matches this canonical item type.
canonical_item = @barcode_item.barcodeable
@item = current_organization.items.by_canonical_item(canonical_item).order("created_at ASC").first
else
# It was a local barcode_item, which maps directly to a known org item. We're set!
@item = @barcode_item.item
end
respond_to do |format|
format.json { render json: @barcode_item.to_json }
format.json { render json: { barcode_item: @barcode_item, item: @item }.to_json }
end
end

Expand Down
5 changes: 5 additions & 0 deletions app/helpers/users_helper.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
module UsersHelper
def gravatar_url(email, size)
gravatar = Digest::MD5.hexdigest(email).downcase
"http://gravatar.com/avatar/#{gravatar}.png?s=#{size}"
end

def reinvite_user_link(user)
if user.reinvitable?
link_to content_tag(:i, "", class: 'fa fa-envelope', alt: "Re-send invitation", title: "Re-send invitation"), resend_user_invitation_organization_path(user_id: user.id), method: :post
Expand Down
4 changes: 3 additions & 1 deletion app/models/barcode_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ class BarcodeItem < ApplicationRecord
# Because it's a polymorphic association, we have to do this join manually.
scope :by_item_partner_key, ->(partner_key) { joins("INNER JOIN items ON items.id = barcode_items.barcodeable_id").where(barcodeable_type: "Item", items: { partner_key: partner_key }) }
scope :by_canonical_item_partner_key, ->(partner_key) { joins("INNER JOIN canonical_items ON canonical_items.id = barcode_items.barcodeable_id").where(barcodeable_type: "CanonicalItem", canonical_items: { partner_key: partner_key }) }
scope :by_value, ->(value) { where(value: value) }
scope :by_value, ->(value) { where(value: value) }
scope :organization_barcodes_with_globals, ->(organization) { where(global: true).or(where(organization_id: organization, global: false)) }
scope :include_global, ->(global) { where(global: [false, global]) }
scope :for_csv_export, ->(organization) {
where(organization: organization)
.includes(:barcodeable)
}
scope :global, -> { where(global: true) }

alias_attribute :item, :barcodeable
alias_attribute :canonical_item, :barcodeable
Expand Down
3 changes: 2 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ class User < ApplicationRecord
# :confirmable, :lockable, :timeoutable and :omniauthable
# :invitable is from the devise_invitable gem
devise :invitable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
:recoverable, :rememberable, :trackable, :validatable,
:timeoutable

validates :name, :email, presence: true

Expand Down
14 changes: 14 additions & 0 deletions app/views/admin/barcode_items/_barcode_item_row.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<tr>
<td><% if barcode_item_row.global %><i class="fa fa-globe"></i><% end %></td>
<td><%= barcode_item_row.barcodeable.name %></td>
<td><%= barcode_item_row.quantity %></td>
<td><%= barcode_item_row.value %></td>
<td class="text-right">
<%= link_to "View", admin_barcode_item_path(barcode_item_row), class: "btn btn-primary btn-xs" %>
<%= link_to edit_admin_barcode_item_path(barcode_item_row), class: "btn btn-info btn-xs" do %>
<i class="fa fa-edit"></i> Edit
<% end %>
<%= link_to admin_barcode_item_path(barcode_item_row), method: :delete, class: "btn btn-danger btn-xs", data: { confirm: confirm_delete_msg(barcode_item_row.item.name) } do %>
<i class="fa fa-trash"></i> Delete
<% end %>
</tr>
31 changes: 31 additions & 0 deletions app/views/admin/barcode_items/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<%= simple_form_for form, html: { role: "form" } do |f| %>
<div class="box-body ">

<div class="row">
<div class="col-xs-8 col-md-6 col-lg-3">
<%= f.input :quantity, label: "Quantity", wrapper: :vertical_input_group do %>
<span class="input-group-addon"><i class="fa fa-sort-numeric-desc"></i></span>
<%= f.input_field :quantity, class: "form-control" %>
<% end %>
</div><!-- ./col-xs-8 -->
</div><!-- /.row -->

<div class="row">
<div class="col-xs-8 col-md-6 col-lg-3">
<%= f.association :barcodeable, collection: @canonical_items, label: "Item" %>
</div>
</div>

<div class="row">
<div class="col-xs-8 col-md-6 col-lg-3">
<%= f.input :value, label: "Barcode", wrapper: :vertical_input_group do %>
<span class="input-group-addon"><i class="fa fa-barcode"></i></span>
<%= f.input_field :value, class: "form-control" %>
<% end %>
</div><!-- ./col-xs-8 -->
</div><!-- /.row -->


<%= f.button :submit, class:"btn btn-primary btn-lg"%>
</div><!-- /.box-body -->
<% end #form %>
30 changes: 30 additions & 0 deletions app/views/admin/barcode_items/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<section class="content-header">
<% content_for :title, "Admin - Inventory - Barcode Items - New" %>
<h1>
Editing Barcode Item
</h1>
<ol class="breadcrumb">
<li><%= link_to(admin_dashboard_path) do %>
<i class="fa fa-lock"></i> Admin
<% end %>
</li>
<li><%= link_to "All Barcodes", (admin_barcode_items_path) %></li>
<li class="active"> Editing Barcode</li>
</ol>
</section>

<!-- Main content -->
<section class="content">

<!-- Default box -->
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Barcode for <%= @barcode_item.quantity %> of <%= @barcode_item.item.name %></h3>
</div>
<div class="box-body">
<%= render partial: "form", object: @barcode_item %>
</div>
</div>
<!-- /.box -->

</section>
68 changes: 68 additions & 0 deletions app/views/admin/barcode_items/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<section class="content-header">
<% content_for :title, "Admin - Barcode Items" %>
<h1>
Barcode Items - Global
</h1>
<ol class="breadcrumb">
<li><%= link_to(admin_dashboard_path) do %>
<i class="fa fa-lock"></i> Admin
<% end %>
</li>
<li><a href="#">Barcode Items</a></li>
</ol>
</section>

<!-- Main content -->
<section class="content">
<div class="box">
<div class="box-header with-border bg-gray">
<section id="filters">
<%= form_tag(admin_barcode_items_path, method: :get) do |f| %>
<div class="row">
<div class="form-group col-lg-4 col-md-4 col-sm-6 col-xs-12">
<%= label_tag "Filter By Canonical Item Category" %>
<%= collection_select(:filters, :barcodeable_id, @canonical_items.order('name'), :id, :name, { include_blank: true }, class: "form-control") %>
</div>
</div><!-- /.row -->
<div class="row">
<div class="col-xs-12">
<%= button_tag type: "submit", class: "btn btn-primary btn-md" do %>
<i class="fa fa-filter"></i> Filter
<% end %>
<%= link_to admin_barcode_items_path, class: "btn btn-outline-primary btn-md" do %>
<i class="fa fa-ban"></i> Clear Filters
<% end %>
<div class="btn-group pull-right">
<%= link_to new_admin_barcode_item_path(organization_id: current_organization), class: "btn btn-success" do %>
<i class="fa fa-plus"></i> Add New Barcode
<% end %>
</div>
</div>
</div><!-- /.row -->
<% end #form %>
</section><!-- /#filters -->
</div><!-- /.box-header -->
<div class="box-body">
<div class="row">
<div class="col-xs-12">
<div class="box-body table-responsive no-padding">
<table id="tbl_barcode_items" class="table table-hover">
<thead>
<tr>
<th>Global</th>
<th>Item Type</th>
<th>Quantity in the Box</th>
<th>Barcode</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<%= render partial: "barcode_item_row", collection: @barcode_items %>
</tbody>
</table>
</div><!-- /.box-body -->
</div><!-- /.col-xs-12 -->
</div><!-- /.row -->
</div><!-- /.box-body -->
</div><!-- /.box -->
</section>
24 changes: 24 additions & 0 deletions app/views/admin/barcode_items/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<section class="content-header">
<% content_for :title, "Admin - Inventory - Barcode Items - New" %>
<h1>
New Barcode Item
</h1>
<ol class="breadcrumb">
<li><%= link_to(admin_dashboard_path) do %>
<i class="fa fa-lock"></i> Admin
<% end %>
</li>
<li><%= link_to "Barcode Items", (admin_barcode_items_path) %></li>
<li class="active"> New Barcode</li>
</ol>
</section>

<!-- Main content -->
<section class="content">

<!-- Default box -->
<div class="box">
<%= render partial: "form", object: [:admin, @barcode_item] %>
</div><!-- /.box -->

</section>
Loading

0 comments on commit fa57dbd

Please sign in to comment.