diff --git a/app/assets/javascripts/admin/tag_rules/controllers/tag_rules_controller.js.coffee b/app/assets/javascripts/admin/tag_rules/controllers/tag_rules_controller.js.coffee index 3522bb56bf..38e12182a0 100644 --- a/app/assets/javascripts/admin/tag_rules/controllers/tag_rules_controller.js.coffee +++ b/app/assets/javascripts/admin/tag_rules/controllers/tag_rules_controller.js.coffee @@ -1,10 +1,11 @@ angular.module("admin.tagRules").controller "TagRulesCtrl", ($scope, $http, enterprise) -> $scope.tagGroups = enterprise.tag_groups + $scope.defaultTagGroup = enterprise.default_tag_group $scope.visibilityOptions = [ { id: "visible", name: "VISIBLE" }, { id: "hidden", name: "NOT VISIBLE" } ] updateRuleCounts = -> - index = 0 + index = $scope.defaultTagGroup.rules.length for tagGroup in $scope.tagGroups tagGroup.startIndex = index index = index + tagGroup.rules.length @@ -18,6 +19,7 @@ angular.module("admin.tagRules").controller "TagRulesCtrl", ($scope, $http, ente $scope.addNewRuleTo = (tagGroup, ruleType) -> newRule = id: null + is_default: tagGroup == $scope.defaultTagGroup preferred_customer_tags: (tag.text for tag in tagGroup.tags).join(",") type: "TagRule::#{ruleType}" switch ruleType diff --git a/app/assets/javascripts/admin/tag_rules/directives/new_rule_dialog.js.coffee b/app/assets/javascripts/admin/tag_rules/directives/new_rule_dialog.js.coffee index 6662d5be35..df09bfd74b 100644 --- a/app/assets/javascripts/admin/tag_rules/directives/new_rule_dialog.js.coffee +++ b/app/assets/javascripts/admin/tag_rules/directives/new_rule_dialog.js.coffee @@ -1,6 +1,8 @@ angular.module("admin.tagRules").directive 'newTagRuleDialog', ($compile, $templateCache, $window) -> restrict: 'A' - scope: true + scope: + tagGroup: '=' + addNewRuleTo: '=' link: (scope, element, attr) -> # Compile modal template template = $compile($templateCache.get('admin/new_tag_rule_dialog.html'))(scope) diff --git a/app/assets/javascripts/templates/admin/tag_rules/tag_rule.html.haml b/app/assets/javascripts/templates/admin/tag_rules/tag_rule.html.haml index 086c3f59cd..0a752ae17b 100644 --- a/app/assets/javascripts/templates/admin/tag_rules/tag_rule.html.haml +++ b/app/assets/javascripts/templates/admin/tag_rules/tag_rule.html.haml @@ -16,6 +16,11 @@ name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][type]", ng: { value: "rule.type" } } + %input{ type: "hidden", + id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_is_default", + name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][is_default]", + ng: { value: "rule.is_default" } } + %input{ type: "hidden", id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_customer_tags", name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_customer_tags]", diff --git a/app/assets/stylesheets/admin/index_panels.css.scss b/app/assets/stylesheets/admin/index_panels.css.scss index d2861eb661..b622212446 100644 --- a/app/assets/stylesheets/admin/index_panels.css.scss +++ b/app/assets/stylesheets/admin/index_panels.css.scss @@ -65,58 +65,60 @@ tbody.panel-ctrl { } &.expanded{ - td { - border-bottom: 1px solid #6788a2; + >tr:not(.panel-row) { + >td { + border-bottom: 1px solid #6788a2; - &.selected { - background-color: #ffffff; - border-left: 1px solid #6788a2; - border-right: 1px solid #6788a2; - border-top: 1px solid #6788a2; - border-bottom: none; - - &:hover { + &.selected { background-color: #ffffff; - } + border-left: 1px solid #6788a2; + border-right: 1px solid #6788a2; + border-top: 1px solid #6788a2; + border-bottom: none; - * { - color: #1b3c56; - } + &:hover { + background-color: #ffffff; + } - i.icon-status::before { - opacity: 1.0; - } + * { + color: #1b3c56; + } - i.icon-chevron::before { - content: "\f077"; - } - } - } - } -} - -tr.panel-row { - &:hover { - td { - background-color: #ffffff; - } - } - - >td { - border-color: #6788a2; - padding: 0; - .panel { - .row{ - margin: 0px -4px; - - padding: 20px 0px; - - .column.alpha, .columns.alpha { - padding-left: 20px; - } - - .column.omega, .columns.omega { - padding-right: 20px; + i.icon-status::before { + opacity: 1.0; + } + + i.icon-chevron::before { + content: "\f077"; + } + } + } + } + } + + tr.panel-row { + &:hover { + td { + background-color: #ffffff; + } + } + + >td { + border-color: #6788a2; + padding: 0; + .panel { + .row{ + margin: 0px -4px; + + padding: 20px 0px; + + .column.alpha, .columns.alpha { + padding-left: 20px; + } + + .column.omega, .columns.omega { + padding-right: 20px; + } } } } diff --git a/app/assets/stylesheets/admin/tag_rules.css.scss b/app/assets/stylesheets/admin/tag_rules.css.scss index 142af801a7..0540dfa89f 100644 --- a/app/assets/stylesheets/admin/tag_rules.css.scss +++ b/app/assets/stylesheets/admin/tag_rules.css.scss @@ -5,7 +5,7 @@ font-weight: bold; } -.customer_tag { +.customer_tag, .default_rules { border: 1px solid #cee1f4; margin-bottom: 40px; diff --git a/app/models/tag_rule.rb b/app/models/tag_rule.rb index 23659bbf0a..1c578d2848 100644 --- a/app/models/tag_rule.rb +++ b/app/models/tag_rule.rb @@ -7,7 +7,7 @@ class TagRule < ActiveRecord::Base validates :enterprise, presence: true - attr_accessible :enterprise, :enterprise_id, :preferred_customer_tags + attr_accessible :enterprise, :enterprise_id, :is_default, :preferred_customer_tags scope :for, ->(enterprise) { where(enterprise_id: enterprise) } scope :of_type, ->(type) { where(type: "TagRule::#{type}") } diff --git a/app/serializers/api/admin/enterprise_serializer.rb b/app/serializers/api/admin/enterprise_serializer.rb index 8f70da1a0d..86b40c90ad 100644 --- a/app/serializers/api/admin/enterprise_serializer.rb +++ b/app/serializers/api/admin/enterprise_serializer.rb @@ -3,19 +3,23 @@ class Api::Admin::EnterpriseSerializer < ActiveModel::Serializer attributes :producer_profile_only, :email, :long_description, :permalink attributes :preferred_shopfront_message, :preferred_shopfront_closed_message, :preferred_shopfront_taxon_order, :preferred_shopfront_order_cycle_order attributes :preferred_product_selection_from_inventory_only - attributes :owner, :users, :tag_groups + attributes :owner, :users, :tag_groups, :default_tag_group has_one :owner, serializer: Api::Admin::UserSerializer has_many :users, serializer: Api::Admin::UserSerializer def tag_groups - tag_groups = [] - object.tag_rules.each do |tag_rule| + object.tag_rules.reject(&:is_default).each_with_object([]) do |tag_rule, tag_groups| tag_group = find_match(tag_groups, tag_rule.preferred_customer_tags.split(",").map{ |t| { text: t } }) tag_groups << tag_group if tag_group[:rules].empty? tag_group[:rules] << Api::Admin::TagRuleSerializer.new(tag_rule).serializable_hash end - tag_groups + end + + def default_tag_group + default_rules = object.tag_rules.select(&:is_default) + serialized_rules = ActiveModel::ArraySerializer.new(default_rules, each_serializer: Api::Admin::TagRuleSerializer) + { tags: [], rules: serialized_rules } end def find_match(tag_groups, tags) diff --git a/app/serializers/api/admin/tag_rule_serializer.rb b/app/serializers/api/admin/tag_rule_serializer.rb index 4f5be5cee7..ca24a02638 100644 --- a/app/serializers/api/admin/tag_rule_serializer.rb +++ b/app/serializers/api/admin/tag_rule_serializer.rb @@ -10,7 +10,7 @@ end module Api::Admin::TagRule class BaseSerializer < ActiveModel::Serializer - attributes :id, :enterprise_id, :type, :preferred_customer_tags + attributes :id, :enterprise_id, :type, :is_default, :preferred_customer_tags end class DiscountOrderSerializer < BaseSerializer diff --git a/app/views/admin/enterprises/form/_tag_rules.html.haml b/app/views/admin/enterprises/form/_tag_rules.html.haml index 76d971f963..5752b25b06 100644 --- a/app/views/admin/enterprises/form/_tag_rules.html.haml +++ b/app/views/admin/enterprises/form/_tag_rules.html.haml @@ -3,6 +3,8 @@ .eleven.columns.alpha.omega .no_tags{ ng: { show: "tagGroups.length == 0" } } No tags apply to this enterprise yet + = render 'admin/enterprises/form/tag_rules/default_rules' + -# = render 'customer_tags' .customer_tag{ ng: { repeat: "tagGroup in tagGroups" } } .header %table @@ -22,6 +24,6 @@ No rules apply to this tag yet .tag_rule{ ng: { repeat: "rule in tagGroup.rules" } } .add_rule.text-center - %input.button.icon-plus{ type: 'button', value: "+ Add A New Rule", "new-tag-rule-dialog" => true } + %input.button.icon-plus{ type: 'button', value: "+ Add A New Rule", "add-new-rule-to" => "addNewRuleTo", "tag-group" => "tagGroup", "new-tag-rule-dialog" => true } .add_tag %input.button.red.icon-plus{ type: 'button', value: "+ Add A New Tag", ng: { click: 'addNewTag()' } } diff --git a/app/views/admin/enterprises/form/tag_rules/_default_rules.html.haml b/app/views/admin/enterprises/form/tag_rules/_default_rules.html.haml new file mode 100644 index 0000000000..c8fdcc2a8a --- /dev/null +++ b/app/views/admin/enterprises/form/tag_rules/_default_rules.html.haml @@ -0,0 +1,14 @@ +.default_rules + .header + %table + %colgroup + %col{width: '100%'} + %tr + %td + %h5 + By Default: + .no_rules{ ng: { show: "defaultTagGroup.rules.length == 0" } } + No default rules apply yet + .tag_rule{ ng: { repeat: "rule in defaultTagGroup.rules" } } + .add_rule.text-center + %input.button.icon-plus{ type: 'button', value: "+ Add A New Default Rule", "add-new-rule-to" => "addNewRuleTo", "tag-group" => "defaultTagGroup", "new-tag-rule-dialog" => true } diff --git a/db/migrate/20160520065217_add_is_default_to_tag_rule.rb b/db/migrate/20160520065217_add_is_default_to_tag_rule.rb new file mode 100644 index 0000000000..209520b693 --- /dev/null +++ b/db/migrate/20160520065217_add_is_default_to_tag_rule.rb @@ -0,0 +1,5 @@ +class AddIsDefaultToTagRule < ActiveRecord::Migration + def change + add_column :tag_rules, :is_default, :boolean, default: false, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 60b72adeea..f68f6c6a0a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20160401043927) do +ActiveRecord::Schema.define(:version => 20160520065217) do create_table "account_invoices", :force => true do |t| t.integer "user_id", :null => false @@ -1159,10 +1159,11 @@ ActiveRecord::Schema.define(:version => 20160401043927) do end create_table "tag_rules", :force => true do |t| - t.integer "enterprise_id", :null => false - t.string "type", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.integer "enterprise_id", :null => false + t.string "type", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.boolean "is_default", :default => false, :null => false end create_table "taggings", :force => true do |t| diff --git a/spec/features/admin/tag_rules_spec.rb b/spec/features/admin/tag_rules_spec.rb index 1e31039523..45b28f603c 100644 --- a/spec/features/admin/tag_rules_spec.rb +++ b/spec/features/admin/tag_rules_spec.rb @@ -26,7 +26,7 @@ feature 'Tag Rules', js: true do click_button '+ Add A New Rule' select2_select 'Show or Hide shipping methods at checkout', from: 'rule_type_selector' click_button "Add Rule" - within("#tr_0") do + within(".customer_tag #tr_0") do find(:css, "tags-input .tags input").set "volunteers-only\n" select2_select "NOT VISIBLE", from: "enterprise_tag_rules_attributes_0_preferred_matched_shipping_methods_visibility" end @@ -35,7 +35,7 @@ feature 'Tag Rules', js: true do click_button '+ Add A New Rule' select2_select 'Show or Hide variants in my shop', from: 'rule_type_selector' click_button "Add Rule" - within("#tr_1") do + within(".customer_tag #tr_1") do find(:css, "tags-input .tags input").set "volunteers-only1\n" select2_select "VISIBLE", from: "enterprise_tag_rules_attributes_1_preferred_matched_variants_visibility" end @@ -44,20 +44,29 @@ feature 'Tag Rules', js: true do click_button '+ Add A New Rule' select2_select 'Show or Hide payment methods at checkout', from: 'rule_type_selector' click_button "Add Rule" - within("#tr_2") do + within(".customer_tag #tr_2") do find(:css, "tags-input .tags input").set "volunteers-only2\n" select2_select "VISIBLE", from: "enterprise_tag_rules_attributes_2_preferred_matched_payment_methods_visibility" end - # New FilterPaymentMethods Rule + # New FilterOrderCycles Rule click_button '+ Add A New Rule' select2_select 'Show or Hide order cycles in my shopfront', from: 'rule_type_selector' click_button "Add Rule" - within("#tr_3") do + within(".customer_tag #tr_3") do find(:css, "tags-input .tags input").set "volunteers-only3\n" select2_select "NOT VISIBLE", from: "enterprise_tag_rules_attributes_3_preferred_matched_order_cycles_visibility" end + # New DEFAULT FilterOrderCycles Rule + click_button '+ Add A New Default Rule' + select2_select 'Show or Hide order cycles in my shopfront', from: 'rule_type_selector' + click_button "Add Rule" + within(".default_rules #tr_0") do + find(:css, "tags-input .tags input").set "wholesale\n" + select2_select "NOT VISIBLE", from: "enterprise_tag_rules_attributes_0_preferred_matched_order_cycles_visibility" + end + # New DiscountOrder Rule # click_button '+ Add A New Rule' # select2_select 'Apply a discount to orders', from: 'rule_type_selector' @@ -85,18 +94,24 @@ feature 'Tag Rules', js: true do expect(tag_rule.preferred_payment_method_tags).to eq "volunteers-only2" expect(tag_rule.preferred_matched_payment_methods_visibility).to eq "visible" - tag_rule = TagRule::FilterOrderCycles.last + tag_rule = TagRule::FilterOrderCycles.all.reject(&:is_default).last expect(tag_rule.preferred_customer_tags).to eq "volunteer" expect(tag_rule.preferred_exchange_tags).to eq "volunteers-only3" expect(tag_rule.preferred_matched_order_cycles_visibility).to eq "hidden" + + tag_rule = TagRule::FilterOrderCycles.all.select(&:is_default).last + expect(tag_rule.preferred_customer_tags).to eq "" + expect(tag_rule.preferred_exchange_tags).to eq "wholesale" + expect(tag_rule.preferred_matched_order_cycles_visibility).to eq "hidden" end end context "updating" do - let!(:fsm_tag_rule) { create(:filter_shipping_methods_tag_rule, enterprise: enterprise, preferred_matched_shipping_methods_visibility: "hidden", preferred_customer_tags: "local", preferred_shipping_method_tags: "local" ) } + let!(:default_fsm_tag_rule) { create(:filter_shipping_methods_tag_rule, enterprise: enterprise, preferred_matched_shipping_methods_visibility: "visible", is_default: true, preferred_shipping_method_tags: "local" ) } let!(:fp_tag_rule) { create(:filter_products_tag_rule, enterprise: enterprise, preferred_matched_variants_visibility: "visible", preferred_customer_tags: "member", preferred_variant_tags: "member" ) } let!(:fpm_tag_rule) { create(:filter_payment_methods_tag_rule, enterprise: enterprise, preferred_matched_payment_methods_visibility: "hidden", preferred_customer_tags: "trusted", preferred_payment_method_tags: "trusted" ) } let!(:foc_tag_rule) { create(:filter_order_cycles_tag_rule, enterprise: enterprise, preferred_matched_order_cycles_visibility: "visible", preferred_customer_tags: "wholesale", preferred_exchange_tags: "wholesale" ) } + let!(:fsm_tag_rule) { create(:filter_shipping_methods_tag_rule, enterprise: enterprise, preferred_matched_shipping_methods_visibility: "hidden", preferred_customer_tags: "local", preferred_shipping_method_tags: "local" ) } # let!(:do_tag_rule) { create(:tag_rule, enterprise: enterprise, preferred_customer_tags: "member" ) } before do @@ -115,16 +130,16 @@ feature 'Tag Rules', js: true do expect(page).to have_selector '.customer_tag .header tags-input .tag-list ti-tag-item', text: "trusted", count: 1 all(:css, ".customer_tag .header tags-input .tags input").each { |node| node.set "volunteer\n" } - # FilterShippingMethods rule - within "#tr_0" do + # DEFAULT FilterShippingMethods rule + within ".default_rules #tr_0" do expect(first('tags-input .tag-list ti-tag-item')).to have_content "local" find(:css, "tags-input .tags input").set "volunteers-only\n" - expect(page).to have_select2 "enterprise_tag_rules_attributes_0_preferred_matched_shipping_methods_visibility", selected: 'NOT VISIBLE' - select2_select 'VISIBLE', from: "enterprise_tag_rules_attributes_0_preferred_matched_shipping_methods_visibility" + expect(page).to have_select2 "enterprise_tag_rules_attributes_0_preferred_matched_shipping_methods_visibility", selected: 'VISIBLE' + select2_select 'NOT VISIBLE', from: "enterprise_tag_rules_attributes_0_preferred_matched_shipping_methods_visibility" end # FilterProducts rule - within "#tr_1" do + within ".customer_tag #tr_1" do expect(first('tags-input .tag-list ti-tag-item')).to have_content "member" find(:css, "tags-input .tags input").set "volunteers-only1\n" expect(page).to have_select2 "enterprise_tag_rules_attributes_1_preferred_matched_variants_visibility", selected: 'VISIBLE' @@ -132,7 +147,7 @@ feature 'Tag Rules', js: true do end # FilterPaymentMethods rule - within "#tr_2" do + within ".customer_tag #tr_2" do expect(first('tags-input .tag-list ti-tag-item')).to have_content "trusted" find(:css, "tags-input .tags input").set "volunteers-only2\n" expect(page).to have_select2 "enterprise_tag_rules_attributes_2_preferred_matched_payment_methods_visibility", selected: 'NOT VISIBLE' @@ -140,13 +155,21 @@ feature 'Tag Rules', js: true do end # FilterOrderCycles rule - within "#tr_3" do + within ".customer_tag #tr_3" do expect(first('tags-input .tag-list ti-tag-item')).to have_content "wholesale" find(:css, "tags-input .tags input").set "volunteers-only3\n" expect(page).to have_select2 "enterprise_tag_rules_attributes_3_preferred_matched_order_cycles_visibility", selected: 'VISIBLE' select2_select 'NOT VISIBLE', from: "enterprise_tag_rules_attributes_3_preferred_matched_order_cycles_visibility" end + # FilterShippingMethods rule + within ".customer_tag #tr_4" do + expect(first('tags-input .tag-list ti-tag-item')).to have_content "local" + find(:css, "tags-input .tags input").set "volunteers-only4\n" + expect(page).to have_select2 "enterprise_tag_rules_attributes_4_preferred_matched_shipping_methods_visibility", selected: 'NOT VISIBLE' + select2_select 'VISIBLE', from: "enterprise_tag_rules_attributes_4_preferred_matched_shipping_methods_visibility" + end + # # DiscountOrder rule # within "#tr_2" do # expect(page).to have_field "enterprise_tag_rules_attributes_2_calculator_attributes_preferred_flat_percent", with: '0' @@ -155,9 +178,14 @@ feature 'Tag Rules', js: true do click_button 'Update' + # FilterShippingMethods rule + expect(default_fsm_tag_rule.preferred_customer_tags).to eq "" + expect(default_fsm_tag_rule.preferred_shipping_method_tags).to eq "local,volunteers-only" + expect(default_fsm_tag_rule.preferred_matched_shipping_methods_visibility).to eq "hidden" + # FilterShippingMethods rule expect(fsm_tag_rule.preferred_customer_tags).to eq "local,volunteer" - expect(fsm_tag_rule.preferred_shipping_method_tags).to eq "local,volunteers-only" + expect(fsm_tag_rule.preferred_shipping_method_tags).to eq "local,volunteers-only4" expect(fsm_tag_rule.preferred_matched_shipping_methods_visibility).to eq "visible" # FilterProducts rule diff --git a/spec/javascripts/unit/admin/tag_rules/controllers/tag_rules_controller_spec.js.coffee b/spec/javascripts/unit/admin/tag_rules/controllers/tag_rules_controller_spec.js.coffee index 4a0c304ee8..2526016d3d 100644 --- a/spec/javascripts/unit/admin/tag_rules/controllers/tag_rules_controller_spec.js.coffee +++ b/spec/javascripts/unit/admin/tag_rules/controllers/tag_rules_controller_spec.js.coffee @@ -7,6 +7,7 @@ describe "TagRulesCtrl", -> module('admin.tagRules') enterprise = id: 45 + default_tag_group: { tags: "", rules: [{ id: 7, preferred_customer_tags: "trusted" }] } tag_groups: [ { tags: "member", rules: [{ id: 1, preferred_customer_tags: "member" }, { id: 2, preferred_customer_tags: "member" }] }, { tags: "volunteer", rules: [{ id: 3, preferred_customer_tags: "local" }] } @@ -18,8 +19,8 @@ describe "TagRulesCtrl", -> describe "tagGroup start indices", -> it "updates on initialization", -> - expect(scope.tagGroups[0].startIndex).toEqual 0 - expect(scope.tagGroups[1].startIndex).toEqual 2 + expect(scope.tagGroups[0].startIndex).toEqual 1 + expect(scope.tagGroups[1].startIndex).toEqual 3 describe "adding a new tag group", -> beforeEach -> @@ -30,8 +31,8 @@ describe "TagRulesCtrl", -> expect(scope.tagGroups[0].rules[2].type).toEqual "TagRule::DiscountOrder" it "updates tagGroup start indices", -> - expect(scope.tagGroups[0].startIndex).toEqual 0 - expect(scope.tagGroups[1].startIndex).toEqual 3 + expect(scope.tagGroups[0].startIndex).toEqual 1 + expect(scope.tagGroups[1].startIndex).toEqual 4 describe "deleting a tag group", -> describe "where the rule is not in the rule list for the tagGroup", -> @@ -58,8 +59,8 @@ describe "TagRulesCtrl", -> expect(scope.tagGroups[0].rules.indexOf(rule)).toEqual -1 it "updates tagGroup start indices", -> - expect(scope.tagGroups[0].startIndex).toEqual 0 - expect(scope.tagGroups[1].startIndex).toEqual 1 + expect(scope.tagGroups[0].startIndex).toEqual 1 + expect(scope.tagGroups[1].startIndex).toEqual 2 describe "without an id", -> rule = null @@ -75,5 +76,5 @@ describe "TagRulesCtrl", -> expect(scope.tagGroups[0].rules.indexOf(rule)).toEqual -1 it "updates tagGroup start indices", -> - expect(scope.tagGroups[0].startIndex).toEqual 0 - expect(scope.tagGroups[1].startIndex).toEqual 1 + expect(scope.tagGroups[0].startIndex).toEqual 1 + expect(scope.tagGroups[1].startIndex).toEqual 2