Skip to content

Commit

Permalink
delete multiple images with select all button
Browse files Browse the repository at this point in the history
  • Loading branch information
argvader committed Sep 13, 2014
1 parent 7e7bd40 commit 4d185d8
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 32 deletions.
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ruby-2.1.0
2 changes: 2 additions & 0 deletions app/assets/javascripts/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@

$('#template_flow button.preview').previewTemplate();

$('#images_flow section.image').imageActions();

$('header.application h1 li:last-of-type').editApplicationName();

var enableNewItem = function(addedItem) {
Expand Down
55 changes: 47 additions & 8 deletions app/assets/javascripts/jquery.image_actions.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,61 @@
(function($) {
$.PMX.MultiImageDestroyer = function(el, options) {
$.PMX.WatchImageSelections = function($el, options) {
var base = this;

base.$el = $(el);
base.xhr = null;
base.$el = $el;

base.defaultOptions = {
allSelector: 'input#all',
observerSelector: 'input[type=checkbox]',
submitSelector: 'button[type=submit]',
deleteCheckbox: '.images input[type=checkbox]'
};

base.init = function () {
base.options = $.extend({}, base.defaultOptions, options);
base.bindEvents();
};
};

$.fn.imageActions = function(options) {
return this.each(function() {
(new $.PMX.MultiImageDestroyer(this, options)).init();
});
base.bindEvents = function() {
base.$el.on('click', base.options.submitSelector, base.submitForm);
base.$el.on('change', base.options.allSelector, base.toggleCheckboxes);
base.$el.on('change', base.options.observerSelector, base.submitState);
};

base.submitForm = function(e) {
var submitButton = $(e.currentTarget);

if (submitButton.hasClass('disabled')) {
e.preventDefault();
}
};

base.submitState = function(e) {
var checked = base.$el.find(base.options.deleteCheckbox).filter(':checked'),
submitButton = base.$el.find(base.options.submitSelector);

if (checked.length > 0) {
submitButton.removeClass('disabled');
} else {
submitButton.addClass('disabled');
}
};

base.toggleCheckboxes = function(e) {
var $target = $(e.currentTarget);

if($target.is(':checked')) {
base.$el.find(base.options.deleteCheckbox).prop('checked', true);
} else {
base.$el.find(base.options.deleteCheckbox).prop('checked', false);
}
};
};

$.fn.imageActions = function(options) {
return this.each(function() {
(new $.PMX.WatchImageSelections($(this), options)).init();
});
};

})(jQuery);
67 changes: 48 additions & 19 deletions app/assets/stylesheets/panamax/images.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,54 @@
}
}

#images_flow .submit-button {
margin-top: 20px;
width: 165px;
position: relative;
padding-left: 25px;
text-align: left;
text-decoration: none;
float: right;

&::after {
@include icon-white;
@extend .icon-x;
content: '';
position: absolute;
left: 9px;
top: 14px;
display: block;
height: 10px;
width: 10px;
#images_flow {
.select-all {
margin-top: 30px;
float: right;
height: 36px;
width: 110px;

.label {
float: left;
color: $grey;
padding: 5px 5px;
}

.styled-check {
float: left;
}
}

.submit-button {
margin-top: 20px;
width: 165px;
position: relative;
padding-left: 25px;
text-align: left;
text-decoration: none;
float: right;

&::after {
@include icon-white;
@extend .icon-x;
content: '';
position: absolute;
left: 9px;
top: 14px;
display: block;
height: 10px;
width: 10px;
}
}

.disabled {
background-color: $grey;

&:hover {
@include box-shadow(0, 0, 0, 0);
border: none;
cursor: default;
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions app/assets/stylesheets/panamax/service_details.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@

.service-details {
padding-bottom: 20px;

a.button-add {
margin: 10px 0;
padding-left: 40px;
padding-right: 20px;
}
}

.service-help-icon {
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/images_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def destroy_multiple
if params[:delete]
count = params[:delete].size
params[:delete].keys.each do |id|
image = LocalImage.find(id).destroy
LocalImage.find(id).destroy
end
flash[:notice] = "#{count} #{'image'.pluralize(count)} successfully removed"
end
Expand Down
10 changes: 8 additions & 2 deletions app/views/images/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
- unless @images.blank?
= form_tag destroy_multiple_images_path, method: :delete do
%section.image
= button_tag 'Remove Selected', type: 'submit', class: 'button-negative submit-button'
= button_tag 'Remove Selected', type: 'submit', class: 'button-negative submit-button disabled'
.select-all
.label
Select All
.styled-check
= check_box_tag 'all', 1
%label{ :for => 'all' }
%ul.images
- @images.each do |image|
%li
Expand All @@ -27,4 +33,4 @@
= check_box_tag "delete[#{image.id}]", 1
%label{ :for => "delete_#{image.id}" }
%section
= button_tag 'Remove Selected', type: 'submit', class: 'button-negative submit-button'
= button_tag 'Remove Selected', type: 'submit', class: 'button-negative submit-button disabled'
17 changes: 17 additions & 0 deletions spec/controllers/images_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,22 @@
expect(flash[:notice]).to eq '2 images successfully removed'
end
end

context 'when an error occurs' do

before do
LocalImage.stub(:find).and_raise(StandardError, 'oops')
end

it 'redirects the user to the image page' do
delete :destroy_multiple, delete: { 'key_1' => 1, 'key_2' => 2 }
expect(response).to redirect_to images_url
end

it 'flashes the error message' do
delete :destroy_multiple, delete: { 'key_1' => 1, 'key_2' => 2 }
expect(flash[:alert]).to eq 'oops'
end
end
end
end
15 changes: 15 additions & 0 deletions spec/javascripts/fixtures/images.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#images_flow
%section.image
= button_tag 'Remove Selected', type: 'submit', class: 'button-negative submit-button disabled'
.select-all
.label
Select All
.styled-check
= check_box_tag 'all', 1
%label{ :for => 'all' }
%ul.images
%li
.actions
.styled-check
= check_box_tag "delete[1]", 1
%label{ :for => "delete_1" }
87 changes: 87 additions & 0 deletions spec/javascripts/jquery.image_actions_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
describe('$.fn.imageActions', function() {
var subject;

beforeEach(function() {
fixture.load('images.html');
subject = new $.PMX.WatchImageSelections($('#images_flow section.image'));
subject.init();
});

describe('clicking "Select All" ', function() {
describe('when not checked', function() {
it('check all of the delete image checkboxes', function() {
var selectAll = $('input#all');
selectAll.prop('checked', false);

selectAll.click();
expect($('.images input[type=checkbox]').filter(':checked').length).toEqual(1);
});

it('enables the submit button', function() {
var selectAll = $('input#all');
selectAll.prop('checked', false);

selectAll.click();
expect($('button[type=submit]').hasClass('disabled')).toBeFalsy();
});
});

describe('when checked', function() {
it('uncheck all of the delete image checkboxes', function() {
var selectAll = $('input#all'),
allBoxes = $('.images input[type=checkbox]');

selectAll.prop('checked', true);
allBoxes.prop('checked', true);

selectAll.click();
expect($('.images input[type=checkbox]').filter(':checked').length).toEqual(0);
});

it('disables the submit button', function() {
var selectAll = $('input#all');
selectAll.prop('checked', true);

selectAll.click();
expect($('button[type=submit]').first().hasClass('disabled')).toBeTruthy();
});
});
});

describe('clicking an image checkbox', function() {
describe('when not checked', function() {
it('enables the submit button', function() {
var checkbox = $('.images input[type=checkbox]').first(),
submitButton = $('button[type=submit]');

checkbox.prop('checked', false);

checkbox.click();
expect(submitButton.hasClass('disabled')).toBeFalsy()
});
});

describe('when checked', function() {
it('disables the submit button', function() {
var checkbox = $('.images input[type=checkbox]').first(),
submitButton = $('button[type=submit]');

checkbox.prop('checked', true);

checkbox.click();
expect(submitButton.hasClass('disabled')).toBeTruthy()
});
});
});

describe('clicking "Remove Selected"', function() {
it ('prevents default when disabled', function() {
var submitButton = $('button[type=submit]'),
clickEvent = $.Event('click');

submitButton.addClass('disabled');
submitButton.trigger(clickEvent);
expect(clickEvent.isDefaultPrevented()).toBeTruthy();
});
})
});
6 changes: 4 additions & 2 deletions spec/support/fixtures/images_representation.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
"id": "65af5f136e080ca65af2c35d2b5d11730913484f0ada631caafef44d3cfc62c6",
"tags": [
"socialize_api:latest"
]
],
"virtual_size": 100
},
{
"id": "156edca13ead93fe108e3432294a10d49771822aa802baf8435661ca8f1c0c26",
"tags": [
"centurylinklabs/socialize-api:latest"
]
],
"virtual_size": 100
}
]

0 comments on commit 4d185d8

Please sign in to comment.