Skip to content

Commit

Permalink
Angularising Order Cycles Index
Browse files Browse the repository at this point in the history
  • Loading branch information
oeoeaio committed Feb 9, 2018
1 parent bf69ed0 commit 2a5f598
Show file tree
Hide file tree
Showing 24 changed files with 437 additions and 182 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ angular.module("ofn.admin").directive "datetimepicker", ->
onSelect: (dateText, inst) ->
scope.$apply (scope) ->
# Fires ngModel.$parsers
ngModel.$setViewValue dateText
ngModel.$setViewValue dateText
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
RequestMonitor.load $scope.lineItems = LineItems.index("q[order][state_not_eq]": "canceled", "q[order][completed_at_not_null]": "true", "q[order][completed_at_gt]": "#{parseDate($scope.startDate)}", "q[order][completed_at_lt]": "#{parseDate($scope.endDate)}")

unless $scope.initialized
RequestMonitor.load $scope.distributors = Enterprises.index(action: "for_line_items", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
RequestMonitor.load $scope.distributors = Enterprises.index(action: "visible", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{daysFromToday(-90)}")
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "for_line_items", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "visible", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")

RequestMonitor.load $q.all([$scope.orders.$promise, $scope.distributors.$promise, $scope.orderCycles.$promise]).then ->
Dereferencer.dereferenceAttr $scope.orders, "distributor", Enterprises.byID
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
angular.module("admin.orderCycles").controller "OrderCyclesCtrl", ($scope, $q, StatusMessage, RequestMonitor, OrderCycles, Enterprises) ->
$scope.RequestMonitor = RequestMonitor
$scope.saveAll = -> OrderCycles.saveChanges($scope.order_cycles_form)
$scope.ordersCloseAtLimit = -31 # days

compileDataFor = (orderCycles) ->
for orderCycle in orderCycles
OrderCycles.linkToEnterprises(orderCycle)
orderCycle.producerNames = orderCycle.producers.map((producer) -> producer.name).join(", ")
orderCycle.shopNames = orderCycle.shops.map((shop) -> shop.name).join(", ")

# NOTE: this is using the Enterprises service from the admin.enterprises module
RequestMonitor.load ($scope.enterprises = Enterprises.index(includeBlank: true, action: "visible", ams_prefix: "basic")).$promise
RequestMonitor.load ($scope.orderCycles = OrderCycles.index(ams_prefix: "index", "q[orders_close_at_gt]": "#{daysFromToday($scope.ordersCloseAtLimit)}")).$promise
RequestMonitor.load $q.all([$scope.enterprises.$promise, $scope.orderCycles.$promise]).then -> compileDataFor($scope.orderCycles)

$scope.$watch 'order_cycles_form.$dirty', (newVal, oldVal) ->
StatusMessage.display 'notice', "You have unsaved changes" if newVal

$scope.showMore = (days) ->
$scope.ordersCloseAtLimit -= days
existingIDs = Object.keys(OrderCycles.orderCyclesByID)
RequestMonitor.load (orderCycles = OrderCycles.index(ams_prefix: "index", "q[orders_close_at_gt]": "#{daysFromToday($scope.ordersCloseAtLimit)}", "q[id_not_in][]": existingIDs)).$promise
orderCycles.$promise.then ->
compileDataFor(orderCycles)
$scope.orderCycles.push(orderCycle) for orderCycle in orderCycles

daysFromToday = (days) ->
now = new Date
now.setHours(0)
now.setMinutes(0)
now.setSeconds(0)
now.setDate( now.getDate() + days )
now
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
angular.module('admin.orderCycles', ['admin.utils', 'admin.indexUtils', 'ngTagsInput'])
angular.module('admin.orderCycles', ['admin.utils', 'admin.indexUtils', 'admin.enterprises', 'ngTagsInput'])

.config ($httpProvider) ->
$httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content')

.directive 'datetimepicker', ($parse) ->
(scope, element, attrs) ->
# using $parse instead of scope[attrs.datetimepicker] for cases
# where attrs.datetimepicker is 'foo.bar.lol'
$(element).datetimepicker
dateFormat: 'yy-mm-dd'
timeFormat: 'HH:mm:ss'
showOn: "button"
buttonImage: "<%= asset_path 'datepicker/cal.gif' %>"
buttonImageOnly: true
stepMinute: 15
onSelect: (dateText, inst) ->
scope.$apply ->
parsed = $parse(attrs.datetimepicker)
parsed.assign(scope, dateText)
.directive 'datetimepicker', ($timeout, $parse) ->
require: "ngModel"
link: (scope, element, attrs, ngModel) ->
$timeout ->
# using $parse instead of scope[attrs.datetimepicker] for cases
# where attrs.datetimepicker is 'foo.bar.lol'
$(element).datetimepicker
dateFormat: 'yy-mm-dd'
timeFormat: 'HH:mm:ss'
showOn: "button"
buttonImage: "<%= asset_path 'datepicker/cal.gif' %>"
buttonImageOnly: true
stepMinute: 15
onSelect: (dateText, inst) ->
scope.$apply(->
element.val(dateText)
parsed = $parse(attrs.datetimepicker)
parsed.assign(scope, dateText)
)


.directive 'ofnOnChange', ->
(scope, element, attrs) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ angular.module("admin.resources").factory 'OrderCycleResource', ($resource) ->
isArray: true
'update':
method: 'PUT'
'bulkUpdate':
method: 'POST'
isArray: true
params:
action: 'bulk_update'
})
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCycleResource) ->
angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCycleResource, StatusMessage, Enterprises, blankOption) ->
new class OrderCycles
all: []
byID: {}
Expand Down Expand Up @@ -30,14 +30,53 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
deferred.reject(response)
deferred.promise

saveChanges: (form) ->
changed = {}
for id, orderCycle of @orderCyclesByID when not @saved(orderCycle)
changed[Object.keys(changed).length] = @changesFor(orderCycle)
if Object.keys(changed).length > 0
StatusMessage.display('progress', "Saving...")
OrderCycleResource.bulkUpdate { order_cycle_set: { collection_attributes: changed } }, (data) =>
for orderCycle in data
angular.extend(@orderCyclesByID[orderCycle.id], orderCycle)
angular.extend(@pristineByID[orderCycle.id], orderCycle)
@linkToEnterprises(orderCycle)
form.$setPristine() if form?
StatusMessage.display('success', "Order cycles have been updated.")
, (response) =>
StatusMessage.display('failure', "Oh no! I was unable to save your changes.")

saved: (order_cycle) ->
@diff(order_cycle).length == 0

diff: (order_cycle) ->
changed = []
for attr, value of order_cycle when not angular.equals(value, @pristineByID[order_cycle.id][attr])
changed.push attr unless attr is "$$hashKey"
changed.push attr if attr in @attrsToSave()
changed

changesFor: (orderCycle) ->
changes = { id: orderCycle.id }
for attr, value of orderCycle when not angular.equals(value, @pristineByID[orderCycle.id][attr])
changes[attr] = orderCycle[attr] if attr in @attrsToSave()
changes

attrsToSave: ->
['orders_open_at','orders_close_at']

resetAttribute: (order_cycle, attribute) ->
order_cycle[attribute] = @pristineByID[order_cycle.id][attribute]

linkAllToEnterprises: ->
for id, orderCycle of @orderCyclesByID
@linkToEnterprises(orderCycle)

linkToEnterprises: (orderCycle) ->
coordinator = Enterprises.enterprisesByID[orderCycle.coordinator.id]
orderCycle.coordinator = coordinator if coordinator?
for producer, i in orderCycle.producers
producer = Enterprises.enterprisesByID[producer.id]
orderCycle.producers[i] = producer if producer?
for shop, i in orderCycle.shops
shop = Enterprises.enterprisesByID[shop.id]
orderCycle.shops[i] = shop if shop?
8 changes: 4 additions & 4 deletions app/controllers/admin/enterprises_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ def for_order_cycle
end
end

def for_line_items
def visible
respond_to do |format|
format.json do
render_as_json @collection, ams_prefix: 'basic', spree_current_user: spree_current_user
render_as_json @collection, ams_prefix: params[:ams_prefix] || 'basic', spree_current_user: spree_current_user
end
end
end
Expand Down Expand Up @@ -157,7 +157,7 @@ def collection
else
Enterprise.where("1=0")
end
when :for_line_items
when :visible
OpenFoodNetwork::Permissions.new(spree_current_user).visible_enterprises.ransack(params[:q]).result
else
# TODO was ordered with is_distributor DESC as well, not sure why or how we want to sort this now
Expand All @@ -168,7 +168,7 @@ def collection
end

def collection_actions
[:index, :for_order_cycle, :for_line_items, :bulk_update]
[:index, :for_order_cycle, :visible, :bulk_update]
end

def load_methods_and_fees
Expand Down
20 changes: 13 additions & 7 deletions app/controllers/admin/order_cycles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,14 @@ def update
def bulk_update
@order_cycle_set = params[:order_cycle_set] && OrderCycleSet.new(params[:order_cycle_set])
if @order_cycle_set.andand.save
redirect_to main_app.admin_order_cycles_path, notice: I18n.t(:order_cycles_bulk_update_notice)
respond_to do |format|
order_cycles = OrderCycle.where(id: params[:order_cycle_set][:collection_attributes].map{ |k,v| v[:id] })
format.json { render_as_json order_cycles, ams_prefix: 'index', current_user: spree_current_user }
end
else
render :index
respond_to do |format|
format.json { render :json => {:success => false} }
end
end
end

Expand All @@ -98,6 +103,7 @@ def notify_producers

protected
def collection
return Enterprise.where("1=0") unless json_request?
ocs = if params[:as] == "distributor"
OrderCycle.ransack(params[:q]).result.
involving_managed_distributors_of(spree_current_user).order('updated_at DESC')
Expand All @@ -120,14 +126,14 @@ def collection_actions

private
def load_data_for_index
@show_more = !!params[:show_more]
unless @show_more || params[:q].andand[:orders_close_at_gt].present?
if json_request?
# Split ransack params into all those that currently exist and new ones to limit returned ocs to recent or undated
orders_close_at_gt = params[:q].andand.delete(:orders_close_at_gt) || 31.days.ago
params[:q] = {
g: [ params.delete(:q) || {}, { m: 'or', orders_close_at_gt: 31.days.ago, orders_close_at_null: true } ]
g: [ params.delete(:q) || {}, { m: 'or', orders_close_at_gt: orders_close_at_gt, orders_close_at_null: true } ]
}
@order_cycle_set = OrderCycleSet.new :collection => (@collection = collection)
end
@order_cycle_set = OrderCycleSet.new :collection => (@collection = collection)
end

def require_coordinator
Expand Down Expand Up @@ -177,7 +183,7 @@ def remove_unauthorized_bulk_attrs
end

def ams_prefix_whitelist
[:basic]
[:basic, :index]
end
end
end
4 changes: 2 additions & 2 deletions app/helpers/order_cycles_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ def active_order_cycle_for_distributor?(distributor)
OrderCycle.active.with_distributor(@distributor).present?
end

def order_cycles_simple_index
@order_cycles_simple_index ||= !OpenFoodNetwork::Permissions.new(spree_current_user).can_manage_complex_order_cycles?
def simple_index
@simple_index ||= !OpenFoodNetwork::Permissions.new(spree_current_user).can_manage_complex_order_cycles?
end

def order_cycles_simple_form
Expand Down
2 changes: 1 addition & 1 deletion app/models/spree/ability_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def add_order_management_abilities(user)
order.distributor.nil? || user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user)
end
can [:admin, :bulk_management, :managed], Spree::Order if user.admin? || user.enterprises.any?(&:is_distributor)
can [:admin , :for_line_items], Enterprise
can [:admin, :visible], Enterprise
can [:admin, :index, :create, :update, :destroy], :line_item
can [:admin, :index, :create], Spree::LineItem
can [:destroy, :update], Spree::LineItem do |item|
Expand Down
65 changes: 65 additions & 0 deletions app/serializers/api/admin/index_order_cycle_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
require 'open_food_network/order_cycle_permissions'

class Api::Admin::IndexOrderCycleSerializer < ActiveModel::Serializer
include OrderCyclesHelper

attributes :id, :name, :orders_open_at, :orders_close_at, :status, :variant_count, :deletable
attributes :coordinator, :producers, :shops, :viewing_as_coordinator
attributes :edit_path, :clone_path, :delete_path

def deletable
can_delete?(object)
end

def variant_count
object.variants.count
end

def status
order_cycle_status_class object
end

def orders_open_at
object.orders_open_at.to_s
end

def orders_close_at
object.orders_close_at.to_s
end

def viewing_as_coordinator
Enterprise.managed_by(options[:current_user]).include? object.coordinator
end

def coordinator
Api::Admin::IdNameSerializer.new(object.coordinator).serializable_hash
end

def producers
producers = object.suppliers.merge(visible_enterprises)
ActiveModel::ArraySerializer.new(producers, {each_serializer: Api::Admin::IdNameSerializer})
end

def shops
shops = object.distributors.merge(visible_enterprises)
ActiveModel::ArraySerializer.new(shops, {each_serializer: Api::Admin::IdNameSerializer})
end

def edit_path
edit_admin_order_cycle_path(object)
end

def clone_path
clone_admin_order_cycle_path(object)
end

def delete_path
admin_order_cycle_path(object)
end

private

def visible_enterprises
@visible_enterprises ||= OpenFoodNetwork::OrderCyclePermissions.new(options[:current_user], object).visible_enterprises
end
end
33 changes: 33 additions & 0 deletions app/views/admin/order_cycles/_header.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
%colgroup
%col
%col{'style' => 'width: 20%;'}
%col{'style' => 'width: 20%;'}
- unless simple_index
%col
%col
%col
%col
%col
%col
%col

%thead
%tr
%th
=t :name
%th
=t :open
%th
=t :close
- unless simple_index
%th
=t :label_producers
%th
=t :coordinator
%th
=t :label_shops
%th
=t :products
%th.actions
%th.actions
%th.actions
4 changes: 4 additions & 0 deletions app/views/admin/order_cycles/_loading_flash.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
%div.sixteen.columns.alpha.omega#loading{ ng: { cloak: true, if: 'RequestMonitor.loading' } }
%img.spinner{ src: "/assets/spinning-circles.svg" }
%h1{ ng: { hide: 'orderCycles.length > 0' } } LOADING ORDER CYCLES
%h1{ ng: { show: 'orderCycles.length > 0' } } LOADING...
Loading

0 comments on commit 2a5f598

Please sign in to comment.