spree_essentials 0.1.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. data/LICENSE +23 -0
  2. data/README.md +187 -0
  3. data/Rakefile +40 -0
  4. data/app/controllers/admin/markdown_controller.rb +7 -0
  5. data/app/controllers/admin/resource_controller.rb +222 -0
  6. data/app/controllers/admin/uploads_controller.rb +34 -0
  7. data/app/helpers/admin/base_helper_decorator.rb +18 -0
  8. data/app/models/image_decorator.rb +7 -0
  9. data/app/models/upload.rb +46 -0
  10. data/app/validators/datetime_validator.rb +6 -0
  11. data/app/views/admin/shared/_contents_sub_menu.html.erb +11 -0
  12. data/app/views/admin/shared/_contents_tab.html.erb +2 -0
  13. data/app/views/admin/uploads/_form.html.erb +8 -0
  14. data/app/views/admin/uploads/edit.html.erb +18 -0
  15. data/app/views/admin/uploads/index.html.erb +50 -0
  16. data/app/views/admin/uploads/new.html.erb +21 -0
  17. data/app/views/admin/uploads/picker.html.erb +11 -0
  18. data/config/locales/en.yml +79 -0
  19. data/config/routes.rb +10 -0
  20. data/lib/generators/essentials_base.rb +23 -0
  21. data/lib/generators/spree_essentials/install_generator.rb +16 -0
  22. data/lib/generators/templates/db/migrate/add_attachment_file_size_to_assets.rb +9 -0
  23. data/lib/spree_core/action_callbacks.rb +26 -0
  24. data/lib/spree_essentials/test_helper.rb +21 -0
  25. data/lib/spree_essentials/version.rb +3 -0
  26. data/lib/spree_essentials.rb +52 -0
  27. data/public/images/admin/icons/pages.png +0 -0
  28. data/public/images/blog/rss.png +0 -0
  29. data/public/images/markitup/bg-container.png +0 -0
  30. data/public/images/markitup/bg-editor.png +0 -0
  31. data/public/images/markitup/bg-picker.png +0 -0
  32. data/public/images/markitup/bold.png +0 -0
  33. data/public/images/markitup/code.png +0 -0
  34. data/public/images/markitup/h1.png +0 -0
  35. data/public/images/markitup/h2.png +0 -0
  36. data/public/images/markitup/h3.png +0 -0
  37. data/public/images/markitup/h4.png +0 -0
  38. data/public/images/markitup/h5.png +0 -0
  39. data/public/images/markitup/h6.png +0 -0
  40. data/public/images/markitup/handle.png +0 -0
  41. data/public/images/markitup/image-picker.png +0 -0
  42. data/public/images/markitup/italic.png +0 -0
  43. data/public/images/markitup/link.png +0 -0
  44. data/public/images/markitup/list-bullet.png +0 -0
  45. data/public/images/markitup/list-numeric.png +0 -0
  46. data/public/images/markitup/menu.png +0 -0
  47. data/public/images/markitup/more-tag.png +0 -0
  48. data/public/images/markitup/picture.png +0 -0
  49. data/public/images/markitup/preview.png +0 -0
  50. data/public/images/markitup/quotes.png +0 -0
  51. data/public/images/markitup/submenu.png +0 -0
  52. data/public/javascripts/date.js +145 -0
  53. data/public/javascripts/jquery.autodate.js +112 -0
  54. data/public/javascripts/jquery.markitup.js +574 -0
  55. data/public/javascripts/markdown.set.js +95 -0
  56. data/public/stylesheets/essentials.css +35 -0
  57. data/public/stylesheets/markitup.css +278 -0
  58. metadata +245 -0
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Redistribution and use in source and binary forms, with or without modification,
2
+ are permitted provided that the following conditions are met:
3
+
4
+ * Redistributions of source code must retain the above copyright notice,
5
+ this list of conditions and the following disclaimer.
6
+ * Redistributions in binary form must reproduce the above copyright notice,
7
+ this list of conditions and the following disclaimer in the documentation
8
+ and/or other materials provided with the distribution.
9
+ * Neither the name of the Rails Dog LLC nor the names of its
10
+ contributors may be used to endorse or promote products derived from this
11
+ software without specific prior written permission.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,187 @@
1
+ Spree Essentials
2
+ ================
3
+
4
+ Spree Essentials is the base for many content related extensions for Spree. It doesn't do much on it's own ;)
5
+
6
+ Spree Essentials provides other extensions with:
7
+
8
+ * An easy markdown editor with ajax preview
9
+ * Image picker for embedding images into markdown editor
10
+
11
+ Current essential-aware extensions include:
12
+
13
+ * [spree_essential_cms](https://github.com/citrus/spree_essential_cms): A full featured CMS with pages, contents, images and more
14
+ * [spree_essential_blog](https://github.com/citrus/spree_essential_blog): A blog complete with archives, tags and related products
15
+ * [spree_essential_news](https://github.com/citrus/spree_essential_news): A news system, also complete with archives, tags and related products. (yes it's pretty much the exact same thing as the blog)
16
+ * [spree_essential_press](https://github.com/citrus/spree_essential_press): A simple press page for displaying media related content.
17
+
18
+
19
+
20
+ **ALL OF THESE UNDER DEVELOPMENT**
21
+
22
+
23
+
24
+ Installation
25
+ ------------
26
+
27
+ If you don't already have an existing Spree site, [click here](https://gist.github.com/946719) then come back later... You can also read the Spree docs [here](http://spreecommerce.com/documentation/getting_started.html)...
28
+
29
+ Spree Essentials hasn't been released to rubygems so you'll have to install it from the source. Just add the following to your Gemfile:
30
+
31
+ gem 'spree_essentials', :git => 'git://github.com/citrus/spree_essentials.git'
32
+
33
+ # Add any of the extensions you wish to use
34
+
35
+ gem 'spree_essential_cms', :git => 'git://github.com/citrus/spree_essential_cms.git'
36
+ gem 'spree_essential_blog', :git => 'git://github.com/citrus/spree_essential_blog.git'
37
+
38
+
39
+
40
+ Then run:
41
+
42
+ bundle install
43
+
44
+
45
+ Once that's complete, run the migration generator and migrate your database:
46
+
47
+ To see your available generators run
48
+
49
+ rails g
50
+
51
+
52
+ Now run the generators for extensions you wish to install
53
+
54
+ rails g spree_essentials:install
55
+ rails g spree_essentials:cms
56
+ rails g spree_essentials:blog
57
+
58
+
59
+ Then migrate your database:
60
+ rake db:migrate
61
+
62
+
63
+ If that all went smoothly, you should be ready to boot the server with:
64
+
65
+ rails s
66
+
67
+
68
+ Now login to the admin and click on the 'Content' tab!
69
+
70
+
71
+
72
+ Essential Awareness
73
+ -------------------
74
+
75
+ Spree Essentials is designed to allow other extensions to reside under it's global 'Content' tab in the admin. [SpreeEssentialPress](https://github.com/citrus/spree_essential_press) is the first of many extensions that can run with or without spree_essentials installed.
76
+
77
+ Setting up an essential aware extension is easy. In your `lib/[extension_name].rb` file, add something like this:
78
+
79
+
80
+ module SpreeEssentialPress
81
+
82
+ def self.tab
83
+ [:press, { :route => :admin_press_index }]
84
+ end
85
+
86
+ def self.sub_tab
87
+ [:press, { :route => :admin_press_index, :label => 'admin.subnav.press', :match_path => '/press' }]
88
+ end
89
+
90
+ def self.independent?
91
+ return true unless defined?(SpreeEssentials)
92
+ !SpreeEssentials.respond_to(:register)
93
+ end
94
+
95
+ end
96
+
97
+ if SpreeEssentialPress.independent?
98
+ require 'spree_essential_press/custom_hooks'
99
+ else
100
+ SpreeEssentials.register :press, SpreeEssentialPress
101
+ end
102
+
103
+
104
+
105
+
106
+ Notes
107
+ -----
108
+
109
+ As I mentioned before, spree_essentials is still being developed... Development is being done on OSX with Ruby 1.9.2 and Spree 0.50.2.
110
+
111
+ Please let me know of any bugs you find or feature requests you'd like to see.
112
+
113
+
114
+ Testing
115
+ -------
116
+
117
+ The test suite is very limited at the moment but can be run like so:
118
+
119
+ git clone git://github.com/citrus/spree_essentials.git
120
+ cd spree_essentials
121
+ bundle install
122
+ rake db:test_prep
123
+ rake
124
+
125
+
126
+ You can also boot spork to run the tests much faster
127
+
128
+ # in one window
129
+ cd spree_essentials
130
+ spork
131
+
132
+ # in another window
133
+ testdrb test/**/*_test.rb
134
+
135
+
136
+
137
+
138
+ To Do
139
+ -----
140
+
141
+ * more tests
142
+ * better documentation
143
+
144
+
145
+
146
+
147
+ Change Log
148
+ ----------
149
+
150
+
151
+ **2011/4/26**
152
+
153
+ * Modularized CMS. It can now be found [here](https://github.com/citrus/spree_essential_cms)
154
+
155
+ **2011/4/12**
156
+
157
+ * Added content contexts for multiple contents per page
158
+ * Namespaced posts into blog/posts
159
+ * Added `<!-- more -->` tag to posts
160
+
161
+
162
+ **2011/4/4**
163
+
164
+ * Added Page Images and starting to remove resource_controller.
165
+
166
+
167
+ **2011/4/3**
168
+
169
+ * Automatically adds [Heroku](http://heroku.com) support when you include [spree_heroku](https://github.com/paxer/spree-heroku) in your Gemfile. Check the [spree_heroku readme](https://github.com/paxer/spree-heroku#readme) for full installation instructions.
170
+ * Creates default content when you create a new page.
171
+
172
+ more in `CHANGELOG.md`
173
+
174
+
175
+ Contributors
176
+ ------------
177
+
178
+ So far it's just me; Spencer Steffen.
179
+
180
+ If you'd like to help out feel free to fork and send me pull requests!
181
+
182
+
183
+
184
+ License
185
+ -------
186
+
187
+ Copyright (c) 2011 Spencer Steffen, released under the New BSD License All rights reserved.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must run `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rake'
10
+ require 'rake/rdoctask'
11
+ require 'rake/testtask'
12
+
13
+ Bundler::GemHelper.install_tasks
14
+
15
+ Rake::TestTask.new(:test) do |t|
16
+ t.libs << 'lib'
17
+ t.libs << 'test'
18
+ t.pattern = 'test/**/*_test.rb'
19
+ t.verbose = false
20
+ end
21
+
22
+ namespace :db do
23
+ desc "preps the test database"
24
+ task :test_prep do
25
+ dir = File.expand_path("../test/dummy/db", __FILE__)
26
+ db = File.join(dir, "test.sqlite3")
27
+ File.delete(db) if File.exists?(db)
28
+ system("cd test/dummy; rake db:migrate RAILS_ENV=test")
29
+ end
30
+ end
31
+
32
+ task :default => :test
33
+
34
+ Rake::RDocTask.new(:rdoc) do |rdoc|
35
+ rdoc.rdoc_dir = 'rdoc'
36
+ rdoc.title = 'SpreeEssentials'
37
+ rdoc.options << '--line-numbers' << '--inline-source'
38
+ rdoc.rdoc_files.include('README.rdoc')
39
+ rdoc.rdoc_files.include('lib/**/*.rb')
40
+ end
@@ -0,0 +1,7 @@
1
+ class Admin::MarkdownController < Admin::BaseController
2
+
3
+ def preview
4
+ render :text => RDiscount.new(params[:data].to_s).to_html
5
+ end
6
+
7
+ end
@@ -0,0 +1,222 @@
1
+ require 'spree_core/action_callbacks'
2
+
3
+ class Admin::ResourceController < Admin::BaseController
4
+ helper_method :new_object_url, :edit_object_url, :object_url, :collection_url
5
+ before_filter :load_resource
6
+
7
+ respond_to :html
8
+
9
+ def new
10
+ render :layout => !request.xhr?
11
+ end
12
+
13
+ def edit
14
+ render :layout => !request.xhr?
15
+ end
16
+
17
+ def update
18
+ invoke_callbacks(:update, :before)
19
+ if @object.update_attributes(params[object_name])
20
+ invoke_callbacks(:update, :after)
21
+ resource_desc = I18n.t(object_name)
22
+ resource_desc += " \"#{@object.name}\"" if @object.respond_to?(:name)
23
+ flash[:notice] = I18n.t(:successfully_updated, :resource => resource_desc)
24
+ respond_to do |format|
25
+ format.html { redirect_to location_after_save }
26
+ format.js { render :layout => false }
27
+ end
28
+ else
29
+ invoke_callbacks(:update, :fails)
30
+ render :edit
31
+ end
32
+ end
33
+
34
+ def create
35
+ invoke_callbacks(:create, :before)
36
+ if @object.save
37
+ invoke_callbacks(:create, :after)
38
+ resource_desc = I18n.t(object_name)
39
+ resource_desc += " \"#{@object.name}\"" if @object.respond_to?(:name)
40
+ flash[:notice] = I18n.t(:successfully_created, :resource => resource_desc)
41
+ respond_to do |format|
42
+ format.html { redirect_to location_after_save }
43
+ format.js { render :layout => false }
44
+ end
45
+ else
46
+ invoke_callbacks(:create, :fails)
47
+ render :new
48
+ end
49
+ end
50
+
51
+ def destroy
52
+ invoke_callbacks(:destroy, :before)
53
+ if @object.destroy
54
+ invoke_callbacks(:destroy, :after)
55
+ resource_desc = I18n.t(object_name)
56
+ resource_desc += " \"#{@object.name}\"" if @object.respond_to?(:name)
57
+ flash[:notice] = I18n.t(:successfully_removed, :resource => resource_desc)
58
+ respond_to do |format|
59
+ format.html { redirect_to collection_url }
60
+ format.js { render :partial => "/admin/shared/destroy" }
61
+ end
62
+ else
63
+ invoke_callbacks(:destroy, :fails)
64
+ redirect_to collection_url
65
+ end
66
+ end
67
+
68
+ protected
69
+
70
+ class << self
71
+ attr_accessor :parent_data
72
+ attr_accessor :callbacks
73
+
74
+ def belongs_to(model_name, options = {})
75
+ @parent_data ||= {}
76
+ @parent_data[:model_name] = model_name
77
+ @parent_data[:model_class] = model_name.to_s.classify.constantize
78
+ @parent_data[:find_by] = options[:find_by] || :id
79
+ end
80
+
81
+ def create
82
+ @callbacks ||= {}
83
+ @callbacks[:create] ||= Spree::ActionCallbacks.new
84
+ end
85
+
86
+ def update
87
+ @callbacks ||= {}
88
+ @callbacks[:update] ||= Spree::ActionCallbacks.new
89
+ end
90
+
91
+ def destroy
92
+ @callbacks ||= {}
93
+ @callbacks[:destroy] ||= Spree::ActionCallbacks.new
94
+ end
95
+ end
96
+
97
+ def model_class
98
+ controller_name.classify.constantize
99
+ end
100
+
101
+ def object_name
102
+ controller_name.singularize
103
+ end
104
+
105
+ def load_resource
106
+ if member_action?
107
+ @object ||= load_resource_instance
108
+ instance_variable_set("@#{object_name}", @object)
109
+ else
110
+ @collection ||= collection
111
+ instance_variable_set("@#{controller_name}", @collection)
112
+ end
113
+ end
114
+
115
+ def load_resource_instance
116
+ if new_actions.include?(params[:action].to_sym)
117
+ build_resource
118
+ elsif params[:id]
119
+ find_resource
120
+ end
121
+ end
122
+
123
+ def parent_data
124
+ self.class.parent_data
125
+ end
126
+
127
+ def parent
128
+ if parent_data.present?
129
+ @parent ||= parent_data[:model_class].where(parent_data[:find_by] => params["#{parent_data[:model_name]}_id"]).first
130
+ instance_variable_set("@#{parent_data[:model_name]}", @parent)
131
+ else
132
+ nil
133
+ end
134
+ end
135
+
136
+ def find_resource
137
+ if parent_data.present?
138
+ parent.send(controller_name).find(params[:id])
139
+ else
140
+ model_class.find(params[:id])
141
+ end
142
+ end
143
+
144
+ def build_resource
145
+ if parent_data.present?
146
+ parent.send(controller_name).build(params[object_name])
147
+ else
148
+ model_class.new(params[object_name])
149
+ end
150
+ end
151
+
152
+ def collection
153
+ return parent.send(controller_name) if parent_data.present?
154
+
155
+ if model_class.respond_to?(:accessible_by) && !current_ability.has_block?(params[:action], model_class)
156
+ model_class.accessible_by(current_ability)
157
+ else
158
+ model_class.scoped
159
+ end
160
+ end
161
+
162
+ def location_after_save
163
+ collection_url
164
+ end
165
+
166
+ def invoke_callbacks(action, callback_type)
167
+ callbacks = self.class.callbacks || {}
168
+ return if callbacks[action].nil?
169
+ case callback_type.to_sym
170
+ when :before then callbacks[action].before_methods.each {|method| send method }
171
+ when :after then callbacks[action].after_methods.each {|method| send method }
172
+ when :fails then callbacks[action].fails_methods.each {|method| send method }
173
+ end
174
+ end
175
+
176
+ # URL helpers
177
+
178
+ def new_object_url(options = {})
179
+ if parent_data.present?
180
+ new_polymorphic_url([:admin, parent, model_class], options)
181
+ else
182
+ new_polymorphic_url([:admin, model_class], options)
183
+ end
184
+ end
185
+
186
+ def edit_object_url(object, options = {})
187
+ if parent_data.present?
188
+ send "edit_admin_#{parent_data[:model_name]}_#{object_name}_url", parent, object, options
189
+ else
190
+ send "edit_admin_#{object_name}_url", object, options
191
+ end
192
+ end
193
+
194
+ def object_url(object = nil, options = {})
195
+ target = object ? object : @object
196
+ if parent_data.present?
197
+ send "admin_#{parent_data[:model_name]}_#{object_name}_url", parent, target, options
198
+ else
199
+ send "admin_#{object_name}_url", target, options
200
+ end
201
+ end
202
+
203
+ def collection_url(options = {})
204
+ if parent_data.present?
205
+ polymorphic_url([:admin, parent, model_class], options)
206
+ else
207
+ polymorphic_url([:admin, model_class], options)
208
+ end
209
+ end
210
+
211
+ def collection_actions
212
+ [:index]
213
+ end
214
+
215
+ def member_action?
216
+ !collection_actions.include? params[:action].to_sym
217
+ end
218
+
219
+ def new_actions
220
+ [:new, :create]
221
+ end
222
+ end
@@ -0,0 +1,34 @@
1
+ class Admin::UploadsController < Admin::BaseController
2
+
3
+ resource_controller
4
+
5
+ index.response do |wants|
6
+ wants.html { render :template => request.xhr? ? 'admin/uploads/picker' : 'admin/uploads/index', :layout => !request.xhr? }
7
+ end
8
+
9
+ new_action.response do |wants|
10
+ wants.html {
11
+ render :action => :new, :layout => false
12
+ }
13
+ end
14
+
15
+ create.response do |wants|
16
+ wants.html {redirect_to admin_uploads_path}
17
+ end
18
+
19
+ update.response do |wants|
20
+ wants.html { redirect_to collection_url }
21
+ end
22
+
23
+ destroy.success.wants.js { render_js_for_destroy }
24
+
25
+ private
26
+
27
+ def collection
28
+ params[:search] ||= {}
29
+ params[:search][:meta_sort] ||= "posted_at.desc"
30
+ @search = end_of_association_chain.metasearch(params[:search])
31
+ @collection = @search.paginate(:per_page => Spree::Config[:orders_per_page], :page => params[:page])
32
+ end
33
+
34
+ end
@@ -0,0 +1,18 @@
1
+ Spree::BaseHelper.class_eval do
2
+
3
+ def markdown_helper
4
+ content_tag('em', :class => 'small') do
5
+ [
6
+ "&nbsp;",
7
+ t('essentials.parsed_with'),
8
+ link_to("Markdown", "http://daringfireball.net/projects/markdown/basics", :onclick => 'window.open(this.href); return false')
9
+ ].join(" ").html_safe
10
+ end
11
+ end
12
+
13
+ def method_missing(method, *args, &block)
14
+ return super unless method.to_s =~ /_path$/
15
+ "/" + method.to_s.sub(/_path$/, '').gsub('_', '-')
16
+ end
17
+
18
+ end
@@ -0,0 +1,7 @@
1
+ Image.class_eval do
2
+
3
+ def has_alt?
4
+ !alt.blank?
5
+ end
6
+
7
+ end
@@ -0,0 +1,46 @@
1
+ class Upload < Asset
2
+
3
+ default_scope where(:type => "Upload")
4
+
5
+ validate :no_attachement_errors
6
+
7
+ # Check for spree_heroku
8
+ # https://github.com/paxer/spree-heroku
9
+ #
10
+ if defined?(SpreeHeroku)
11
+ has_attached_file :attachment,
12
+ :styles => Proc.new{ |clip| clip.instance.attachment_sizes },
13
+ :default_style => :medium,
14
+ :path => "assets/uploads/:id/:style/:basename.:extension",
15
+ :storage => "s3",
16
+ :s3_credentials => "#{Rails.root}/config/s3.yml"
17
+ else
18
+ has_attached_file :attachment,
19
+ :styles => Proc.new{ |clip| clip.instance.attachment_sizes },
20
+ :default_style => :medium,
21
+ :url => "/assets/uploads/:id/:style/:basename.:extension",
22
+ :path => ":rails_root/public/assets/uploads/:id/:style/:basename.:extension"
23
+ end
24
+
25
+ def image_content?
26
+ attachment_content_type.match(/\/(jpeg|png|gif|tiff|x-photoshop)/)
27
+ end
28
+
29
+ def attachment_sizes
30
+ if image_content?
31
+ { :mini => '48x48>', :small => '150x150>', :medium => '420x300>', :large => '800x500>' }
32
+ else
33
+ {}
34
+ end
35
+ end
36
+
37
+ def no_attachement_errors
38
+ if attachment_file_name.blank? || !attachment.errors.empty?
39
+ # uncomment this to get rid of the less-than-useful interrim messages
40
+ errors.clear
41
+ errors.add :attachment, "Paperclip returned errors for file '#{attachment_file_name}' - check ImageMagick installation or image source file."
42
+ false
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,6 @@
1
+ class DatetimeValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ date = DateTime.parse(value.to_s) rescue ArgumentError
4
+ record.errors.add(attribute, I18n.t(:invalid_date_time, :scope => [:activerecord, :errors, :messages])) if date == ArgumentError
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ <% content_for :sub_menu do %>
2
+ <ul id="sub_nav">
3
+ <%= hook :admin_contents_sub_tabs do %>
4
+ <%= tab :pages, :label => 'admin.subnav.pages', :match_path => '/pages' %>
5
+ <% SpreeEssentials.essentials.each do |cls| %>
6
+ <%= tab *cls.sub_tab if defined?(cls.sub_tab) %>
7
+ <% end %>
8
+ <%= tab :uploads, :label => 'admin.subnav.uploads' %>
9
+ <% end %>
10
+ </ul>
11
+ <% end %>
@@ -0,0 +1,2 @@
1
+ <%= tab *[:pages, :contents, SpreeEssentials.essentials.map{|cls| cls.tab if defined?(cls.tab) }, :uploads, { :label => '.content' }].flatten %>
2
+
@@ -0,0 +1,8 @@
1
+ <p>
2
+ <%= form.label :attachment %>:<br/>
3
+ <%= form.file_field :attachment %>
4
+ </p>
5
+ <p>
6
+ <%= form.label :alt, t('description') %>:<br/>
7
+ <%= form.text_field :alt %>
8
+ </p>
@@ -0,0 +1,18 @@
1
+ <%= render :partial => 'admin/shared/contents_sub_menu' %>
2
+
3
+ <% if @upload.try(:errors).present? %>
4
+ <%= render 'shared/error_messages', :target => @upload %>
5
+ <% end %>
6
+
7
+ <% form_for([:admin, @upload], :url => admin_upload_url(@upload), :html => { :multipart => true }) do |f| %>
8
+ <p>
9
+ <%= label_tag ("thumbnail") %>:<br/>
10
+ <%= link_to(image_tag(@upload.attachment.url(:mini)), @upload.attachment.url(:product)) %>
11
+ </p>
12
+ <%= render "form", :form => f %>
13
+ </table>
14
+ <p class="form-buttons">
15
+ <%= button t("update") %>
16
+ or <%= link_to t("cancel"), admin_uploads_url, :id => "cancel_link" %>
17
+ </p>
18
+ <% end %>
@@ -0,0 +1,50 @@
1
+ <%= render :partial => 'admin/shared/contents_sub_menu' %>
2
+
3
+ <table class="index">
4
+ <tr>
5
+ <th><%= t("thumbnail") %></th>
6
+ <th><%= sort_link @search, :attachment_file_name, t("upload.file_name") %></th>
7
+ <th><%= sort_link @search, :description, t("description") %></th>
8
+ <th><%= sort_link @search, :attachment_file_size, t("upload.size") %></th>
9
+ <th><%= t("action") %></th>
10
+ </tr>
11
+
12
+ <% @uploads.each do |upload| %>
13
+ <tr id="<%= dom_id(upload) %>">
14
+ <td class="thumbnail">
15
+ <% if upload.image_content? %>
16
+ <%= link_to image_tag(upload.attachment.url(:mini)), upload.attachment.url(:large) %>
17
+ <% end %>
18
+ </td>
19
+ <td><%= link_to upload.attachment_file_name, upload.attachment.url(:original) %></td>
20
+ <td><%= upload.alt %></td>
21
+ <td><%= upload.attachment_file_size.to_i / 1024 %> kb</td>
22
+ <td class="actions">
23
+ <%= link_to_with_icon('edit', t("edit"), edit_admin_upload_url(upload)) %>
24
+ &nbsp;
25
+ <%= link_to_delete upload, {:url => admin_upload_url(upload) }%>
26
+ </td>
27
+ </tr>
28
+ <% end %>
29
+
30
+ </table>
31
+
32
+ <div id="images"></div>
33
+ <br/>
34
+ <p>
35
+ <%= link_to icon('add') + ' ' + t(".new_upload"), new_admin_upload_url, :id => "new_image_link" %>
36
+ </p>
37
+
38
+ <% content_for :head do %>
39
+ <script type="text/javascript">
40
+ jQuery(document).ready(function(){
41
+
42
+ jQuery('#new_image_link').click(function(event) {
43
+ event.preventDefault();
44
+ jQuery(this).hide();
45
+ jQuery.ajax({type: 'GET', url: this.href, data: ({authenticity_token: AUTH_TOKEN}), success: function(r){ jQuery('#images').html(r);} });
46
+ });
47
+
48
+ });
49
+ </script>
50
+ <% end %>