liquid_cms 0.3.0.10 → 0.3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/CHANGELOG.rdoc +12 -0
  2. data/app/controllers/cms/assets_controller.rb +32 -10
  3. data/app/controllers/cms/components_controller.rb +3 -3
  4. data/app/controllers/cms/main_controller.rb +2 -0
  5. data/app/controllers/cms/pages_controller.rb +2 -2
  6. data/app/helpers/cms/pages_helper.rb +0 -12
  7. data/app/liquid/cms_paperclip_extension.rb +1 -1
  8. data/app/liquid/drops/cms_asset_drop.rb +15 -0
  9. data/app/liquid/filters/cms_filters.rb +1 -1
  10. data/app/liquid/tags/asset_search_tag.rb +26 -0
  11. data/app/liquid/tags/cms/tag_common.rb +29 -0
  12. data/app/liquid/tags/data_tag.rb +59 -0
  13. data/app/models/cms/asset.rb +109 -2
  14. data/app/models/cms/component.rb +21 -17
  15. data/app/models/cms/page.rb +1 -3
  16. data/app/models/cms/tag.rb +21 -0
  17. data/app/models/cms/taggable.rb +78 -0
  18. data/app/models/cms/tagging.rb +6 -0
  19. data/app/views/cms/assets/_asset.html.erb +2 -3
  20. data/app/views/cms/assets/_form.html.erb +53 -2
  21. data/app/views/cms/assets/_list.html.erb +16 -1
  22. data/app/views/cms/assets/_meta_field.html.erb +15 -0
  23. data/app/views/cms/documentation/_cms_drops.html.erb +18 -0
  24. data/app/views/cms/documentation/_cms_tags.html.erb +13 -0
  25. data/app/views/cms/pages/_page.html.erb +1 -3
  26. data/app/views/cms/shared/_sidebar.html.erb +30 -28
  27. data/config/initializers/cms/liquid_cms.rb +8 -0
  28. data/config/locales/cms/en.yml +5 -0
  29. data/generators/liquid_cms/templates/migration_rev1.rb +38 -0
  30. data/lib/generators/liquid_cms/install_generator.rb +7 -9
  31. data/lib/generators/liquid_cms/templates/migration_rev1.rb +38 -0
  32. data/lib/generators/liquid_cms/templates/public/cms/stylesheets/sidebar.css +25 -7
  33. data/lib/generators/liquid_cms/templates/public/cms/stylesheets/simple_form.css +79 -4
  34. data/lib/generators/liquid_cms/templates/public/cms/stylesheets/styles.css +0 -8
  35. data/lib/generators/liquid_cms/templates/public/cms/stylesheets/themes/dark.css +3 -0
  36. data/lib/liquid_cms/configuration.rb +12 -0
  37. data/lib/liquid_cms/version.rb +1 -1
  38. data/test/functional/assets_controller_test.rb +64 -16
  39. data/test/functional/components_controller_test.rb +90 -1
  40. data/test/functional/main_controller_test.rb +21 -0
  41. data/test/integration/pages_test.rb +123 -0
  42. data/test/integration/pages_test_no_context.rb +57 -0
  43. data/test/rails_app/db/migrate/20110329201435_create_liquid_cms_upgrade_rev1.rb +38 -0
  44. data/test/test_helper.rb +2 -0
  45. data/test/test_helpers/asset_helpers.rb +6 -4
  46. data/test/test_helpers/component_helpers.rb +37 -0
  47. data/test/test_helpers/file_helpers.rb +11 -0
  48. data/test/unit/asset_test.rb +114 -8
  49. data/test/unit/component_test.rb +64 -1
  50. data/test/unit/helpers/cms/common_helper_test.rb +4 -0
  51. metadata +37 -6
  52. data/app/views/cms/assets/destroy.js.rjs +0 -2
  53. data/test/rails_app/config/initializers/cms/vestal_versions.rb +0 -11
@@ -1,4 +1,12 @@
1
1
  Cms.setup do |config|
2
+ # Valid component file extensions that are allowed to be uploaded to the CMS.
3
+ # Defaults to %w(.css .js .png .jpg .jpeg .gif .json .xml .fla .ico .txt)
4
+ #config.valid_component_exts += %w(.xhtml .bmp)
5
+
6
+ # Compnent file types that can be edited (text based) in the CMS. Make sure new extensions here are also set in the valid_component_exts setting.
7
+ # Defaults to %w(.js .css .html .xml .txt)
8
+ #config.editable_component_exts += %w(.xhtml)
9
+
2
10
  # The class of your apps context object if it has one. This attribute must be set last.
3
11
  #config.context_class = :Context
4
12
  end
@@ -61,6 +61,7 @@ en:
61
61
  root: 'Home Page'
62
62
  cms_asset:
63
63
  asset_file_name: 'File'
64
+ tag_list: 'Tags'
64
65
  hints:
65
66
  cms_page:
66
67
  name: 'The name must contain no whitespace or any other special characters. Letters, numbers, hyphens, underscores and periods are valid.<br/>The extensions <em>.css</em>, <em>.js</em>, <em>.xml</em>, <em>.json</em> and <em>.txt</em> can used to auto-identify the content-type. If no extension is provided, html is the default type.'
@@ -71,6 +72,10 @@ en:
71
72
  file_content: '<em>No liquid support for editing components.</em> Use ctrl+s to save.'
72
73
  cms_asset:
73
74
  asset: 'Upload an asset file.'
75
+ tag_list: 'Seperate tags with commas.'
76
+ dimensions: 'Specify custom dimensions in pixels as width x height. The aspect ratio will be maintained, so actual dimensions may differ. Applies to image assets only.'
77
+ meta:
78
+ name: 'The name must begin with a letter and consist only of lowercase letters, numbers and underscores.'
74
79
  file_content: '<em>No liquid support for editing assets.</em> Use ctrl+s to save.'
75
80
  edit:
76
81
  asset: 'An existing file has been uploaded. Upload a new file to replace it.'
@@ -0,0 +1,38 @@
1
+ class CreateLiquidCmsUpgradeRev1 < ActiveRecord::Migration
2
+ def self.up
3
+ change_table :cms_assets do |t|
4
+ t.integer :custom_height
5
+ t.integer :custom_width
6
+ t.text :meta_data # serialized yaml
7
+ end
8
+
9
+ drop_table :versions
10
+
11
+ create_table :cms_tags do |t|
12
+ t.column :name, :string
13
+ end
14
+
15
+ create_table :cms_taggings do |t|
16
+ t.column :tag_id, :integer
17
+ t.column :taggable_id, :integer
18
+ t.column :taggable_type, :string
19
+
20
+ t.column :created_at, :datetime
21
+ end
22
+
23
+ add_index :cms_taggings, :tag_id
24
+ add_index :cms_taggings, [:taggable_id, :taggable_type]
25
+ end
26
+
27
+ def self.down
28
+ drop_table :cms_taggings
29
+ drop_table :cms_tags
30
+
31
+ create_table :versions do |t|
32
+ end
33
+
34
+ change_table :cms_assets do |t|
35
+ t.remove :custom_height, :custom_width, :meta_data
36
+ end
37
+ end
38
+ end
@@ -8,11 +8,13 @@ module LiquidCms
8
8
  source_root File.expand_path('templates', File.dirname(__FILE__))
9
9
 
10
10
  def copy_migration_file
11
- name = 'create_liquid_cms_setup'
12
- if self.class.migration_exists?(File.join('db', 'migrate'), name).blank?
13
- migration_template 'migration.rb', File.join('db', 'migrate', name)
14
- else
15
- puts "Migration '#{name}' already exists... skipping"
11
+ [{name: 'create_liquid_cms_setup', file: 'migration.rb'}, {name: 'create_liquid_cms_upgrade_rev1', file: 'migration_rev1.rb'}].each do |m|
12
+ name = m[:name]
13
+ if self.class.migration_exists?(File.join('db', 'migrate'), name).blank?
14
+ migration_template m[:file], File.join('db', 'migrate', name)
15
+ else
16
+ puts "Migration '#{name}' already exists... skipping"
17
+ end
16
18
  end
17
19
  end
18
20
 
@@ -20,10 +22,6 @@ module LiquidCms
20
22
  ActiveRecord::Generators::Base.next_migration_number migration_dir
21
23
  end
22
24
 
23
- def add_unreleased_gem_dependencies
24
- append_file 'Gemfile', %q(gem 'vestal_versions', '~> 1.2.1', :git => 'git://github.com/adamcooper/vestal_versions.git')
25
- end
26
-
27
25
  def copy_setup_controller
28
26
  copy_file 'setup_controller.rb', File.join('app', 'controllers', 'cms', 'setup_controller.rb')
29
27
  end
@@ -0,0 +1,38 @@
1
+ class CreateLiquidCmsUpgradeRev1 < ActiveRecord::Migration
2
+ def self.up
3
+ change_table :cms_assets do |t|
4
+ t.integer :custom_height
5
+ t.integer :custom_width
6
+ t.text :meta_data # serialized yaml
7
+ end
8
+
9
+ drop_table :versions
10
+
11
+ create_table :cms_tags do |t|
12
+ t.column :name, :string
13
+ end
14
+
15
+ create_table :cms_taggings do |t|
16
+ t.column :tag_id, :integer
17
+ t.column :taggable_id, :integer
18
+ t.column :taggable_type, :string
19
+
20
+ t.column :created_at, :datetime
21
+ end
22
+
23
+ add_index :cms_taggings, :tag_id
24
+ add_index :cms_taggings, [:taggable_id, :taggable_type]
25
+ end
26
+
27
+ def self.down
28
+ drop_table :cms_taggings
29
+ drop_table :cms_tags
30
+
31
+ create_table :versions do |t|
32
+ end
33
+
34
+ change_table :cms_assets do |t|
35
+ t.remove :custom_height, :custom_width, :meta_data
36
+ end
37
+ end
38
+ end
@@ -19,15 +19,35 @@
19
19
  margin: 0;
20
20
  padding: 0;
21
21
  }
22
- #sidebar #assets li {
22
+ #sidebar #assets li.cms_asset {
23
+ position: relative;
24
+ }
25
+ #sidebar #assets li.group.tagged {
26
+ margin-bottom: 0.5em;
27
+ }
28
+ #sidebar #assets li.group li {
23
29
  border: 1px solid #AAA;
24
30
  padding: 0.3em 0.4em;
25
31
  margin-bottom: 0.3em;
26
32
  }
27
- #sidebar #assets li:hover {
33
+ #sidebar #assets li.group h4 {
34
+ background-color: #BBB;
35
+ border: 1px solid #999;
36
+ margin: 0.2em 0;
37
+ padding: 0.4em;
38
+ text-shadow: -1px -1px 1px #CCCCCC;
39
+ }
40
+ #sidebar #assets li.group.tagged h4 {
41
+ background: url("/cms/images/icons/tag_blue.png") no-repeat scroll 5px center #BBB;
42
+ padding: 0.4em 0.4em 0.4em 25px;
43
+ }
44
+ #sidebar #assets li.group h4 a {
45
+ float: right;
46
+ }
47
+ #sidebar #assets li.group li:hover {
28
48
  background-color: #BFD6FF !important;
29
49
  }
30
- #sidebar #assets li.light {
50
+ #sidebar #assets li.group li.light {
31
51
  background-color: #DDD;
32
52
  }
33
53
  #sidebar .asset_details {
@@ -41,7 +61,8 @@
41
61
  }
42
62
  #sidebar .asset_size {
43
63
  font-size: 8pt;
44
- float: right;
64
+ position: absolute;
65
+ right: 0.4em;
45
66
  }
46
67
  #sidebar #components form {
47
68
  margin-bottom: 0.5em;
@@ -120,9 +141,6 @@
120
141
  #cms ul.tree li { margin: 0; padding: 0 0px 0 12px; line-height: 20px; background: url(/cms/images/tree/node.png) no-repeat; color: #369; font-weight: bold; }
121
142
  #cms ul.tree li:last-child { background: url(/cms/images/tree/lastnode.png) no-repeat; }
122
143
 
123
- #cms ul.tree, #sidebar #assets ul {
124
- margin-bottom: 0.5em;
125
- }
126
144
  #cms ul.tree ul {
127
145
  margin-left: 15px;
128
146
  }
@@ -43,17 +43,18 @@ form.simple_form a.cancel:hover {
43
43
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#F55), color-stop(1.0,#C11));
44
44
  }
45
45
 
46
- form.simple_form div.string, form.simple_form div.text, form.simple_form div.boolean, form.simple_form div.select, form.simple_form div.file {
46
+ form.simple_form div.string, form.simple_form div.text, form.simple_form div.boolean, form.simple_form div.select, form.simple_form div.file, form.simple_form div.integer {
47
47
  margin-bottom: 1.3em;
48
48
  }
49
- form.simple_form label {
50
- color: #333;
49
+ form.simple_form label, form.simple_form .label {
51
50
  float: left;
51
+ width: 9%;
52
+ color: #333;
52
53
  font-size: 10pt;
53
54
  font-family: Verdana;
54
55
  font-weight: bold;
55
56
  line-height: 1.8em;
56
- width: 9%;
57
+ text-shadow: 1px 1px 1px #DDD;
57
58
  }
58
59
  form.simple_form input.string {
59
60
  display: block;
@@ -66,6 +67,13 @@ form.simple_form .buttons { margin-left: 9%; margin-top: 1.5em; }
66
67
  form.simple_form span.hint { color: #666; display: block; font-size: 8pt; font-style: italic; margin: 0.5em 0 0 9%;}
67
68
  form.simple_form span.hint em { color: #333; font-weight: bold; }
68
69
 
70
+ form.simple_form div.fieldWithErrors:first-child {
71
+ width: 9%;
72
+ float: left;
73
+ }
74
+ form.simple_form div.fieldWithErrors:first-child label {
75
+ float: none;
76
+ }
69
77
  form.simple_form div.fieldWithErrors { background-color: #FBE3E4; padding: 0.5em 0; }
70
78
  form.simple_form span.error {
71
79
  background: white;
@@ -77,3 +85,70 @@ form.simple_form span.error {
77
85
  margin-top: 0.5em;
78
86
  padding: 0.5em;
79
87
  }
88
+
89
+ form.simple_form .preview {
90
+ margin-bottom: 1em;
91
+ }
92
+ form.simple_form .preview h4 {
93
+ margin-top: 0;
94
+ margin-bottom: 0.5em;
95
+ }
96
+ form.simple_form .preview img {
97
+ border: 1px solid #CCC;
98
+ }
99
+ form.simple_form .details p:first-child {
100
+ margin-top: 0;
101
+ }
102
+ form.simple_form .details .label {
103
+ display: inline-block;
104
+ float: none;
105
+ }
106
+
107
+ .CodeMirror-wrapping {
108
+ display: inline-block;
109
+ }
110
+ .CodeMirror-wrapping iframe {
111
+ background-color: white;
112
+ border: 1px solid #BBBBBB !important;
113
+ }
114
+
115
+ div.dimensions {
116
+ margin-bottom: 1.3em;
117
+ }
118
+ div.dimensions div.integer {
119
+ display: inline;
120
+ }
121
+
122
+ fieldset legend {
123
+ font-weight: bold;
124
+ text-shadow: 1px 1px 1px #DDD;
125
+ }
126
+ ul#meta_fields {
127
+ list-style-type: none;
128
+ padding-left: 0;
129
+ margin: 0.5em 0 0;
130
+ }
131
+ ul#meta_fields li {
132
+ position: relative;
133
+ background: #EEE;
134
+ background: -moz-linear-gradient(0deg, #EEEEEE 0%, #F3F3F3 100%) repeat scroll 0 0 transparent;
135
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#EEE), color-stop(1.0,#F3F3F3));
136
+ border: 1px solid #999;
137
+ margin-bottom: 0.5em;
138
+ padding: 0.5em;
139
+ padding-bottom: 0;
140
+ }
141
+ ul#meta_fields li div.field {
142
+ margin-top: 0.5em;
143
+ }
144
+ ul#meta_fields li div.field input.string {
145
+ width: auto;
146
+ }
147
+ ul#meta_fields li .delete {
148
+ position: absolute;
149
+ bottom: 0.5em;
150
+ right: 0.5em;
151
+ }
152
+ form.simple_form ul div.string, form.simple_form ul div.text {
153
+ margin-bottom: 0.5em;
154
+ }
@@ -105,14 +105,6 @@ h2 p.message {
105
105
  float: right;
106
106
  }
107
107
 
108
- .CodeMirror-wrapping {
109
- display: inline-block;
110
- }
111
- .CodeMirror-wrapping iframe {
112
- background-color: white;
113
- border: 1px solid #BBBBBB !important;
114
- }
115
-
116
108
  .cms_pages #content h2 {
117
109
  background: url("/cms/images/icons/page.png") no-repeat scroll right 50% transparent;
118
110
  }
@@ -13,6 +13,9 @@ body {
13
13
  #content a {
14
14
  color: #FFE900;
15
15
  }
16
+ #content form.simple_form a {
17
+ color: #170;
18
+ }
16
19
  #content h2 {
17
20
  color: #AAA;
18
21
  text-shadow: -1px -1px 2px #000000;
@@ -20,6 +20,18 @@ module Cms
20
20
  bind_to.instance_variable_set :@cms_context, context
21
21
  end
22
22
 
23
+ mattr_reader :valid_component_exts
24
+ def self.valid_component_exts=(exts)
25
+ @@valid_component_exts = exts.to_a
26
+ end
27
+ @@valid_component_exts = %w(.css .js .png .jpg .jpeg .gif .json .xml .fla .ico .txt)
28
+
29
+ mattr_reader :editable_component_exts
30
+ def self.editable_component_exts=(exts)
31
+ @@editable_component_exts = exts.to_a
32
+ end
33
+ @@editable_component_exts = %w(.js .css .html .xml .txt)
34
+
23
35
  def self.setup
24
36
  yield self
25
37
  end
@@ -1,3 +1,3 @@
1
1
  module Cms
2
- VERSION = "0.3.0.10"
2
+ VERSION = "0.3.1.0"
3
3
  end
@@ -13,6 +13,53 @@ class Cms::AssetsControllerTest < ActionController::TestCase
13
13
  assert_select 'div.text', false
14
14
  #assert_select 'div.file .hint', 'Upload an asset file.'
15
15
  end
16
+
17
+ should "populate the new asset with tag and meta details" do
18
+ asset = Factory(:image_asset, :context => @company, :tag_list => 'test', :meta_data => [{:name => 'field1', :value => 'test1'}, {:name => 'field2', :value => 'test2'}], :custom_width => 200, :custom_height => 100)
19
+ get :new, :tag => asset.tag_list.to_s
20
+ assert_response :success
21
+
22
+ new_asset = assigns(:asset)
23
+ assert_equal 'test', new_asset.tag_list.to_s
24
+ assert_equal 2, new_asset.meta_data.length
25
+ # values are removed from new assets
26
+ assert_equal 'field1', new_asset.meta_data[0][:name]
27
+ assert_equal '', new_asset.meta_data[0][:value]
28
+ assert_equal 'field2', new_asset.meta_data[1][:name]
29
+ assert_equal '', new_asset.meta_data[1][:value]
30
+ assert_equal 200, new_asset.custom_width
31
+ assert_equal 100, new_asset.custom_height
32
+
33
+ assert_select '#meta_fields li', new_asset.meta_data.length
34
+ end
35
+
36
+ should "not populate the new asset with tag and meta details" do
37
+ asset = Factory(:image_asset, :context => @company, :tag_list => 'test', :meta_data => [{:name => 'field1', :value => 'test1'}, {:name => 'field2', :value => 'test2'}])
38
+ get :new, :tag => 'unknown'
39
+ assert_response :success
40
+
41
+ new_asset = assigns(:asset)
42
+ assert_equal 'unknown', new_asset.tag_list.to_s
43
+ assert_nil new_asset.meta_data
44
+ end
45
+ end
46
+
47
+ context "create" do
48
+ teardown do
49
+ cleanup_assets
50
+ end
51
+
52
+ should "create an asset" do
53
+ asset_file = asset_file('new_test.pdf')
54
+ setup_asset asset_file
55
+
56
+ post :create, :cms_asset => {:asset => fixture_file_upload(File.join('assets', File.basename(asset_file))), :meta => {'new_0' => {:name => 'key_a', :value => 'test'}, 'new_1' => {:name => 'key_b', :value => 'test'}} }
57
+ assert_response :redirect
58
+ assert_redirected_to cms_root_path
59
+
60
+ asset = assigns(:asset)
61
+ assert_equal 2, asset.meta_data.length
62
+ end
16
63
  end
17
64
 
18
65
  context "show" do
@@ -39,7 +86,7 @@ class Cms::AssetsControllerTest < ActionController::TestCase
39
86
 
40
87
  context "edit" do
41
88
  should "show form for an editable asset with a textarea" do
42
- Cms::Asset.any_instance.stubs(:asset).returns(stub(:to_file => stub(:read => 'test contents')))
89
+ Cms::Asset.any_instance.stubs(:asset).returns(stub(:url => 'test.com', :to_file => stub(:read => 'test contents')))
43
90
  asset = Factory(:js_asset, :context => @company)
44
91
 
45
92
  get :edit, :id => asset.id
@@ -78,24 +125,33 @@ class Cms::AssetsControllerTest < ActionController::TestCase
78
125
  assert_equal File.basename(new_asset_file), asset.reload.asset_file_name
79
126
  end
80
127
 
81
- should "modify the contents of an editable asset file" do
128
+ should "modify the contents of a non-editable asset file" do
82
129
  asset = Factory(:pdf_asset, :context => @company)
83
- put :update, :id => asset, :file_content => 'new content'
84
- assert_response :success
85
- assert_template 'edit'
130
+
131
+ # file contents are ignored for non-editable assets
132
+ put :update, :id => asset, :cms_asset => {:file_content => 'new content'}
133
+ assert_response :redirect
134
+ assert_redirected_to cms_root_path
86
135
  end
87
136
 
88
- should "modify the contents of an non-editable asset file" do
137
+ should "modify the contents of an editable asset file and it's meta data" do
89
138
  asset = Factory(:js_asset, :context => @company)
139
+ assert_nil asset.meta_data
140
+ assert_equal 0, asset.meta.length
90
141
 
91
142
  asset_file = asset_file(asset.asset_file_name)
92
143
  setup_asset asset_file
93
144
 
94
145
  Cms::Asset.any_instance.stubs(:asset => stub(:path => asset_file))
95
- Cms::Asset.any_instance.expects(:write).with('new content').returns(true)
146
+ Cms::Asset.any_instance.expects(:file_content=).with('new content').returns('new content')
96
147
 
97
- put :update, :id => asset, :file_content => 'new content'
148
+ put :update, :id => asset, :cms_asset => {:file_content => 'new content', :meta => {'new_0' => {:name => 'key_a', :value => 'test'}, 'new_1' => {:name => 'key_b', :value => 'test'}}}
98
149
  assert_response :redirect
150
+ assert_redirected_to cms_root_path
151
+
152
+ asset.reload
153
+ assert_not_nil asset.meta_data
154
+ assert_equal 2, asset.meta.length
99
155
  end
100
156
  end
101
157
 
@@ -112,14 +168,6 @@ class Cms::AssetsControllerTest < ActionController::TestCase
112
168
  assert_redirected_to cms_root_path
113
169
  assert_nil @company.assets.find_by_id(@asset.id)
114
170
  end
115
-
116
- should "destroy asset via XHR :DELETE" do
117
- assert_not_nil @company.assets.find_by_id(@asset.id)
118
-
119
- xhr :delete, :destroy, :id => @asset
120
- assert_response :success
121
- assert_nil @company.assets.find_by_id(@asset.id)
122
- end
123
171
  end
124
172
  end
125
173
  end