From bf72864c2bf095782509370d625b89f1e8788335 Mon Sep 17 00:00:00 2001 From: Rob Harrington Date: Wed, 16 Mar 2016 11:29:35 +1100 Subject: [PATCH] Tag Rules can be deleted --- .../tag_rules_controller.js.coffee | 17 +++++- .../stylesheets/admin/tag_rules.css.scss | 32 +++++++++-- app/controllers/admin/tag_rules_controller.rb | 10 ++++ app/models/spree/ability_decorator.rb | 4 ++ .../enterprises/form/_tag_rules.html.haml | 31 +++++++---- config/routes.rb | 2 + .../admin/tag_rules_controller_spec.rb | 36 +++++++++++++ spec/features/admin/enterprises_spec.rb | 22 ++++++++ .../tag_rules_controller_spec.js.coffee | 54 ++++++++++++++++++- 9 files changed, 193 insertions(+), 15 deletions(-) create mode 100644 app/controllers/admin/tag_rules_controller.rb create mode 100644 spec/controllers/admin/tag_rules_controller_spec.rb diff --git a/app/assets/javascripts/admin/enterprises/controllers/tag_rules_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/tag_rules_controller.js.coffee index e8c95558df..096cce250d 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/tag_rules_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/tag_rules_controller.js.coffee @@ -1,4 +1,4 @@ -angular.module("admin.enterprises").controller "TagRulesCtrl", ($scope) -> +angular.module("admin.enterprises").controller "TagRulesCtrl", ($scope, $http) -> $scope.tagGroups = $scope.Enterprise.tag_groups updateRuleCounts = -> @@ -24,3 +24,18 @@ angular.module("admin.enterprises").controller "TagRulesCtrl", ($scope) -> $scope.addNewTag = -> $scope.tagGroups.push { tags: [], rules: [] } + + $scope.deleteTagRule = (tagGroup, tagRule) -> + index = tagGroup.rules.indexOf(tagRule) + return unless index >= 0 + if tagRule.id is null + tagGroup.rules.splice(index, 1) + updateRuleCounts() + else + if confirm("Are you sure?") + $http + method: "DELETE" + url: "/admin/enterprises/#{$scope.Enterprise.id}/tag_rules/#{tagRule.id}.json" + .success -> + tagGroup.rules.splice(index, 1) + updateRuleCounts() diff --git a/app/assets/stylesheets/admin/tag_rules.css.scss b/app/assets/stylesheets/admin/tag_rules.css.scss index cbaed55587..985ed7d727 100644 --- a/app/assets/stylesheets/admin/tag_rules.css.scss +++ b/app/assets/stylesheets/admin/tag_rules.css.scss @@ -13,6 +13,16 @@ padding: 8px 10px; background-color: #eff5fc; border-bottom: 1px solid #cee1f4; + + table { + padding: 0px; + margin: 0px 0px 0px 0px; + tr { + td { + border: none; + } + } + } } .no_rules { @@ -23,9 +33,25 @@ font-weight: bold; } - .tag_rule { - padding: 8px 10px; - margin-bottom: 10px; + table { + padding: 0px; + margin: 0px 0px 10px 0px; + + tr.tag_rule { + border: none; + padding: 0px; + margin: 0px; + + td { + border: none; + padding: 4px 10px; + margin: 0px; + + input { + width: auto; + } + } + } } .add_rule { diff --git a/app/controllers/admin/tag_rules_controller.rb b/app/controllers/admin/tag_rules_controller.rb new file mode 100644 index 0000000000..7d60cb4888 --- /dev/null +++ b/app/controllers/admin/tag_rules_controller.rb @@ -0,0 +1,10 @@ +module Admin + class TagRulesController < ResourceController + + respond_to :json + + respond_override destroy: { json: { + success: lambda { render nothing: true, :status => 204 } + } } + end +end diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index 8c93fe4b71..c234cf1358 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -72,6 +72,10 @@ class AbilityDecorator can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], ProducerProperty + can [:admin, :destroy], TagRule do |tag_rule| + user.enterprises.include? tag_rule.enterprise + end + can [:admin, :index, :create], Enterprise can [:read, :edit, :update, :bulk_update, :resend_confirmation], Enterprise do |enterprise| OpenFoodNetwork::Permissions.new(user).editable_enterprises.include? enterprise diff --git a/app/views/admin/enterprises/form/_tag_rules.html.haml b/app/views/admin/enterprises/form/_tag_rules.html.haml index ecb8b54f2e..9a3c0f7a40 100644 --- a/app/views/admin/enterprises/form/_tag_rules.html.haml +++ b/app/views/admin/enterprises/form/_tag_rules.html.haml @@ -5,17 +5,28 @@ No tags apply to this enterprise yet .customer_tag{ ng: { repeat: "tagGroup in tagGroups" }, bindonce: true } .header - %h3 - For customers tagged: - %tags-input{ ng: { model: 'tagGroup.tags'}, - min: { tags: "1" }, - on: { tag: { added: "updateTagsRulesFor(tagGroup)", removed: "updateTagsRulesFor(tagGroup)" } } } + %table + %colgroup + %col{width: '35%'} + %col{width: '65%'} + %tr + %td + %h5 + For customers tagged: + %td + %tags-input{ ng: { model: 'tagGroup.tags'}, + min: { tags: "1" }, + on: { tag: { added: "updateTagsRulesFor(tagGroup)", removed: "updateTagsRulesFor(tagGroup)" } } } .no_rules{ ng: { show: "tagGroup.rules.length == 0" } } No rules apply to this tag yet - .tag_rule{ ng: { repeat: "rule in tagGroup.rules" } } - %discount-order{ bo: { if: "rule.type == 'TagRule::DiscountOrder'" } } - .add_rule + %table + %tr.tag_rule{ id: "tr_{{rule.id}}", ng: { repeat: "rule in tagGroup.rules" } } + %td + %discount-order{ bo: { if: "rule.type == 'TagRule::DiscountOrder'" } } + %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)' } } - .add_tag - %input.button.icon-plus{ type: 'button', value: "+ Add A New Tag", ng: { click: 'addNewTag()' } } + .add_tage + %input.button.red.icon-plus{ type: 'button', value: "+ Add A New Tag", ng: { click: 'addNewTag()' } } diff --git a/config/routes.rb b/config/routes.rb index c314747786..26d675838c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -87,6 +87,8 @@ Openfoodnetwork::Application.routes.draw do resources :producer_properties do post :update_positions, on: :collection end + + resources :tag_rules, only: [:destroy] end resources :enterprise_relationships diff --git a/spec/controllers/admin/tag_rules_controller_spec.rb b/spec/controllers/admin/tag_rules_controller_spec.rb new file mode 100644 index 0000000000..fa95650479 --- /dev/null +++ b/spec/controllers/admin/tag_rules_controller_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe Admin::TagRulesController, type: :controller do + + describe "destroy" do + context "json" do + let(:format) { :json } + + let(:enterprise) { create(:distributor_enterprise) } + let!(:tag_rule) { create(:tag_rule, enterprise: enterprise) } + let(:params) { { format: format, id: tag_rule.id } } + + context "where I don't manage the tag rule enterprise" do + let(:user) { create(:user) } + + before do + user.owned_enterprises << create(:enterprise) + allow(controller).to receive(:spree_current_user) { user } + end + + it "redirects to unauthorized" do + spree_delete :destroy, params + expect(response).to redirect_to spree.unauthorized_path + end + end + + context "where I manage the tag rule enterprise" do + before do + allow(controller).to receive(:spree_current_user) { enterprise.owner } + end + + it { expect{ spree_delete :destroy, params }.to change{TagRule.count}.by(-1) } + end + end + end +end diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb index 2b77d6e18b..cc923cd89e 100644 --- a/spec/features/admin/enterprises_spec.rb +++ b/spec/features/admin/enterprises_spec.rb @@ -334,6 +334,28 @@ feature %q{ expect(tag_rule.calculator.preferred_flat_percent).to eq 45 end end + + context "deleting" do + let!(:tag_rule) { create(:tag_rule, enterprise: enterprise, preferred_customer_tags: "member" ) } + + before do + login_to_admin_section + visit main_app.edit_admin_enterprise_path(enterprise) + end + + it "deletes rules from the database" do + click_link "Tag Rules" + + expect(page).to have_selector "#tr_#{tag_rule.id}" + + expect{ + within "#tr_#{tag_rule.id}" do + first("a.delete-tag-rule").click + end + expect(page).to_not have_selector "#tr_#{tag_rule.id}" + }.to change{TagRule.count}.by(-1) + end + end end diff --git a/spec/javascripts/unit/admin/enterprises/controllers/tag_rules_controller_spec.js.coffee b/spec/javascripts/unit/admin/enterprises/controllers/tag_rules_controller_spec.js.coffee index dd2fcee449..988040694c 100644 --- a/spec/javascripts/unit/admin/enterprises/controllers/tag_rules_controller_spec.js.coffee +++ b/spec/javascripts/unit/admin/enterprises/controllers/tag_rules_controller_spec.js.coffee @@ -6,6 +6,7 @@ describe "TagRulesCtrl", -> beforeEach -> module('admin.enterprises') enterprise = + id: 45 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" }] } @@ -21,7 +22,58 @@ describe "TagRulesCtrl", -> expect(scope.tagGroups[0].startIndex).toEqual 0 expect(scope.tagGroups[1].startIndex).toEqual 2 - it "updates when tags are added to a tagGroup", -> + describe "adding a new tag group", -> + beforeEach -> scope.addNewRuleTo(scope.tagGroups[0]) + + it "adds a new rule to the rules array for the tagGroup", -> + expect(scope.tagGroups[0].rules.length).toEqual 3 + + it "updates tagGroup start indices", -> expect(scope.tagGroups[0].startIndex).toEqual 0 expect(scope.tagGroups[1].startIndex).toEqual 3 + + describe "deleting a tag group", -> + describe "where the rule is not in the rule list for the tagGroup", -> + beforeEach -> + scope.deleteTagRule(scope.tagGroups[0],scope.tagGroups[1].rules[0]) + + it "does not remove any rules", -> + expect(scope.tagGroups[0].rules.length).toEqual 2 + expect(scope.tagGroups[1].rules.length).toEqual 1 + + describe "with an id", -> + rule = null + + beforeEach inject ($httpBackend) -> + rule = scope.tagGroups[0].rules[0] + spyOn(window, "confirm").andReturn(true) + $httpBackend.expectDELETE('/admin/enterprises/45/tag_rules/1.json').respond(status: 204) + scope.deleteTagRule(scope.tagGroups[0], rule) + $httpBackend.flush() + + it "removes the specified rule from the rules list", -> + expect(scope.tagGroups[0].rules.length).toEqual 1 + expect(scope.tagGroups[1].rules.length).toEqual 1 + 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 + + describe "without an id", -> + rule = null + + beforeEach inject ($httpBackend) -> + rule = scope.tagGroups[0].rules[0] + rule.id = null + scope.deleteTagRule(scope.tagGroups[0], rule) + + it "removes the specified rule from the rules list", -> + expect(scope.tagGroups[0].rules.length).toEqual 1 + expect(scope.tagGroups[1].rules.length).toEqual 1 + 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