refinerycms-images 0.9.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/app/controllers/admin/images_controller.rb +108 -0
  2. data/app/helpers/admin/images_helper.rb +27 -0
  3. data/app/models/image.rb +72 -0
  4. data/app/views/admin/images/_existing_image.html.erb +73 -0
  5. data/app/views/admin/images/_form.html.erb +54 -0
  6. data/app/views/admin/images/_grid_view.html.erb +19 -0
  7. data/app/views/admin/images/_images.html.erb +2 -0
  8. data/app/views/admin/images/_list_view.html.erb +10 -0
  9. data/app/views/admin/images/_list_view_image.html.erb +17 -0
  10. data/app/views/admin/images/edit.html.erb +1 -0
  11. data/app/views/admin/images/index.html.erb +38 -0
  12. data/app/views/admin/images/insert.html.erb +47 -0
  13. data/app/views/admin/images/new.html.erb +1 -0
  14. data/config/locales/cs.yml +41 -0
  15. data/config/locales/da.yml +41 -0
  16. data/config/locales/de.yml +41 -0
  17. data/config/locales/el.yml +41 -0
  18. data/config/locales/en.yml +41 -0
  19. data/config/locales/es.yml +40 -0
  20. data/config/locales/fr.yml +41 -0
  21. data/config/locales/it.yml +47 -0
  22. data/config/locales/lolcat.yml +41 -0
  23. data/config/locales/lt.yml +41 -0
  24. data/config/locales/lv.yml +41 -0
  25. data/config/locales/nb.yml +42 -0
  26. data/config/locales/nl.yml +40 -0
  27. data/config/locales/pl.yml +42 -0
  28. data/config/locales/pt-BR.yml +42 -0
  29. data/config/locales/rs.yml +42 -0
  30. data/config/locales/ru.yml +41 -0
  31. data/config/locales/sl.yml +40 -0
  32. data/config/locales/sv.yml +41 -0
  33. data/config/locales/vi.yml +41 -0
  34. data/config/locales/zh-CN.yml +41 -0
  35. data/config/locales/zh-TW.yml +41 -0
  36. data/config/routes.rb +12 -0
  37. data/db/migrate/20100913234707_create_refinerycms_images_schema.rb +23 -0
  38. data/features/manage_images.feature +49 -0
  39. data/features/step_definitions/image_steps.rb +40 -0
  40. data/features/support/factories.rb +5 -0
  41. data/features/support/paths.rb +17 -0
  42. data/features/uploads/beach.jpeg +0 -0
  43. data/features/uploads/id-rather-be-here.jpg +0 -0
  44. data/features/uploads/refinery_is_awesome.txt +1 -0
  45. data/lib/gemspec.rb +35 -0
  46. data/lib/generators/refinerycms_images_generator.rb +8 -0
  47. data/lib/refinerycms-images.rb +69 -0
  48. data/license.md +21 -0
  49. data/readme.md +34 -0
  50. data/refinerycms-images.gemspec +97 -0
  51. data/spec/models/image_spec.rb +87 -0
  52. data/spec/uploads/beach.jpeg +0 -0
  53. metadata +142 -0
@@ -0,0 +1,108 @@
1
+ module Admin
2
+ class ImagesController < Admin::BaseController
3
+
4
+ include Admin::ImagesHelper
5
+
6
+ crudify :image,
7
+ :order => "created_at DESC",
8
+ :sortable => false
9
+
10
+ before_filter :change_list_mode_if_specified, :init_dialog
11
+
12
+ def index
13
+ search_all_images if searching?
14
+ paginate_all_images
15
+
16
+ render :partial => 'images' if request.xhr?
17
+ end
18
+
19
+ def new
20
+ @image = Image.new if @image.nil?
21
+
22
+ @url_override = admin_images_url(:dialog => from_dialog?)
23
+ end
24
+
25
+ # This renders the image insert dialog
26
+ def insert
27
+ self.new if @image.nil?
28
+
29
+ @url_override = admin_images_url(:dialog => from_dialog?, :insert => true)
30
+
31
+ if params[:conditions].present?
32
+ extra_condition = params[:conditions].split(',')
33
+
34
+ extra_condition[1] = true if extra_condition[1] == "true"
35
+ extra_condition[1] = false if extra_condition[1] == "false"
36
+ extra_condition[1] = nil if extra_condition[1] == "nil"
37
+ end
38
+
39
+ find_all_images(({extra_condition[0].to_sym => extra_condition[1]} if extra_condition.present?))
40
+ search_all_images if searching?
41
+
42
+ paginate_images
43
+
44
+ render :action => "insert"
45
+ end
46
+
47
+ def create
48
+ @images = []
49
+ begin
50
+ unless params[:image].present? and params[:image][:image].is_a?(Array)
51
+ @images << (@image = Image.create(params[:image]))
52
+ else
53
+ params[:image][:image].each do |image|
54
+ @images << (@image = Image.create(:image => image))
55
+ end
56
+ end
57
+ rescue Dragonfly::FunctionManager::UnableToHandle
58
+ logger.warn($!.message)
59
+ @image = Image.new
60
+ end
61
+
62
+ unless params[:insert]
63
+ if @images.all?{|i| i.valid?}
64
+ flash.notice = t('created', :scope => 'refinery.crudify', :what => "'#{@images.collect{|i| i.title}.join("', '")}'")
65
+ unless from_dialog?
66
+ redirect_to :action => 'index'
67
+ else
68
+ render :text => "<script>parent.window.location = '#{admin_images_url}';</script>"
69
+ end
70
+ else
71
+ self.new # important for dialogs
72
+ render :action => 'new'
73
+ end
74
+ else
75
+ if @images.all?{|i| i.valid?}
76
+ @image_id = @image.id if @image.persisted?
77
+ @image = nil
78
+ end
79
+ self.insert
80
+ end
81
+ end
82
+
83
+ protected
84
+
85
+ def init_dialog
86
+ @app_dialog = params[:app_dialog].present?
87
+ @field = params[:field]
88
+ @update_image = params[:update_image]
89
+ @thumbnail = params[:thumbnail]
90
+ @callback = params[:callback]
91
+ @conditions = params[:conditions]
92
+ end
93
+
94
+ def paginate_images
95
+ @images = @images.paginate(:page => (@paginate_page_number ||= params[:page]),
96
+ :per_page => Image.per_page(from_dialog?, !@app_dialog))
97
+ end
98
+
99
+ def restrict_controller
100
+ super unless action_name == 'insert'
101
+ end
102
+
103
+ def store_current_location!
104
+ super unless action_name == 'insert' or from_dialog?
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,27 @@
1
+ module Admin
2
+ module ImagesHelper
3
+
4
+ def image_views
5
+ RefinerySetting.find_or_set(:image_views, [:grid, :list])
6
+ end
7
+
8
+ def current_image_view
9
+ RefinerySetting.find_or_set(:preferred_image_view, :grid)
10
+ end
11
+
12
+ def other_image_views
13
+ image_views.reject {|image_view| image_view.to_s == current_image_view.to_s }
14
+ end
15
+
16
+ def change_list_mode_if_specified
17
+ if action_name == 'index' and params[:view].present? and image_views.include?(params[:view].to_sym)
18
+ RefinerySetting.set(:preferred_image_view, params[:view])
19
+ end
20
+ end
21
+
22
+ def images_paginator(collection, dialog = false)
23
+ will_paginate collection, :renderer => Refinery::LinkRenderer
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,72 @@
1
+ # encoding: utf-8
2
+
3
+ class Image < ActiveRecord::Base
4
+
5
+ # What is the max image size a user can upload
6
+ MAX_SIZE_IN_MB = 5
7
+
8
+ image_accessor :image
9
+
10
+ validates :image, :presence => {},
11
+ :length => { :maximum => MAX_SIZE_IN_MB.megabytes }
12
+ validates_property :mime_type, :of => :image, :in => %w(image/jpeg image/png image/gif image/tiff),
13
+ :message => :incorrect_format
14
+
15
+ # Docs for acts_as_indexed http://github.com/dougal/acts_as_indexed
16
+ acts_as_indexed :fields => [:title]
17
+
18
+ # when a dialog pops up with images, how many images per page should there be
19
+ PAGES_PER_DIALOG = 18
20
+
21
+ # when a dialog pops up with images, but that dialog has image resize options
22
+ # how many images per page should there be
23
+ PAGES_PER_DIALOG_THAT_HAS_SIZE_OPTIONS = 12
24
+
25
+ # when listing images out in the admin area, how many images should show per page
26
+ PAGES_PER_ADMIN_INDEX = 20
27
+
28
+ delegate :size, :mime_type, :url, :width, :height, :to => :image
29
+
30
+ class << self
31
+ # How many images per page should be displayed?
32
+ def per_page(dialog = false, has_size_options = false)
33
+ if dialog
34
+ unless has_size_options
35
+ PAGES_PER_DIALOG
36
+ else
37
+ PAGES_PER_DIALOG_THAT_HAS_SIZE_OPTIONS
38
+ end
39
+ else
40
+ PAGES_PER_ADMIN_INDEX
41
+ end
42
+ end
43
+
44
+ def user_image_sizes
45
+ RefinerySetting.find_or_set(:user_image_sizes, {
46
+ :small => '110x110>',
47
+ :medium => '225x255>',
48
+ :large => '450x450>'
49
+ }, :destroyable => false)
50
+ end
51
+ end
52
+
53
+ # Get a thumbnail job object given a geometry.
54
+ def thumbnail(geometry = nil)
55
+ if geometry.is_a?(Symbol) and self.class.user_image_sizes.keys.include?(geometry)
56
+ geometry = self.class.user_image_sizes[geometry]
57
+ end
58
+
59
+ if geometry.present? && !geometry.is_a?(Symbol)
60
+ image.thumb(geometry)
61
+ else
62
+ image
63
+ end
64
+ end
65
+
66
+ # Returns a titleized version of the filename
67
+ # my_file.jpg returns My File
68
+ def title
69
+ CGI::unescape(image_name.to_s).gsub(/\.\w+$/, '').titleize
70
+ end
71
+
72
+ end
@@ -0,0 +1,73 @@
1
+ <div id='existing_image_area' class='dialog_area' <%= "style='display:none;'" if @image.errors.any? %>>
2
+ <%= render :partial => '/shared/admin/search',
3
+ :locals => {:url => insert_admin_images_url(params.dup.delete(:image))} %>
4
+ <input type='hidden' name='selected_image' id='selected_image' />
5
+ <div id='existing_image_area_content' class='clearfix'>
6
+ <% if @images.any? %>
7
+ <ul>
8
+ <%
9
+ @images.each do |image|
10
+ thumbnail_urls = {
11
+ :"data-original" => image.url,
12
+ :"data-grid" => image.thumbnail('135x135#c').url
13
+ }
14
+ ::Image.user_image_sizes.sort_by{|key,geometry| geometry}.each do |size, pixels|
15
+ thumbnail_urls[:"data-#{size.to_s.parameterize}"] = image.thumbnail(pixels).url
16
+ end
17
+ -%>
18
+ <li<%= " class='selected'" if @image_id == image.id %>>
19
+ <%= image_fu(image, '106x106#c', {
20
+ :alt => image.title,
21
+ :title => image.title,
22
+ :id => "image_#{image.id}",
23
+ :'data-id' => image.id
24
+ }.merge(thumbnail_urls)) -%>
25
+ </li>
26
+ <% end -%>
27
+ </ul>
28
+ <% elsif searching? %>
29
+ <%= t('no_results', :scope => 'shared.admin.search') %>
30
+ <% end %>
31
+ </div>
32
+
33
+ <%= images_paginator @images, from_dialog? %>
34
+
35
+ <% unless @app_dialog or @images.empty? %>
36
+ <div id='existing_image_size_area' class='clearfix'>
37
+ <input type='hidden' name='selected_image_size' id='selected_image_size' />
38
+ <p>
39
+ <input type="checkbox" id="wants_to_resize_image" name="wants_to_resize_image" value="1" checked="checked" />
40
+ <label for='wants_to_resize_image' class='stripped' style='font-weight: bold;'>
41
+ <%= t('.resize_image') %>
42
+ </label>
43
+ </p>
44
+ <ul>
45
+ <%
46
+ ::Image.user_image_sizes.sort_by { |key, geometry| geometry }.each_with_index do |(size, pixels), index|
47
+ safe_pixels = pixels.to_s.gsub(/[<>=]/, '')
48
+ # (parndt): ' selected' if size.to_s == 'medium' is not very generic, but I
49
+ # can't think of a decent way of making it so for even sets (e.g. 2,4,6,8,etc image sizes).
50
+ -%>
51
+ <li id="image_dialog_size_<%= index %>" class="image_dialog_size<%= ' selected' if size.to_s == 'medium' %>">
52
+ <%= link_to size.to_s, "##{size}",
53
+ :'data-geometry' => pixels,
54
+ :'data-size' => size.to_s.parameterize,
55
+ :title => "#{size} image (#{safe_pixels})",
56
+ :tooltip => "#{size} image (#{safe_pixels})" %>
57
+ </li>
58
+ <% end -%>
59
+ </ul>
60
+ </div>
61
+ <% end %>
62
+
63
+ <%= render :partial => "/shared/admin/form_actions",
64
+ :locals => {
65
+ :f => nil,
66
+ :cancel_url => '',
67
+ :submit_button_text => t('.button_text'),
68
+ :hide_submit => @images.empty?,
69
+ :hide_cancel => false,
70
+ :hide_delete => true,
71
+ :cancel_title => nil
72
+ } if @app_dialog or @images.any? or searching? %>
73
+ </div>
@@ -0,0 +1,54 @@
1
+ <%= form_for [:admin, @image], :url => @url_override || @url, :html => {:multipart => true} do |f| %>
2
+
3
+ <%= render :partial => "/shared/admin/error_messages",
4
+ :locals => {
5
+ :object => @image,
6
+ :include_object_name => false
7
+ } %>
8
+
9
+ <div class='field'>
10
+ <% if action_name =~ /(edit)|(update)/ %>
11
+ <p>
12
+ <%= t('.use_current_image') %>
13
+ <em><%= t('.or') %></em><%= t('.replace_image') %>
14
+ </p>
15
+ <p>
16
+ <%= f.file_field :image %>
17
+ </p>
18
+ <% else %>
19
+ <% # we must only hint at multiple when it's a new record otherwise update fails. %>
20
+ <%= f.file_field :image, :multiple => true %>
21
+ <% end %>
22
+ </div>
23
+
24
+ <div class='field'>
25
+ <label><%= t('.maximum_image_size', :megabytes => Image::MAX_SIZE_IN_MB) %></label>
26
+ </div>
27
+
28
+ <input type='hidden' name='wymeditor' value='<%= params[:wymeditor] %>'>
29
+
30
+ <%= render :partial => "/shared/admin/form_actions",
31
+ :locals => {
32
+ :f => f,
33
+ :continue_editing => false,
34
+ :hide_cancel => (@app_dialog or action_name == "insert" or from_dialog?),
35
+ :delete_title => t('delete', :scope => 'admin.images'),
36
+ :delete_confirmation => t('message', :scope => 'shared.admin.delete', :title => @image.image_name)
37
+ } -%>
38
+
39
+ <% if @app_dialog %>
40
+ <input type='hidden' name='app_dialog' value='<%= @app_dialog %>' />
41
+ <input type='hidden' name='field' value='<%= @field %>' />
42
+ <input type='hidden' name='update_image' value='<%= @update_image %>' />
43
+ <input type='hidden' name='thumbnail' value='<%= @thumbnail %>' />
44
+ <input type='hidden' name='callback' value='<%= @callback %>' />
45
+ <input type='hidden' name='conditions' value='<%= @conditions %>' />
46
+ <% end %>
47
+ <% end %>
48
+
49
+ <% if action_name =~ /(edit)|(update)/ %>
50
+ <div id='existing_image'>
51
+ <label><%=t('.current_image') %></label>
52
+ <%= image_fu @image, '225x255>', :class => "brown_border" %>
53
+ </div>
54
+ <% end %>
@@ -0,0 +1,19 @@
1
+ <ul id="image_grid" class="<%= ['clearfix', 'pagination_frame', pagination_css_class].compact.join(' ') %>">
2
+ <% @images.each_with_index do |image, index| -%>
3
+ <li id="image_<%= image.id %>" class='image_<%= index % 5 %>'>
4
+ <%= image_fu image, '135x135#c', :title => image.title %>
5
+ <span class='actions'>
6
+ <%= link_to refinery_icon_tag('eye.png'), image.url,
7
+ :target => "_blank",
8
+ :title => t('.view_live_html') %>
9
+ <%= link_to refinery_icon_tag('application_edit.png'), edit_admin_image_path(image),
10
+ :title => t('edit', :scope => 'admin.images') %>
11
+ <%= link_to refinery_icon_tag('delete.png'), admin_image_path(image),
12
+ :class => "cancel confirm-delete",
13
+ :title => t('delete', :scope => 'admin.images'),
14
+ :confirm => t('message', :scope => 'shared.admin.delete', :title => image.title),
15
+ :method => :delete %>
16
+ </span>
17
+ </li>
18
+ <% end -%>
19
+ </ul>
@@ -0,0 +1,2 @@
1
+ <%= will_paginate @images %>
2
+ <%= render :partial => "#{current_image_view}_view" %>
@@ -0,0 +1,10 @@
1
+ <div class="<%= ['clearfix', 'pagination_frame', pagination_css_class].compact.join(' ') %>">
2
+ <% group_by_date(@images).each do |container| %>
3
+ <% date_time = (image_group = container.last).first.created_at %>
4
+ <% date = Date.parse(date_time.to_s) %>
5
+ <h3><%= l(date, :format => :long ) %></h3>
6
+ <ul>
7
+ <%= render :partial => 'list_view_image', :collection => image_group %>
8
+ </ul>
9
+ <% end %>
10
+ </div>
@@ -0,0 +1,17 @@
1
+ <li id="sortable_<%= list_view_image.id %>" class='clearfix record <%= cycle("on", "on-hover") %>'>
2
+ <span class='title'>
3
+ <%= list_view_image.title %> <span class="preview">&nbsp;</span>
4
+ </span>
5
+ <span class='actions'>
6
+ <%= link_to refinery_icon_tag('eye.png'), list_view_image.url,
7
+ :target => "_blank",
8
+ :title => "#{image_fu list_view_image, '96x96#c', :size => '96x96'}" %>
9
+ <%= link_to refinery_icon_tag('application_edit.png'), edit_admin_image_path(list_view_image),
10
+ :title => t('edit', :scope => 'admin.images') %>
11
+ <%= link_to refinery_icon_tag('delete.png'), admin_image_path(list_view_image),
12
+ :class => "cancel confirm-delete",
13
+ :title => t('delete', :scope => 'admin.images'),
14
+ :confirm => t('message', :scope => 'shared.admin.delete', :title => list_view_image.title),
15
+ :method => :delete %>
16
+ </span>
17
+ </li>
@@ -0,0 +1 @@
1
+ <%= render :partial => "form" %>
@@ -0,0 +1,38 @@
1
+ <div id='records'>
2
+ <% if searching? %>
3
+ <h2><%= t('results_for', :scope => 'shared.admin.search', :query => params[:search]) %></h2>
4
+ <% end %>
5
+ <% if @images.any? %>
6
+ <div class='pagination_container'>
7
+ <%= render :partial => 'images' %>
8
+ </div>
9
+ <% else %>
10
+ <p>
11
+ <% unless searching? %>
12
+ <strong>
13
+ <%= t('.no_images_yet') %>
14
+ </strong>
15
+ <% else %>
16
+ <%= t('no_results', :scope => 'shared.admin.search') %>
17
+ <% end %>
18
+ </p>
19
+ <% end %>
20
+ </div>
21
+ <div id='actions'>
22
+ <ul>
23
+ <li>
24
+ <%= render :partial => "/shared/admin/search", :locals => {:url => admin_images_url} %>
25
+ </li>
26
+ <li>
27
+ <%= link_to t('.create_new_image'), new_admin_image_url(:dialog => true, :width => 600, :height => 300),
28
+ :class => "add_icon" %>
29
+ </li>
30
+ <% other_image_views.each do |image_view| %>
31
+ <li>
32
+ <%= link_to t('switch_to', :scope => 'admin.images.index.view', :view_name => t("#{image_view}", :scope => 'admin.images.index.view')),
33
+ admin_images_url(:view => image_view, :page => params[:page]),
34
+ :class => "reorder_icon" %>
35
+ </li>
36
+ <% end %>
37
+ </ul>
38
+ </div>
@@ -0,0 +1,47 @@
1
+ <% user_can_modify_images = ::Refinery::Plugins.active.names.include?("refinery_images") %>
2
+ <div id='dialog_menu_left'>
3
+ <% if (any_images = @images.any?) or searching? %>
4
+ <span id="existing_image_radio" class="radio<%= " selected_radio" if (no_errors = @image.errors.empty?) %>">
5
+ <input type='radio' name='image_type' value='existing_image' id='image_type_existing'<%= " checked='true'" if no_errors or searching? %> />
6
+ <label for='image_type_existing' class='stripped'><%= t('.existing_image') %></label>
7
+ </span>
8
+ <% end %>
9
+ <% if user_can_modify_images %>
10
+ <span id="upload_image_radio" class="radio<%= " selected_radio" if !no_errors and !any_images %>">
11
+ <input type='radio' name='image_type' value='upload_image' id='image_type_upload'<%= " checked='true'" if (!any_images or !no_errors) and !searching? %> />
12
+ <label for='image_type_upload' class='stripped'><%= t('.new_image') %></label>
13
+ </span>
14
+ <% end %>
15
+ </div>
16
+
17
+ <div id='dialog_main'>
18
+ <% if any_images or user_can_modify_images %>
19
+ <%= render :partial => "existing_image" if any_images or searching? %>
20
+
21
+ <% if user_can_modify_images %>
22
+ <div id='upload_image_area' class='dialog_area'<%= " style='display:none;'" if any_images and (no_errors or searching?) %>>
23
+ <%= render :partial => "form", :locals => {:insert => true} %>
24
+ </div>
25
+ <% end %>
26
+ <% else %>
27
+ <% flash.now[:error] = t('no_images_yet', :scope => 'admin.images.index').split('.').first.html_safe + "." %>
28
+ <%= render :partial => "/shared/admin/form_actions",
29
+ :locals => {
30
+ :f => nil,
31
+ :cancel_url => '',
32
+ :hide_cancel => false,
33
+ :hide_delete => true,
34
+ :hide_submit => true,
35
+ :cancel_button_text => t('close', :scope => 'shared.admin.form_actions'),
36
+ :cancel_title => nil
37
+ } %>
38
+ <% end %>
39
+ </div>
40
+
41
+ <% content_for :javascripts do %>
42
+ <script>
43
+ $(document).ready(function(){
44
+ image_dialog.init(<%= @callback.present? ? "self.parent.#{@callback}" : "null" %>);
45
+ });
46
+ </script>
47
+ <% end %>