diff --git a/app/assets/javascripts/admin/dropdown/controllers/dropdown_controller.js.coffee b/app/assets/javascripts/admin/dropdown/controllers/dropdown_controller.js.coffee deleted file mode 100644 index 02e47ff9f7..0000000000 --- a/app/assets/javascripts/admin/dropdown/controllers/dropdown_controller.js.coffee +++ /dev/null @@ -1,2 +0,0 @@ -angular.module("admin.dropdown").controller "DropDownCtrl", ($scope) -> - $scope.expanded = false diff --git a/app/assets/javascripts/admin/dropdown/directives/close_on_click.js.coffee b/app/assets/javascripts/admin/dropdown/directives/close_on_click.js.coffee index 9b506cb8fb..1ab9e5c8a4 100644 --- a/app/assets/javascripts/admin/dropdown/directives/close_on_click.js.coffee +++ b/app/assets/javascripts/admin/dropdown/directives/close_on_click.js.coffee @@ -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() diff --git a/app/assets/javascripts/admin/dropdown/directives/dropdown.js.coffee b/app/assets/javascripts/admin/dropdown/directives/dropdown.js.coffee index b4ca2869d7..f26894afbc 100644 --- a/app/assets/javascripts/admin/dropdown/directives/dropdown.js.coffee +++ b/app/assets/javascripts/admin/dropdown/directives/dropdown.js.coffee @@ -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 diff --git a/app/assets/javascripts/admin/index_utils/directives/toggle_column.js.coffee b/app/assets/javascripts/admin/index_utils/directives/toggle_column.js.coffee index 2910e9a7a1..614b8d9346 100644 --- a/app/assets/javascripts/admin/index_utils/directives/toggle_column.js.coffee +++ b/app/assets/javascripts/admin/index_utils/directives/toggle_column.js.coffee @@ -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 diff --git a/app/assets/javascripts/admin/index_utils/directives/toggle_view.js.coffee b/app/assets/javascripts/admin/index_utils/directives/toggle_view.js.coffee new file mode 100644 index 0000000000..5741c06fc7 --- /dev/null +++ b/app/assets/javascripts/admin/index_utils/directives/toggle_view.js.coffee @@ -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 diff --git a/app/assets/javascripts/admin/index_utils/services/views.js.coffee b/app/assets/javascripts/admin/index_utils/services/views.js.coffee new file mode 100644 index 0000000000..cf26a73ad8 --- /dev/null +++ b/app/assets/javascripts/admin/index_utils/services/views.js.coffee @@ -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) diff --git a/app/assets/javascripts/admin/utils/directives/alert_row.js.coffee b/app/assets/javascripts/admin/utils/directives/alert_row.js.coffee index 1c9afdb5b6..c7bd2840a1 100644 --- a/app/assets/javascripts/admin/utils/directives/alert_row.js.coffee +++ b/app/assets/javascripts/admin/utils/directives/alert_row.js.coffee @@ -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 diff --git a/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee b/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee index 8cd60fefb9..b754c9b722 100644 --- a/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee +++ b/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee @@ -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 -> diff --git a/app/assets/javascripts/admin/variant_overrides/filters/inventory_products_filter.js.coffee b/app/assets/javascripts/admin/variant_overrides/filters/inventory_products_filter.js.coffee index 4f5a3c5191..6025e43826 100644 --- a/app/assets/javascripts/admin/variant_overrides/filters/inventory_products_filter.js.coffee +++ b/app/assets/javascripts/admin/variant_overrides/filters/inventory_products_filter.js.coffee @@ -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) diff --git a/app/assets/javascripts/admin/variant_overrides/filters/inventory_variants_filter.js.coffee b/app/assets/javascripts/admin/variant_overrides/filters/inventory_variants_filter.js.coffee index 51238fa189..81ddc8215f 100644 --- a/app/assets/javascripts/admin/variant_overrides/filters/inventory_variants_filter.js.coffee +++ b/app/assets/javascripts/admin/variant_overrides/filters/inventory_variants_filter.js.coffee @@ -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) diff --git a/app/assets/javascripts/admin/variant_overrides/filters/new_inventory_products_filter.js.coffee b/app/assets/javascripts/admin/variant_overrides/filters/new_inventory_products_filter.js.coffee index ec1148c22e..fcc6f395d8 100644 --- a/app/assets/javascripts/admin/variant_overrides/filters/new_inventory_products_filter.js.coffee +++ b/app/assets/javascripts/admin/variant_overrides/filters/new_inventory_products_filter.js.coffee @@ -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) diff --git a/app/assets/javascripts/admin/variant_overrides/filters/new_inventory_variants_filter.js.coffee b/app/assets/javascripts/admin/variant_overrides/filters/new_inventory_variants_filter.js.coffee deleted file mode 100644 index d06724a704..0000000000 --- a/app/assets/javascripts/admin/variant_overrides/filters/new_inventory_variants_filter.js.coffee +++ /dev/null @@ -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) diff --git a/app/assets/javascripts/templates/admin/alert_row.html.haml b/app/assets/javascripts/templates/admin/alert_row.html.haml index ed1ce00849..c1dfe45c6f 100644 --- a/app/assets/javascripts/templates/admin/alert_row.html.haml +++ b/app/assets/javascripts/templates/admin/alert_row.html.haml @@ -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 diff --git a/app/assets/stylesheets/admin/components/alert_row.css.scss b/app/assets/stylesheets/admin/components/alert_row.css.scss index 6ddf9e731b..4c74afc56f 100644 --- a/app/assets/stylesheets/admin/components/alert_row.css.scss +++ b/app/assets/stylesheets/admin/components/alert_row.css.scss @@ -1,4 +1,5 @@ .alert-row{ + margin-bottom: 10px; font-weight: bold; background-color: #eff5fc; diff --git a/app/assets/stylesheets/admin/dropdown.css.scss b/app/assets/stylesheets/admin/dropdown.css.scss index 2dfa369c87..b848bc3c2c 100644 --- a/app/assets/stylesheets/admin/dropdown.css.scss +++ b/app/assets/stylesheets/admin/dropdown.css.scss @@ -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 { diff --git a/app/assets/stylesheets/admin/offets.css.scss b/app/assets/stylesheets/admin/offsets.css.scss similarity index 100% rename from app/assets/stylesheets/admin/offets.css.scss rename to app/assets/stylesheets/admin/offsets.css.scss diff --git a/app/assets/stylesheets/admin/variant_overrides.css.sass b/app/assets/stylesheets/admin/variant_overrides.css.sass index c0f51658b8..0488c1d56b 100644 --- a/app/assets/stylesheets/admin/variant_overrides.css.sass +++ b/app/assets/stylesheets/admin/variant_overrides.css.sass @@ -1,3 +1,6 @@ .variant-override-unit float: right font-style: italic + +button.hide:hover + background-color: #DA5354 diff --git a/app/views/admin/shared/_bulk_actions_dropdown.html.haml b/app/views/admin/shared/_bulk_actions_dropdown.html.haml index c1a7f3167d..15959a6d15 100644 --- a/app/views/admin/shared/_bulk_actions_dropdown.html.haml +++ b/app/views/admin/shared/_bulk_actions_dropdown.html.haml @@ -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 }} diff --git a/app/views/admin/shared/_columns_dropdown.html.haml b/app/views/admin/shared/_columns_dropdown.html.haml index b16d388c1d..ee8e552bb3 100644 --- a/app/views/admin/shared/_columns_dropdown.html.haml +++ b/app/views/admin/shared/_columns_dropdown.html.haml @@ -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 }} diff --git a/app/views/admin/shared/_views_dropdown.html.haml b/app/views/admin/shared/_views_dropdown.html.haml new file mode 100644 index 0000000000..addf43a1ce --- /dev/null +++ b/app/views/admin/shared/_views_dropdown.html.haml @@ -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 }} diff --git a/app/views/admin/variant_overrides/_controls.html.haml b/app/views/admin/variant_overrides/_controls.html.haml new file mode 100644 index 0000000000..bb70f2cf5a --- /dev/null +++ b/app/views/admin/variant_overrides/_controls.html.haml @@ -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' diff --git a/app/views/admin/variant_overrides/_hidden_products.html.haml b/app/views/admin/variant_overrides/_hidden_products.html.haml new file mode 100644 index 0000000000..1ef143afe0 --- /dev/null +++ b/app/views/admin/variant_overrides/_hidden_products.html.haml @@ -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) diff --git a/app/views/admin/variant_overrides/_loading_flash.html.haml b/app/views/admin/variant_overrides/_loading_flash.html.haml new file mode 100644 index 0000000000..24cc7c041d --- /dev/null +++ b/app/views/admin/variant_overrides/_loading_flash.html.haml @@ -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 diff --git a/app/views/admin/variant_overrides/_new_products.html.haml b/app/views/admin/variant_overrides/_new_products.html.haml new file mode 100644 index 0000000000..f4e519ce3f --- /dev/null +++ b/app/views/admin/variant_overrides/_new_products.html.haml @@ -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) diff --git a/app/views/admin/variant_overrides/_new_products_alert.html.haml b/app/views/admin/variant_overrides/_new_products_alert.html.haml new file mode 100644 index 0000000000..48b9d041c5 --- /dev/null +++ b/app/views/admin/variant_overrides/_new_products_alert.html.haml @@ -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')" } } diff --git a/app/views/admin/variant_overrides/_new_variants.html.haml b/app/views/admin/variant_overrides/_new_variants.html.haml deleted file mode 100644 index fe75a29cd8..0000000000 --- a/app/views/admin/variant_overrides/_new_variants.html.haml +++ /dev/null @@ -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' } } diff --git a/app/views/admin/variant_overrides/_no_results.html.haml b/app/views/admin/variant_overrides/_no_results.html.haml new file mode 100644 index 0000000000..be274faf04 --- /dev/null +++ b/app/views/admin/variant_overrides/_no_results.html.haml @@ -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. diff --git a/app/views/admin/variant_overrides/_products.html.haml b/app/views/admin/variant_overrides/_products.html.haml index 81fde749b3..9032f519ca 100644 --- a/app/views/admin/variant_overrides/_products.html.haml +++ b/app/views/admin/variant_overrides/_products.html.haml @@ -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' diff --git a/app/views/admin/variant_overrides/_products_variants.html.haml b/app/views/admin/variant_overrides/_products_variants.html.haml index 1af6dab3d8..7ae5f09db3 100644 --- a/app/views/admin/variant_overrides/_products_variants.html.haml +++ b/app/views/admin/variant_overrides/_products_variants.html.haml @@ -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) diff --git a/app/views/admin/variant_overrides/_show_more.html.haml b/app/views/admin/variant_overrides/_show_more.html.haml new file mode 100644 index 0000000000..ad943c853e --- /dev/null +++ b/app/views/admin/variant_overrides/_show_more.html.haml @@ -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' } } diff --git a/app/views/admin/variant_overrides/index.html.haml b/app/views/admin/variant_overrides/index.html.haml index 5c7a250cb9..d939465bac 100644 --- a/app/views/admin/variant_overrides/index.html.haml +++ b/app/views/admin/variant_overrides/index.html.haml @@ -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   - = 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' diff --git a/spec/features/admin/variant_overrides_spec.rb b/spec/features/admin/variant_overrides_spec.rb index fafcb348db..392b5b48b3 100644 --- a/spec/features/admin/variant_overrides_spec.rb +++ b/spec/features/admin/variant_overrides_spec.rb @@ -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 diff --git a/spec/javascripts/unit/admin/index_utils/services/views_spec.js.coffee b/spec/javascripts/unit/admin/index_utils/services/views_spec.js.coffee new file mode 100644 index 0000000000..7333882d5d --- /dev/null +++ b/spec/javascripts/unit/admin/index_utils/services/views_spec.js.coffee @@ -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 }