@@ -97,7 +97,7 @@ class ScenariosController < ApplicationController |
||
| 97 | 97 |
|
| 98 | 98 |
def destroy |
| 99 | 99 |
@scenario = current_user.scenarios.find(params[:id]) |
| 100 |
- @scenario.destroy |
|
| 100 |
+ @scenario.destroy_with_mode(params[:mode]) |
|
| 101 | 101 |
|
| 102 | 102 |
respond_to do |format| |
| 103 | 103 |
format.html { redirect_to scenarios_path }
|
@@ -16,7 +16,25 @@ class Scenario < ActiveRecord::Base |
||
| 16 | 16 |
|
| 17 | 17 |
validate :agents_are_owned |
| 18 | 18 |
|
| 19 |
- protected |
|
| 19 |
+ def destroy_with_mode(mode) |
|
| 20 |
+ case mode |
|
| 21 |
+ when 'all_agents' |
|
| 22 |
+ Agent.destroy(agents.pluck(:id)) |
|
| 23 |
+ when 'unique_agents' |
|
| 24 |
+ Agent.destroy(unique_agent_ids) |
|
| 25 |
+ end |
|
| 26 |
+ |
|
| 27 |
+ destroy |
|
| 28 |
+ end |
|
| 29 |
+ |
|
| 30 |
+ private |
|
| 31 |
+ |
|
| 32 |
+ def unique_agent_ids |
|
| 33 |
+ agents.joins(:scenario_memberships) |
|
| 34 |
+ .group('scenario_memberships.agent_id')
|
|
| 35 |
+ .having('count(scenario_memberships.agent_id) = 1')
|
|
| 36 |
+ .pluck('scenario_memberships.agent_id')
|
|
| 37 |
+ end |
|
| 20 | 38 |
|
| 21 | 39 |
def agents_are_owned |
| 22 | 40 |
errors.add(:agents, "must be owned by you") unless agents.all? {|s| s.user == user }
|
@@ -0,0 +1,46 @@ |
||
| 1 |
+<div id="confirm-scenario-deletion-<%= scenario.id %>" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true"> |
|
| 2 |
+ <div class="modal-dialog"> |
|
| 3 |
+ <div class="modal-content"> |
|
| 4 |
+ <%= form_for(scenario, url: scenario_path(scenario), method: :delete) do |f| %> |
|
| 5 |
+ <div class="modal-header"> |
|
| 6 |
+ <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> |
|
| 7 |
+ <h4 class="modal-title"> |
|
| 8 |
+ <% if @scenario && @scenario == scenario %> |
|
| 9 |
+ How do you want to delete this Scenario? |
|
| 10 |
+ <% else %> |
|
| 11 |
+ How do you want to delete the Scenario '<%= scenario.name %>'? |
|
| 12 |
+ <% end %> |
|
| 13 |
+ </h4> |
|
| 14 |
+ </div> |
|
| 15 |
+ <div class="modal-body"> |
|
| 16 |
+ <div class="radio"> |
|
| 17 |
+ <%= label_tag do %> |
|
| 18 |
+ <%= radio_button_tag :mode, '', true %> |
|
| 19 |
+ <h4><span class="label label-success">Scenario only</span></h4> |
|
| 20 |
+ Only delete the Scenerio, keep the Agents. |
|
| 21 |
+ <% end %> |
|
| 22 |
+ </div> |
|
| 23 |
+ <div class="radio"> |
|
| 24 |
+ <%= label_tag do %> |
|
| 25 |
+ <%= radio_button_tag :mode, :unique_agents %> |
|
| 26 |
+ <h4><span class="label label-warning">Scenario and unique Agents</span></h4> |
|
| 27 |
+ Also deletes Agents that are used in this Scenario only. |
|
| 28 |
+ <% end %> |
|
| 29 |
+ </div> |
|
| 30 |
+ <div class="radio"> |
|
| 31 |
+ <%= label_tag do %> |
|
| 32 |
+ <%= radio_button_tag :mode, :all_agents %> |
|
| 33 |
+ <h4><span class="label label-danger">Scenario and all included Agents</span></h4> |
|
| 34 |
+ Deletes Scenario and all included Agents, even if they are used in different Scenarios. |
|
| 35 |
+ <% end %> |
|
| 36 |
+ </div> |
|
| 37 |
+ </div> |
|
| 38 |
+ <div class="modal-footer"> |
|
| 39 |
+ <%= f.button 'Abort', class: 'btn btn-default', 'data-dismiss' => 'modal' %> |
|
| 40 |
+ <%= f.submit 'Delete', class: 'btn btn-danger' %> |
|
| 41 |
+ </div> |
|
| 42 |
+ <% end %> |
|
| 43 |
+ </div> |
|
| 44 |
+ </div> |
|
| 45 |
+</div> |
|
| 46 |
+ |
@@ -31,8 +31,9 @@ |
||
| 31 | 31 |
<%= link_to 'Show', scenario, class: "btn btn-default" %> |
| 32 | 32 |
<%= link_to 'Edit', edit_scenario_path(scenario), class: "btn btn-default" %> |
| 33 | 33 |
<%= link_to 'Share', share_scenario_path(scenario), class: "btn btn-default" %> |
| 34 |
- <%= link_to 'Delete', scenario_path(scenario), method: :delete, data: { confirm: "This will remove the '#{scenario.name}' Scenerio from all Agents and delete it. Are you sure?" }, class: "btn btn-default" %>
|
|
| 34 |
+ <%= link_to 'Delete', '#', data: { toggle: 'modal', target: "#confirm-scenario-deletion-#{scenario.id}"}, class: "btn btn-default" %>
|
|
| 35 | 35 |
</div> |
| 36 |
+ <%= render 'scenarios/confirm_deletion_modal', scenario: scenario %> |
|
| 36 | 37 |
</td> |
| 37 | 38 |
</tr> |
| 38 | 39 |
<% end %> |
@@ -23,8 +23,9 @@ |
||
| 23 | 23 |
<%= link_to icon_tag('glyphicon-refresh') + ' Update', new_scenario_imports_path(url: @scenario.source_url), class: "btn btn-default" %>
|
| 24 | 24 |
<% end %> |
| 25 | 25 |
<%= link_to icon_tag('glyphicon-share-alt') + ' Share', share_scenario_path(@scenario), class: "btn btn-default" %>
|
| 26 |
- <%= link_to icon_tag('glyphicon-trash') + ' Delete', scenario_path(@scenario), method: :delete, data: { confirm: "This will remove the '#{@scenario.name}' Scenerio from all Agents and delete it. Are you sure?" }, class: "btn btn-default" %>
|
|
| 26 |
+ <%= link_to icon_tag('glyphicon-trash') + ' Delete', '#', data: { toggle: 'modal', target: "#confirm-scenario-deletion-#{@scenario.id}"}, class: "btn btn-default" %>
|
|
| 27 | 27 |
</div> |
| 28 | 28 |
</div> |
| 29 | 29 |
</div> |
| 30 | 30 |
</div> |
| 31 |
+<%= render 'scenarios/confirm_deletion_modal', scenario: @scenario %> |
@@ -150,5 +150,11 @@ describe ScenariosController do |
||
| 150 | 150 |
delete :destroy, :id => scenarios(:jane_weather).to_param |
| 151 | 151 |
}.to raise_error(ActiveRecord::RecordNotFound) |
| 152 | 152 |
end |
| 153 |
+ |
|
| 154 |
+ it "passes the mode to the model" do |
|
| 155 |
+ expect {
|
|
| 156 |
+ delete :destroy, id: scenarios(:bob_weather).to_param, mode: 'all_agents' |
|
| 157 |
+ }.to change(Agent, :count).by(-2) |
|
| 158 |
+ end |
|
| 153 | 159 |
end |
| 154 | 160 |
end |
@@ -6,6 +6,10 @@ jane_rain_notifier_agent_scenario_membership: |
||
| 6 | 6 |
agent: jane_rain_notifier_agent |
| 7 | 7 |
scenario: jane_weather |
| 8 | 8 |
|
| 9 |
+jane_rain_notifier_agent_scenario_membership_duplicate: |
|
| 10 |
+ agent: jane_weather_agent |
|
| 11 |
+ scenario: jane_weather_duplicate |
|
| 12 |
+ |
|
| 9 | 13 |
bob_weather_agent_scenario_membership: |
| 10 | 14 |
agent: bob_weather_agent |
| 11 | 15 |
scenario: bob_weather |
@@ -5,6 +5,12 @@ jane_weather: |
||
| 5 | 5 |
public: false |
| 6 | 6 |
guid: random-guid-generated-by-bob |
| 7 | 7 |
|
| 8 |
+jane_weather_duplicate: |
|
| 9 |
+ name: Jane's duplicated, incomplete weather alert Scenario |
|
| 10 |
+ user: jane |
|
| 11 |
+ public: false |
|
| 12 |
+ guid: random-guid-generated-by-jane2 |
|
| 13 |
+ |
|
| 8 | 14 |
bob_weather: |
| 9 | 15 |
name: Bob's weather alert Scenario |
| 10 | 16 |
user: bob |
@@ -64,4 +64,35 @@ describe Scenario do |
||
| 64 | 64 |
}.to change { users(:bob).reload.scenario_count }.by(-1)
|
| 65 | 65 |
end |
| 66 | 66 |
end |
| 67 |
+ |
|
| 68 |
+ context '#unique_agents' do |
|
| 69 |
+ it "equals agents when no agents are shared" do |
|
| 70 |
+ agent_ids = scenarios(:bob_weather).agents.map(&:id).sort |
|
| 71 |
+ unique_agent_ids = scenarios(:bob_weather).send(:unique_agent_ids).sort |
|
| 72 |
+ expect(agent_ids).to eq(unique_agent_ids) |
|
| 73 |
+ end |
|
| 74 |
+ |
|
| 75 |
+ it "includes only agents that are not present in two scnearios" do |
|
| 76 |
+ unique_agent_ids = scenarios(:jane_weather).send(:unique_agent_ids) |
|
| 77 |
+ expect(unique_agent_ids).to eq([agents(:jane_rain_notifier_agent).id]) |
|
| 78 |
+ end |
|
| 79 |
+ |
|
| 80 |
+ it "returns no agents when all are also used in a different scenario" do |
|
| 81 |
+ expect(scenarios(:jane_weather_duplicate).send(:unique_agent_ids)).to eq([]) |
|
| 82 |
+ end |
|
| 83 |
+ end |
|
| 84 |
+ |
|
| 85 |
+ context '#destroy_with_mode' do |
|
| 86 |
+ it "only destroys the scenario when no mode is passed" do |
|
| 87 |
+ expect { scenarios(:jane_weather).destroy_with_mode('') }.not_to change(Agent, :count)
|
|
| 88 |
+ end |
|
| 89 |
+ |
|
| 90 |
+ it "only destroys unique agents when 'unique_agents' is passed" do |
|
| 91 |
+ expect { scenarios(:jane_weather).destroy_with_mode('unique_agents') }.to change(Agent, :count).by(-1)
|
|
| 92 |
+ end |
|
| 93 |
+ |
|
| 94 |
+ it "destroys all agents when 'all_agents' is passed" do |
|
| 95 |
+ expect { scenarios(:jane_weather).destroy_with_mode('all_agents') }.to change(Agent, :count).by(-2)
|
|
| 96 |
+ end |
|
| 97 |
+ end |
|
| 67 | 98 |
end |