spree_essential_cms 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +23 -0
- data/README.md +78 -0
- data/Rakefile +21 -0
- data/app/controllers/admin/contents_controller.rb +41 -0
- data/app/controllers/admin/page_images_controller.rb +37 -0
- data/app/controllers/admin/pages_controller.rb +38 -0
- data/app/controllers/page_controller.rb +19 -0
- data/app/controllers/pages_controller.rb +28 -0
- data/app/controllers/spree_base_controller_decorator.rb +11 -0
- data/app/models/content.rb +82 -0
- data/app/models/page.rb +61 -0
- data/app/models/page_image.rb +40 -0
- data/app/views/admin/contents/_form.html.erb +74 -0
- data/app/views/admin/contents/edit.html.erb +16 -0
- data/app/views/admin/contents/index.html.erb +59 -0
- data/app/views/admin/contents/new.html.erb +18 -0
- data/app/views/admin/contents/show.html.erb +11 -0
- data/app/views/admin/page_images/_form.html.erb +8 -0
- data/app/views/admin/page_images/edit.html.erb +20 -0
- data/app/views/admin/page_images/index.html.erb +42 -0
- data/app/views/admin/page_images/new.html.erb +20 -0
- data/app/views/admin/pages/_form.html.erb +73 -0
- data/app/views/admin/pages/edit.html.erb +14 -0
- data/app/views/admin/pages/index.html.erb +62 -0
- data/app/views/admin/pages/new.html.erb +16 -0
- data/app/views/admin/pages/show.html.erb +23 -0
- data/app/views/admin/shared/_page_tabs.html.erb +23 -0
- data/app/views/pages/home.html.erb +28 -0
- data/app/views/pages/show.html.erb +3 -0
- data/app/views/shared/_content.html.erb +33 -0
- data/app/views/shared/_main_menu.html.erb +7 -0
- data/app/views/shared/_slideshow.html.erb +8 -0
- data/config/locales/en.yml +55 -0
- data/config/routes.rb +38 -0
- data/lib/dummy_hooks/after_migrate.rb +1 -0
- data/lib/dummy_hooks/after_migrate.rb.sample +1 -0
- data/lib/dummy_hooks/before_migrate.rb +6 -0
- data/lib/generators/essentials_base.rb +23 -0
- data/lib/generators/spree_essentials/cms_generator.rb +17 -0
- data/lib/generators/templates/db/migrate/create_contents.rb +27 -0
- data/lib/generators/templates/db/migrate/create_pages.rb +24 -0
- data/lib/spree_essential_cms/version.rb +3 -0
- data/lib/spree_essential_cms.rb +43 -0
- metadata +236 -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,78 @@
|
|
1
|
+
SpreeEssentialCms
|
2
|
+
=================
|
3
|
+
|
4
|
+
SpreeEssentialCms is a full featured CMS for managing pages and content on your [Spree](http://spreecommerce.com) site.
|
5
|
+
|
6
|
+
|
7
|
+
Installation
|
8
|
+
------------
|
9
|
+
|
10
|
+
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)...
|
11
|
+
|
12
|
+
Otherwise, follow these steps to get up and running with SpreeEssentialCms:
|
13
|
+
|
14
|
+
Add the necessary gems to your Gemfile... they haven't been released to Rubygems yet so we'll grab them from git.
|
15
|
+
|
16
|
+
gem 'spree_essentials', :git => 'git://github.com/citrus/spree_essentials.git'
|
17
|
+
gem 'spree_essential_cms', :git => 'git://github.com/citrus/spree_essential_cms.git'
|
18
|
+
|
19
|
+
Run the generators to create the migration files.
|
20
|
+
|
21
|
+
rails g spree_essentials:install
|
22
|
+
rails g spree_essentials:cms
|
23
|
+
|
24
|
+
Now migrate your database...
|
25
|
+
|
26
|
+
rake db:migrate
|
27
|
+
|
28
|
+
Boot your server and checkout the admin!
|
29
|
+
|
30
|
+
rails s
|
31
|
+
|
32
|
+
|
33
|
+
Demo
|
34
|
+
----
|
35
|
+
|
36
|
+
You can easily use the test/dummy app as a demo of spree_essential_cms. Just `cd` to where you develop and run:
|
37
|
+
|
38
|
+
git clone git://github.com/citrus/spree_essential_cms.git
|
39
|
+
cd spree_essential_cms
|
40
|
+
mv lib/dummy_hooks/after_migrate.rb.sample lib/dummy_hooks/after_migrate.rb
|
41
|
+
bundle install
|
42
|
+
bundle exec dummier
|
43
|
+
cd test/dummy
|
44
|
+
rails s
|
45
|
+
|
46
|
+
|
47
|
+
Change Log
|
48
|
+
----------
|
49
|
+
|
50
|
+
**2011/4/26**
|
51
|
+
|
52
|
+
* Extracted from the Spree Essentials core.
|
53
|
+
|
54
|
+
|
55
|
+
To Do
|
56
|
+
-----
|
57
|
+
|
58
|
+
* more tests... many many more.
|
59
|
+
* A 'create translation' button that clones the current page's contents into another language
|
60
|
+
* add widgets that you can drop into any page
|
61
|
+
* page and menu caching/sweeping
|
62
|
+
* nested set for pages
|
63
|
+
* 0.30 and 0.40 compatibility
|
64
|
+
* create wiki pages
|
65
|
+
|
66
|
+
|
67
|
+
Contributors
|
68
|
+
------------
|
69
|
+
|
70
|
+
So far it's just me; Spencer Steffen.
|
71
|
+
|
72
|
+
If you'd like to help out feel free to fork and send me pull requests!
|
73
|
+
|
74
|
+
|
75
|
+
License
|
76
|
+
-------
|
77
|
+
|
78
|
+
Copyright (c) 2011 Spencer Steffen, released under the New BSD License All rights reserved.
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
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/testtask'
|
11
|
+
|
12
|
+
Bundler::GemHelper.install_tasks
|
13
|
+
|
14
|
+
Rake::TestTask.new(:test) do |t|
|
15
|
+
t.libs << 'lib'
|
16
|
+
t.libs << 'test'
|
17
|
+
t.pattern = 'test/**/*_test.rb'
|
18
|
+
t.verbose = false
|
19
|
+
end
|
20
|
+
|
21
|
+
task :default => :test
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Admin::ContentsController < Admin::BaseController
|
2
|
+
|
3
|
+
resource_controller
|
4
|
+
belongs_to :page
|
5
|
+
|
6
|
+
create.response do |wants|
|
7
|
+
wants.html { redirect_to collection_url }
|
8
|
+
end
|
9
|
+
|
10
|
+
update.response do |wants|
|
11
|
+
wants.html { redirect_to collection_url }
|
12
|
+
end
|
13
|
+
|
14
|
+
def update_positions
|
15
|
+
@page = parent_object
|
16
|
+
params[:positions].each do |id, index|
|
17
|
+
@page.contents.update_all(['position=?', index], ['id=?', id])
|
18
|
+
end
|
19
|
+
|
20
|
+
respond_to do |format|
|
21
|
+
format.html { redirect_to admin_page_contents_url(@oage) }
|
22
|
+
format.js { render :text => 'Ok' }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
destroy.success.wants.js { render_js_for_destroy }
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def parent_object
|
31
|
+
@page ||= Page.find_by_path(params[:page_id])
|
32
|
+
end
|
33
|
+
|
34
|
+
def collection
|
35
|
+
params[:search] ||= {}
|
36
|
+
params[:search][:meta_sort] ||= "page.asc"
|
37
|
+
@search = end_of_association_chain.metasearch(params[:search])
|
38
|
+
@collection = @search.paginate(:per_page => Spree::Config[:orders_per_page], :page => params[:page])
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Admin::PageImagesController < Admin::ResourceController
|
2
|
+
|
3
|
+
before_filter :load_data
|
4
|
+
|
5
|
+
create.before :set_viewable
|
6
|
+
update.before :set_viewable
|
7
|
+
destroy.before :destroy_before
|
8
|
+
|
9
|
+
def update_positions
|
10
|
+
params[:positions].each do |id, index|
|
11
|
+
PageImage.update_all(['position=?', index], ['id=?', id])
|
12
|
+
end
|
13
|
+
|
14
|
+
respond_to do |format|
|
15
|
+
format.js { render :text => 'Ok' }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def location_after_save
|
22
|
+
admin_page_images_url(@page)
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_data
|
26
|
+
@page = Page.find_by_path(params[:page_id])
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_viewable
|
30
|
+
@page_image.viewable = @page
|
31
|
+
end
|
32
|
+
|
33
|
+
def destroy_before
|
34
|
+
@viewable = @page_image.viewable
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Admin::PagesController < Admin::BaseController
|
2
|
+
resource_controller
|
3
|
+
|
4
|
+
create.response do |wants|
|
5
|
+
wants.html { redirect_to edit_admin_page_content_path(@page, @page.contents.first) }
|
6
|
+
end
|
7
|
+
|
8
|
+
update.response do |wants|
|
9
|
+
wants.html { redirect_to object_url }
|
10
|
+
end
|
11
|
+
|
12
|
+
destroy.success.wants.js { render_js_for_destroy }
|
13
|
+
|
14
|
+
def update_positions
|
15
|
+
params[:positions].each do |id, index|
|
16
|
+
Page.update_all(['position=?', index], ['id=?', id])
|
17
|
+
end
|
18
|
+
|
19
|
+
respond_to do |format|
|
20
|
+
format.html { redirect_to admin_pages_url }
|
21
|
+
format.js { render :text => 'Ok' }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def object
|
28
|
+
@object ||= Page.find_by_path(params[:id])
|
29
|
+
end
|
30
|
+
|
31
|
+
def collection
|
32
|
+
params[:search] ||= {}
|
33
|
+
params[:search][:meta_sort] ||= "page.asc"
|
34
|
+
@search = end_of_association_chain.metasearch(params[:search])
|
35
|
+
@collection = @search.order(:position).paginate(:per_page => Spree::Config[:orders_per_page], :page => params[:page])
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class PageController < ApplicationController
|
2
|
+
|
3
|
+
before_filter :get_page, :only => :index
|
4
|
+
|
5
|
+
def show
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def get_page
|
11
|
+
@page = Page.active.find_by_path(page_path)
|
12
|
+
return raise ActionController::RoutingError.new(page_path) unless @page
|
13
|
+
end
|
14
|
+
|
15
|
+
def page_path
|
16
|
+
params[:path] || "/"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class PagesController < ApplicationController
|
2
|
+
|
3
|
+
before_filter :get_page, :only => :show
|
4
|
+
|
5
|
+
def show
|
6
|
+
if @page.root?
|
7
|
+
@posts = Post.live.limit(5) if SpreeEssentials.has?(:blog)
|
8
|
+
@articles = Article.live.limit(5) if SpreeEssentials.has?(:news)
|
9
|
+
render :template => 'pages/home'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def get_page
|
16
|
+
@page = Page.active.find_by_path(page_path) rescue nil
|
17
|
+
return raise ActionController::RoutingError.new(page_path) unless @page
|
18
|
+
end
|
19
|
+
|
20
|
+
def page_path
|
21
|
+
params[:page_path] || "/"
|
22
|
+
end
|
23
|
+
|
24
|
+
def accurate_title
|
25
|
+
@page.meta_title
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
class Content < ActiveRecord::Base
|
2
|
+
|
3
|
+
belongs_to :page
|
4
|
+
validates_associated :page
|
5
|
+
validates_presence_of :title
|
6
|
+
|
7
|
+
|
8
|
+
if defined?(SpreeHeroku)
|
9
|
+
has_attached_file :attachment,
|
10
|
+
:styles => Proc.new{ |clip| clip.instance.attachment_sizes },
|
11
|
+
:default_style => :preview,
|
12
|
+
:path => "assets/contents/:id/:style/:basename.:extension",
|
13
|
+
:storage => "s3",
|
14
|
+
:s3_credentials => "#{Rails.root}/config/s3.yml"
|
15
|
+
else
|
16
|
+
has_attached_file :attachment,
|
17
|
+
:styles => Proc.new{ |clip| clip.instance.attachment_sizes },
|
18
|
+
:default_style => :preview,
|
19
|
+
:url => "/assets/contents/:id/:style/:basename.:extension",
|
20
|
+
:path => ":rails_root/public/assets/contents/:id/:style/:basename.:extension"
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
cattr_reader :per_page
|
25
|
+
@@per_page = 10
|
26
|
+
|
27
|
+
|
28
|
+
scope :for, Proc.new{|context| where(:context => context)}
|
29
|
+
|
30
|
+
|
31
|
+
[ :link_text, :link, :body ].each do |property|
|
32
|
+
define_method "has_#{property.to_s}?" do
|
33
|
+
has_value property
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def has_full_link?
|
38
|
+
has_link? && has_link_text?
|
39
|
+
end
|
40
|
+
|
41
|
+
def has_image?
|
42
|
+
has_value(:attachment_file_name) && attachment_file_name.match(/gif|jpg|png/i)
|
43
|
+
end
|
44
|
+
|
45
|
+
def hide_title?
|
46
|
+
self.hide_title == true
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def rendered_body
|
51
|
+
RDiscount.new(body.to_s).to_html.html_safe
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def default_attachment_sizes
|
56
|
+
{ :mini => '48x48>', :medium => '427x287>' }
|
57
|
+
end
|
58
|
+
|
59
|
+
def attachment_sizes
|
60
|
+
case self.context
|
61
|
+
when 'slideshow'
|
62
|
+
sizes = default_attachment_sizes.merge(:slide => '955x476#')
|
63
|
+
else
|
64
|
+
sizes = default_attachment_sizes
|
65
|
+
end
|
66
|
+
sizes
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
def context=(value)
|
72
|
+
write_attribute :context, value.to_s.parameterize
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def has_value(selector)
|
78
|
+
v = self.send selector
|
79
|
+
v && !v.to_s.blank?
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
data/app/models/page.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
class Page < ActiveRecord::Base
|
2
|
+
|
3
|
+
validates_presence_of :title
|
4
|
+
validates :path, :presence => true, :uniqueness => { :case_sensitive => false }
|
5
|
+
|
6
|
+
scope :active, where(:accessible => true)
|
7
|
+
scope :visible, active.where(:visible => true)
|
8
|
+
|
9
|
+
has_many :contents, :order => :position, :dependent => :destroy
|
10
|
+
has_many :images, :as => :viewable, :class_name => 'PageImage', :order => :position, :dependent => :destroy
|
11
|
+
|
12
|
+
before_validation :set_defaults
|
13
|
+
after_create :create_default_content
|
14
|
+
|
15
|
+
def self.find_by_path(_path)
|
16
|
+
return super("/") if _path == 'home'
|
17
|
+
super(_path.to_s.sub(/^\/?/, '/').gsub('--', '/'))
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_param
|
21
|
+
return 'home' if path == '/'
|
22
|
+
path.sub(/^\//, '').gsub('/', '--')
|
23
|
+
end
|
24
|
+
|
25
|
+
def meta_title
|
26
|
+
val = read_attribute(:meta_title)
|
27
|
+
val.blank? ? title : val
|
28
|
+
end
|
29
|
+
|
30
|
+
def for_context(context)
|
31
|
+
contents.where(:context => context)
|
32
|
+
end
|
33
|
+
|
34
|
+
def has_context?(context)
|
35
|
+
contents.where(:context => context).count
|
36
|
+
end
|
37
|
+
|
38
|
+
def matches?(_path)
|
39
|
+
(root? && _path == "/") || (!root? && _path.match(path))
|
40
|
+
end
|
41
|
+
|
42
|
+
def root?
|
43
|
+
self.path == "/"
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def set_defaults
|
49
|
+
return if title.blank?
|
50
|
+
return errors.add(:path, "is reserved. Please use another") if path.to_s =~ /home/
|
51
|
+
self.nav_title = title if nav_title.blank?
|
52
|
+
self.path = nav_title.parameterize if path.blank?
|
53
|
+
self.path = "/" + path.sub(/^\//, '')
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_default_content
|
57
|
+
self.contents.create(:title => title)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class PageImage < Image
|
2
|
+
|
3
|
+
validate :no_attachement_errors
|
4
|
+
|
5
|
+
if defined?(SpreeHeroku)
|
6
|
+
has_attached_file :attachment,
|
7
|
+
:styles => Proc.new{ |clip| clip.instance.attachment_sizes },
|
8
|
+
:default_style => :medium,
|
9
|
+
:path => "assets/posts/:id/:style/:basename.:extension",
|
10
|
+
:storage => "s3",
|
11
|
+
:s3_credentials => "#{Rails.root}/config/s3.yml"
|
12
|
+
else
|
13
|
+
has_attached_file :attachment,
|
14
|
+
:styles => Proc.new{ |clip| clip.instance.attachment_sizes },
|
15
|
+
:default_style => :medium,
|
16
|
+
:url => "/assets/posts/:id/:style/:basename.:extension",
|
17
|
+
:path => ":rails_root/public/assets/posts/:id/:style/:basename.:extension"
|
18
|
+
end
|
19
|
+
|
20
|
+
def image_content?
|
21
|
+
attachment_content_type.match(/\/(jpeg|png|gif|tiff|x-photoshop)/)
|
22
|
+
end
|
23
|
+
|
24
|
+
def attachment_sizes
|
25
|
+
sizes = {}
|
26
|
+
sizes.merge!(:mini => '48x48>', :small => '150x150>', :medium => '420x300>', :large => '900x650>') if image_content?
|
27
|
+
sizes.merge!(:slide => '950x250#') if viewable.respond_to?(:path) && viewable.path == "/"
|
28
|
+
sizes
|
29
|
+
end
|
30
|
+
|
31
|
+
def no_attachement_errors
|
32
|
+
unless attachment.errors.empty?
|
33
|
+
# uncomment this to get rid of the less-than-useful interrim messages
|
34
|
+
errors.clear
|
35
|
+
errors.add :attachment, "Paperclip returned errors for file '#{attachment_file_name}' - check ImageMagick installation or image source file."
|
36
|
+
false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
<%= form.field_container :title do %>
|
2
|
+
<%= form.label :title, t('content.title') %><br />
|
3
|
+
<%= form.text_field :title, :class => "title" %>
|
4
|
+
<%= error_message_on :content, :title %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<%= form.field_container :page do %>
|
8
|
+
<%= form.label :page_id, t('content.page') %><br />
|
9
|
+
<%= form.select :page_id, @pages.collect{|i| [i.title, i.id]} %>
|
10
|
+
<%= error_message_on :content, :page_id %>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<%= form.field_container :body do %>
|
14
|
+
<%= form.label :title, t('content.body') %><%= markdown_helper %><br />
|
15
|
+
<%= form.text_area :body %>
|
16
|
+
<%= error_message_on :content, :body %>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<p><%= link_to "Optional Fields <span>▲</span>".html_safe, "#options", :id => "btn_optional" %></p>
|
20
|
+
|
21
|
+
<div class="optional" style="display: none;">
|
22
|
+
|
23
|
+
<%= form.field_container :attachment do %>
|
24
|
+
<%= form.label :attachment, t('content.attachment') %><br />
|
25
|
+
<%= form.file_field :attachment %>
|
26
|
+
<%= error_message_on :content, :attachment %>
|
27
|
+
<% end %>
|
28
|
+
|
29
|
+
<% if @content.has_image? %>
|
30
|
+
<p><%= image_tag @content.attachment.url(:mini) %></p>
|
31
|
+
<% end %>
|
32
|
+
|
33
|
+
<%= form.field_container :link do %>
|
34
|
+
<%= form.label :link, t('content.link') %><br />
|
35
|
+
<%= form.text_field :link, :class => "text" %>
|
36
|
+
<%= error_message_on :content, :link %>
|
37
|
+
<% end %>
|
38
|
+
|
39
|
+
<%= form.field_container :link_text do %>
|
40
|
+
<%= form.label :link_text, t('content.link_text') %><br />
|
41
|
+
<%= form.text_field :link_text, :class => "text" %>
|
42
|
+
<%= error_message_on :content, :link_text %>
|
43
|
+
<% end %>
|
44
|
+
|
45
|
+
<%= form.field_container :context do %>
|
46
|
+
<%= form.label :context, t('content.context') %><br />
|
47
|
+
<%= form.text_field :context, :class => "text" %>
|
48
|
+
<%= error_message_on :content, :context %>
|
49
|
+
<% end %>
|
50
|
+
|
51
|
+
<%= form.field_container :hide_title do %>
|
52
|
+
<%= form.check_box :hide_title, :class => "checkbox" %>
|
53
|
+
<%= form.label :hide_title, t('content.hide_title') %><br />
|
54
|
+
<%= error_message_on :content, :hide_title %>
|
55
|
+
<% end %>
|
56
|
+
|
57
|
+
</div>
|
58
|
+
|
59
|
+
<% content_for :head do %>
|
60
|
+
<%= stylesheet_link_tag "markitup.css" %>
|
61
|
+
<%= javascript_include_tag 'jquery.markitup.js', 'markdown.set.js' %>
|
62
|
+
<script type="text/javascript">
|
63
|
+
//<![CDATA[
|
64
|
+
$(document).ready(function() {
|
65
|
+
$('#content_body').markItUp(markdownSettings);
|
66
|
+
$('#btn_optional').click(function(evt) {
|
67
|
+
evt.preventDefault();
|
68
|
+
var vis = $('.optional').toggle().css('display') == 'block';
|
69
|
+
$(this).find('span').html(vis ? '▼' : '▲');
|
70
|
+
});
|
71
|
+
});
|
72
|
+
//]]>
|
73
|
+
</script>
|
74
|
+
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<%= render :partial => 'admin/shared/contents_sub_menu' %>
|
2
|
+
|
3
|
+
<%= render :partial => 'admin/shared/page_tabs', :locals => {:current => 'Contents'} %>
|
4
|
+
|
5
|
+
<% if @content.try(:errors).present? %>
|
6
|
+
<%= render 'shared/error_messages', :target => @content %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<h2><%= t('.edit_content') %></h2>
|
10
|
+
|
11
|
+
<%= form_for([:admin, @page, @content], :html => { :multipart => true }) do |f| %>
|
12
|
+
<%= render "form", :form => f %>
|
13
|
+
<p class="form-buttons">
|
14
|
+
<%= button t("update") %> <%= t('or') %> <%= link_to t('cancel'), collection_url %>
|
15
|
+
</p>
|
16
|
+
<% end %>
|
@@ -0,0 +1,59 @@
|
|
1
|
+
<%= render :partial => 'admin/shared/contents_sub_menu' %>
|
2
|
+
|
3
|
+
<div class='toolbar'>
|
4
|
+
<ul class='actions'>
|
5
|
+
<li>
|
6
|
+
<p><%= button_link_to t('.new_content'), new_object_url, :icon => 'add' %></p>
|
7
|
+
</li>
|
8
|
+
</ul>
|
9
|
+
<br class='clear' />
|
10
|
+
</div>
|
11
|
+
|
12
|
+
<%= render :partial => 'admin/shared/page_tabs', :locals => {:current => 'Contents'} %>
|
13
|
+
|
14
|
+
<h2><%= t('.listing_contents') %></h2>
|
15
|
+
|
16
|
+
<table class="index sortable">
|
17
|
+
<thead>
|
18
|
+
<tr>
|
19
|
+
<th><%= sort_link @search, :title, t("content.title") %></th>
|
20
|
+
<th><%= sort_link @search, :context, t("content.context") %></th>
|
21
|
+
<th><%= t("action") %></th>
|
22
|
+
</tr>
|
23
|
+
</thead>
|
24
|
+
<tbody>
|
25
|
+
<%- @collection.each do |content|%>
|
26
|
+
<tr id="<%= dom_id content %>">
|
27
|
+
<td><span class="handle"> </span> <%= link_to content.title, object_url(content) %></td>
|
28
|
+
<td><%= content.context %>
|
29
|
+
<td>
|
30
|
+
<%= link_to_edit content %>
|
31
|
+
<%= link_to_delete content %>
|
32
|
+
</td>
|
33
|
+
</tr>
|
34
|
+
<% end %>
|
35
|
+
</tbody>
|
36
|
+
</table>
|
37
|
+
|
38
|
+
<%= will_paginate(@contents, :prev => "« #{t('previous')}", :next => "#{t('next')} »") %>
|
39
|
+
|
40
|
+
<% content_for :sidebar do %>
|
41
|
+
|
42
|
+
<div class="box">
|
43
|
+
<h3><%= t(:search) %></h3>
|
44
|
+
|
45
|
+
<% @content = Content.metasearch %>
|
46
|
+
<%= form_for [:admin, @page, @content] do |f| %>
|
47
|
+
<%- locals = {:f => f} %>
|
48
|
+
<%= hook :admin_contents_index_search, locals do %>
|
49
|
+
<p>
|
50
|
+
<label><%= t('content.title') %></label><br />
|
51
|
+
<%= f.text_field :title_like, :size => 25 %>
|
52
|
+
</p>
|
53
|
+
<% end %>
|
54
|
+
<%= hook :admin_contents_index_search_buttons, locals do %>
|
55
|
+
<p><%= button t("search") %></p>
|
56
|
+
<% end %>
|
57
|
+
<% end %>
|
58
|
+
</div>
|
59
|
+
<% end %>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%= render :partial => 'admin/shared/contents_sub_menu' %>
|
2
|
+
|
3
|
+
<%= render :partial => 'admin/shared/page_tabs', :locals => {:current => 'Contents'} %>
|
4
|
+
|
5
|
+
<% if @content.try(:errors).present? %>
|
6
|
+
<%= render 'shared/error_messages', :target => @content %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<h2><%= t('.new_content') %></h2>
|
10
|
+
|
11
|
+
<% form_for([:admin, @page, @content], :html => { :multipart => true }) do |f| %>
|
12
|
+
<%= render "form", :form => f %>
|
13
|
+
|
14
|
+
<p class="form-buttons">
|
15
|
+
<%= button t("create") %> <%= t('or') %> <%= link_to t('cancel'), collection_url %>
|
16
|
+
</p>
|
17
|
+
<% end %>
|
18
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%= render :partial => 'admin/shared/contents_sub_menu' %>
|
2
|
+
<%= render :partial => 'admin/shared/page_tabs', :locals => {:current => 'Contents'} %>
|
3
|
+
|
4
|
+
<h2><%= h @content.title %></h2>
|
5
|
+
|
6
|
+
<%= RDiscount.new(@content.body).to_html.html_safe %>
|
7
|
+
|
8
|
+
<p>
|
9
|
+
<%= link_to_edit @user %>
|
10
|
+
<%= link_to t('back'), collection_url %>
|
11
|
+
</p>
|