slices 1.0.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.
Files changed (215) hide show
  1. data/CHANGELOG.md +3 -0
  2. data/README.md +51 -0
  3. data/Rakefile +9 -0
  4. data/app/assets/images/slices/ajax-loader.gif +0 -0
  5. data/app/assets/images/slices/asset-background.png +0 -0
  6. data/app/assets/images/slices/asset-spinner.gif +0 -0
  7. data/app/assets/images/slices/bg_header.gif +0 -0
  8. data/app/assets/images/slices/black-Linen.png +0 -0
  9. data/app/assets/images/slices/calendar.svg +68 -0
  10. data/app/assets/images/slices/chosen-sprite.png +0 -0
  11. data/app/assets/images/slices/drag-handle.svg +9 -0
  12. data/app/assets/images/slices/icon_admins.png +0 -0
  13. data/app/assets/images/slices/icon_app.png +0 -0
  14. data/app/assets/images/slices/icon_assets.png +0 -0
  15. data/app/assets/images/slices/icon_collapse.png +0 -0
  16. data/app/assets/images/slices/icon_drag.png +0 -0
  17. data/app/assets/images/slices/icon_files.png +0 -0
  18. data/app/assets/images/slices/icon_generic_file.png +0 -0
  19. data/app/assets/images/slices/icon_images.png +0 -0
  20. data/app/assets/images/slices/icon_padlock.png +0 -0
  21. data/app/assets/images/slices/icon_page.png +0 -0
  22. data/app/assets/images/slices/icon_search.png +0 -0
  23. data/app/assets/images/slices/icon_set-link.png +0 -0
  24. data/app/assets/images/slices/icon_set.png +0 -0
  25. data/app/assets/images/slices/icon_sitemap.png +0 -0
  26. data/app/assets/images/slices/icon_snippets.png +0 -0
  27. data/app/assets/images/slices/icon_template.jpg +0 -0
  28. data/app/assets/images/slices/icon_upload_happy.png +0 -0
  29. data/app/assets/images/slices/icon_upload_sad.png +0 -0
  30. data/app/assets/images/slices/icon_upload_thinking.png +0 -0
  31. data/app/assets/images/slices/noise.png +0 -0
  32. data/app/assets/images/slices/sitemap_icon_ghost.png +0 -0
  33. data/app/assets/images/slices/sitemap_icon_home.png +0 -0
  34. data/app/assets/images/slices/sitemap_icon_page.png +0 -0
  35. data/app/assets/images/slices/sitemap_icon_set_page.png +0 -0
  36. data/app/assets/images/slices/sitemap_icon_virtual_page.png +0 -0
  37. data/app/assets/images/slices/sitemap_overlay.png +0 -0
  38. data/app/assets/images/slices/spinner.gif +0 -0
  39. data/app/assets/images/slices/trash.png +0 -0
  40. data/app/assets/javascripts/admin.js.erb +18 -0
  41. data/app/assets/javascripts/slices/app/backbones/admins.js +114 -0
  42. data/app/assets/javascripts/slices/app/backbones/entries.js +172 -0
  43. data/app/assets/javascripts/slices/app/backbones/generic.js +101 -0
  44. data/app/assets/javascripts/slices/app/backbones/snippets.js +113 -0
  45. data/app/assets/javascripts/slices/app/helpers/assets.js +61 -0
  46. data/app/assets/javascripts/slices/app/helpers/breadcrumbs.js +30 -0
  47. data/app/assets/javascripts/slices/app/helpers/composer.js +26 -0
  48. data/app/assets/javascripts/slices/app/helpers/date_field.js +16 -0
  49. data/app/assets/javascripts/slices/app/helpers/get_value.js +31 -0
  50. data/app/assets/javascripts/slices/app/helpers/icon_upload_names.js.erb +5 -0
  51. data/app/assets/javascripts/slices/app/helpers/layout.js +20 -0
  52. data/app/assets/javascripts/slices/app/helpers/sitemap.js +150 -0
  53. data/app/assets/javascripts/slices/app/helpers/slice_preview.js +48 -0
  54. data/app/assets/javascripts/slices/app/helpers/tagging.js +73 -0
  55. data/app/assets/javascripts/slices/app/helpers/token_field.js +17 -0
  56. data/app/assets/javascripts/slices/app/helpers/upload_icons.js.erb +5 -0
  57. data/app/assets/javascripts/slices/app/helpers/uploader.js +127 -0
  58. data/app/assets/javascripts/slices/app/models/asset.js +29 -0
  59. data/app/assets/javascripts/slices/app/models/asset_collection.js +41 -0
  60. data/app/assets/javascripts/slices/app/models/attachment.js +29 -0
  61. data/app/assets/javascripts/slices/app/models/attachment_collection.js +7 -0
  62. data/app/assets/javascripts/slices/app/models/composer_item.js +1 -0
  63. data/app/assets/javascripts/slices/app/models/composer_item_collection.js +3 -0
  64. data/app/assets/javascripts/slices/app/models/file.js +103 -0
  65. data/app/assets/javascripts/slices/app/models/page.js +186 -0
  66. data/app/assets/javascripts/slices/app/models/s3_file.js +64 -0
  67. data/app/assets/javascripts/slices/app/slices.js +661 -0
  68. data/app/assets/javascripts/slices/app/views/asset_editor_view.js.erb +209 -0
  69. data/app/assets/javascripts/slices/app/views/asset_library_view.js +720 -0
  70. data/app/assets/javascripts/slices/app/views/asset_thumb_view.js.erb +191 -0
  71. data/app/assets/javascripts/slices/app/views/attachment_composer_view.js +350 -0
  72. data/app/assets/javascripts/slices/app/views/attachment_view.js +101 -0
  73. data/app/assets/javascripts/slices/app/views/calendar_view.js +198 -0
  74. data/app/assets/javascripts/slices/app/views/composer_item_view.js +54 -0
  75. data/app/assets/javascripts/slices/app/views/composer_view.js +130 -0
  76. data/app/assets/javascripts/slices/app/views/date_field_view.js +177 -0
  77. data/app/assets/javascripts/slices/app/views/file_view.js +142 -0
  78. data/app/assets/javascripts/slices/app/views/token_field_view.js +253 -0
  79. data/app/assets/javascripts/slices/lib/freeze.js +14 -0
  80. data/app/assets/javascripts/slices/lib/human_file_size.js +16 -0
  81. data/app/assets/javascripts/slices/lib/json_patch.js +9 -0
  82. data/app/assets/javascripts/slices/lib/moment.js +47 -0
  83. data/app/assets/javascripts/slices/lib/plugins.js +101 -0
  84. data/app/assets/javascripts/slices/lib/sortable.js +14 -0
  85. data/app/assets/javascripts/slices/slices.js +27 -0
  86. data/app/assets/javascripts/slices/vendor/autoscroll.js +188 -0
  87. data/app/assets/javascripts/slices/vendor/backbone.js +38 -0
  88. data/app/assets/javascripts/slices/vendor/handlebars.js +1920 -0
  89. data/app/assets/javascripts/slices/vendor/jqmodal.js +69 -0
  90. data/app/assets/javascripts/slices/vendor/jquery-ui.js +274 -0
  91. data/app/assets/javascripts/slices/vendor/jquery-ui_nested-sortable.js +357 -0
  92. data/app/assets/javascripts/slices/vendor/jquery.ajaxprogress.js +76 -0
  93. data/app/assets/javascripts/slices/vendor/jquery.js +2 -0
  94. data/app/assets/javascripts/slices/vendor/livefield.js +459 -0
  95. data/app/assets/javascripts/slices/vendor/moment.js +6 -0
  96. data/app/assets/javascripts/slices/vendor/rails.js +315 -0
  97. data/app/assets/javascripts/slices/vendor/underscore-string.js +1 -0
  98. data/app/assets/javascripts/slices/vendor/underscore.js +5 -0
  99. data/app/assets/stylesheets/admin.css +1 -0
  100. data/app/assets/stylesheets/slices/admin.css.erb +2237 -0
  101. data/app/assets/stylesheets/slices/reset_html5.css +106 -0
  102. data/app/assets/stylesheets/slices/slices.css +7 -0
  103. data/app/controllers/admin/admin_controller.rb +10 -0
  104. data/app/controllers/admin/admins_controller.rb +76 -0
  105. data/app/controllers/admin/assets_controller.rb +53 -0
  106. data/app/controllers/admin/auth/omniauth_callbacks_controller.rb +15 -0
  107. data/app/controllers/admin/auth/passwords_controller.rb +4 -0
  108. data/app/controllers/admin/auth/sessions_controller.rb +4 -0
  109. data/app/controllers/admin/entries_controller.rb +88 -0
  110. data/app/controllers/admin/page_search_controller.rb +12 -0
  111. data/app/controllers/admin/pages_controller.rb +103 -0
  112. data/app/controllers/admin/site_maps_controller.rb +15 -0
  113. data/app/controllers/admin/snippets_controller.rb +33 -0
  114. data/app/controllers/application_controller.rb +4 -0
  115. data/app/controllers/pages_controller.rb +45 -0
  116. data/app/controllers/slices_controller.rb +63 -0
  117. data/app/controllers/static_assets_controller.rb +52 -0
  118. data/app/helpers/admin/admin_helper.rb +63 -0
  119. data/app/helpers/admin/assets_helper.rb +36 -0
  120. data/app/helpers/admin/entries_helper.rb +13 -0
  121. data/app/helpers/admin/site_maps_helper.rb +104 -0
  122. data/app/helpers/assets_helper.rb +64 -0
  123. data/app/helpers/navigation_helper.rb +195 -0
  124. data/app/helpers/pages_helper.rb +119 -0
  125. data/app/models/admin.rb +34 -0
  126. data/app/models/asset.rb +211 -0
  127. data/app/models/attachment.rb +11 -0
  128. data/app/models/layout.rb +44 -0
  129. data/app/models/page.rb +214 -0
  130. data/app/models/placeholder_slice.rb +8 -0
  131. data/app/models/set_page.rb +12 -0
  132. data/app/models/set_slice.rb +57 -0
  133. data/app/models/site_map.rb +24 -0
  134. data/app/models/slice.rb +80 -0
  135. data/app/models/snippet.rb +21 -0
  136. data/app/observers/asset_observer.rb +6 -0
  137. data/app/observers/page_observer.rb +37 -0
  138. data/app/presenters/entry_presenter.rb +17 -0
  139. data/app/presenters/page_presenter.rb +67 -0
  140. data/app/presenters/presenter.rb +9 -0
  141. data/app/presenters/set_page_presenter.rb +2 -0
  142. data/app/views/admin/admins/index.html.erb +26 -0
  143. data/app/views/admin/admins/show.html.erb +27 -0
  144. data/app/views/admin/assets/index.html.erb +1 -0
  145. data/app/views/admin/auth/passwords/edit.html.erb +20 -0
  146. data/app/views/admin/auth/passwords/new.html.erb +14 -0
  147. data/app/views/admin/auth/sessions/_form.html.erb +35 -0
  148. data/app/views/admin/auth/sessions/new.html.erb +14 -0
  149. data/app/views/admin/entries/index.html.erb +32 -0
  150. data/app/views/admin/pages/_breadcrumbs.html.erb +32 -0
  151. data/app/views/admin/pages/_slices.html.erb +27 -0
  152. data/app/views/admin/pages/new.html.erb +14 -0
  153. data/app/views/admin/pages/show.html.erb +50 -0
  154. data/app/views/admin/shared/_asset_storage.html.erb +17 -0
  155. data/app/views/admin/shared/_custom_links.html.erb +1 -0
  156. data/app/views/admin/shared/_custom_navigation.html.erb +1 -0
  157. data/app/views/admin/shared/_navigation.html.erb +5 -0
  158. data/app/views/admin/site_maps/_page_li.html.erb +20 -0
  159. data/app/views/admin/site_maps/_set_page_li.html.erb +23 -0
  160. data/app/views/admin/site_maps/index.html.erb +29 -0
  161. data/app/views/admin/snippets/form.html.erb +12 -0
  162. data/app/views/admin/snippets/index.html.erb +20 -0
  163. data/app/views/admin/snippets/update.html.erb +0 -0
  164. data/app/views/layouts/admin.html.erb +72 -0
  165. data/lib/ext/file_store_cache.rb +18 -0
  166. data/lib/generators/humans/USAGE +8 -0
  167. data/lib/generators/humans/humans_generator.rb +10 -0
  168. data/lib/generators/humans/templates/humans.txt +6 -0
  169. data/lib/generators/slice/USAGE +28 -0
  170. data/lib/generators/slice/slice_generator.rb +123 -0
  171. data/lib/generators/slice/templates/main_fields.hbs +11 -0
  172. data/lib/generators/slice/templates/meta_fields.hbs +11 -0
  173. data/lib/generators/slice/templates/page.rb +19 -0
  174. data/lib/generators/slice/templates/presenter.rb +53 -0
  175. data/lib/generators/slice/templates/set.html.erb +8 -0
  176. data/lib/generators/slice/templates/set_slice.rb +14 -0
  177. data/lib/generators/slice/templates/set_slice_fields.hbs +5 -0
  178. data/lib/generators/slice/templates/show.html.erb +48 -0
  179. data/lib/generators/slice/templates/show_slice.rb +20 -0
  180. data/lib/generators/slice/templates/slice.rb +58 -0
  181. data/lib/generators/slice/templates/slice_fields.hbs +74 -0
  182. data/lib/generators/templates/slices.rb +211 -0
  183. data/lib/mongo_search.rb +84 -0
  184. data/lib/paperclip_validator.rb +5 -0
  185. data/lib/rack_utf8_fix.rb +10 -0
  186. data/lib/sRGB.icc +0 -0
  187. data/lib/set_link_renderer.rb +31 -0
  188. data/lib/slices.rb +68 -0
  189. data/lib/slices/asset/maker.rb +55 -0
  190. data/lib/slices/asset/rename.rb +67 -0
  191. data/lib/slices/available_slices.rb +43 -0
  192. data/lib/slices/cms_form_builder.rb +42 -0
  193. data/lib/slices/config.rb +93 -0
  194. data/lib/slices/container_parser.rb +70 -0
  195. data/lib/slices/generator_macros.rb +36 -0
  196. data/lib/slices/has_attachments.rb +111 -0
  197. data/lib/slices/has_slices.rb +88 -0
  198. data/lib/slices/i18n.rb +6 -0
  199. data/lib/slices/i18n/backend.rb +32 -0
  200. data/lib/slices/i18n_backend.rb +24 -0
  201. data/lib/slices/paperclip.rb +13 -0
  202. data/lib/slices/position_helper.rb +98 -0
  203. data/lib/slices/renderer.rb +52 -0
  204. data/lib/slices/slices_engine.rb +51 -0
  205. data/lib/slices/split_date_time_field.rb +14 -0
  206. data/lib/slices/tasks/assets.rake +35 -0
  207. data/lib/slices/tasks/db.rake +50 -0
  208. data/lib/slices/tasks/seeds.rake +93 -0
  209. data/lib/slices/tasks/validate.rake +62 -0
  210. data/lib/slices/tree.rb +306 -0
  211. data/lib/slices/version.rb +4 -0
  212. data/lib/slices/will_paginate.rb +12 -0
  213. data/lib/slices/will_paginate_mongoid.rb +45 -0
  214. data/lib/standard_tree.rb +193 -0
  215. metadata +483 -0
@@ -0,0 +1,84 @@
1
+ module MongoSearch
2
+ class KeywordsExtractor
3
+ def self.extract(text)
4
+ if text.blank?
5
+ []
6
+ else
7
+ text.mb_chars.normalize(:kd).to_s
8
+ .gsub(/[^\x00-\x7F]/,'')
9
+ .downcase
10
+ .split(/[\s\.\-_]+/)
11
+ end
12
+ end
13
+ end
14
+
15
+ module Searchable
16
+ extend ActiveSupport::Concern
17
+
18
+ included do
19
+ cattr_accessor :search_fields, :match
20
+ end
21
+
22
+ module ClassMethods
23
+ def text_search_in(*args)
24
+ options = args.pop if args.last.has_key?(:match)
25
+ self.match = options[:match]
26
+ rescue NoMethodError
27
+ ensure
28
+ self.match ||= :all
29
+ self.search_fields = args
30
+
31
+ field :_keywords, type: Array
32
+ index :_keywords
33
+
34
+ before_save :set_keywords
35
+ end
36
+
37
+ def search_in(*args)
38
+ warn('[DEPRECATION `search_in` is deprecated. Please use `text_search_in` instead.')
39
+ text_search_in(args)
40
+ end
41
+
42
+ def text_search(query)
43
+ words = KeywordsExtractor.extract(query).map { |word| /#{word}/ }
44
+ self.send("#{self.match}_in", _keywords: words)
45
+ end
46
+
47
+ def search(query)
48
+ warn("[DEPRECATION] `search` is deprecated. Please use `text_search` instead.")
49
+ text_search(query)
50
+ end
51
+ end
52
+
53
+ private
54
+ def set_keywords
55
+ self._keywords = []
56
+ search_fields.each do |field|
57
+ if field.respond_to?(:each)
58
+ field.each do |name, attribute|
59
+ extract_keywords_for_association(name, attribute)
60
+ end
61
+ elsif respond_to?(field)
62
+ extract_keywords(send(field))
63
+ else
64
+ extract_keywords(self[field])
65
+ end
66
+ end
67
+ self._keywords.uniq!
68
+ end
69
+
70
+ def extract_keywords(text)
71
+ self._keywords += KeywordsExtractor.extract(text) unless text.nil?
72
+ end
73
+
74
+ def extract_keywords_for_association(name, attribute)
75
+ association = send(name)
76
+ return [] if association.nil?
77
+ if association.respond_to?(:each)
78
+ association.each { |doc| extract_keywords(doc[attribute]) }
79
+ else
80
+ extract_keywords(association[attribute])
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,5 @@
1
+ class PaperclipValidator < ActiveModel::Validator
2
+ def validate(record)
3
+ record.errors[:file] << 'Must specify a file' unless record.file_file_name.present?
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ require 'escape_utils'
2
+
3
+ module Rack
4
+ module Utils
5
+ def escape s
6
+ EscapeUtils.escape_url s.to_s
7
+ end
8
+ end
9
+ end
10
+
data/lib/sRGB.icc ADDED
Binary file
@@ -0,0 +1,31 @@
1
+ require 'will_paginate/view_helpers/action_view'
2
+
3
+ class SetLinkRenderer < WillPaginate::ViewHelpers::LinkRenderer
4
+ protected
5
+ # This method has been largely robbed from will_paginate's
6
+ # lib/will_paginate/view_helpers/action_view.rb file, whose
7
+ # implementation only differs in that it assumes that you're using
8
+ # controller: 'foo', action: 'bar' compatible routes.
9
+ #
10
+ def url(page)
11
+ @base_url_params ||= begin
12
+ url_params = base_url_params
13
+ merge_optional_params(url_params)
14
+ url_params
15
+ end
16
+
17
+ url_params = @base_url_params.dup
18
+ path = url_params.delete(:path)
19
+ add_current_page_param(url_params, page)
20
+ remove_unwanted_params(url_params)
21
+ if url_params.empty?
22
+ "/#{path}"
23
+ else
24
+ "/#{path}?" + url_params.map { |k, v| "#{k}=#{v}" }.join('&')
25
+ end
26
+ end
27
+
28
+ def remove_unwanted_params(url_params)
29
+ [:controller, :action, :escape].each { |p| url_params.delete(p) }
30
+ end
31
+ end
data/lib/slices.rb ADDED
@@ -0,0 +1,68 @@
1
+ require 'rails'
2
+ require 'bson'
3
+ require 'devise'
4
+ require 'mongo'
5
+ require 'mongoid'
6
+ require 'mongoid_paperclip'
7
+ require 'RedCloth'
8
+ require 'redcarpet'
9
+ require 'stringex'
10
+
11
+ require 'slices/paperclip'
12
+ require 'slices/version'
13
+
14
+ require 'mongo_search'
15
+ require 'ext/file_store_cache'
16
+
17
+ module Slices
18
+ autoload :Config, 'slices/config'
19
+ autoload :CmsFormBuilder, 'slices/cms_form_builder'
20
+ autoload :AvailableSlices, 'slices/available_slices'
21
+ autoload :ContainerParser, 'slices/container_parser'
22
+ autoload :GeneratorMacros, 'slices/generator_macros'
23
+ autoload :HasSlices, 'slices/has_slices'
24
+ autoload :HasAttachments, 'slices/has_attachments'
25
+ autoload :Renderer, 'slices/renderer'
26
+ autoload :PositionHelper, 'slices/position_helper'
27
+ autoload :SplitDateTimeField, 'slices/split_date_time_field'
28
+ autoload :Tree, 'slices/tree'
29
+
30
+ module Asset
31
+ autoload :Maker, 'slices/asset/maker'
32
+ autoload :Rename, 'slices/asset/rename'
33
+ end
34
+
35
+ def self.gem_path
36
+ File.expand_path('..', File.dirname(__FILE__))
37
+ end
38
+
39
+ def self.load_slice_classes_into_object_space(root)
40
+ Dir.glob(File.join(root, 'app', 'slices', '**/*.rb')).each do |file|
41
+ constant = File.basename(file, '.rb').camelize
42
+ Object.const_get(constant)
43
+ end
44
+ end
45
+
46
+ def self.test_environment?
47
+ Rails.env.test? && Rails.root.to_s == Slices.gem_path
48
+ end
49
+
50
+ end
51
+
52
+ require 'slices/slices_engine' if defined?(Rails)
53
+ require 'slices/i18n'
54
+ require 'slices/will_paginate_mongoid'
55
+ require 'slices/will_paginate'
56
+ require 'set_link_renderer'
57
+
58
+ if Rails.env.development?
59
+ Slices::Config.use_snippets!
60
+ end
61
+ if Rails.env.test? || Rails.env.development?
62
+ require 'standard_tree'
63
+ end
64
+
65
+ Mime::Type.register_alias 'text/plain', :hbs
66
+ Time::DATE_FORMATS.merge!(
67
+ day_month_year: '%d %B %Y'
68
+ )
@@ -0,0 +1,55 @@
1
+ module Slices
2
+ module Asset
3
+ class Maker
4
+
5
+ attr_accessor :args, :new_asset
6
+
7
+ def self.run(args)
8
+ new(args).run
9
+ end
10
+
11
+ def initialize(args)
12
+ self.args = args
13
+ end
14
+
15
+ def create_new_asset
16
+ ::Asset.create!(args)
17
+ end
18
+
19
+ def find_matching_asset(new_asset)
20
+ ::Asset.first(conditions: {
21
+ file_fingerprint: new_asset.file_fingerprint, :_id.ne => new_asset.id
22
+ })
23
+ end
24
+
25
+ def tempfile_stored_on_s3?
26
+ Slices::Config.s3_storage? &&
27
+ args[:file].is_a?(URI)
28
+ end
29
+
30
+ def s3_path
31
+ s3_path = args[:file].path
32
+ s3_path[s3_path.index(Slices::Config::S3_TEMPFILE_KEY_PREFIX) .. -1]
33
+ end
34
+
35
+ def delete_tempfile_from_s3
36
+ directory = new_asset.file.send(:directory)
37
+ directory.files.new(key: s3_path).destroy
38
+ end
39
+
40
+ def run
41
+ self.new_asset = create_new_asset
42
+ delete_tempfile_from_s3 if tempfile_stored_on_s3?
43
+ matching_asset = find_matching_asset(new_asset)
44
+
45
+ if matching_asset.present?
46
+ new_asset.destroy
47
+ matching_asset.soft_restore!
48
+ matching_asset
49
+ else
50
+ new_asset
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,67 @@
1
+ require 'active_support/inflector'
2
+
3
+ module Slices
4
+ module Asset
5
+ module Rename
6
+ class UnsupportedStorage < ::StandardError; end
7
+
8
+ def self.run(file, new_file_name)
9
+ klass = ('Slices::Asset::Rename::' + file.options[:storage].to_s.classify).constantize
10
+ klass.new(file, new_file_name).run
11
+ rescue NameError
12
+ raise UnsupportedStorage,
13
+ "Renaming files with '#{file.options[:storage]}' is not supported"
14
+ end
15
+
16
+ class Base
17
+ attr_accessor :file, :new_file_name
18
+
19
+ def initialize(file, new_file_name)
20
+ self.file = file
21
+ self.new_file_name = new_file_name
22
+ end
23
+
24
+ def run
25
+ (file.styles.keys + [:original]).each do |style|
26
+ next unless file.exists?(style)
27
+ rename(style)
28
+ end
29
+ end
30
+
31
+ def rename(style)
32
+ @old_path = file.path(style)
33
+ @new_path = File.join(File.dirname(@old_path), @new_file_name)
34
+ end
35
+ end
36
+
37
+ class Filesystem < Base
38
+ def rename(style)
39
+ super
40
+ File.rename(@old_path, @new_path)
41
+ end
42
+ end
43
+
44
+ class Fog < Base
45
+ def new_path
46
+ @new_path[1 .. -1]
47
+ end
48
+
49
+ def rename(style)
50
+ super
51
+ file = directory.files.new(key: @old_path)
52
+ file.copy(
53
+ directory.key,
54
+ @new_path,
55
+ {'x-amz-acl' => 'public-read'}
56
+ )
57
+ file.destroy
58
+ end
59
+
60
+ def directory
61
+ @directory ||= file.send(:directory)
62
+ end
63
+ end
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,43 @@
1
+ module Slices
2
+ class AvailableSlices
3
+
4
+ def self.all
5
+ # We've memoized the slices so that we never try and load them all
6
+ # twice. If we iterate over ObjectSpace twice (see find_all_slices)
7
+ # we sometimes find that an incomplete set of slices objects is
8
+ # returned on subsequent calls.
9
+ @all ||= find_all_slices
10
+ end
11
+
12
+ private
13
+
14
+ def self.find_all_slices
15
+ slices = []
16
+
17
+ Dir.glob(File.join(Rails.root, 'app/slices/**/*_slice.rb')).each do |path|
18
+
19
+ slice_name = File.basename(path, '.rb')
20
+ klass = slice_name.camelize.constantize
21
+ basename = File.basename(path, '_slice.rb')
22
+ folder = File.basename(File.dirname(path))
23
+
24
+ fields = {
25
+ 'name' => basename.humanize.titleize,
26
+ 'template' => File.join(folder, basename),
27
+ 'restricted' => klass.restricted?
28
+ }
29
+
30
+ klass.fields.each do |name, field|
31
+ next if Slice.fields[name]
32
+ fields[name] = field.default
33
+ end
34
+
35
+ slices << [basename, fields]
36
+
37
+ end
38
+
39
+ Hash[*slices.sort.flatten]
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,42 @@
1
+ module Slices
2
+ class CmsFormBuilder < ActionView::Helpers::FormBuilder
3
+
4
+ FIELD_ERROR_PROC = proc do |html_tag, instance_tag|
5
+ html_tag
6
+ end
7
+
8
+ %w{email_field password_field select text_area text_field}.each do |selector|
9
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
10
+ def cms_#{selector}(attribute, options = {}) # def cms_text_field(attribute, options = {})
11
+ wrap_field(:#{selector}, attribute, options) # wrap_field(:text_field, attribute, options)
12
+ end # end
13
+ RUBY_EVAL
14
+ end
15
+
16
+ private
17
+
18
+ def wrap_field(selector, attribute, options)
19
+ with_custom_field_error_proc do
20
+ content = send(selector, attribute, options)
21
+ options = {}
22
+ errors = @object.errors[attribute]
23
+
24
+ if errors.any?
25
+ options[:class] = 'error'
26
+ content << @template.send(:content_tag, :p, errors.join(' and '))
27
+ end
28
+
29
+ @template.content_tag(:li, label(attribute) + content, options)
30
+ end
31
+ end
32
+
33
+ def with_custom_field_error_proc(&block)
34
+ default_field_error_proc = ::ActionView::Base.field_error_proc
35
+ ::ActionView::Base.field_error_proc = FIELD_ERROR_PROC
36
+ yield
37
+ ensure
38
+ ::ActionView::Base.field_error_proc = default_field_error_proc
39
+ end
40
+ end
41
+
42
+ end
@@ -0,0 +1,93 @@
1
+ module Slices
2
+ class Config
3
+ S3_TEMPFILE_KEY_PREFIX = 'uploads'
4
+
5
+ # Set the asset styles for the app, this is a hash with the keys as the
6
+ # style names and Papcerlip resize options
7
+ #
8
+ # Slices::Config.add_asset_styles(
9
+ # :thumbnail => "220x146#",
10
+ # :full_width => "971x440#",
11
+ # :feature_full => "971x475#",
12
+ # :slideshow => "723x440>",
13
+ # )
14
+ #
15
+ # @param [Hash] options
16
+ def self.add_asset_styles(options = {})
17
+ @asset_styles = options.merge(admin_asset_styles)
18
+ end
19
+
20
+ # The list of asset styles in use
21
+ #
22
+ # @return [Hash]
23
+ def self.asset_styles
24
+ @asset_styles || add_asset_styles
25
+ end
26
+
27
+ # Enable snippets
28
+ def self.use_snippets!
29
+ @snippets = true
30
+ end
31
+
32
+ # Does this app use snippets?
33
+ # @return [Boolean]
34
+ def self.snippets?
35
+ @snippets || false
36
+ end
37
+
38
+ def self.s3_storage?
39
+ Paperclip::Attachment.default_options[:storage].to_sym == :fog
40
+ end
41
+
42
+ # S3 credentaials taken from the papercip defaults
43
+ #
44
+ # {
45
+ # :bucket => 'slices-demo',
46
+ # :access_key_id => 'access key id',
47
+ # :secret_access_key => 'secret access key',
48
+ # }
49
+ #
50
+ # @return Hash
51
+ def self.s3_credentials
52
+ default_options = Paperclip::Attachment.default_options
53
+ {
54
+ bucket: default_options[:fog_directory],
55
+ access_key_id: default_options[:fog_credentials][:aws_access_key_id],
56
+ secret_access_key: default_options[:fog_credentials][:aws_secret_access_key],
57
+ }
58
+ end
59
+
60
+ # Google Apps domain for quick auth.
61
+ #
62
+ # @return [String] the domain
63
+ def self.google_apps_domain
64
+ @google_apps_domain
65
+ end
66
+
67
+ # Set Google Apps domain for quick auth.
68
+ #
69
+ # @param [String] the domain
70
+ def self.google_apps_domain=(domain)
71
+ @google_apps_domain = domain
72
+ end
73
+
74
+ private
75
+ def self.admin_asset_styles
76
+ { admin: '180x180#' }
77
+ end
78
+
79
+ # Addition Paperclip convert options which are applied to all styles.
80
+ # This removes colour profiles, sets the dpi to 72 dpi (the image is not
81
+ # resampled). The colour depth is set to 8 bits per pixel
82
+ def self.asset_convert_options
83
+ Hash.new.tap do |options|
84
+ asset_styles.keys.each do |style|
85
+ next if style == :original
86
+ options[style] = "-strip -density 72x72 -depth 8"
87
+ end
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ end