slices 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +3 -0
- data/README.md +51 -0
- data/Rakefile +9 -0
- data/app/assets/images/slices/ajax-loader.gif +0 -0
- data/app/assets/images/slices/asset-background.png +0 -0
- data/app/assets/images/slices/asset-spinner.gif +0 -0
- data/app/assets/images/slices/bg_header.gif +0 -0
- data/app/assets/images/slices/black-Linen.png +0 -0
- data/app/assets/images/slices/calendar.svg +68 -0
- data/app/assets/images/slices/chosen-sprite.png +0 -0
- data/app/assets/images/slices/drag-handle.svg +9 -0
- data/app/assets/images/slices/icon_admins.png +0 -0
- data/app/assets/images/slices/icon_app.png +0 -0
- data/app/assets/images/slices/icon_assets.png +0 -0
- data/app/assets/images/slices/icon_collapse.png +0 -0
- data/app/assets/images/slices/icon_drag.png +0 -0
- data/app/assets/images/slices/icon_files.png +0 -0
- data/app/assets/images/slices/icon_generic_file.png +0 -0
- data/app/assets/images/slices/icon_images.png +0 -0
- data/app/assets/images/slices/icon_padlock.png +0 -0
- data/app/assets/images/slices/icon_page.png +0 -0
- data/app/assets/images/slices/icon_search.png +0 -0
- data/app/assets/images/slices/icon_set-link.png +0 -0
- data/app/assets/images/slices/icon_set.png +0 -0
- data/app/assets/images/slices/icon_sitemap.png +0 -0
- data/app/assets/images/slices/icon_snippets.png +0 -0
- data/app/assets/images/slices/icon_template.jpg +0 -0
- data/app/assets/images/slices/icon_upload_happy.png +0 -0
- data/app/assets/images/slices/icon_upload_sad.png +0 -0
- data/app/assets/images/slices/icon_upload_thinking.png +0 -0
- data/app/assets/images/slices/noise.png +0 -0
- data/app/assets/images/slices/sitemap_icon_ghost.png +0 -0
- data/app/assets/images/slices/sitemap_icon_home.png +0 -0
- data/app/assets/images/slices/sitemap_icon_page.png +0 -0
- data/app/assets/images/slices/sitemap_icon_set_page.png +0 -0
- data/app/assets/images/slices/sitemap_icon_virtual_page.png +0 -0
- data/app/assets/images/slices/sitemap_overlay.png +0 -0
- data/app/assets/images/slices/spinner.gif +0 -0
- data/app/assets/images/slices/trash.png +0 -0
- data/app/assets/javascripts/admin.js.erb +18 -0
- data/app/assets/javascripts/slices/app/backbones/admins.js +114 -0
- data/app/assets/javascripts/slices/app/backbones/entries.js +172 -0
- data/app/assets/javascripts/slices/app/backbones/generic.js +101 -0
- data/app/assets/javascripts/slices/app/backbones/snippets.js +113 -0
- data/app/assets/javascripts/slices/app/helpers/assets.js +61 -0
- data/app/assets/javascripts/slices/app/helpers/breadcrumbs.js +30 -0
- data/app/assets/javascripts/slices/app/helpers/composer.js +26 -0
- data/app/assets/javascripts/slices/app/helpers/date_field.js +16 -0
- data/app/assets/javascripts/slices/app/helpers/get_value.js +31 -0
- data/app/assets/javascripts/slices/app/helpers/icon_upload_names.js.erb +5 -0
- data/app/assets/javascripts/slices/app/helpers/layout.js +20 -0
- data/app/assets/javascripts/slices/app/helpers/sitemap.js +150 -0
- data/app/assets/javascripts/slices/app/helpers/slice_preview.js +48 -0
- data/app/assets/javascripts/slices/app/helpers/tagging.js +73 -0
- data/app/assets/javascripts/slices/app/helpers/token_field.js +17 -0
- data/app/assets/javascripts/slices/app/helpers/upload_icons.js.erb +5 -0
- data/app/assets/javascripts/slices/app/helpers/uploader.js +127 -0
- data/app/assets/javascripts/slices/app/models/asset.js +29 -0
- data/app/assets/javascripts/slices/app/models/asset_collection.js +41 -0
- data/app/assets/javascripts/slices/app/models/attachment.js +29 -0
- data/app/assets/javascripts/slices/app/models/attachment_collection.js +7 -0
- data/app/assets/javascripts/slices/app/models/composer_item.js +1 -0
- data/app/assets/javascripts/slices/app/models/composer_item_collection.js +3 -0
- data/app/assets/javascripts/slices/app/models/file.js +103 -0
- data/app/assets/javascripts/slices/app/models/page.js +186 -0
- data/app/assets/javascripts/slices/app/models/s3_file.js +64 -0
- data/app/assets/javascripts/slices/app/slices.js +661 -0
- data/app/assets/javascripts/slices/app/views/asset_editor_view.js.erb +209 -0
- data/app/assets/javascripts/slices/app/views/asset_library_view.js +720 -0
- data/app/assets/javascripts/slices/app/views/asset_thumb_view.js.erb +191 -0
- data/app/assets/javascripts/slices/app/views/attachment_composer_view.js +350 -0
- data/app/assets/javascripts/slices/app/views/attachment_view.js +101 -0
- data/app/assets/javascripts/slices/app/views/calendar_view.js +198 -0
- data/app/assets/javascripts/slices/app/views/composer_item_view.js +54 -0
- data/app/assets/javascripts/slices/app/views/composer_view.js +130 -0
- data/app/assets/javascripts/slices/app/views/date_field_view.js +177 -0
- data/app/assets/javascripts/slices/app/views/file_view.js +142 -0
- data/app/assets/javascripts/slices/app/views/token_field_view.js +253 -0
- data/app/assets/javascripts/slices/lib/freeze.js +14 -0
- data/app/assets/javascripts/slices/lib/human_file_size.js +16 -0
- data/app/assets/javascripts/slices/lib/json_patch.js +9 -0
- data/app/assets/javascripts/slices/lib/moment.js +47 -0
- data/app/assets/javascripts/slices/lib/plugins.js +101 -0
- data/app/assets/javascripts/slices/lib/sortable.js +14 -0
- data/app/assets/javascripts/slices/slices.js +27 -0
- data/app/assets/javascripts/slices/vendor/autoscroll.js +188 -0
- data/app/assets/javascripts/slices/vendor/backbone.js +38 -0
- data/app/assets/javascripts/slices/vendor/handlebars.js +1920 -0
- data/app/assets/javascripts/slices/vendor/jqmodal.js +69 -0
- data/app/assets/javascripts/slices/vendor/jquery-ui.js +274 -0
- data/app/assets/javascripts/slices/vendor/jquery-ui_nested-sortable.js +357 -0
- data/app/assets/javascripts/slices/vendor/jquery.ajaxprogress.js +76 -0
- data/app/assets/javascripts/slices/vendor/jquery.js +2 -0
- data/app/assets/javascripts/slices/vendor/livefield.js +459 -0
- data/app/assets/javascripts/slices/vendor/moment.js +6 -0
- data/app/assets/javascripts/slices/vendor/rails.js +315 -0
- data/app/assets/javascripts/slices/vendor/underscore-string.js +1 -0
- data/app/assets/javascripts/slices/vendor/underscore.js +5 -0
- data/app/assets/stylesheets/admin.css +1 -0
- data/app/assets/stylesheets/slices/admin.css.erb +2237 -0
- data/app/assets/stylesheets/slices/reset_html5.css +106 -0
- data/app/assets/stylesheets/slices/slices.css +7 -0
- data/app/controllers/admin/admin_controller.rb +10 -0
- data/app/controllers/admin/admins_controller.rb +76 -0
- data/app/controllers/admin/assets_controller.rb +53 -0
- data/app/controllers/admin/auth/omniauth_callbacks_controller.rb +15 -0
- data/app/controllers/admin/auth/passwords_controller.rb +4 -0
- data/app/controllers/admin/auth/sessions_controller.rb +4 -0
- data/app/controllers/admin/entries_controller.rb +88 -0
- data/app/controllers/admin/page_search_controller.rb +12 -0
- data/app/controllers/admin/pages_controller.rb +103 -0
- data/app/controllers/admin/site_maps_controller.rb +15 -0
- data/app/controllers/admin/snippets_controller.rb +33 -0
- data/app/controllers/application_controller.rb +4 -0
- data/app/controllers/pages_controller.rb +45 -0
- data/app/controllers/slices_controller.rb +63 -0
- data/app/controllers/static_assets_controller.rb +52 -0
- data/app/helpers/admin/admin_helper.rb +63 -0
- data/app/helpers/admin/assets_helper.rb +36 -0
- data/app/helpers/admin/entries_helper.rb +13 -0
- data/app/helpers/admin/site_maps_helper.rb +104 -0
- data/app/helpers/assets_helper.rb +64 -0
- data/app/helpers/navigation_helper.rb +195 -0
- data/app/helpers/pages_helper.rb +119 -0
- data/app/models/admin.rb +34 -0
- data/app/models/asset.rb +211 -0
- data/app/models/attachment.rb +11 -0
- data/app/models/layout.rb +44 -0
- data/app/models/page.rb +214 -0
- data/app/models/placeholder_slice.rb +8 -0
- data/app/models/set_page.rb +12 -0
- data/app/models/set_slice.rb +57 -0
- data/app/models/site_map.rb +24 -0
- data/app/models/slice.rb +80 -0
- data/app/models/snippet.rb +21 -0
- data/app/observers/asset_observer.rb +6 -0
- data/app/observers/page_observer.rb +37 -0
- data/app/presenters/entry_presenter.rb +17 -0
- data/app/presenters/page_presenter.rb +67 -0
- data/app/presenters/presenter.rb +9 -0
- data/app/presenters/set_page_presenter.rb +2 -0
- data/app/views/admin/admins/index.html.erb +26 -0
- data/app/views/admin/admins/show.html.erb +27 -0
- data/app/views/admin/assets/index.html.erb +1 -0
- data/app/views/admin/auth/passwords/edit.html.erb +20 -0
- data/app/views/admin/auth/passwords/new.html.erb +14 -0
- data/app/views/admin/auth/sessions/_form.html.erb +35 -0
- data/app/views/admin/auth/sessions/new.html.erb +14 -0
- data/app/views/admin/entries/index.html.erb +32 -0
- data/app/views/admin/pages/_breadcrumbs.html.erb +32 -0
- data/app/views/admin/pages/_slices.html.erb +27 -0
- data/app/views/admin/pages/new.html.erb +14 -0
- data/app/views/admin/pages/show.html.erb +50 -0
- data/app/views/admin/shared/_asset_storage.html.erb +17 -0
- data/app/views/admin/shared/_custom_links.html.erb +1 -0
- data/app/views/admin/shared/_custom_navigation.html.erb +1 -0
- data/app/views/admin/shared/_navigation.html.erb +5 -0
- data/app/views/admin/site_maps/_page_li.html.erb +20 -0
- data/app/views/admin/site_maps/_set_page_li.html.erb +23 -0
- data/app/views/admin/site_maps/index.html.erb +29 -0
- data/app/views/admin/snippets/form.html.erb +12 -0
- data/app/views/admin/snippets/index.html.erb +20 -0
- data/app/views/admin/snippets/update.html.erb +0 -0
- data/app/views/layouts/admin.html.erb +72 -0
- data/lib/ext/file_store_cache.rb +18 -0
- data/lib/generators/humans/USAGE +8 -0
- data/lib/generators/humans/humans_generator.rb +10 -0
- data/lib/generators/humans/templates/humans.txt +6 -0
- data/lib/generators/slice/USAGE +28 -0
- data/lib/generators/slice/slice_generator.rb +123 -0
- data/lib/generators/slice/templates/main_fields.hbs +11 -0
- data/lib/generators/slice/templates/meta_fields.hbs +11 -0
- data/lib/generators/slice/templates/page.rb +19 -0
- data/lib/generators/slice/templates/presenter.rb +53 -0
- data/lib/generators/slice/templates/set.html.erb +8 -0
- data/lib/generators/slice/templates/set_slice.rb +14 -0
- data/lib/generators/slice/templates/set_slice_fields.hbs +5 -0
- data/lib/generators/slice/templates/show.html.erb +48 -0
- data/lib/generators/slice/templates/show_slice.rb +20 -0
- data/lib/generators/slice/templates/slice.rb +58 -0
- data/lib/generators/slice/templates/slice_fields.hbs +74 -0
- data/lib/generators/templates/slices.rb +211 -0
- data/lib/mongo_search.rb +84 -0
- data/lib/paperclip_validator.rb +5 -0
- data/lib/rack_utf8_fix.rb +10 -0
- data/lib/sRGB.icc +0 -0
- data/lib/set_link_renderer.rb +31 -0
- data/lib/slices.rb +68 -0
- data/lib/slices/asset/maker.rb +55 -0
- data/lib/slices/asset/rename.rb +67 -0
- data/lib/slices/available_slices.rb +43 -0
- data/lib/slices/cms_form_builder.rb +42 -0
- data/lib/slices/config.rb +93 -0
- data/lib/slices/container_parser.rb +70 -0
- data/lib/slices/generator_macros.rb +36 -0
- data/lib/slices/has_attachments.rb +111 -0
- data/lib/slices/has_slices.rb +88 -0
- data/lib/slices/i18n.rb +6 -0
- data/lib/slices/i18n/backend.rb +32 -0
- data/lib/slices/i18n_backend.rb +24 -0
- data/lib/slices/paperclip.rb +13 -0
- data/lib/slices/position_helper.rb +98 -0
- data/lib/slices/renderer.rb +52 -0
- data/lib/slices/slices_engine.rb +51 -0
- data/lib/slices/split_date_time_field.rb +14 -0
- data/lib/slices/tasks/assets.rake +35 -0
- data/lib/slices/tasks/db.rake +50 -0
- data/lib/slices/tasks/seeds.rake +93 -0
- data/lib/slices/tasks/validate.rake +62 -0
- data/lib/slices/tree.rb +306 -0
- data/lib/slices/version.rb +4 -0
- data/lib/slices/will_paginate.rb +12 -0
- data/lib/slices/will_paginate_mongoid.rb +45 -0
- data/lib/standard_tree.rb +193 -0
- metadata +483 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
module Slices
|
2
|
+
class ContainerParser
|
3
|
+
class MissingLayoutError < StandardError; end
|
4
|
+
|
5
|
+
def initialize(path)
|
6
|
+
raise MissingLayoutError if path.nil?
|
7
|
+
@path = path
|
8
|
+
@containers = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse
|
12
|
+
@page = Page.new
|
13
|
+
erb_template = File.read(@path)
|
14
|
+
@erb = ActionView::Template::Handlers::Erubis.new(erb_template)
|
15
|
+
parse_with_block {}
|
16
|
+
@containers
|
17
|
+
end
|
18
|
+
|
19
|
+
# Define a +container+ in a layout, a container holds slices on a page.
|
20
|
+
#
|
21
|
+
# This container is called Title and only allows title and You Tube slices
|
22
|
+
#
|
23
|
+
# container "title", :only => [TitleSlice, YouTubeSlice]
|
24
|
+
#
|
25
|
+
# Here's a container called body which is the primary and does not allow
|
26
|
+
# title slices.
|
27
|
+
#
|
28
|
+
# container "body", :primary => true, :except => TitleSlice
|
29
|
+
#
|
30
|
+
# @param [String] name Name of container
|
31
|
+
# @param [Hash] options
|
32
|
+
# @option options [Boolean] :primary (false) Is this container the primary
|
33
|
+
# @option options [Class,Array] :except Disallow these slice(s) from this container
|
34
|
+
# @option options [Class,Array] :only Only allow these slice(s) from this container
|
35
|
+
# @return [String]
|
36
|
+
#
|
37
|
+
def container(name, options = {})
|
38
|
+
[:except, :only].each do |type|
|
39
|
+
if options.has_key? type
|
40
|
+
options[type] = convert_slice_classes_to_symbols(options[type])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
@containers[name] = options.reverse_merge name: name.titleize
|
45
|
+
end
|
46
|
+
|
47
|
+
def method_missing(meth, *args, &block)
|
48
|
+
yield if block_given?
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def parse_with_block(&block)
|
54
|
+
@erb.result(binding)
|
55
|
+
end
|
56
|
+
|
57
|
+
def convert_slice_classes_to_symbols(options = [])
|
58
|
+
[options].flatten.select do |klass|
|
59
|
+
klass.is_a?(Class)
|
60
|
+
end.map do |klass|
|
61
|
+
convert_slice_class_to_symbol(klass)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def convert_slice_class_to_symbol(klass)
|
66
|
+
klass.name.underscore.split('_')[0 .. -2].join('_').to_sym
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Slices
|
2
|
+
module GeneratorMacros
|
3
|
+
# Defines a generator method.
|
4
|
+
#
|
5
|
+
# e.g.
|
6
|
+
#
|
7
|
+
# generator :home do
|
8
|
+
# Page.where(path: '/').first || Page.make(
|
9
|
+
# name: 'Home'
|
10
|
+
# )
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# Results in:
|
14
|
+
#
|
15
|
+
# MyStandardTree.home
|
16
|
+
#
|
17
|
+
#
|
18
|
+
# @param [Symbol] name
|
19
|
+
# @param [Proc] block macro body
|
20
|
+
#
|
21
|
+
def generator name, &block
|
22
|
+
define_singleton_method name, &block
|
23
|
+
generators << name
|
24
|
+
end
|
25
|
+
|
26
|
+
# Simple catalogue of generators.
|
27
|
+
def generators
|
28
|
+
@generators ||= []
|
29
|
+
end
|
30
|
+
|
31
|
+
# Invokes all generators.
|
32
|
+
def generate!
|
33
|
+
generators.map { |m| send m }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Slices
|
2
|
+
module HasAttachments
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
|
7
|
+
def has_attachments(embed_name = :attachments, options = {})
|
8
|
+
klass = if options.has_key?(:class_name)
|
9
|
+
options[:class_name].constantize
|
10
|
+
else
|
11
|
+
Attachment
|
12
|
+
end
|
13
|
+
|
14
|
+
default = options[:default] || options[:singular] ? nil : []
|
15
|
+
type = options[:singular] ? Hash : Array
|
16
|
+
|
17
|
+
if options[:singular]
|
18
|
+
define_method embed_name do
|
19
|
+
if embed = read_attribute(embed_name)
|
20
|
+
klass.new embed
|
21
|
+
end
|
22
|
+
end
|
23
|
+
else
|
24
|
+
define_method embed_name do
|
25
|
+
(read_attribute(embed_name) || []).collect do |embed|
|
26
|
+
klass.new embed
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
attachment_fields << embed_name
|
32
|
+
|
33
|
+
field embed_name, type: type, default: default
|
34
|
+
end
|
35
|
+
|
36
|
+
def attachment_fields
|
37
|
+
@attachment_fields ||= if superclass.respond_to?(:attachment_fields)
|
38
|
+
superclass.attachment_fields.dup
|
39
|
+
else
|
40
|
+
[]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
module PageInstanceMethods
|
47
|
+
|
48
|
+
def attachment_assets
|
49
|
+
attachment_asset_ids.inject([]) do |memo, asset_id|
|
50
|
+
begin
|
51
|
+
memo << ::Asset.find(asset_id)
|
52
|
+
rescue Mongoid::Errors::DocumentNotFound
|
53
|
+
end
|
54
|
+
memo
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def slice_attachment_asset_ids
|
59
|
+
[].tap do |asset_ids|
|
60
|
+
self.class.slice_embeds.each do |slice_embed|
|
61
|
+
slices_for(slice_embed).each do |slice|
|
62
|
+
if slice.respond_to? :attachment_asset_ids
|
63
|
+
asset_ids.concat slice.attachment_asset_ids
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
alias :attachment_asset_ids :slice_attachment_asset_ids
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
def as_json options = nil
|
74
|
+
super.merge(attachments_as_json)
|
75
|
+
end
|
76
|
+
|
77
|
+
def attachments_as_json
|
78
|
+
self.class.attachment_fields.inject({}) do |hash, name|
|
79
|
+
value = send name
|
80
|
+
|
81
|
+
hash[name] = if value.respond_to?(:map)
|
82
|
+
value.map &:as_json
|
83
|
+
else
|
84
|
+
value.as_json
|
85
|
+
end
|
86
|
+
|
87
|
+
hash
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def attachment_asset_ids
|
92
|
+
_attachment_asset_ids.tap do |asset_ids|
|
93
|
+
if respond_to? :slice_attachment_asset_ids
|
94
|
+
asset_ids.concat slice_attachment_asset_ids
|
95
|
+
end
|
96
|
+
asset_ids.uniq!
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def _attachment_asset_ids
|
101
|
+
attachment_asset_ids = self.class.attachment_fields.collect do |attachments|
|
102
|
+
[send(attachments)].flatten.collect do |attachment|
|
103
|
+
attachment.asset_id
|
104
|
+
end.reject {|i| i.nil? }
|
105
|
+
end.flat_map {|i| i }
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Slices
|
2
|
+
module HasSlices
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
validate :validate_slices
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def has_slices(embed_name)
|
11
|
+
embeds_many embed_name, class_name: 'Slice', validate: false
|
12
|
+
accepts_nested_attributes_for embed_name, allow_destroy: true
|
13
|
+
|
14
|
+
class_attribute :slice_embeds if self == Page
|
15
|
+
if slice_embeds.nil?
|
16
|
+
self.slice_embeds = [embed_name]
|
17
|
+
else
|
18
|
+
self.slice_embeds = slice_embeds + [embed_name]
|
19
|
+
end
|
20
|
+
|
21
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
22
|
+
def ordered_#{embed_name} # def orderd_slices
|
23
|
+
#{embed_name}.ascending(:position) # slices.ascending(:position)
|
24
|
+
end # end
|
25
|
+
RUBY
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def update_attributes(attributes)
|
30
|
+
[:slices, :set_slices].each do |type|
|
31
|
+
next if attributes[type].nil?
|
32
|
+
|
33
|
+
attributes[type] = attributes[type].map { |slice|
|
34
|
+
slice = slice.symbolize_keys
|
35
|
+
next if slice[:_destroy]
|
36
|
+
slice.delete :_new
|
37
|
+
klass = (slice[:type] + '_slice').camelize.constantize
|
38
|
+
klass.new(slice)
|
39
|
+
}.compact
|
40
|
+
end
|
41
|
+
|
42
|
+
super
|
43
|
+
end
|
44
|
+
|
45
|
+
def slices_for(embed_name)
|
46
|
+
send(embed_name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def ordered_slices_for(embed_name=nil)
|
50
|
+
embed_name = self.class.slice_embeds.first if embed_name.nil?
|
51
|
+
send("ordered_#{embed_name}")
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_slices
|
55
|
+
embeded_slices do |embed_name|
|
56
|
+
_slice_errors = slice_errors_for(embed_name)
|
57
|
+
if _slice_errors.any?
|
58
|
+
errors.add(embed_name, _slice_errors)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def slice_errors_for(embed_name)
|
64
|
+
Hash.new.tap do |message|
|
65
|
+
slices_for(embed_name).each do |slice|
|
66
|
+
if ! slice.valid? && ! slice.to_delete?
|
67
|
+
message[slice.id_or_client_id] = messages_from_errors(slice.errors)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def embeded_slices(&block)
|
74
|
+
self.class.slice_embeds.each do |embed_name|
|
75
|
+
yield(embed_name)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def messages_from_errors(errors)
|
80
|
+
if errors.respond_to?(:messages)
|
81
|
+
errors.messages
|
82
|
+
else
|
83
|
+
errors
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
data/lib/slices/i18n.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Slices
|
2
|
+
module I18n
|
3
|
+
|
4
|
+
class Backend
|
5
|
+
module Implementation
|
6
|
+
include ::I18n::Backend::Base, ::I18n::Backend::Flatten
|
7
|
+
|
8
|
+
# This method receives a locale, a data hash and options for storing translations.
|
9
|
+
# Should be implemented
|
10
|
+
def store_translations(locale, data, options = {})
|
11
|
+
raise NotImplementedError
|
12
|
+
end
|
13
|
+
|
14
|
+
def available_locales
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def lookup(locale, key, scope = [], options = {})
|
21
|
+
key = normalize_flat_keys(locale, key, scope, options[:separator])
|
22
|
+
Snippet.find_value_by_key("#{locale}.#{key}")
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
include Implementation
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
saise 'aaaaa'
|
2
|
+
module Slices
|
3
|
+
|
4
|
+
class I18nBackend
|
5
|
+
include I18n::Backend::Simple::Implementation
|
6
|
+
|
7
|
+
# Translates the given local and key. See the I18n API documentation for details.
|
8
|
+
#
|
9
|
+
# @return [Object] the translated key (usually a String)
|
10
|
+
def translate(locale, key, options = {})
|
11
|
+
content = super(locale, key, options.merge(fallback: true))
|
12
|
+
if content.respond_to?(:html_safe)
|
13
|
+
content.html_safe
|
14
|
+
else
|
15
|
+
content
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
I18n.backend = I18n::Backend::Chain.new(
|
22
|
+
Slices::I18n::Backend.new,
|
23
|
+
I18n.backend
|
24
|
+
)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Paperclip.options[:log] = true
|
2
|
+
require 'paperclip_validator'
|
3
|
+
|
4
|
+
Paperclip.interpolates :mon_year do |attachment, style|
|
5
|
+
attachment.instance.id.generation_time.strftime("%m%Y")
|
6
|
+
end
|
7
|
+
|
8
|
+
#This is a hack used to access Paperclip's internal cache
|
9
|
+
#of attributes it reads from the attachment. Used as part
|
10
|
+
#of the file renaming code.
|
11
|
+
class Paperclip::Attachment
|
12
|
+
attr_accessor :_file_file_name
|
13
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module Slices
|
2
|
+
module PositionHelper
|
3
|
+
|
4
|
+
# Returns an array of slices in the same container, including self.
|
5
|
+
#
|
6
|
+
# @return [Array]
|
7
|
+
#
|
8
|
+
def peers
|
9
|
+
@peers ||= normal_or_set_page.ordered_slices.select do |slice|
|
10
|
+
slice.container == self.container
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the previous slice in the container, or +nil+ if this is the
|
15
|
+
# first slice.
|
16
|
+
#
|
17
|
+
# @return [Slice]
|
18
|
+
#
|
19
|
+
def previous_slice
|
20
|
+
index = peers.index(self) - 1
|
21
|
+
index < 0 ? nil : peers[index]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the next slice in the container, or +nil+ if this is the
|
25
|
+
# last slice.
|
26
|
+
#
|
27
|
+
# @return [Slice]
|
28
|
+
#
|
29
|
+
def next_slice
|
30
|
+
peers[peers.index(self) + 1]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Is this the first slice in the container?
|
34
|
+
#
|
35
|
+
def first_in_container?
|
36
|
+
self == peers.first
|
37
|
+
end
|
38
|
+
|
39
|
+
# Is the previous slice of the same type?
|
40
|
+
#
|
41
|
+
def first_adjacent_of_type?
|
42
|
+
previous_slice.try(:class) != self.class
|
43
|
+
end
|
44
|
+
|
45
|
+
# Is this the last slice in the container?
|
46
|
+
#
|
47
|
+
def last_in_container?
|
48
|
+
self == peers.last
|
49
|
+
end
|
50
|
+
|
51
|
+
# Is the next slice the same type?
|
52
|
+
#
|
53
|
+
def last_adjacent_of_type?
|
54
|
+
next_slice.try(:class) != self.class
|
55
|
+
end
|
56
|
+
|
57
|
+
# Is this the only slice in the container?
|
58
|
+
#
|
59
|
+
def alone_in_container?
|
60
|
+
peers.size == 1
|
61
|
+
end
|
62
|
+
|
63
|
+
# Are both the next and previous slices different types?
|
64
|
+
#
|
65
|
+
def alone_in_adjacent_of_type?
|
66
|
+
first_adjacent_of_type? && last_adjacent_of_type?
|
67
|
+
end
|
68
|
+
|
69
|
+
# The position of the slice in the container, the first slice has a position
|
70
|
+
# of 1
|
71
|
+
#
|
72
|
+
# @return [Integer]
|
73
|
+
#
|
74
|
+
def position_in_container
|
75
|
+
peers.index(self) + 1
|
76
|
+
end
|
77
|
+
|
78
|
+
# The position of the slice in a group of the same slices
|
79
|
+
#
|
80
|
+
# For example, given the following slices
|
81
|
+
# [TitleSlice, CopySlice, CopySlice, CopySlice]
|
82
|
+
#
|
83
|
+
# The second +CopySlice+ would have a +position_in_adjacent_of_type+ of 2
|
84
|
+
#
|
85
|
+
# @return [Integer]
|
86
|
+
#
|
87
|
+
def position_in_adjacent_of_type
|
88
|
+
slices = []
|
89
|
+
reversed = peers.reverse
|
90
|
+
reversed[reversed.index(self)..-1].each do |slice|
|
91
|
+
break unless slice.class == self.class
|
92
|
+
slices << slice
|
93
|
+
end
|
94
|
+
slices.length
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|