mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Updating Tag Rules UI to allow management of new FilterShippingMethods rule type
This commit is contained in:
@@ -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 = ->
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
angular.module("admin.tagRules").directive "filterShippingMethods", ->
|
||||
restrict: "E"
|
||||
replace: true
|
||||
templateUrl: "admin/tag_rules/filter_shipping_methods.html"
|
||||
@@ -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)' } }
|
||||
@@ -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 %
|
||||
|
||||
@@ -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" }
|
||||
88
app/assets/stylesheets/admin/components/jquery_dialog.scss
Normal file
88
app/assets/stylesheets/admin/components/jquery_dialog.scss
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()' } }
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user