Updating Tag Rules UI to allow management of new FilterShippingMethods rule type

This commit is contained in:
Rob Harrington
2016-03-18 12:22:54 +11:00
parent 82bc26fe90
commit d278b72289
15 changed files with 273 additions and 27 deletions

View File

@@ -1,6 +1,8 @@
angular.module("admin.tagRules").controller "TagRulesCtrl", ($scope, $http, enterprise) ->
$scope.tagGroups = enterprise.tag_groups
$scope.visibilityOptions = [ { id: "visible", name: "VISIBLE" }, { id: "hidden", name: "NOT VISIBLE" } ]
updateRuleCounts = ->
index = 0
for tagGroup in $scope.tagGroups
@@ -13,13 +15,18 @@ angular.module("admin.tagRules").controller "TagRulesCtrl", ($scope, $http, ente
for tagRule in tagGroup.rules
tagRule.preferred_customer_tags = (tag.text for tag in tagGroup.tags).join(",")
$scope.addNewRuleTo = (tagGroup) ->
tagGroup.rules.push
id: null
preferred_customer_tags: (tag.text for tag in tagGroup.tags).join(",")
type: "TagRule::DiscountOrder"
calculator:
preferred_flat_percent: 0
$scope.addNewRuleTo = (tagGroup, ruleType) ->
newRule =
id: null
preferred_customer_tags: (tag.text for tag in tagGroup.tags).join(",")
type: "TagRule::#{ruleType}"
switch ruleType
when "DiscountOrder"
newRule.calculator = { preferred_flat_percent: 0 }
when "FilterShippingMethods"
newRule.peferred_shipping_method_tags = []
newRule.preferred_matched_shipping_methods_visibility = "visible"
tagGroup.rules.push(newRule)
updateRuleCounts()
$scope.addNewTag = ->

View File

@@ -0,0 +1,31 @@
angular.module("admin.tagRules").directive 'newTagRuleDialog', ($compile, $templateCache) ->
restrict: 'A'
scope: true
link: (scope, element, attr) ->
# Compile modal template
template = $compile($templateCache.get('admin/new_tag_rule_dialog.html'))(scope)
scope.ruleTypes = [
{ id: "DiscountOrder", name: 'Apply a discount to orders' }
{ id: "FilterShippingMethods", name: 'Show/Hide shipping methods' }
]
scope.ruleType = "DiscountOrder"
# Set Dialog options
template.dialog
autoOpen: false
resizable: false
width: 'auto'
scaleW: 0.4
modal: true
clickOut: true
# Link opening of dialog to click event on element
element.bind 'click', (e) ->
template.dialog('open')
scope.addRule = (tagGroup, ruleType) ->
scope.addNewRuleTo(tagGroup, ruleType)
template.dialog('close')
return

View File

@@ -0,0 +1,4 @@
angular.module("admin.tagRules").directive "filterShippingMethods", ->
restrict: "E"
replace: true
templateUrl: "admin/tag_rules/filter_shipping_methods.html"

View File

@@ -0,0 +1,10 @@
#new-tag-rule-dialog
.text-normal.margin-bottom-30.text-center
Select a rule type:
.text-center.margin-bottom-30
-# %select.fullwidth{ 'select2-min-search' => 5, 'ng-model' => 'newRuleType', 'ng-options' => 'ruleType.id as ruleType.name for ruleType in availableRuleTypes' }
%input.ofn-select2.fullwidth{ :id => 'rule_type_selector', ng: { model: "ruleType" }, data: "ruleTypes", 'min-search' => "5" }
.text-center
%input.button.red.icon-plus{ type: 'button', value: "Add Rule", ng: { click: 'addRule(tagGroup, ruleType)' } }

View File

@@ -28,12 +28,10 @@
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][calculator_attributes][preferred_flat_percent]",
ng: { value: "rule.calculator.preferred_flat_percent" } }
%span.text-normal {{ $index + 1 }}. Apply a discount of
%span.input-symbol.after
%span.text-normal %
%input.text-big{ type: "number",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_calculator_attributes_preferred_flat_percent",
min: -100,
max: 100,
ng: { model: "rule.calculator.preferred_flat_percent" }, 'invert-number' => true }
%span.text-normal to order subtotals
%span.text-normal {{ $index + 1 }}. Orders are discounted by
%input{ type: "number",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_calculator_attributes_preferred_flat_percent",
min: -100,
max: 100,
ng: { model: "rule.calculator.preferred_flat_percent" }, 'invert-number' => true }
%span.text-normal %

View File

@@ -0,0 +1,27 @@
%div
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_id",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][id]",
ng: { value: "rule.id" } }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_type",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][type]",
value: "TagRule::FilterShippingMethods" }
%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]",
ng: { value: "rule.preferred_customer_tags" } }
%input{ type: "hidden",
id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_shipping_method_tags",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_shipping_method_tags]",
ng: { value: "rule.preferred_customer_tags" } }
%span.text-normal {{ $index + 1 }}. Shipping methods with matching tags are
%input.light.ofn-select2{ id: "enterprise_tag_rules_attributes_{{tagGroup.startIndex + $index}}_preferred_matched_shipping_methods_visibility",
name: "enterprise[tag_rules_attributes][{{tagGroup.startIndex + $index}}][preferred_matched_shipping_methods_visibility]",
ng: { model: "rule.preferred_matched_shipping_methods_visibility"},
data: 'visibilityOptions', "min-search" => 5 }
-# %tags-with-translation{ object: "rule", "tags-attr" => "shipping_method_tags", "tag-list-attr" => "preferred_shipping_method_tags" }

View File

@@ -0,0 +1,88 @@
/**
Main colors:
dark: #545454
light: #ccc
*/
.ui-dialog {
border: 2px solid #4a4a4a;
border-radius:3px;
padding:0px;
-moz-box-shadow: 3px 3px 4px #797979;
-webkit-box-shadow: 3px 3px 4px #797979;
box-shadow: 3px 3px 4px #797979;
/* For IE 8 */
-ms-filter: "progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#545454')";
/* For IE 5.5 - 7 */
filter: progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color='#545454');
}
.ui-dialog .ui-dialog-titlebar{
border-radius: 3px;
}
.ui-dialog .ui-state-hover {
&.ui-dialog-titlebar-close{
}
}
/*.ui-dialog .ui-icon-closethick{background:url(/static/assets/dialogCloseButton.png);}*/
.ui-dialog .ui-widget-header{
background-image: none;
background-color: #ffffff;
border:0px;
border-radius: 3px;
padding: 0px 5px 0px 5px;
}
.ui-dialog .ui-widget-content{
border: none;
border-radius: 3px;
padding: 0px 50px 30px 50px;
}
.ui-dialog .ui-corner-all{
border-radius:0px;
}
.ui-dialog {
.ui-state-hover, .ui-state-focus{
border: none;
background: none;
color: #545454;
}
}
.ui-state-hover, .ui-widget-header .ui-state-hover, .ui-widget-content .ui-state-hover {
background-color: #ffffff;
background: none;
}
.ui-dialog-titlebar-close {
float: right;
&:before {
color: #000000;
font-size: 2em;
font-weight: 400;
content: '\00d7';
display: inline;
}
&:hover {
&:before {
color: #da5354;
}
}
.ui-icon {
&.ui-icon-closethick {
display: none;
}
}
}
.ui-widget-overlay {
background: #e9e9e9;
opacity: 0.6;
}

View File

@@ -1,5 +1,8 @@
.select2-container {
.select2-choice {
.select2-search-choice-close {
display: none;
}
.select2-arrow {
width: 22px;
border: none;
@@ -7,4 +10,36 @@
background-color: transparent;
}
}
&.light {
.select2-choice{
background-color: #ffffff;
font-weight: normal;
border: 1px solid #5498da !important;
color: #5498da !important;
.select2-arrow {
&:before {
color: #5498da;
font-size: 1rem;
font-weight: 400;
content: '\25be';
display: inline;
}
}
}
&:hover, &.select2-container-active {
.select2-choice{
color: #ffffff !important;
background-color: #5498da !important;
.select2-arrow {
&:before {
color: #ffffff;
}
}
}
}
}
}

View File

@@ -44,7 +44,7 @@
td {
border: none;
padding: 4px 10px;
padding: 4px 10px 10px 10px;
margin: 0px;
input {
@@ -59,3 +59,10 @@
margin-bottom: 10px;
}
}
#new-tag-rule-dialog{
.select2-chosen, .select2-result-label{
font-size: 1rem;
font-weight: lighter;
}
}

View File

@@ -16,4 +16,12 @@ module Api::Admin::TagRule
class DiscountOrderSerializer < BaseSerializer
has_one :calculator, serializer: Api::Admin::Calculator::FlatPercentItemTotalSerializer
end
class FilterShippingMethodsSerializer < BaseSerializer
attributes :preferred_matched_shipping_methods_visibility, :shipping_method_tags
def shipping_method_tags
object.preferred_shipping_method_tags.split(",")
end
end
end

View File

@@ -24,9 +24,10 @@
%tr.tag_rule{ id: "tr_{{rule.id}}", ng: { repeat: "rule in tagGroup.rules" } }
%td
%discount-order{ bo: { if: "rule.type == 'TagRule::DiscountOrder'" } }
%filter-shipping-methods{ bo: { if: "rule.type == 'TagRule::FilterShippingMethods'" } }
%td.actions
%a{ ng: { click: "deleteTagRule(tagGroup, rule)" }, :class => "delete-tag-rule icon-trash no-text" }
.add_rule.text-center
%input.button.icon-plus{ type: 'button', value: "+ Add A New Rule", ng: { click: 'addNewRuleTo(tagGroup)' } }
%input.button.icon-plus{ type: 'button', value: "+ Add A New Rule", "new-tag-rule-dialog" => true }
.add_tage
%input.button.red.icon-plus{ type: 'button', value: "+ Add A New Tag", ng: { click: 'addNewTag()' } }

View File

@@ -286,7 +286,7 @@ FactoryGirl.define do
month { 1 + rand(12) }
end
factory :filter_shipping_method_tag_rule, class: TagRule::FilterShippingMethods do
factory :filter_shipping_methods_tag_rule, class: TagRule::FilterShippingMethods do
enterprise { FactoryGirl.create :distributor_enterprise }
end

View File

@@ -12,47 +12,76 @@ feature 'Tag Rules', js: true do
visit main_app.edit_admin_enterprise_path(enterprise)
end
it "creates a new rule" do
it "allows creation of rules of each type" do
click_link "Tag Rules"
# Creating a new tag
expect(page).to_not have_selector '.customer_tag'
expect(page).to have_content 'No tags apply to this enterprise yet'
click_button '+ Add A New Tag'
find(:css, "tags-input .tags input").set "volunteer\n"
# New DiscountOrder Rule
expect(page).to have_content 'No rules apply to this tag yet'
click_button '+ Add A New Rule'
select2_select 'Apply a discount to orders', from: 'rule_type_selector'
click_button "Add Rule"
fill_in "enterprise_tag_rules_attributes_0_calculator_attributes_preferred_flat_percent", with: 22
# New FilterShippingMethods Rule
click_button '+ Add A New Rule'
select2_select 'Show/Hide shipping methods', from: 'rule_type_selector'
click_button "Add Rule"
select2_select "NOT VISIBLE", from: "enterprise_tag_rules_attributes_1_preferred_matched_shipping_methods_visibility"
click_button 'Update'
tag_rule = TagRule::DiscountOrder.last
expect(tag_rule.preferred_customer_tags).to eq "volunteer"
expect(tag_rule.calculator.preferred_flat_percent).to eq -22
tag_rule = TagRule::FilterShippingMethods.last
expect(tag_rule.preferred_customer_tags).to eq "volunteer"
expect(tag_rule.preferred_shipping_method_tags).to eq "volunteer"
expect(tag_rule.preferred_matched_shipping_methods_visibility).to eq "hidden"
end
end
context "updating" do
let!(:tag_rule) { create(:tag_rule, enterprise: enterprise, preferred_customer_tags: "member" ) }
let!(:do_tag_rule) { create(:tag_rule, enterprise: enterprise, preferred_customer_tags: "member" ) }
let!(:fsm_tag_rule) { create(:filter_shipping_methods_tag_rule, enterprise: enterprise, preferred_matched_shipping_methods_visibility: "hidden", preferred_customer_tags: "member" ) }
before do
login_to_admin_section
visit main_app.edit_admin_enterprise_path(enterprise)
end
it "saves changes to the rule" do
it "saves changes to rules of each type" do
click_link "Tag Rules"
# Tag group exists
expect(first('.customer_tag .header')).to have_content "For customers tagged:"
expect(first('tags-input .tag-list ti-tag-item')).to have_content "member"
find(:css, "tags-input .tags input").set "volunteer\n"
# DiscountOrder rule
expect(page).to have_field "enterprise_tag_rules_attributes_0_calculator_attributes_preferred_flat_percent", with: '0'
fill_in "enterprise_tag_rules_attributes_0_calculator_attributes_preferred_flat_percent", with: 45
# FilterShippingMethods rule
expect(page).to have_select2 "enterprise_tag_rules_attributes_1_preferred_matched_shipping_methods_visibility", selected: 'NOT VISIBLE'
select2_select 'VISIBLE', from: "enterprise_tag_rules_attributes_1_preferred_matched_shipping_methods_visibility"
click_button 'Update'
expect(tag_rule.preferred_customer_tags).to eq "member,volunteer"
expect(tag_rule.calculator.preferred_flat_percent).to eq -45
# DiscountOrder rule
expect(do_tag_rule.preferred_customer_tags).to eq "member,volunteer"
expect(do_tag_rule.calculator.preferred_flat_percent).to eq -45
# FilterShippingMethods rule
expect(fsm_tag_rule.preferred_customer_tags).to eq "member,volunteer"
expect(fsm_tag_rule.preferred_shipping_method_tags).to eq "member,volunteer"
expect(fsm_tag_rule.preferred_matched_shipping_methods_visibility).to eq "visible"
end
end

View File

@@ -23,10 +23,11 @@ describe "TagRulesCtrl", ->
describe "adding a new tag group", ->
beforeEach ->
scope.addNewRuleTo(scope.tagGroups[0])
scope.addNewRuleTo(scope.tagGroups[0], "DiscountOrder")
it "adds a new rule to the rules array for the tagGroup", ->
it "adds a new rule of the specified type to the rules array for the tagGroup", ->
expect(scope.tagGroups[0].rules.length).toEqual 3
expect(scope.tagGroups[0].rules[2].type).toEqual "TagRule::DiscountOrder"
it "updates tagGroup start indices", ->
expect(scope.tagGroups[0].startIndex).toEqual 0

View File

@@ -1,7 +1,7 @@
require 'spec_helper'
describe TagRule::DiscountOrder, type: :model do
let!(:tag_rule) { create(:filter_shipping_method_tag_rule) }
let!(:tag_rule) { create(:filter_shipping_methods_tag_rule) }
describe "determining whether tags match for a given shipping method" do
context "when the shipping method is nil" do