liquid_cms 0.2.0.13 → 0.2.1.0
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/CHANGELOG.rdoc +12 -0
- data/app/controllers/cms/assets_controller.rb +32 -10
- data/app/controllers/cms/components_controller.rb +3 -3
- data/app/controllers/cms/main_controller.rb +2 -0
- data/app/controllers/cms/pages_controller.rb +2 -2
- data/app/helpers/cms/pages_helper.rb +0 -12
- data/app/liquid/cms_paperclip_extension.rb +1 -1
- data/app/liquid/drops/cms_asset_drop.rb +15 -0
- data/app/liquid/filters/cms_filters.rb +1 -1
- data/app/liquid/tags/asset_search_tag.rb +26 -0
- data/app/liquid/tags/cms/tag_common.rb +29 -0
- data/app/liquid/tags/data_tag.rb +59 -0
- data/app/models/cms/asset.rb +109 -2
- data/app/models/cms/component.rb +21 -17
- data/app/models/cms/page.rb +1 -3
- data/app/models/cms/tag.rb +21 -0
- data/app/models/cms/taggable.rb +78 -0
- data/app/models/cms/tagging.rb +6 -0
- data/app/views/cms/assets/_asset.html.erb +2 -3
- data/app/views/cms/assets/_form.html.erb +53 -3
- data/app/views/cms/assets/_list.html.erb +16 -1
- data/app/views/cms/assets/_meta_field.html.erb +15 -0
- data/app/views/cms/documentation/_cms_drops.html.erb +18 -0
- data/app/views/cms/documentation/_cms_tags.html.erb +13 -0
- data/app/views/cms/pages/_page.html.erb +1 -3
- data/app/views/cms/shared/_sidebar.html.erb +30 -29
- data/generators/liquid_cms/lib/insert_commands.rb +14 -0
- data/generators/liquid_cms/liquid_cms_generator.rb +5 -1
- data/generators/liquid_cms/templates/config/initializers/cms/liquid_cms.rb +8 -0
- data/generators/liquid_cms/templates/config/locales/cms/en.yml +5 -0
- data/generators/liquid_cms/templates/migration_rev1.rb +38 -0
- data/generators/liquid_cms/templates/public/cms/stylesheets/sidebar.css +25 -7
- data/generators/liquid_cms/templates/public/cms/stylesheets/simple_form.css +79 -4
- data/generators/liquid_cms/templates/public/cms/stylesheets/styles.css +0 -8
- data/generators/liquid_cms/templates/public/cms/stylesheets/themes/dark.css +3 -0
- data/lib/liquid_cms/configuration.rb +12 -0
- data/lib/liquid_cms/version.rb +1 -1
- data/rails/init.rb +0 -1
- data/test/functional/assets_controller_test.rb +64 -16
- data/test/functional/components_controller_test.rb +90 -1
- data/test/functional/main_controller_test.rb +21 -0
- data/test/integration/pages_test.rb +124 -0
- data/test/integration/pages_test_no_context.rb +57 -0
- data/test/rails_app/db/migrate/20110329201435_create_liquid_cms_upgrade_rev1.rb +38 -0
- data/test/test_helper.rb +2 -0
- data/test/test_helpers/asset_helpers.rb +6 -4
- data/test/test_helpers/component_helpers.rb +35 -0
- data/test/test_helpers/file_helpers.rb +11 -0
- data/test/unit/asset_test.rb +114 -8
- data/test/unit/component_test.rb +65 -2
- data/test/unit/helpers/cms/common_helper_test.rb +4 -0
- metadata +35 -7
- data/app/views/cms/assets/destroy.js.rjs +0 -2
- data/generators/liquid_cms/templates/config/initializers/cms/vestal_versions.rb +0 -9
- data/test/rails_app/config/initializers/cms/vestal_versions.rb +0 -9
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
== Master
|
2
|
+
|
3
|
+
* Enhancements
|
4
|
+
* Many improvements to assets including the addition of meta data fields, tags and the ability to specify custom image sizes.
|
5
|
+
* Assets can now be searched for using the liquid 'asset_data' tag. {% asset_data tag:'test' %}
|
6
|
+
See the built-in docs for more details on how to use "asset_data" and asset drops.
|
7
|
+
* Asset drops (accessible via the asset_data tag) give you access to the meta data and custom image information.
|
8
|
+
* limit and random ordering for collection retrieved from the asset_data tag.
|
9
|
+
|
10
|
+
* Fixes
|
11
|
+
* Optimize asset image file sizes with -strip
|
12
|
+
|
1
13
|
== 0.2.0.13
|
2
14
|
|
3
15
|
* Enhancements
|
@@ -6,11 +6,13 @@ class Cms::AssetsController < Cms::MainController
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def new
|
9
|
-
@asset =
|
9
|
+
@asset = create_tagged_asset
|
10
10
|
end
|
11
11
|
|
12
12
|
def create
|
13
|
-
@asset = @context.assets.build
|
13
|
+
@asset = @context.assets.build
|
14
|
+
@asset.assign_ordered_attributes params[:cms_asset]
|
15
|
+
|
14
16
|
if @asset.save
|
15
17
|
flash[:notice] = t('assets.flash.created')
|
16
18
|
redirect_to cms_root_path
|
@@ -25,14 +27,9 @@ class Cms::AssetsController < Cms::MainController
|
|
25
27
|
|
26
28
|
def update
|
27
29
|
@asset = @context.assets.find params[:id]
|
30
|
+
@asset.assign_ordered_attributes params[:cms_asset]
|
28
31
|
|
29
|
-
|
30
|
-
@asset.write params[:file_content]
|
31
|
-
else
|
32
|
-
@asset.update_attributes params[:cms_asset]
|
33
|
-
end
|
34
|
-
|
35
|
-
if success
|
32
|
+
if @asset.save
|
36
33
|
flash[:notice] = t('assets.flash.updated')
|
37
34
|
redirect_to cms_root_path
|
38
35
|
else
|
@@ -48,7 +45,32 @@ class Cms::AssetsController < Cms::MainController
|
|
48
45
|
|
49
46
|
respond_to do |format|
|
50
47
|
format.html { redirect_to cms_root_path }
|
51
|
-
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
# pre-populate an asset with tagged data and meta fields if a tag param is present
|
53
|
+
def create_tagged_asset
|
54
|
+
asset = Cms::Asset.new
|
55
|
+
curr_tag = (params[:tag] || '').strip
|
56
|
+
|
57
|
+
if curr_tag.present?
|
58
|
+
asset.tag_list = curr_tag
|
59
|
+
|
60
|
+
meta_asset = @context.assets.tagged_with(curr_tag).first :conditions => 'meta_data is not null'
|
61
|
+
if meta_asset
|
62
|
+
# remove meta values since we only want the key names
|
63
|
+
# new values will be provided for the new asset
|
64
|
+
asset.meta_data = meta_asset.meta_data.collect{|m| {:name => m[:name], :value => ''}}
|
65
|
+
|
66
|
+
# assign custom dims
|
67
|
+
asset.custom_width = meta_asset.custom_width
|
68
|
+
asset.custom_height = meta_asset.custom_height
|
69
|
+
end
|
70
|
+
|
71
|
+
asset
|
72
|
+
else
|
73
|
+
asset
|
52
74
|
end
|
53
75
|
end
|
54
76
|
end
|
@@ -17,10 +17,10 @@ class Cms::ComponentsController < Cms::MainController
|
|
17
17
|
@component = Cms::Component.new(@context, @path)
|
18
18
|
@component.write params[:file_content]
|
19
19
|
|
20
|
-
flash[:notice] = "
|
20
|
+
flash[:notice] = "The component file has been updated."
|
21
21
|
redirect_to cms_root_path
|
22
22
|
else
|
23
|
-
flash[:error] = "Not an editable
|
23
|
+
flash[:error] = "Not an editable component."
|
24
24
|
redirect_to :controller => 'cms/components', :action => 'edit', :url => @path
|
25
25
|
end
|
26
26
|
end
|
@@ -39,7 +39,7 @@ class Cms::ComponentsController < Cms::MainController
|
|
39
39
|
component_zip = params[:zip_file]
|
40
40
|
|
41
41
|
if component_zip.present? && File.extname(component_zip.original_filename) == '.zip'
|
42
|
-
Cms::Component.
|
42
|
+
Cms::Component.expand @context, component_zip.path
|
43
43
|
flash[:notice] = 'The component has been uploaded.'
|
44
44
|
else
|
45
45
|
flash[:error] = 'The component file must be a zip archive.'
|
@@ -10,7 +10,7 @@ class Cms::PagesController < Cms::MainController
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def create
|
13
|
-
@page = @context.pages.build(
|
13
|
+
@page = @context.pages.build(params[:cms_page])
|
14
14
|
if @page.save
|
15
15
|
flash[:notice] = t('pages.flash.created')
|
16
16
|
redirect_to cms_root_path
|
@@ -25,7 +25,7 @@ class Cms::PagesController < Cms::MainController
|
|
25
25
|
|
26
26
|
def update
|
27
27
|
@page = @context.pages.find params[:id]
|
28
|
-
if @page.update_attributes(
|
28
|
+
if @page.update_attributes(params[:cms_page])
|
29
29
|
flash[:notice] = t('pages.flash.updated')
|
30
30
|
redirect_to edit_cms_page_path(@page)
|
31
31
|
else
|
@@ -3,18 +3,6 @@ module Cms::PagesHelper
|
|
3
3
|
page.new_record? ? @context.pages.layouts : @context.pages.layouts.reject{|pg| pg == page}
|
4
4
|
end
|
5
5
|
|
6
|
-
def delete_page_link(page)
|
7
|
-
options = {:method => :delete, :confirm => "Are you sure you want to delete the \"#{page}\" page?"}
|
8
|
-
|
9
|
-
# use a remote link if there are no children since if we remove the current page list item, all the children items get removed (in the UI) as well
|
10
|
-
# it's easier to just remove the item otherwise with a normal post and refresh the page
|
11
|
-
if page.content_pages.empty?
|
12
|
-
link_to_remote cms_icon('delete.png', :title => 'Delete'), {:url => cms_page_path(page), :indicator => dom_id(page, 'progress')}.merge(options)
|
13
|
-
else
|
14
|
-
link_to cms_icon('delete.png', :title => 'Delete'), cms_page_path(page), options
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
6
|
# find the # of term matches in each page and sorts the pages by the match count (highest to lowest)
|
19
7
|
# only shows the first SEARCH_LIMIT pages
|
20
8
|
def page_match_order(pages, term)
|
@@ -7,7 +7,7 @@ module Paperclip
|
|
7
7
|
all_styles = self.styles.keys + ['original']
|
8
8
|
all_styles.each do |style|
|
9
9
|
g = Paperclip::Geometry.from_file(self.path(style)) rescue nil
|
10
|
-
h[style] = {'width' => g.width.to_i, 'height' => g.height.to_i, 'url' => self.url(style)} unless g.nil?
|
10
|
+
h[style.to_s] = {'width' => g.width.to_i, 'height' => g.height.to_i, 'url' => self.url(style)} unless g.nil?
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -88,7 +88,7 @@ module CmsFilters
|
|
88
88
|
|
89
89
|
def component_url(path)
|
90
90
|
context = @context.registers[:context]
|
91
|
-
"/" +
|
91
|
+
"/" + Cms::Component.base_path(context).join(path).to_s
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Syntax
|
2
|
+
# {% asset_data tag'test', as:'sale_vehicles' %}
|
3
|
+
|
4
|
+
class AssetDataTag < Cms::DataTag
|
5
|
+
def get_data
|
6
|
+
raise Liquid::ArgumentError.new("The required 'tag' parameter is missing.") if options[:tag].blank?
|
7
|
+
|
8
|
+
collection = uses_random do |random_func|
|
9
|
+
assets = context_object.assets.tagged_with(options[:tag])
|
10
|
+
|
11
|
+
assets = if options[:random] == true
|
12
|
+
assets.scoped(:order => random_func)
|
13
|
+
else
|
14
|
+
assets.scoped(:order => 'cms_assets.created_at ASC')
|
15
|
+
end
|
16
|
+
|
17
|
+
assets = assets.scoped(:limit => options[:limit]) if options[:limit]
|
18
|
+
|
19
|
+
assets.all
|
20
|
+
end
|
21
|
+
|
22
|
+
yield 'assets', collection
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Liquid::Template.register_tag('asset_data', AssetDataTag)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Cms::TagCommon
|
2
|
+
extend ActiveSupport::Memoizable
|
3
|
+
|
4
|
+
HyphenatedTagAttributes = /([\w-]+)\s*\:\s*(#{Liquid::QuotedFragment})/
|
5
|
+
|
6
|
+
def parse_options(context, markup)
|
7
|
+
begin
|
8
|
+
options = HashWithIndifferentAccess.new
|
9
|
+
return options if markup.blank?
|
10
|
+
|
11
|
+
markup.scan(HyphenatedTagAttributes) do |key, value|
|
12
|
+
options[key.to_sym] = context[value]
|
13
|
+
end
|
14
|
+
|
15
|
+
options
|
16
|
+
rescue ArgumentError => e
|
17
|
+
raise SyntaxError.new("Syntax Error in 'tag options' - Valid syntax: name:value")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def context_object(context)
|
22
|
+
context.registers[:context].object
|
23
|
+
end
|
24
|
+
memoize :context_object
|
25
|
+
|
26
|
+
def params(context)
|
27
|
+
context.registers[:controller].params.except(:controller, :action)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class Cms::DataTag < Liquid::Tag
|
2
|
+
module TagMethods
|
3
|
+
extend Cms::TagCommon
|
4
|
+
end
|
5
|
+
|
6
|
+
attr_reader :context
|
7
|
+
attr_reader :options
|
8
|
+
|
9
|
+
def initialize(tag_name, markup, tokens)
|
10
|
+
@markup = markup
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def context_object
|
15
|
+
TagMethods.context_object(@context)
|
16
|
+
end
|
17
|
+
|
18
|
+
def params
|
19
|
+
TagMethods.params(@context)
|
20
|
+
end
|
21
|
+
|
22
|
+
def render(context)
|
23
|
+
@context = context
|
24
|
+
@options = TagMethods.parse_options(context, @markup)
|
25
|
+
|
26
|
+
get_data do |name, data|
|
27
|
+
context[@options[:as] || name] = data
|
28
|
+
end
|
29
|
+
''
|
30
|
+
end
|
31
|
+
|
32
|
+
def uses_random(&block)
|
33
|
+
collection = []
|
34
|
+
|
35
|
+
# random sql func supported by postgresql and sqlite (perhaps others)
|
36
|
+
random_func = "random()"
|
37
|
+
|
38
|
+
begin
|
39
|
+
collection = yield random_func
|
40
|
+
rescue ActiveRecord::StatementInvalid => e
|
41
|
+
if options[:random] == true
|
42
|
+
# the random function used was invalid, so we'll try an alternative syntax for mysql (perhaps others)
|
43
|
+
mysql_func = "rand()"
|
44
|
+
|
45
|
+
if random_func != mysql_func
|
46
|
+
random_func = mysql_func
|
47
|
+
else
|
48
|
+
# set random to false and just use the default order since the alt didn't work either
|
49
|
+
options[:random] = false
|
50
|
+
end
|
51
|
+
|
52
|
+
# retry the query
|
53
|
+
retry
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
collection
|
58
|
+
end
|
59
|
+
end
|
data/app/models/cms/asset.rb
CHANGED
@@ -1,22 +1,76 @@
|
|
1
1
|
module Cms
|
2
2
|
class Asset < ActiveRecord::Base
|
3
|
+
unloadable
|
4
|
+
|
3
5
|
set_table_name 'cms_assets'
|
4
6
|
|
7
|
+
include Cms::Taggable
|
8
|
+
define_tag_association :assets
|
9
|
+
|
10
|
+
def self.tags_for_context(context)
|
11
|
+
common_options = {:order => 'name ASC'}
|
12
|
+
context.object ? Cms::Tag.all({:include => :assets, :conditions => {'cms_assets.context_id' => context.object.id}}.merge(common_options)) : Cms::Tag.all(common_options)
|
13
|
+
end
|
14
|
+
|
15
|
+
class Meta
|
16
|
+
attr_reader :name, :value, :errors
|
17
|
+
|
18
|
+
def initialize(data)
|
19
|
+
@name, @value = data[:name], data[:value]
|
20
|
+
@errors = ActiveRecord::Errors.new(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid?
|
24
|
+
validate
|
25
|
+
errors.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate
|
29
|
+
errors.clear
|
30
|
+
if @name.blank?
|
31
|
+
errors.add :name, 'must be set'
|
32
|
+
else
|
33
|
+
errors.add :name, "is an invalid format" if (@name =~ /^[a-z]+[a-z0-9_]*$/).nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
serialize :meta_data
|
39
|
+
|
5
40
|
has_attached_file :asset,
|
6
|
-
:styles => { :tiny => '50x50>', :thumb => '100x100>'
|
41
|
+
:styles => { :tiny => '50x50>', :thumb => '100x100>', :large => '200x200>', :custom => Proc.new{|instance| custom_dimensions(instance)} },
|
42
|
+
:convert_options => {:all => '-strip -quality 90'},
|
7
43
|
:path => ":rails_root/public/cms/assets/:id/:style/:filename",
|
8
44
|
:url => "/cms/assets/:id/:style/:filename"
|
9
45
|
|
10
46
|
validates_attachment_presence :asset
|
47
|
+
validate :meta_data_check
|
11
48
|
|
12
49
|
named_scope :ordered, :order => 'asset_file_name ASC'
|
13
50
|
|
51
|
+
after_save :reprocess_custom_dimensions
|
14
52
|
before_post_process :process_check
|
15
53
|
|
16
54
|
def to_s
|
17
55
|
asset_file_name
|
18
56
|
end
|
19
57
|
|
58
|
+
def assign_ordered_attributes(params)
|
59
|
+
# force the custom dimensions to be assigned first so that when the asset is assigned, the custom dims are present
|
60
|
+
# if the custom dims aren't set before the asset is assigned, the custom size won't be generated properly
|
61
|
+
# this can occur if the attribute hash is iterated with the asset coming before the dims
|
62
|
+
self.attributes = params.slice(:custom_height, :custom_width)
|
63
|
+
self.attributes = params
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.context_tags(context)
|
67
|
+
if context
|
68
|
+
Tag.all :joins => 'inner join taggings on taggings.tag_id = tags.id inner join cms_assets on taggings.taggable_id = cms_assets.id', :conditions => {'cms_assets.context_id' => context.id}
|
69
|
+
else
|
70
|
+
Tag.all
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
20
74
|
def image?
|
21
75
|
!(asset_content_type =~ /^image.*/).blank?
|
22
76
|
end
|
@@ -30,6 +84,40 @@ module Cms
|
|
30
84
|
!(asset_content_type =~ /(javascript|css|xml|html)$/).blank?
|
31
85
|
end
|
32
86
|
|
87
|
+
def file_content
|
88
|
+
read
|
89
|
+
end
|
90
|
+
|
91
|
+
def file_content=(content)
|
92
|
+
write content
|
93
|
+
end
|
94
|
+
|
95
|
+
def meta
|
96
|
+
return @_meta if @_meta.present?
|
97
|
+
@_meta = (meta_data || []).collect{|m| Meta.new(m)}
|
98
|
+
end
|
99
|
+
|
100
|
+
def meta=(data)
|
101
|
+
# reset the cached meta collection
|
102
|
+
@_meta = nil
|
103
|
+
|
104
|
+
# data ex:
|
105
|
+
# {"new_1301457489798"=>{"name"=>"test1", "value"=>"test1"}, "new_1301457493800"=>{"name"=>"test2", "value"=>"test2"}}
|
106
|
+
# converted to:
|
107
|
+
# [{"name"=>"test1", "value"=>"test1"}, {"name"=>"test2", "value"=>"test2"}]
|
108
|
+
# strip spaces of name and value
|
109
|
+
temp_data = data.to_a.sort{|a,b| a.first <=> b.first}.collect{|a| h = a[1]; {:name => h[:name].strip, :value => h[:value].strip} }
|
110
|
+
# remove any elements that have both name and value blank
|
111
|
+
temp_data = temp_data.reject{|d| d[:name].blank? && d[:value].blank?}
|
112
|
+
|
113
|
+
self.meta_data = temp_data
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_liquid
|
117
|
+
Cms::AssetDrop.new(self)
|
118
|
+
end
|
119
|
+
|
120
|
+
protected
|
33
121
|
def read
|
34
122
|
return '' if !editable?
|
35
123
|
asset.to_file(:original).read
|
@@ -46,9 +134,28 @@ module Cms
|
|
46
134
|
end
|
47
135
|
end
|
48
136
|
|
49
|
-
|
137
|
+
def meta_data_check
|
138
|
+
if !meta.find_all{|m| !m.valid?}.empty?
|
139
|
+
errors.add :meta_data, "is invalid"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.custom_dimensions(record)
|
144
|
+
if !record.custom_width.to_i.zero? && !record.custom_height.to_i.zero?
|
145
|
+
"#{record.custom_width}x#{record.custom_height}>"
|
146
|
+
else
|
147
|
+
''
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
50
151
|
def process_check
|
51
152
|
image? && !icon?
|
52
153
|
end
|
154
|
+
|
155
|
+
def reprocess_custom_dimensions
|
156
|
+
if custom_height_changed? || custom_width_changed?
|
157
|
+
asset.reprocess!
|
158
|
+
end
|
159
|
+
end
|
53
160
|
end
|
54
161
|
end
|