WIP: Splitting Variant overrides into views

This commit is contained in:
Rob Harrington
2016-02-01 15:30:08 +11:00
parent 8f37aa0522
commit 28b143da73
33 changed files with 311 additions and 172 deletions

View File

@@ -1,2 +0,0 @@
angular.module("admin.dropdown").controller "DropDownCtrl", ($scope) ->
$scope.expanded = false

View File

@@ -1,4 +1,4 @@
angular.module("admin.dropdown").directive "ofnCloseOnClick", ($document) ->
angular.module("admin.dropdown").directive "closeOnClick", () ->
link: (scope, element, attrs) ->
element.click (event) ->
event.stopPropagation()

View File

@@ -1,6 +1,9 @@
angular.module("admin.dropdown").directive "ofnDropDown", ($document) ->
restrict: 'C'
scope: true
link: (scope, element, attrs) ->
scope.expanded = false
outsideClickListener = (event) ->
unless $(event.target).is("div.ofn-drop-down##{attrs.id} div.menu") ||
$(event.target).parents("div.ofn-drop-down##{attrs.id} div.menu").length > 0

View File

@@ -1,4 +1,4 @@
angular.module("admin.indexUtils").directive "ofnToggleColumn", (Columns) ->
angular.module("admin.indexUtils").directive "toggleColumn", (Columns) ->
link: (scope, element, attrs) ->
element.addClass "selected" if scope.column.visible

View File

@@ -0,0 +1,11 @@
angular.module("admin.indexUtils").directive "toggleView", (Views) ->
link: (scope, element, attrs) ->
Views.register
element.addClass "selected" if scope.view.visible
element.click "click", ->
scope.$apply ->
Views.selectView(scope.viewKey)
scope.$watch "view.visible", (newValue, oldValue) ->
element.toggleClass "selected", scope.view.visible

View File

@@ -0,0 +1,16 @@
angular.module("admin.indexUtils").factory 'Views', ($rootScope) ->
new class Views
views: {}
currentView: null
setViews: (views) =>
@views = {}
for key, view of views
@views[key] = view
@selectView(key) if view.visible
@views
selectView: (selectedKey) =>
@currentView = @views[selectedKey]
for key, view of @views
view.visible = (key == selectedKey)

View File

@@ -5,11 +5,14 @@ angular.module("admin.utils").directive "alertRow", ->
message: '@'
buttonText: '@?'
buttonAction: '&?'
dismissed: '=?'
close: "&?"
transclude: true
templateUrl: "admin/alert_row.html"
link: (scope, element, attrs) ->
scope.dismissed = false
scope.dismiss = ->
scope.dismissed = true
scope.close() if scope.close?
element.hide()
return false

View File

@@ -1,17 +1,23 @@
angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl", ($scope, $http, $timeout, Indexer, Columns, SpreeApiAuth, PagedFetcher, StatusMessage, RequestMonitor, hubs, producers, hubPermissions, InventoryItems, VariantOverrides, DirtyVariantOverrides) ->
angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl", ($scope, $http, $timeout, Indexer, Columns, Views, SpreeApiAuth, PagedFetcher, StatusMessage, RequestMonitor, hubs, producers, hubPermissions, InventoryItems, VariantOverrides, DirtyVariantOverrides) ->
$scope.hubs = Indexer.index hubs
$scope.hub = null
$scope.products = []
$scope.producers = producers
$scope.producersByID = Indexer.index producers
$scope.hubPermissions = hubPermissions
$scope.showHidden = false
$scope.productLimit = 10
$scope.variantOverrides = VariantOverrides.variantOverrides
$scope.inventoryItems = InventoryItems.inventoryItems
$scope.setVisibility = InventoryItems.setVisibility
$scope.StatusMessage = StatusMessage
$scope.RequestMonitor = RequestMonitor
$scope.selectView = Views.selectView
$scope.currentView = -> Views.currentView
$scope.views = Views.setViews
inventory: { name: "Inventory Products", visible: true }
hidden: { name: "Hidden Products", visible: false }
new: { name: "New Products", visible: false }
$scope.columns = Columns.setColumns
producer: { name: "Producer", visible: true }
@@ -22,7 +28,9 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl",
on_demand: { name: "On Demand", visible: false }
reset: { name: "Reset Stock Level", visible: false }
inheritance: { name: "Inheritance", visible: false }
visibility: { name: "Show/Hide", visible: false }
visibility: { name: "Hide", visible: false }
$scope.bulkActions = [ name: "Reset Stock Levels To Defaults", callback: 'resetStock' ]
$scope.resetSelectFilters = ->
$scope.producerFilter = 0
@@ -30,6 +38,9 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl",
$scope.resetSelectFilters()
$scope.filtersApplied = ->
$scope.producerFilter != 0 || $scope.query != ''
$scope.initialise = ->
SpreeApiAuth.authorise()
.then ->

View File

@@ -1,12 +1,17 @@
angular.module("admin.variantOverrides").filter "inventoryProducts", ($filter, InventoryItems) ->
return (products, hub_id, showHidden) ->
return (products, hub_id, views) ->
return [] if !hub_id
return $filter('filter')(products, (product) ->
for variant in product.variants
if InventoryItems.inventoryItems.hasOwnProperty(hub_id) && InventoryItems.inventoryItems[hub_id].hasOwnProperty(variant.id)
if showHidden
return true
if InventoryItems.inventoryItems[hub_id][variant.id].visible
# Important to only return if true, as other variants for this product might be visible
return true if views.inventory.visible
else
return true if InventoryItems.inventoryItems[hub_id][variant.id].visible
false
# Important to only return if true, as other variants for this product might be visible
return true if views.hidden.visible
else
# Important to only return if true, as other variants for this product might be visible
return true if views.new.visible
false
, true)

View File

@@ -1,12 +1,12 @@
angular.module("admin.variantOverrides").filter "inventoryVariants", ($filter, InventoryItems) ->
return (variants, hub_id, showHidden) ->
return (variants, hub_id, views) ->
return [] if !hub_id
return $filter('filter')(variants, (variant) ->
if InventoryItems.inventoryItems.hasOwnProperty(hub_id) && InventoryItems.inventoryItems[hub_id].hasOwnProperty(variant.id)
if showHidden
return true
if InventoryItems.inventoryItems[hub_id][variant.id].visible
return views.inventory.visible
else
return InventoryItems.inventoryItems[hub_id][variant.id].visible
return views.hidden.visible
else
false
return views.new.visible
, true)

View File

@@ -5,4 +5,5 @@ angular.module("admin.variantOverrides").filter "newInventoryProducts", ($filter
return $filter('filter')(products, (product) ->
for variant in product.variants
return true if !InventoryItems.inventoryItems[hub_id].hasOwnProperty(variant.id)
false
, true)

View File

@@ -1,7 +0,0 @@
angular.module("admin.variantOverrides").filter "newInventoryVariants", ($filter, InventoryItems) ->
return (variants, hub_id) ->
return [] if !hub_id
return variants unless InventoryItems.inventoryItems.hasOwnProperty(hub_id)
return $filter('filter')(variants, (variant) ->
!InventoryItems.inventoryItems[hub_id].hasOwnProperty(variant.id)
, true)

View File

@@ -1,6 +1,6 @@
.sixteen.columns.alpha.omega.alert-row
.sixteen.columns.alpha.omega.alert-row{ ng: { show: '!dismissed' } }
.fifteen.columns.pad.alpha
%span.text-big{ ng: { bind: 'message'} }
%span.message.text-big{ ng: { bind: 'message'} }
   
%input{ type: 'button', ng: { value: "buttonText", show: 'buttonText && buttonAction', click: "buttonAction()" } }
.one.column.omega.pad.text-center

View File

@@ -1,4 +1,5 @@
.alert-row{
margin-bottom: 10px;
font-weight: bold;
background-color: #eff5fc;

View File

@@ -27,9 +27,12 @@
-ms-user-select: none;
user-select: none;
text-align: center;
margin-right: 10px;
&.right {
float: right;
margin-right: 0px;
margin-left: 10px;
}
&:hover, &.expanded {
@@ -55,12 +58,35 @@
background-color: #ffffff;
box-shadow: 1px 3px 10px #888888;
z-index: 100;
white-space: nowrap;
.menu_item {
margin: 0px;
padding: 2px 0px;
padding: 2px 10px;
color: #454545;
text-align: left;
display: block;
.check {
display: inline-block;
text-align: center;
width: 40px;
&:before {
content: "\00a0";
}
}
.name {
display: inline-block;
padding: 0px 15px 0px 0px;
}
&.selected{
.check:before {
content: "\2713";
}
}
}
.menu_item:hover {

View File

@@ -1,3 +1,6 @@
.variant-override-unit
float: right
font-style: italic
button.hide:hover
background-color: #DA5354

View File

@@ -1,7 +1,6 @@
.three.columns
.ofn-drop-down#bulk-actions-dropdown{ 'ng-controller' => "DropDownCtrl" }
%span.icon-check   Actions
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
%div.menu{ 'ng-show' => "expanded" }
.three.columns.alpha.menu_item{ 'ng-repeat' => "action in bulkActions", 'ng-click' => "$eval(action.callback)(filteredLineItems)", 'ofn-close-on-click' => true }
%span.three.columns.omega {{ action.name }}
.ofn-drop-down#bulk-actions-dropdown
%span.icon-check   Actions
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
.menu{ 'ng-show' => "expanded" }
.menu_item{ 'ng-repeat' => "action in bulkActions", 'ng-click' => "$eval(action.callback)(filteredLineItems)", 'close-on-click' => true }
%span.name {{ action.name }}

View File

@@ -1,8 +1,7 @@
%div.three.columns.omega
%div.ofn-drop-down.right#columns-dropdown{ 'ng-controller' => "DropDownCtrl" }
%span{ :class => 'icon-reorder' }   Columns
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
%div.menu{ 'ng-show' => "expanded" }
%div.menu_item.three.columns.alpha.omega{ 'ng-repeat' => "column in columns", 'ofn-toggle-column' => true }
%span.one.column.alpha.text-center {{ column.visible && "✓" || !column.visible && " " }}
%span.two.columns.omega {{column.name }}
.ofn-drop-down.right#columns-dropdown
%span{ :class => 'icon-reorder' }   Columns
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
%div.menu{ 'ng-show' => "expanded" }
%div.menu_item{ ng: { repeat: "column in columns" }, toggle: { column: true } }
%span.check
%span.name {{column.name }}

View File

@@ -0,0 +1,7 @@
.ofn-drop-down#views-dropdown
%span{ :class => 'icon-eye-open' }   Viewing: {{ currentView().name }}
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
%div.menu{ 'ng-show' => "expanded" }
%div.menu_item{ ng: { repeat: "(viewKey, view) in views" }, toggle: { view: true }, 'close-on-click' => true }
%span.check
%span.name {{ view.name }}

View File

@@ -0,0 +1,15 @@
%hr.divider.sixteen.columns.alpha.omega{ ng: { show: 'hub && products.length > 0' } }
.controls.sixteen.columns.alpha.omega{ ng: { show: 'hub && products.length > 0' } }
.eight.columns.alpha
= render 'admin/shared/bulk_actions_dropdown'
= render 'admin/shared/views_dropdown'
%span.text-big.with-tip.icon-question-sign{ ng: { show: 'views.inventory.visible' } , data: { powertip: 'This is your inventory of products. Products must be listed here before you can sell them in your shop. To add products to your inventory, select \'New Products\' from the Viewing dropdown.' } }
%span.text-big.with-tip.icon-question-sign{ ng: { show: 'views.hidden.visible' } , data: { powertip: 'These products have been hidden from your inventory and will not be available in your shop. You can click \'Add\' to add a product to you inventory.' } }
%span.text-big.with-tip.icon-question-sign{ ng: { show: 'views.new.visible' } , data: { powertip: 'These products are available to be added to your inventory. Click \'Add\' to add a product to your inventory, or \'Hide\' to hide it from view. You can always change your mind later!' } }
.four.columns  
.four.columns.omega{ ng: { show: 'views.new.visible' } }
%button.fullwidth{ type: 'button', ng: { click: "selectView('inventory')" } }
%i.icon-chevron-left
Back to my inventory
.four.columns.omega{ng: { show: 'views.inventory.visible' } }
= render 'admin/shared/columns_dropdown'

View File

@@ -0,0 +1,22 @@
%div{ ng: { show: 'views.hidden.visible' } }
%table#hidden-products{ ng: { show: 'filteredProducts.length > 0' } }
%col.producer{ width: "20%" }
%col.product{ width: "20%" }
%col.variant{ width: "30%" }
%col.add{ width: "15%" }
%thead
%tr
%th.producer Producer
%th.product Product
%th.variant Variant
%th.add Add
%tbody{ bindonce: true, ng: { repeat: 'product in filteredProducts | limitTo:productLimit' } }
%tr{ id: "v_{{variant.id}}", ng: { repeat: 'variant in product.variants | inventoryVariants:hub.id:views' } }
%td.producer{ bo: { bind: 'producersByID[product.producer_id].name'} }
%td.product{ bo: { bind: 'product.name'} }
%td.variant
%span{ bo: { bind: 'variant.display_name || ""'} }
.variant-override-unit{ bo: { bind: 'variant.unit_to_display'} }
%td.add
%button.fullwidth.icon-plus{ ng: { click: "setVisibility(hub.id,variant.id,true)" } }
= t(:add)

View File

@@ -0,0 +1,3 @@
%div.sixteen.columns.alpha.omega#loading{ ng: { cloak: true, if: 'hub && products.length == 0 && RequestMonitor.loading' } }
%img.spinner{ src: "/assets/spinning-circles.svg" }
%h1 LOADING INVENTORY

View File

@@ -0,0 +1,26 @@
%table#new-products{ ng: { show: 'views.new.visible && filteredProducts.length > 0' } }
%col.producer{ width: "20%" }
%col.product{ width: "20%" }
%col.variant{ width: "30%" }
%col.add{ width: "15%" }
%col.hide{ width: "15%" }
%thead
%tr
%th.producer Producer
%th.product Product
%th.variant Variant
%th.add Add
%th.hide Hide
%tbody{ bindonce: true, ng: { repeat: 'product in filteredProducts | limitTo:productLimit' } }
%tr{ id: "v_{{variant.id}}", ng: { repeat: 'variant in product.variants | inventoryVariants:hub.id:views' } }
%td.producer{ bo: { bind: 'producersByID[product.producer_id].name'} }
%td.product{ bo: { bind: 'product.name'} }
%td.variant
%span{ bo: { bind: 'variant.display_name || ""'} }
.variant-override-unit{ bo: { bind: 'variant.unit_to_display'} }
%td.add
%button.fullwidth.icon-plus{ ng: { click: "setVisibility(hub.id,variant.id,true)" } }
= t(:add)
%td.hide
%button.fullwidth.hide.icon-remove{ ng: { click: "setVisibility(hub.id,variant.id,false)" } }
= t(:hide)

View File

@@ -0,0 +1,5 @@
%div{ ng: { show: '(newProductCount = (products | newInventoryProducts:hub_id).length) > 0 && !views.new.visible && !alertDismissed' } }
%hr.divider.sixteen.columns.alpha.omega
%alert-row{ message: "There are {{ newProductCount }} new products available to add to your inventory.",
dismissed: "alertDismissed",
button: { text: 'Review Now', action: "selectView('new')" } }

View File

@@ -1,56 +0,0 @@
%hr.divider.sixteen.columns.alpha.omega{ ng: { show: 'newProducts.length > 0 && addingNewVariants != false' } }
%alert-row{ message: "There are {{ newProducts.length }} new products available to add to your inventory.",
button: { text: 'Review Now', action: "addingNewVariants = true" },
close: "addingNewVariants = false",
ng: { show: 'newProducts.length > 0 && addingNewVariants == undefined' } }
%div{ ng: { show: 'newProducts.length > 0 && addingNewVariants' } }
.sixteen.columns.alpha.omega.margin-bottom-20
.two-thirds.column.alpha.text-normal
Add products to your inventory by clicking 'Add', or hide them from view by clicking 'Ignore'. Don't worry, you can always change your mind later.
.one-third.column.omega
%button.fullwidth{ type: 'button', ng: { click: 'addingNewVariants = false' } }
%i.icon-chevron-left
Back to my inventory
-# .one-third.column
-# %button.text-big.fullwidth{ type: 'button', ng: { click: 'setVisibility(hub.id,variantIDs(filteredNewProducts),true)' } }
-# %i.icon-plus
-# Add All ({{filteredNewProducts.length}})
-# .one-third.column.omega
-# %button.text-big.fullwidth{ type: 'button', ng: { click: 'setVisibility(hub.id,variantIDs(filteredNewProducts),false)' } }
-# %i.icon-remove
-# Ignore All ({{filteredNewProducts.length}})
%h2#no_results{ ng: { show: 'filteredNewProducts.length == 0' } }
No new products match the filters provided.
%table#new-variants{ ng: { show: 'filteredNewProducts.length > 0' } }
%col.producer{ width: "20%" }
%col.product{ width: "20%" }
%col.variant{ width: "40%" }
%col.add{ width: "10%" }
%col.ignore{ width: "10%" }
%thead
%tr
%th.producer Producer
%th.product Product
%th.variant Variant
%th.add Add
%th.ignore Ignore
%tbody{ bindonce: true, ng: { repeat: 'product in filteredNewProducts = (newProducts = (products | hubPermissions:hubPermissions:hub.id | newInventoryProducts:hub.id) | attrFilter:{producer_id:producerFilter} | filter:query) | limitTo:productLimit' } }
%tr{ id: "nv_{{variant.id}}", ng: { repeat: 'variant in product.variants | newInventoryVariants:hub.id'} }
%td.producer{ bo: { bind: 'producersByID[product.producer_id].name'} }
%td.product{ bo: { bind: 'product.name'} }
%td.variant
%span{ bo: { bind: 'variant.display_name || ""'} }
.variant-override-unit{ bo: { bind: 'variant.unit_to_display'} }
%td.add
%input.fullwidth{ :type => 'button', value: "Add", ng: { click: "setVisibility(hub.id,variant.id,true)" } }
%td.ignore
%input.fullwidth{ :type => 'button', value: "Ignore", ng: { click: "setVisibility(hub.id,variant.id,false)" } }
.sixteen.columns.alpha.omega.text-center{ ng: {show: 'productLimit < filteredNewProducts.length'}}
%input{ type: 'button', value: 'Show More', ng: { click: 'productLimit = productLimit + 10' } }
or
%input{ type: 'button', value: "Show All ({{ filteredNewProducts.length - productLimit }} More)", ng: { click: 'productLimit = filteredNewProducts.length' } }

View File

@@ -0,0 +1,7 @@
%div.text-big.no-results{ ng: { show: 'hub && products.length > 0 && filteredProducts.length == 0' } }
%span{ ng: { show: 'views.inventory.visible && !filtersApplied()' } } You inventory is currently empty.
%span{ ng: { show: 'views.inventory.visible && filtersApplied()' } } No matching products found in your inventory.
%span{ ng: { show: 'views.hidden.visible && !filtersApplied()' } } No products have been hidden from this inventory.
%span{ ng: { show: 'views.hidden.visible && filtersApplied()' } } No hidden products match your search criteria.
%span{ ng: { show: 'views.new.visible && !filtersApplied()' } } No new products available to add this inventory.
%span{ ng: { show: 'views.new.visible && filtersApplied()' } } No new products match your search criteria.

View File

@@ -1,30 +1,27 @@
%table.index.bulk#variant-overrides
%col.producer{ width: "20%", ng: { show: 'columns.producer.visible' } }
%col.product{ width: "20%", ng: { show: 'columns.product.visible' } }
%col.sku{ width: "20%", ng: { show: 'columns.sku.visible' } }
%col.price{ width: "10%", ng: { show: 'columns.price.visible' } }
%col.on_hand{ width: "10%", ng: { show: 'columns.on_hand.visible' } }
%col.on_demand{ width: "10%", ng: { show: 'columns.on_demand.visible' } }
%col.reset{ width: "1%", ng: { show: 'columns.reset.visible' } }
%col.reset{ width: "15%", ng: { show: 'columns.reset.visible' } }
%col.inheritance{ width: "5%", ng: { show: 'columns.inheritance.visible' } }
%col.visibility{ width: "10%", ng: { show: 'columns.visibility.visible' } }
%thead
%tr{ ng: { controller: "ColumnsCtrl" } }
%th.producer{ ng: { show: 'columns.producer.visible' } } Producer
%th.product{ ng: { show: 'columns.product.visible' } } Product
%th.sku{ ng: { show: 'columns.sku.visible' } } SKU
%th.price{ ng: { show: 'columns.price.visible' } } Price
%th.on_hand{ ng: { show: 'columns.on_hand.visible' } } On hand
%th.on_demand{ ng: { show: 'columns.on_demand.visible' } } On Demand?
%th.reset{ colspan: 2, ng: { show: 'columns.reset.visible' } } Enable Stock Level Reset?
%th.inheritance{ ng: { show: 'columns.inheritance.visible' } } Inherit?
%th.visibility{ ng: { show: 'columns.visibility.visible' } } Show/Hide?
%tbody{bindonce: true, ng: {repeat: 'product in filteredProducts = (products | hubPermissions:hubPermissions:hub.id | inventoryProducts:hub.id:showHidden | attrFilter:{producer_id:producerFilter} | filter:query) | limitTo:productLimit' } }
= render 'admin/variant_overrides/products_product'
= render 'admin/variant_overrides/products_variants'
.sixteen.columns.alpha.omega.text-center{ ng: {show: 'productLimit < filteredProducts.length'}}
%input{ type: 'button', value: 'Show More', ng: { click: 'productLimit = productLimit + 10' } }
or
%input{ type: 'button', value: "Show All ({{ filteredProducts.length - productLimit }} More)", ng: { click: 'productLimit = filteredProducts.length' } }
%form{ name: 'variant_overrides_form', ng: { show: "views.inventory.visible" } }
%save-bar{ save: "update()", form: "variant_overrides_form" }
%table.index.bulk#variant-overrides
%col.producer{ width: "20%", ng: { show: 'columns.producer.visible' } }
%col.product{ width: "20%", ng: { show: 'columns.product.visible' } }
%col.sku{ width: "20%", ng: { show: 'columns.sku.visible' } }
%col.price{ width: "10%", ng: { show: 'columns.price.visible' } }
%col.on_hand{ width: "10%", ng: { show: 'columns.on_hand.visible' } }
%col.on_demand{ width: "10%", ng: { show: 'columns.on_demand.visible' } }
%col.reset{ width: "1%", ng: { show: 'columns.reset.visible' } }
%col.reset{ width: "15%", ng: { show: 'columns.reset.visible' } }
%col.inheritance{ width: "5%", ng: { show: 'columns.inheritance.visible' } }
%col.visibility{ width: "10%", ng: { show: 'columns.visibility.visible' } }
%thead
%tr{ ng: { controller: "ColumnsCtrl" } }
%th.producer{ ng: { show: 'columns.producer.visible' } } Producer
%th.product{ ng: { show: 'columns.product.visible' } } Product
%th.sku{ ng: { show: 'columns.sku.visible' } } SKU
%th.price{ ng: { show: 'columns.price.visible' } } Price
%th.on_hand{ ng: { show: 'columns.on_hand.visible' } } On hand
%th.on_demand{ ng: { show: 'columns.on_demand.visible' } } On Demand?
%th.reset{ colspan: 2, ng: { show: 'columns.reset.visible' } } Enable Stock Level Reset?
%th.inheritance{ ng: { show: 'columns.inheritance.visible' } } Inherit?
%th.visibility{ ng: { show: 'columns.visibility.visible' } } Hide
%tbody{bindonce: true, ng: {repeat: 'product in filteredProducts = (products | hubPermissions:hubPermissions:hub.id | inventoryProducts:hub.id:views | attrFilter:{producer_id:producerFilter} | filter:query) | limitTo:productLimit' } }
= render 'admin/variant_overrides/products_product'
= render 'admin/variant_overrides/products_variants'

View File

@@ -1,4 +1,4 @@
%tr.variant{ id: "v_{{variant.id}}", ng: {repeat: 'variant in product.variants | inventoryVariants:hub.id:showHidden'}}
%tr.variant{ id: "v_{{variant.id}}", ng: {repeat: 'variant in product.variants | inventoryVariants:hub.id:views'}}
%td.producer{ ng: { show: 'columns.producer.visible' } }
%td.product{ ng: { show: 'columns.product.visible' } }
%span{ bo: { bind: 'variant.display_name || ""'} }
@@ -18,4 +18,5 @@
%td.inheritance{ ng: { show: 'columns.inheritance.visible' } }
%input.field{ :type => 'checkbox', name: 'variant-overrides-{{ variant.id }}-inherit', ng: { model: 'inherit' }, 'track-inheritance' => true }
%td.visibility{ ng: { show: 'columns.visibility.visible' } }
%input.fullwidth{ :type => 'button', ng: { value: "inventoryItems[hub.id][variant.id].visible ? 'Hide' : 'Show'", click: "setVisibility(hub.id,variant.id,!inventoryItems[hub.id][variant.id].visible)", class: "{ hidden: !inventoryItems[hub.id][variant.id].visible}" } }
%button.icon-remove.hide.fullwidth{ :type => 'button', ng: { click: "setVisibility(hub.id,variant.id,false)" } }
= t(:hide)

View File

@@ -0,0 +1,4 @@
.sixteen.columns.alpha.omega.text-center{ ng: {show: 'productLimit < filteredProducts.length'}}
%input{ type: 'button', value: 'Show More', ng: { click: 'productLimit = productLimit + 10' } }
or
%input{ type: 'button', value: "Show All ({{ filteredProducts.length - productLimit }} More)", ng: { click: 'productLimit = filteredProducts.length' } }

View File

@@ -3,24 +3,12 @@
.margin-bottom-50{ ng: { app: 'admin.variantOverrides', controller: 'AdminVariantOverridesCtrl', init: 'initialise()' } }
= render 'admin/variant_overrides/filters'
%div.sixteen.columns.alpha#loading{ ng: { cloak: true, if: 'hub && products.length == 0 && RequestMonitor.loading' } }
%img.spinner{ src: "/assets/spinning-circles.svg" }
%h1 LOADING INVENTORY
= render 'admin/variant_overrides/new_variants'
%span.text-big.no-results{ ng: { show: 'hub && !addingNewVariants && products.length > 0 && filteredProducts.length == 0' } }
No products matching products found.
%span.text-big.no-results{ ng: { show: 'hub && !addingNewVariants && products.length == 0 && !RequestMonitor.loading' } }
There are no products in {{ hub.name }}'s inventory
%button{ value: 'Add Some!' }
%div{ ng: { cloak: true, show: 'hub && !addingNewVariants && filteredProducts.length > 0' } }
%hr.divider.sixteen.columns.alpha.omega
.controls.sixteen.columns.alpha.omega
%input.four.columns.alpha{ type: 'button', value: 'Reset Stock to Defaults', 'ng-click' => 'resetStock()' }
%input.four.columns{ type: 'button', ng: { value: "showHidden ? 'Hide Hidden' : 'Show Hidden'", click: 'showHidden = !showHidden' } }
%div.five.columns &nbsp;
= render 'admin/shared/columns_dropdown'
%form{ name: 'variant_overrides_form' }
%save-bar{ save: "update()", form: "variant_overrides_form" }
= render 'admin/variant_overrides/products'
= render 'admin/variant_overrides/new_products_alert'
= render 'admin/variant_overrides/loading_flash'
= render 'admin/variant_overrides/controls'
= render 'admin/variant_overrides/no_results'
%div{ ng: { cloak: true, show: 'hub && filteredProducts.length > 0' } }
= render 'admin/variant_overrides/new_products'
= render 'admin/variant_overrides/hidden_products'
= render 'admin/variant_overrides/products'
= render 'admin/variant_overrides/show_more'

View File

@@ -99,23 +99,24 @@ feature %q{
# Show/Hide products
first("div#columns-dropdown", :text => "COLUMNS").click
first("div#columns-dropdown div.menu div.menu_item", text: "Show/Hide").click
first("div#columns-dropdown div.menu div.menu_item", text: "Hide").click
first("div#columns-dropdown", :text => "COLUMNS").click
expect(page).to have_selector "tr#v_#{variant.id}"
expect(page).to have_selector "tr#v_#{variant_related.id}"
within "tr#v_#{variant.id}" do click_button 'Hide' end
expect(page).to_not have_selector "tr#v_#{variant.id}"
expect(page).to have_selector "tr#v_#{variant_related.id}"
click_button 'Show Hidden'
expect(page).to have_selector "tr#v_#{variant.id}"
expect(page).to have_selector "tr#v_#{variant_related.id}"
within "tr#v_#{variant.id}" do click_button 'Show' end
within "tr#v_#{variant_related.id}" do click_button 'Hide' end
expect(page).to have_selector "tr#v_#{variant.id}"
expect(page).to have_selector "tr#v_#{variant_related.id}"
click_button 'Hide Hidden'
first("div#views-dropdown").click
first("div#views-dropdown div.menu div.menu_item", text: "Hidden Products").click
expect(page).to have_selector "tr#v_#{variant.id}"
expect(page).to_not have_selector "tr#v_#{variant_related.id}"
within "tr#v_#{variant.id}" do click_button 'Add' end
expect(page).to_not have_selector "tr#v_#{variant.id}"
expect(page).to_not have_selector "tr#v_#{variant_related.id}"
first("div#views-dropdown").click
first("div#views-dropdown div.menu div.menu_item", text: "Inventory Products").click
expect(page).to have_selector "tr#v_#{variant.id}"
expect(page).to have_selector "tr#v_#{variant_related.id}"
end
it "creates new overrides" do
@@ -271,7 +272,8 @@ feature %q{
end
it "resets stock to defaults" do
click_button 'Reset Stock to Defaults'
first("div#bulk-actions-dropdown").click
first("div#bulk-actions-dropdown div.menu div.menu_item", text: "Reset Stock Levels To Defaults").click
page.should have_content 'Stocks reset to defaults.'
vo.reload
page.should have_input "variant-overrides-#{variant.id}-count_on_hand", with: '1000', placeholder: '12'
@@ -279,7 +281,8 @@ feature %q{
end
it "doesn't reset stock levels if the behaviour is disabled" do
click_button 'Reset Stock to Defaults'
first("div#bulk-actions-dropdown").click
first("div#bulk-actions-dropdown div.menu div.menu_item", text: "Reset Stock Levels To Defaults").click
vo_no_reset.reload
page.should have_input "variant-overrides-#{variant2.id}-count_on_hand", with: '40', placeholder: '12'
vo_no_reset.count_on_hand.should == 40
@@ -287,7 +290,8 @@ feature %q{
it "prompts to save changes before reset if any are pending" do
fill_in "variant-overrides-#{variant.id}-price", with: '200'
click_button 'Reset Stock to Defaults'
first("div#bulk-actions-dropdown").click
first("div#bulk-actions-dropdown div.menu div.menu_item", text: "Reset Stock Levels To Defaults").click
page.should have_content "Save changes first"
end
end
@@ -305,20 +309,30 @@ feature %q{
select2_select hub.name, from: 'hub_id'
end
it "shows new variants, and allows them to be added or ignored" do
it "alerts the user to the presence of new products, and allows them to be added or hidden" do
expect(page).to_not have_selector "table#variant-overrides tr#v_#{variant1.id}"
expect(page).to_not have_selector "table#variant-overrides tr#v_#{variant2.id}"
expect(page).to have_table_row ['PRODUCER', 'PRODUCT', 'VARIANT', 'ADD', 'IGNORE']
expect(page).to have_selector "table#new-variants tr#nv_#{variant1.id}"
expect(page).to have_selector "table#new-variants tr#nv_#{variant2.id}"
within "table#new-variants tr#nv_#{variant1.id}" do click_button 'Add' end
within "table#new-variants tr#nv_#{variant2.id}" do click_button 'Ignore' end
expect(page).to_not have_selector "table#new-variants tr#nv_#{variant1.id}"
expect(page).to_not have_selector "table#new-variants tr#nv_#{variant2.id}"
expect(page).to have_selector '.alert-row span.message', text: "There are 1 new products available to add to your inventory."
click_button "Review Now"
expect(page).to have_table_row ['PRODUCER', 'PRODUCT', 'VARIANT', 'ADD', 'HIDE']
expect(page).to have_selector "table#new-products tr#v_#{variant1.id}"
expect(page).to have_selector "table#new-products tr#v_#{variant2.id}"
within "table#new-products tr#v_#{variant1.id}" do click_button 'Add' end
within "table#new-products tr#v_#{variant2.id}" do click_button 'Hide' end
expect(page).to_not have_selector "table#new-products tr#v_#{variant1.id}"
expect(page).to_not have_selector "table#new-products tr#v_#{variant2.id}"
click_button "Back to my inventory"
expect(page).to have_selector "table#variant-overrides tr#v_#{variant1.id}"
expect(page).to_not have_selector "table#variant-overrides tr#v_#{variant2.id}"
first("div#views-dropdown").click
first("div#views-dropdown div.menu div.menu_item", text: "Hidden Products").click
expect(page).to_not have_selector "table#hidden-products tr#v_#{variant1.id}"
expect(page).to have_selector "table#hidden-products tr#v_#{variant2.id}"
end
end
end

View File

@@ -0,0 +1,37 @@
describe "Views service", ->
Views = null
beforeEach ->
module 'admin.indexUtils'
inject (_Views_) ->
Views = _Views_
describe "setting views", ->
beforeEach ->
spyOn(Views, "selectView").andCallThrough()
Views.setViews
view1: { name: 'View1', visible: true }
view2: { name: 'View2', visible: false }
view3: { name: 'View3', visible: true }
it "sets resets @views and copies each view of the provided object across", ->
expect(Object.keys(Views.views)).toEqual ['view1', 'view2', 'view3']
it "calls selectView if visible is true", ->
expect(Views.selectView).toHaveBeenCalledWith('view1')
expect(Views.selectView).not.toHaveBeenCalledWith('view2');
expect(Views.selectView).toHaveBeenCalledWith('view3')
expect(view.visible for key, view of Views.views).toEqual [false, false, true]
describe "selecting a view", ->
beforeEach ->
Views.currentView = "some View"
Views.views = { view7: { name: 'View7', visible: false } }
Views.selectView('view7')
it "sets the currentView", ->
expect(Views.currentView.name).toEqual 'View7'
it "switches the visibility of the given view", ->
expect(Views.currentView).toEqual { name: 'View7', visible: true }