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.
- data/LICENSE +23 -0
- data/README.md +187 -0
- data/Rakefile +40 -0
- data/app/controllers/admin/markdown_controller.rb +7 -0
- data/app/controllers/admin/resource_controller.rb +222 -0
- data/app/controllers/admin/uploads_controller.rb +34 -0
- data/app/helpers/admin/base_helper_decorator.rb +18 -0
- data/app/models/image_decorator.rb +7 -0
- data/app/models/upload.rb +46 -0
- data/app/validators/datetime_validator.rb +6 -0
- data/app/views/admin/shared/_contents_sub_menu.html.erb +11 -0
- data/app/views/admin/shared/_contents_tab.html.erb +2 -0
- data/app/views/admin/uploads/_form.html.erb +8 -0
- data/app/views/admin/uploads/edit.html.erb +18 -0
- data/app/views/admin/uploads/index.html.erb +50 -0
- data/app/views/admin/uploads/new.html.erb +21 -0
- data/app/views/admin/uploads/picker.html.erb +11 -0
- data/config/locales/en.yml +79 -0
- data/config/routes.rb +10 -0
- data/lib/generators/essentials_base.rb +23 -0
- data/lib/generators/spree_essentials/install_generator.rb +16 -0
- data/lib/generators/templates/db/migrate/add_attachment_file_size_to_assets.rb +9 -0
- data/lib/spree_core/action_callbacks.rb +26 -0
- data/lib/spree_essentials/test_helper.rb +21 -0
- data/lib/spree_essentials/version.rb +3 -0
- data/lib/spree_essentials.rb +52 -0
- data/public/images/admin/icons/pages.png +0 -0
- data/public/images/blog/rss.png +0 -0
- data/public/images/markitup/bg-container.png +0 -0
- data/public/images/markitup/bg-editor.png +0 -0
- data/public/images/markitup/bg-picker.png +0 -0
- data/public/images/markitup/bold.png +0 -0
- data/public/images/markitup/code.png +0 -0
- data/public/images/markitup/h1.png +0 -0
- data/public/images/markitup/h2.png +0 -0
- data/public/images/markitup/h3.png +0 -0
- data/public/images/markitup/h4.png +0 -0
- data/public/images/markitup/h5.png +0 -0
- data/public/images/markitup/h6.png +0 -0
- data/public/images/markitup/handle.png +0 -0
- data/public/images/markitup/image-picker.png +0 -0
- data/public/images/markitup/italic.png +0 -0
- data/public/images/markitup/link.png +0 -0
- data/public/images/markitup/list-bullet.png +0 -0
- data/public/images/markitup/list-numeric.png +0 -0
- data/public/images/markitup/menu.png +0 -0
- data/public/images/markitup/more-tag.png +0 -0
- data/public/images/markitup/picture.png +0 -0
- data/public/images/markitup/preview.png +0 -0
- data/public/images/markitup/quotes.png +0 -0
- data/public/images/markitup/submenu.png +0 -0
- data/public/javascripts/date.js +145 -0
- data/public/javascripts/jquery.autodate.js +112 -0
- data/public/javascripts/jquery.markitup.js +574 -0
- data/public/javascripts/markdown.set.js +95 -0
- data/public/stylesheets/essentials.css +35 -0
- data/public/stylesheets/markitup.css +278 -0
- 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,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
|
+
" ",
|
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,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,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
|
+
|
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 %>
|