From 0e03b5f2097c619da588aeba282ffce58db2ef15 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 16 Oct 2014 12:41:11 +1100 Subject: [PATCH] Admin can change the format that Spree::Images are stored/served in --- .../image_settings_controller_decorator.rb | 11 +++++ app/helpers/admin/image_settings_helper.rb | 21 +++++++++ app/models/spree/image_decorator.rb | 23 ++++++++++ .../edit/add_image_format.html.haml.deface | 11 +++++ spec/features/admin/image_settings_spec.rb | 43 +++++++++++++++++++ spec/models/spree/image_spec.rb | 18 ++++++++ 6 files changed, 127 insertions(+) create mode 100644 app/controllers/spree/admin/image_settings_controller_decorator.rb create mode 100644 app/helpers/admin/image_settings_helper.rb create mode 100644 app/models/spree/image_decorator.rb create mode 100644 app/overrides/spree/admin/image_settings/edit/add_image_format.html.haml.deface create mode 100644 spec/features/admin/image_settings_spec.rb create mode 100644 spec/models/spree/image_spec.rb diff --git a/app/controllers/spree/admin/image_settings_controller_decorator.rb b/app/controllers/spree/admin/image_settings_controller_decorator.rb new file mode 100644 index 0000000000..5fe7dae551 --- /dev/null +++ b/app/controllers/spree/admin/image_settings_controller_decorator.rb @@ -0,0 +1,11 @@ +Spree::Admin::ImageSettingsController.class_eval do + # Spree stores attachent definitions in JSON. This converts the style name and format to + # strings. However, when paperclip encounters these, it doesn't recognise the format. + # Here we solve that problem by converting format and style name to symbols. + def update_paperclip_settings_with_format_styles + update_paperclip_settings_without_format_styles + Spree::Image.reformat_styles + end + + alias_method_chain :update_paperclip_settings, :format_styles +end diff --git a/app/helpers/admin/image_settings_helper.rb b/app/helpers/admin/image_settings_helper.rb new file mode 100644 index 0000000000..10c34fe372 --- /dev/null +++ b/app/helpers/admin/image_settings_helper.rb @@ -0,0 +1,21 @@ +module Admin + module ImageSettingsHelper + def admin_image_settings_format_options + [['Unchanged', ''], ['PNG', 'png'], ['JPEG', 'jpg']] + end + + def admin_image_settings_geometry_from_style(style) + geometry, format = admin_image_settings_split_style style + geometry + end + + def admin_image_settings_format_from_style(style) + geometry, format = admin_image_settings_split_style style + format + end + + def admin_image_settings_split_style(style) + [style, nil].flatten[0..1] + end + end +end diff --git a/app/models/spree/image_decorator.rb b/app/models/spree/image_decorator.rb new file mode 100644 index 0000000000..7d86aae3a6 --- /dev/null +++ b/app/models/spree/image_decorator.rb @@ -0,0 +1,23 @@ +Spree::Image.class_eval do + # Spree stores attachent definitions in JSON. This converts the style name and format to + # strings. However, when paperclip encounters these, it doesn't recognise the format. + # Here we solve that problem by converting format and style name to symbols. + # See also: ImageSettingsController decorator. + # + # eg. {'mini' => ['48x48>', 'png']} is converted to {mini: ['48x48>', :png]} + def self.format_styles(styles) + styles_a = styles.map do |name, style| + style[1] = style[1].to_sym if style.is_a? Array + [name.to_sym, style] + end + + Hash[styles_a] + end + + def self.reformat_styles + Spree::Image.attachment_definitions[:attachment][:styles] = + format_styles(Spree::Image.attachment_definitions[:attachment][:styles]) + end + + reformat_styles +end diff --git a/app/overrides/spree/admin/image_settings/edit/add_image_format.html.haml.deface b/app/overrides/spree/admin/image_settings/edit/add_image_format.html.haml.deface new file mode 100644 index 0000000000..deb79b5bbf --- /dev/null +++ b/app/overrides/spree/admin/image_settings/edit/add_image_format.html.haml.deface @@ -0,0 +1,11 @@ +/ replace_contents '#styles_list' + +- @styles.each_with_index do |(style_name, style_value), index| + .field.three.columns + = label_tag "attachment_styles[#{style_name}]", style_name + %a.destroy_style.with-tip{:alt => t(:destroy), :href => "#", :title => t(:destroy)} + %i.icon-trash + = text_field_tag "attachment_styles[#{style_name}][]", admin_image_settings_geometry_from_style(style_value), :class => 'fullwidth' + %br/ + - current_format = admin_image_settings_format_from_style(style_value) || '' + = select_tag "attachment_styles[#{style_name}][]", options_for_select(admin_image_settings_format_options, current_format), :class => 'fullwidth', :id => "attachment_styles_format_#{style_name}" diff --git a/spec/features/admin/image_settings_spec.rb b/spec/features/admin/image_settings_spec.rb new file mode 100644 index 0000000000..a83a072235 --- /dev/null +++ b/spec/features/admin/image_settings_spec.rb @@ -0,0 +1,43 @@ +require 'spec_helper' + +feature %q{ + As an admin + I want to manage image formats +} do + include AuthenticationWorkflow + include WebHelper + + before(:all) do + styles = {"mini" => "48x48>", + "small" => "100x100>", + "product" => "240x240>", + "large" => "600x600>"} + + Spree::Config[:attachment_styles] = ActiveSupport::JSON.encode(styles) + Spree::Image.attachment_definitions[:attachment][:styles] = ActiveSupport::JSON.decode(Spree::Config[:attachment_styles]) + Spree::Image.reformat_styles + end + + scenario "setting the image format for a paperclip style" do + # When I go to the image settings page + login_to_admin_section + visit spree.edit_admin_image_settings_path + + # All the styles should default to "Unchanged" + page.should have_select 'attachment_styles_format_mini', selected: 'Unchanged' + page.should have_select 'attachment_styles_format_small', selected: 'Unchanged' + page.should have_select 'attachment_styles_format_product', selected: 'Unchanged' + page.should have_select 'attachment_styles_format_large', selected: 'Unchanged' + + # When I change a style to "PNG" and save + select 'PNG', from: 'attachment_styles_format_mini' + click_button 'Update' + + # Then the change should be saved to the image formats + page.should have_content "Image Settings successfully updated." + page.should have_select 'attachment_styles_format_mini', selected: 'PNG' + + styles = Spree::Image.attachment_definitions[:attachment][:styles] + styles[:mini].should == ['48x48>', :png] + end +end diff --git a/spec/models/spree/image_spec.rb b/spec/models/spree/image_spec.rb new file mode 100644 index 0000000000..56665fa641 --- /dev/null +++ b/spec/models/spree/image_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +module Spree + describe Image do + describe "attachment definitions" do + let(:name_str) { {"mini" => "48x48>"} } + let(:formatted) { {mini: ["48x48>", "png"]} } + + it "converts style names to symbols" do + Image.format_styles(name_str).should == {:mini => "48x48>"} + end + + it "converts formats to symbols" do + Image.format_styles(formatted).should == {:mini => ["48x48>", :png]} + end + end + end +end