Skip to content

Commit

Permalink
Merge pull request #37 from nihonjinrxs/add-pod
Browse files Browse the repository at this point in the history
New DistributionPoints feature
  • Loading branch information
tdooner authored Sep 20, 2018
2 parents 0bcbeff + 06a1aa8 commit 0b04412
Show file tree
Hide file tree
Showing 32 changed files with 835 additions and 82 deletions.
6 changes: 6 additions & 0 deletions app/assets/javascripts/channels/distribution_point.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
App.distribution_point = App.cable.subscriptions.create("DistributionPointChannel", {
connected: function() {},
received: function(data) {
App.updatedDistributionPoints.add(data.distribution_point)
}
})
9 changes: 9 additions & 0 deletions app/channels/distribution_point_channel.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class DistributionPointChannel < ApplicationCable::Channel
def subscribed
stream_for "distribution_points"
end

def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
end
22 changes: 22 additions & 0 deletions app/controllers/api/v1/distribution_points_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Api::V1::DistributionPointsController < ApplicationController
include FilterByParams

before_action do
request.format = :json
end

filterable_params [
{ type: :geocoords },
{ type: :text, param: :county, field: 'county' },
{ type: :text, param: :name, field: 'facility_name' },
{ type: :boolean, param: :active, field: 'active' }
]

def index
@distribution_points, @filters = apply_filters(DistributionPoint.all)
end

def outdated
@distribution_points, @filters = apply_filters(DistributionPoint.outdated.order('updated_at DESC'))
end
end
90 changes: 30 additions & 60 deletions app/controllers/api/v1/shelters_controller.rb
Original file line number Diff line number Diff line change
@@ -1,72 +1,42 @@
class Api::V1::SheltersController < ApplicationController
include FilterByParams

before_action do
request.format = :json
end

filterable_params [
{ type: :geocoords },
{ type: :text, param: :county, field: 'county' },
{ type: :text, param: :name, field: 'shelter' },
{ type: :text, param: :shelter, field: 'shelter' },
{ type: :boolean, param: :active, field: 'active' },
{ type: :boolean, param: :special_needs, field: 'special_needs' },
{ type: :text, param: :accessibility, field: 'accessibility' },
{ type: :boolean, param: :unofficial, field: 'unofficial' },
{
type: :callback,
param: :accepting,
fn: lambda do |query, value, filters|
filters[:accepting] =
case value
when 'yes', 'no', 'unknown'
value.to_sym
when 'false'
:no
else
:yes
end
query.where(accepting: filters[:accepting])
end
}
]

def index
@shelters, @filters = apply_params(Shelter.all)
@shelters, @filters = apply_filters(Shelter.all)
end

def outdated
@outdated, @filters = apply_params(Shelter.outdated.order('updated_at DESC'))
end

private

def apply_params(shelters)
filters = {}

if params[:lat].present? && params[:lon].present?
filters[:lon] = params[:lon]
filters[:lat] = params[:lat]
shelters = shelters.near([params[:lat], params[:lon]], 100)
end

if params[:county].present?
filters[:county] = params[:county]
shelters = shelters.where("county ILIKE ?", "%#{filters[:county]}%")
end

if params[:shelter].present?
filters[:shelter] = params[:shelter]
shelters = shelters.where("shelter ILIKE ?", "%#{filters[:shelter]}%")
end

if params[:accepting].present?
val = case params[:accepting]
when 'yes', 'no', 'unknown'
params[:accepting].to_sym
when 'true'
:yes
when 'false'
:no
else
:yes
end
filters[:accepting] = val
shelters = shelters.where(accepting: val)
end

if params[:special_needs].present?
filters[:special_needs] = params[:special_needs]
shelters = shelters.where(special_needs: true)
end

if params[:accessibility].present?
filters[:accessibility] = params[:accessibility]
shelters = shelters.where("accessibility ILIKE ?", "%#{filters[:accessibility]}%")
end

if params[:unofficial].present?
filters[:unofficial] = params[:unofficial]
shelters = shelters.where(unofficial: true)
end

if params[:limit].to_i.positive?
shelters = shelters.limit(params[:limit].to_i)
end

[shelters, filters]
@outdated, @filters = apply_filters(Shelter.outdated.order('updated_at DESC'))
end
end
2 changes: 2 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ class ApplicationController < ActionController::Base
@application_name = ENV.fetch('CANONICAL_NAME', 'Disaster API')
end

helper_method :admin?

def admin?
user_signed_in? && current_user.admin?
end
Expand Down
56 changes: 56 additions & 0 deletions app/controllers/concerns/filter_by_params.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module FilterByParams
extend ActiveSupport::Concern


#
# filterable_params creates a parameter function `apply_filters` that
# automatically filters activerecord results by params when applied
#
# valid `types` include:
# :exact => search where the field is an exact match to the parameter
# :text => where clause using ILIKE
# :boolean => where if the value is true
# :callback => uses a lambda to determine how to move forward
# the passed function must be a lambda of signature:
# `lambda do |query, value, filters|`
# AND MUST RETURN AN ACTIVERECORD QUERY OBJECT
# Does not support joins or fields outside the calling model
#

included do
def self.filterable_params(filterables)
define_method(:apply_filters) do |to_filter|
filters = {}
list = filterables.reduce(to_filter) do |m, f|
if f[:type] == :geocoords && params[:lat].present? && params[:lon].present? && m.respond_to?(:near)
filters[:lon] = params[:lon]
filters[:lat] = params[:lat]
m.near([params[:lat], params[:lon]], 100)
elsif params[f[:param]].present?
filters[f[:param]] = params[f[:param]]

case f[:type]
when :exact
m.where(f[:field] => filters[f[:param]])
when :text
cls = m.table.name.classify.constantize
m.where(cls.arel_table[f[:field]].matches("%#{filters[f[:param]]}%"))
when :boolean
m.where(f[:field] => true)
when :callback
f[:fn].call(m, filters[f[:param]], filters)
else
m
end
else
m
end
end

list = list.limit(params[:limit].to_i) if params[:limit].to_i.positive?

[list, filters]
end
end
end
end
137 changes: 137 additions & 0 deletions app/controllers/distribution_points_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
class DistributionPointsController < ApplicationController
before_action :set_headers, except: [:index]
before_action :set_index_headers, only: [:index]
before_action :set_distribution_point, only: [:show, :edit, :update, :destroy, :archive]

# GET /distribution_points
# GET /distribution_points.json
def index
@distribution_points = DistributionPoint.all
@page = Page.distribution_points.first_or_initialize
respond_to do |format|
format.html
format.csv { send_data @distribution_points.to_csv, filename: "distribution_points-#{Date.today}.csv" }
end
end

# GET /distribution_points/new
def new
@distribution_point = DistributionPoint.new
end

# GET /distribution_points/1
# GET /distribution_points/1.json
def show
end

# GET /distribution_points/1/edit
def edit
end

# POST /distribution_points
# POST /distribution_points.json
def create
if admin?
@distribution_point = DistributionPoint.new(distribution_point_params)

if @distribution_point.save
redirect_to distribution_points_path, notice: 'Distribution Point was successfully created.'
else
render :new
end
else
draft = Draft.new(info: distribution_point_params, created_by: current_user, record_type: DistributionPoint)

if draft.save
redirect_to draft, notice: 'Your new distribution point is pending approval.'
else
@distribution_point = DistributionPoint.new(distribution_point_params)
render :new
end
end
end

# PATCH/PUT /distribution_points/1
# PATCH/PUT /distribution_points/1.json
def update
if admin?
if @distribution_point.update(distribution_point_params)
redirect_to distribution_points_path, notice: 'Distribution Point was successfully updated.'
else
render :edit
end
else
draft = Draft.new(record: @distribution_point, info: distribution_point_params, created_by: current_user)

if draft.save
redirect_to draft, notice: 'Your distribution point update is pending approval.'
else
render :edit
end
end
end

# DELETE /distribution_points/1
# DELETE /distribution_points/1.json
def destroy
end

def archive
if admin?
@distribution_point.update_attributes(active: false)
redirect_to distribution_points_path, notice: "Archived!"
else
redirect_to distribution_points_path, notice: "You must be an admin to archive."
end
end

def drafts
@drafts = Draft.includes(:record).where("record_type = ? OR info->>'record_type' = ?", DistributionPoint.name, DistributionPoint.name).where(accepted_by_id: nil).where(denied_by_id: nil)
end

def csv
render :index, format: :csv
end

def outdated
@distribution_points = DistributionPoint.outdated.order('updated_at DESC')
@columns = DistributionPoint::OutdatedViewColumnNames - DistributionPoint::IndexHiddenColumnNames
@headers = @columns.map(&:titleize)
end

private
# This is the definition of a beautiful hack. 1 part gross, 2 parts simplicity. Does something neat not clever.
def set_headers
@columns =
if admin?
DistributionPoint::ColumnNames + DistributionPoint::PrivateFields
else
DistributionPoint::ColumnNames
end
@headers = @columns.map(&:titleize)
end

def set_index_headers
@columns =
if admin?
(DistributionPoint::ColumnNames + DistributionPoint::PrivateFields) - DistributionPoint::IndexHiddenColumnNames
else
DistributionPoint::ColumnNames - DistributionPoint::IndexHiddenColumnNames
end
@headers = @columns.map(&:titleize)
end

# Use callbacks to share common setup or constraints between actions.
def set_distribution_point
@distribution_point = DistributionPoint.find(params[:id])
end

# Never trust parameters from the scary internet, only allow the white list through.
def distribution_point_params
if admin?
params.require(:distribution_point).permit(DistributionPoint::UpdateFields + DistributionPoint::PrivateFields).keep_if { |_,v| v.present? }
else
params.require(:distribution_point).permit(DistributionPoint::UpdateFields).keep_if { |_,v| v.present? }
end
end
end
15 changes: 15 additions & 0 deletions app/jobs/distribution_point_update_notifier_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class DistributionPointUpdateNotifierJob < ApplicationJob
queue_as :default

def perform distribution_point
ShelterChannel.broadcast_to "distribution_points", distribution_point: render(distribution_point)
end

def render distribution_point
ApplicationController.render partial: 'api/v1/distribution_points/distribution_point',
locals: {
distribution_point: distribution_point
}
end

end
Loading

0 comments on commit 0b04412

Please sign in to comment.