smithycms 0.0.1
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/MIT-LICENSE +20 -0
- data/README.md +142 -0
- data/Rakefile +27 -0
- data/app/assets/images/smithy/logo.png +0 -0
- data/app/assets/images/smithy/logo2.png +0 -0
- data/app/assets/javascripts/smithy/application.js +13 -0
- data/app/assets/javascripts/smithy/assets.js.coffee +35 -0
- data/app/assets/javascripts/smithy/guides.js +23 -0
- data/app/assets/javascripts/smithy/jquery-ui.min.js +5 -0
- data/app/assets/javascripts/smithy/nested_forms.js +55 -0
- data/app/assets/javascripts/smithy/page_contents.js +4 -0
- data/app/assets/javascripts/smithy/pages.js +41 -0
- data/app/assets/javascripts/smithy/settings.js +0 -0
- data/app/assets/javascripts/smithy/templates.js +25 -0
- data/app/assets/stylesheets/smithy/application.css.scss +29 -0
- data/app/assets/stylesheets/smithy/assets.css.scss +3 -0
- data/app/assets/stylesheets/smithy/bootstrap_and_overrides.css.scss +12 -0
- data/app/assets/stylesheets/smithy/content_blocks.css.scss +2 -0
- data/app/assets/stylesheets/smithy/forms.css.scss +3 -0
- data/app/assets/stylesheets/smithy/guides.css.scss +5 -0
- data/app/assets/stylesheets/smithy/layout.css.scss +113 -0
- data/app/assets/stylesheets/smithy/pages.css.scss +35 -0
- data/app/assets/stylesheets/smithy/templates.css.scss +14 -0
- data/app/controllers/smithy/assets_controller.rb +50 -0
- data/app/controllers/smithy/base_controller.rb +14 -0
- data/app/controllers/smithy/caches_controller.rb +13 -0
- data/app/controllers/smithy/content_blocks_controller.rb +50 -0
- data/app/controllers/smithy/content_pieces_controller.rb +97 -0
- data/app/controllers/smithy/contents_controller.rb +41 -0
- data/app/controllers/smithy/guides_controller.rb +9 -0
- data/app/controllers/smithy/images_controller.rb +41 -0
- data/app/controllers/smithy/page_contents_controller.rb +90 -0
- data/app/controllers/smithy/pages_controller.rb +110 -0
- data/app/controllers/smithy/settings_controller.rb +46 -0
- data/app/controllers/smithy/sitemap_controller.rb +13 -0
- data/app/controllers/smithy/templates_controller.rb +79 -0
- data/app/helpers/smithy/application_helper.rb +36 -0
- data/app/helpers/smithy/assets_helper.rb +9 -0
- data/app/helpers/smithy/pages_helper.rb +12 -0
- data/app/helpers/smithy/settings_helper.rb +4 -0
- data/app/helpers/smithy/templates_helper.rb +4 -0
- data/app/helpers/smithy/upload_helper.rb +110 -0
- data/app/models/smithy/asset.rb +64 -0
- data/app/models/smithy/content.rb +35 -0
- data/app/models/smithy/content_block.rb +41 -0
- data/app/models/smithy/content_block_template.rb +26 -0
- data/app/models/smithy/image.rb +41 -0
- data/app/models/smithy/page.rb +94 -0
- data/app/models/smithy/page_content.rb +62 -0
- data/app/models/smithy/page_list.rb +61 -0
- data/app/models/smithy/page_proxy.rb +63 -0
- data/app/models/smithy/setting.rb +6 -0
- data/app/models/smithy/site.rb +30 -0
- data/app/models/smithy/template.rb +53 -0
- data/app/models/smithy/template_container.rb +16 -0
- data/app/views/layouts/smithy/application.html.erb +27 -0
- data/app/views/layouts/smithy/guides.html.erb +16 -0
- data/app/views/layouts/smithy/modal.html.erb +10 -0
- data/app/views/layouts/smithy/shared/_flash.html.erb +6 -0
- data/app/views/layouts/smithy/shared/_footer.html.erb +3 -0
- data/app/views/layouts/smithy/shared/_head.html.erb +8 -0
- data/app/views/layouts/smithy/shared/_nav.html.erb +37 -0
- data/app/views/layouts/smithy/shared/_tail.html.erb +4 -0
- data/app/views/layouts/smithy/wide.html.erb +24 -0
- data/app/views/smithy/assets/_asset.html.erb +10 -0
- data/app/views/smithy/assets/_form.html.erb +13 -0
- data/app/views/smithy/assets/_upload_form.html.erb +13 -0
- data/app/views/smithy/assets/create.js.erb +5 -0
- data/app/views/smithy/assets/edit.html.erb +5 -0
- data/app/views/smithy/assets/index.html.erb +13 -0
- data/app/views/smithy/assets/new.html.erb +13 -0
- data/app/views/smithy/caches/show.html.erb +8 -0
- data/app/views/smithy/content_blocks/_content_block.html.erb +1 -0
- data/app/views/smithy/content_blocks/_secondary_nav.html.erb +12 -0
- data/app/views/smithy/content_blocks/_template_fields.html.erb +19 -0
- data/app/views/smithy/content_blocks/edit.html.erb +31 -0
- data/app/views/smithy/content_blocks/index.html.erb +17 -0
- data/app/views/smithy/content_blocks/new.html.erb +12 -0
- data/app/views/smithy/content_pieces/edit.html.erb +13 -0
- data/app/views/smithy/content_pieces/index.html.erb +21 -0
- data/app/views/smithy/content_pieces/new.html.erb +1 -0
- data/app/views/smithy/contents/_form.html.erb +6 -0
- data/app/views/smithy/contents/_form_fields.html.erb +12 -0
- data/app/views/smithy/contents/edit.html.erb +3 -0
- data/app/views/smithy/contents/new.html.erb +3 -0
- data/app/views/smithy/guides/markdown.html.erb +150 -0
- data/app/views/smithy/images/_form.html.erb +6 -0
- data/app/views/smithy/images/_form_fields.html.erb +28 -0
- data/app/views/smithy/images/edit.html.erb +3 -0
- data/app/views/smithy/images/new.html.erb +3 -0
- data/app/views/smithy/page_contents/edit.html.erb +18 -0
- data/app/views/smithy/page_contents/new.html.erb +28 -0
- data/app/views/smithy/page_lists/_form_fields.html.erb +6 -0
- data/app/views/smithy/pages/_container.html.erb +24 -0
- data/app/views/smithy/pages/_form.html.erb +57 -0
- data/app/views/smithy/pages/_page.html.erb +6 -0
- data/app/views/smithy/pages/_page_nav.html.erb +6 -0
- data/app/views/smithy/pages/_page_related.html.erb +21 -0
- data/app/views/smithy/pages/_parent.html.erb +10 -0
- data/app/views/smithy/pages/_root.html.erb +5 -0
- data/app/views/smithy/pages/edit.html.erb +7 -0
- data/app/views/smithy/pages/index.html.erb +17 -0
- data/app/views/smithy/pages/new.html.erb +7 -0
- data/app/views/smithy/settings/_form.html.erb +7 -0
- data/app/views/smithy/settings/_setting.html.erb +6 -0
- data/app/views/smithy/settings/edit.html.erb +3 -0
- data/app/views/smithy/settings/index.html.erb +9 -0
- data/app/views/smithy/settings/new.html.erb +3 -0
- data/app/views/smithy/settings/show.html.erb +10 -0
- data/app/views/smithy/sitemap/show.xml.erb +10 -0
- data/app/views/smithy/templates/_secondary_nav.html.erb +21 -0
- data/app/views/smithy/templates/_template.html.erb +1 -0
- data/app/views/smithy/templates/edit.html.erb +36 -0
- data/app/views/smithy/templates/index.html.erb +17 -0
- data/app/views/smithy/templates/new.html.erb +13 -0
- data/config/initializers/aws.rb +5 -0
- data/config/initializers/dragonfly.rb +48 -0
- data/config/initializers/formtastic.rb +77 -0
- data/config/initializers/kaminari_config.rb +10 -0
- data/config/initializers/liquid.rb +2 -0
- data/config/routes.rb +38 -0
- data/db/migrate/20120911193140_create_smithy_templates.rb +11 -0
- data/db/migrate/20120911203618_create_smithy_settings.rb +10 -0
- data/db/migrate/20121018182146_create_smithy_pages.rb +27 -0
- data/db/migrate/20121019145543_create_smithy_template_containers.rb +11 -0
- data/db/migrate/20121019160426_create_smithy_page_contents.rb +21 -0
- data/db/migrate/20121024213357_create_smithy_content_blocks.rb +10 -0
- data/db/migrate/20121025011733_create_smithy_content_block_templates.rb +12 -0
- data/db/migrate/20121029175812_create_smithy_contents.rb +9 -0
- data/db/migrate/20121105222537_create_smithy_assets.rb +16 -0
- data/db/migrate/20121115215053_create_smithy_images.rb +15 -0
- data/db/migrate/20121127205022_add_external_link_to_smithy_pages.rb +5 -0
- data/db/migrate/20130115190505_add_markdown_content_to_smithy_contents.rb +5 -0
- data/db/migrate/20130123170918_set_defaults_for_show_in_navigation_and_cache_length.rb +6 -0
- data/db/migrate/20130311203806_create_smithy_page_lists.rb +15 -0
- data/db/migrate/20130312161116_remove_description_from_content_block.rb +5 -0
- data/db/migrate/20130326191051_add_html_attributes_to_images.rb +5 -0
- data/db/migrate/20131003210228_add_publishable_to_smithy_page_contents.rb +11 -0
- data/db/migrate/20131220160755_add_content_to_images.rb +5 -0
- data/db/migrate/20131223145710_add_position_to_smithy_template_containers.rb +5 -0
- data/lib/smithy/content_blocks/model.rb +16 -0
- data/lib/smithy/content_blocks/registry.rb +30 -0
- data/lib/smithy/content_blocks.rb +2 -0
- data/lib/smithy/content_pieces/base.rb +10 -0
- data/lib/smithy/content_pieces/registry.rb +39 -0
- data/lib/smithy/dependencies.rb +19 -0
- data/lib/smithy/dragonfly/asset_helper.rb +67 -0
- data/lib/smithy/dragonfly/remote_data_store.rb +33 -0
- data/lib/smithy/dragonfly.rb +30 -0
- data/lib/smithy/engine.rb +48 -0
- data/lib/smithy/formatter.rb +46 -0
- data/lib/smithy/liquid/database.rb +12 -0
- data/lib/smithy/liquid/drops/base.rb +16 -0
- data/lib/smithy/liquid/drops/page.rb +78 -0
- data/lib/smithy/liquid/filters/asset_tag.rb +33 -0
- data/lib/smithy/liquid/filters/resize.rb +12 -0
- data/lib/smithy/liquid/rendering.rb +50 -0
- data/lib/smithy/liquid/tags/asset.rb +54 -0
- data/lib/smithy/liquid/tags/csrf.rb +30 -0
- data/lib/smithy/liquid/tags/html.rb +61 -0
- data/lib/smithy/liquid/tags/nav.rb +76 -0
- data/lib/smithy/liquid.rb +8 -0
- data/lib/smithy/logger.rb +12 -0
- data/lib/smithy/version.rb +3 -0
- data/lib/smithy.rb +21 -0
- data/lib/smithycms.rb +1 -0
- data/lib/tasks/smithy_tasks.rake +4 -0
- data/lib/templates/erb/scaffold/_form.html.erb +11 -0
- metadata +871 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
require_dependency "smithy/base_controller"
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
class PageContentsController < BaseController
|
5
|
+
before_filter :load_page
|
6
|
+
before_filter :load_page_content, :only => [ :edit, :update, :destroy, :preview ]
|
7
|
+
before_filter :build_content_block, :only => [ :edit, :update ]
|
8
|
+
before_filter :load_content_blocks, :only => [ :new, :create ]
|
9
|
+
respond_to :html, :json
|
10
|
+
|
11
|
+
def new
|
12
|
+
@page_content = Smithy::PageContent.new(params[:page_content])
|
13
|
+
@page_content.label = [@page.title, @page_content.container.titleize].join(' - ') unless @page_content.label?
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
@page_content = Smithy::PageContent.new
|
18
|
+
# we have to ensure that the content_block_type gets added before the content_block_attributes
|
19
|
+
# see PageContent#content_block_attributes=
|
20
|
+
@page_content.content_block_type = params[:page_content][:content_block_type]
|
21
|
+
@page_content.attributes = params[:page_content]
|
22
|
+
@page_content.page = @page
|
23
|
+
@page_content.save
|
24
|
+
respond_with @page_content do |format|
|
25
|
+
format.html { @page_content.persisted? ? redirect_to(edit_page_content_path(@page.id, @page_content)) : render(:action => 'new') }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def edit
|
30
|
+
respond_with @page_content
|
31
|
+
end
|
32
|
+
|
33
|
+
def update
|
34
|
+
@page_content = Smithy::PageContent.find(params[:id])
|
35
|
+
@saved = @page_content.update_attributes(params[:page_content])
|
36
|
+
flash.notice = "Your content was saved" if @saved
|
37
|
+
respond_with @page_content do |format|
|
38
|
+
format.html { @saved ? redirect_to(edit_page_path(@page.id)) : render(:action => "edit") }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def destroy
|
43
|
+
@page_content.destroy
|
44
|
+
respond_with @page_content do |format|
|
45
|
+
format.html { redirect_to edit_page_path(@page.id), :notice => "Your content was deleted from the page" }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def preview
|
50
|
+
respond_with @page_content do |format|
|
51
|
+
format.html { render :text => @page_content.render, :layout => 'smithy/modal' }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def order
|
56
|
+
params[:order].each_with_index do |page_content_id, index|
|
57
|
+
page_content = @page.contents.find(page_content_id)
|
58
|
+
page_content.update_attribute(:position, index)
|
59
|
+
end
|
60
|
+
if request.xhr?
|
61
|
+
render :nothing => true, :status => 200
|
62
|
+
else
|
63
|
+
redirect_to edit_page_path(@page.id)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def build_content_block
|
69
|
+
unless @page_content.content_block.present?
|
70
|
+
klass = "Smithy::#{@page_content.content_block_type.classify}".safe_constantize || @page_content.content_block_type.classify.safe_constantize
|
71
|
+
if klass
|
72
|
+
@page_content.content_block = klass.new
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def load_content_blocks
|
78
|
+
@content_blocks = Smithy::ContentBlock.all
|
79
|
+
end
|
80
|
+
|
81
|
+
def load_page
|
82
|
+
@page = Smithy::Page.find(params[:page_id])
|
83
|
+
end
|
84
|
+
|
85
|
+
def load_page_content
|
86
|
+
@page_content = Smithy::PageContent.find(params[:id])
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require_dependency "smithy/base_controller"
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
class PagesController < BaseController
|
5
|
+
skip_before_filter :authenticate_smithy_admin, :only => [ :show ]
|
6
|
+
include Smithy::Liquid::Rendering
|
7
|
+
before_filter :load_page_from_path, :only => [ :show ]
|
8
|
+
before_filter :initialize_page, :only => [ :new, :create ]
|
9
|
+
before_filter :load_page, :only => [ :edit, :update, :destroy ]
|
10
|
+
before_filter :load_parent, :except => [ :index, :show, :order ]
|
11
|
+
before_filter :load_root, :only => [ :index ]
|
12
|
+
respond_to :html, :json
|
13
|
+
|
14
|
+
def index
|
15
|
+
respond_with @root
|
16
|
+
end
|
17
|
+
|
18
|
+
def show
|
19
|
+
render_page and return if smithy_current_user # no caching if you're editing
|
20
|
+
# adding :public param allow Rack::Cache to cache the result
|
21
|
+
@page.cache_length == 0 ? expires_now : expires_in(@page.cache_length.to_i.seconds, :public => true)
|
22
|
+
render_page if stale?(:etag => @page, :last_modified => @page.updated_at.utc, :public => true)
|
23
|
+
end
|
24
|
+
|
25
|
+
def new
|
26
|
+
respond_with @page
|
27
|
+
end
|
28
|
+
|
29
|
+
def create
|
30
|
+
@page.save
|
31
|
+
flash.notice = "Your page was created #{@page.published? ? 'and published' : 'as a draft'}" if @page.persisted?
|
32
|
+
respond_with @page do |format|
|
33
|
+
format.html { @page.persisted? ? redirect_to(edit_page_path(@page.id)) : render(:action => 'new') }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def edit
|
38
|
+
respond_with @page
|
39
|
+
end
|
40
|
+
|
41
|
+
def update
|
42
|
+
flash.notice = "Your page was saved #{@page.published? ? 'and published' : 'as a draft'}" if @page.update_attributes(params[:page])
|
43
|
+
respond_with @page do |format|
|
44
|
+
format.html { redirect_to edit_page_path(@page.id) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def destroy
|
49
|
+
@page.destroy
|
50
|
+
respond_with @page.parent ? @page.parent : @page
|
51
|
+
end
|
52
|
+
|
53
|
+
def order
|
54
|
+
first = Smithy::Page.find(params[:order].shift)
|
55
|
+
@parent = first.parent
|
56
|
+
if @parent && @parent.children.count > 1 # Only need to order if there are multiple children.
|
57
|
+
left = first.id
|
58
|
+
params[:order].each do |page_id|
|
59
|
+
page = Smithy::Page.find(page_id)
|
60
|
+
page.move_to_right_of(left)
|
61
|
+
left = page.id
|
62
|
+
end
|
63
|
+
end
|
64
|
+
render :nothing => true, :status => 200 and return if request.xhr?
|
65
|
+
redirect_to pages_path
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def initialize_page
|
70
|
+
@page = Page.new(params[:page])
|
71
|
+
set_publish
|
72
|
+
end
|
73
|
+
|
74
|
+
def load_page
|
75
|
+
@page = Page.find(params[:id])
|
76
|
+
@root = @page if Page.root == @page
|
77
|
+
set_publish
|
78
|
+
end
|
79
|
+
|
80
|
+
def load_page_from_path
|
81
|
+
@page = Page.find(page_path)
|
82
|
+
redirect_to @page.external_link and return false if @page.external_link?
|
83
|
+
end
|
84
|
+
|
85
|
+
def load_parent
|
86
|
+
@parent = @page.parent
|
87
|
+
end
|
88
|
+
|
89
|
+
def load_root
|
90
|
+
@root = Page.root
|
91
|
+
end
|
92
|
+
|
93
|
+
def page_path
|
94
|
+
params[:path] = '' if params[:id].nil? && params[:path].nil? # sets the root path when nothing else is passed
|
95
|
+
params[:path].nil? ? params[:id] : "/#{params[:path]}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def render_page
|
99
|
+
respond_with @page do |format|
|
100
|
+
format.html { render_smithy_page }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_publish
|
105
|
+
@page.publish = true if params[:publish].present?
|
106
|
+
@page.publish = false if params[:draft].present?
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_dependency "smithy/base_controller"
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
class SettingsController < BaseController
|
5
|
+
respond_to :html, :json
|
6
|
+
|
7
|
+
def index
|
8
|
+
@settings = Setting.all
|
9
|
+
respond_with @settings
|
10
|
+
end
|
11
|
+
|
12
|
+
def show
|
13
|
+
@setting = Setting.find(params[:id])
|
14
|
+
respond_with @setting
|
15
|
+
end
|
16
|
+
|
17
|
+
def new
|
18
|
+
@setting = Setting.new(params[:setting])
|
19
|
+
respond_with @setting
|
20
|
+
end
|
21
|
+
|
22
|
+
def create
|
23
|
+
@setting = Setting.new(params[:setting])
|
24
|
+
@setting.save
|
25
|
+
flash.notice = "Your setting was created" if @setting.persisted?
|
26
|
+
respond_with @setting
|
27
|
+
end
|
28
|
+
|
29
|
+
def edit
|
30
|
+
@setting = Setting.find(params[:id])
|
31
|
+
respond_with @setting
|
32
|
+
end
|
33
|
+
|
34
|
+
def update
|
35
|
+
@setting = Setting.find(params[:id])
|
36
|
+
flash.notice = "Your setting was saved" if @setting.update_attributes(params[:setting])
|
37
|
+
respond_with @setting
|
38
|
+
end
|
39
|
+
|
40
|
+
def destroy
|
41
|
+
@setting = Setting.find(params[:id])
|
42
|
+
@setting.destroy
|
43
|
+
respond_with @setting
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_dependency "smithy/base_controller"
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
class SitemapController < BaseController
|
5
|
+
respond_to :xml
|
6
|
+
skip_before_filter :authenticate_smithy_admin
|
7
|
+
|
8
|
+
def show
|
9
|
+
@pages = Smithy::Page.root.self_and_descendants
|
10
|
+
respond_with @pages
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_dependency "smithy/base_controller"
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
class TemplatesController < BaseController
|
5
|
+
skip_before_filter :authenticate_smithy_admin, :only => [ :javascript, :stylesheet ]
|
6
|
+
before_filter :load_templates
|
7
|
+
respond_to :html, :json
|
8
|
+
|
9
|
+
def index
|
10
|
+
respond_with @templates
|
11
|
+
end
|
12
|
+
|
13
|
+
def new
|
14
|
+
@template = Template.new(params[:template])
|
15
|
+
respond_with @template
|
16
|
+
end
|
17
|
+
|
18
|
+
def create
|
19
|
+
@template = Template.new(params[:template])
|
20
|
+
@template.save
|
21
|
+
flash.notice = "Your template was created" if @template.persisted?
|
22
|
+
respond_with @template do |format|
|
23
|
+
format.html { redirect_to [:edit, @template] }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def edit
|
28
|
+
@template = Template.find(params[:id])
|
29
|
+
@template_editor_type = case @template.template_type
|
30
|
+
when 'javascript'
|
31
|
+
'javascript'
|
32
|
+
when 'stylesheet'
|
33
|
+
'css'
|
34
|
+
else
|
35
|
+
'liquid'
|
36
|
+
end
|
37
|
+
respond_with @template
|
38
|
+
end
|
39
|
+
|
40
|
+
def update
|
41
|
+
@template = Template.find(params[:id])
|
42
|
+
flash.notice = "Your template was saved" if @template.update_attributes(params[:template])
|
43
|
+
respond_with @template do |format|
|
44
|
+
format.html { redirect_to [:edit, @template] }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def destroy
|
49
|
+
@template = Template.find(params[:id])
|
50
|
+
@template.destroy
|
51
|
+
respond_with @template
|
52
|
+
end
|
53
|
+
|
54
|
+
def javascript
|
55
|
+
@javascript = Template.javascripts.find_by_name(params[:javascript].sub(/\.js$/, ''))
|
56
|
+
render_asset_template(@javascript, params[:javascript], 'text/javascript')
|
57
|
+
end
|
58
|
+
|
59
|
+
def stylesheet
|
60
|
+
@stylesheet = Template.stylesheets.find_by_name(params[:stylesheet].sub(/\.css$/, ''))
|
61
|
+
render_asset_template(@stylesheet, params[:stylesheet], 'text/css')
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def load_templates
|
66
|
+
@templates = Template.templates
|
67
|
+
@includes = Template.partials
|
68
|
+
@javascripts = Template.javascripts
|
69
|
+
@stylesheets = Template.stylesheets
|
70
|
+
end
|
71
|
+
|
72
|
+
def render_asset_template(template, template_name, content_type)
|
73
|
+
raise ActiveRecord::RecordNotFound, "No such stylesheet '#{template_name}'" unless template.present?
|
74
|
+
expires_in(2592000.seconds, :public => true) # cache for 30 days
|
75
|
+
headers['X-Content-Digest'] = Digest::SHA1.hexdigest(template.content) # digest of the content for cache control when the template changes
|
76
|
+
render :text => template.content, :content_type => content_type
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Smithy
|
2
|
+
module ApplicationHelper
|
3
|
+
def link_to_add_fields(name, association, form_builder)
|
4
|
+
html = content_tag(:div, :id => "#{association}_fields_blueprint", :style => "display:none;") do
|
5
|
+
form_builder.semantic_fields_for(association, model_object(form_builder, association), :child_index => "new_#{association}") do |builder|
|
6
|
+
form_builder.template.concat(raw render("#{form_builder.object.class.to_s.tableize}/#{association.to_s.singularize}_fields", :f => builder))
|
7
|
+
end
|
8
|
+
end
|
9
|
+
form_builder.template.concat(html)
|
10
|
+
form_builder.template.link_to(name, "javascript:void(0)", :class => "add_nested_fields", "data-association" => association)
|
11
|
+
end
|
12
|
+
|
13
|
+
def link_to_remove_fields(name, form_builder)
|
14
|
+
form_builder.hidden_field(:_destroy) + @template.link_to(name, "javascript:void(0)", :class => "remove_nested_fields")
|
15
|
+
end
|
16
|
+
|
17
|
+
def render_markdown_input(fieldname, editor_name, form_builder)
|
18
|
+
content_for(:javascript) do
|
19
|
+
javascript_tag do
|
20
|
+
raw("var editor = ace_edit('#{form_builder.object.id || 'new'}', 'markdown', '#{editor_name}');\n") +
|
21
|
+
raw("editor.renderer.setShowGutter(false);")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
hint = "Use markdown syntax for formatting. You can also use HTML directly. <a href=\"#{guide_path('markdown')}\" data-toggle=\"remote-load\" data-target=\"#content-guide\">See our markdown syntax reference</a>".html_safe
|
25
|
+
form_builder.input(fieldname, :as => :text, :input_html => { :class => "span12", :id => "#{editor_name}-#{form_builder.object.id || 'new'}" }, :hint => hint) +
|
26
|
+
content_tag(:div, nil, :id => "#{editor_name}_editor-#{form_builder.object.id || 'new'}", :class => "#{editor_name}_editor ace_editor") +
|
27
|
+
content_tag(:div, nil, :id => 'content-guide')
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def model_object(form_builder, association)
|
32
|
+
model_object = form_builder.object.class.reflect_on_association(association).klass.new
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Smithy
|
2
|
+
module PagesHelper
|
3
|
+
def tree_for_select
|
4
|
+
tree_for_select = []
|
5
|
+
Smithy::Page.each_with_level(Smithy::Page.root.self_and_descendants) do |page, level|
|
6
|
+
prepend = level == 0 ? '' : "#{'-' * level} "
|
7
|
+
tree_for_select << [ "#{prepend}#{page.title}", page.id]
|
8
|
+
end if Smithy::Page.root.present?
|
9
|
+
tree_for_select
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Smithy
|
2
|
+
module UploadHelper
|
3
|
+
def uploader_form(object, options = {}, &block)
|
4
|
+
# s3_uploader = S3Uploader.new(options)
|
5
|
+
# uploader = s3_uploader.s3_available? ? s3_uploader : FileUploader.new(options)
|
6
|
+
uploader = S3Uploader.new(options)
|
7
|
+
form_tag(uploader.url, uploader.form_options) do
|
8
|
+
uploader.fields.map do |name, value|
|
9
|
+
hidden_field_tag(name, value)
|
10
|
+
end.join.html_safe + capture(&block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Base
|
15
|
+
def form_options
|
16
|
+
{
|
17
|
+
id: @options[:id],
|
18
|
+
method: "post",
|
19
|
+
authenticity_token: false,
|
20
|
+
multipart: true,
|
21
|
+
data: {
|
22
|
+
post: @options[:post],
|
23
|
+
as: @options[:as]
|
24
|
+
}
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class FileUploader < Base
|
30
|
+
def initialize(options)
|
31
|
+
@options = options.reverse_merge( id: "fileupload" )
|
32
|
+
end
|
33
|
+
|
34
|
+
def fields
|
35
|
+
{ :key => key }
|
36
|
+
end
|
37
|
+
|
38
|
+
def key
|
39
|
+
@key ||= "uploads/assets/${filename}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def url
|
43
|
+
@options[:post]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class S3Uploader < Base
|
48
|
+
def initialize(options)
|
49
|
+
@options = options.reverse_merge(
|
50
|
+
id: "fileupload",
|
51
|
+
aws_access_key_id: ENV["AWS_ACCESS_KEY_ID"],
|
52
|
+
aws_secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"],
|
53
|
+
bucket: ENV["AWS_S3_BUCKET"],
|
54
|
+
acl: "public-read",
|
55
|
+
expiration: 10.hours.from_now,
|
56
|
+
max_file_size: 500.megabytes,
|
57
|
+
as: "file"
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
def fields
|
62
|
+
{
|
63
|
+
:key => key,
|
64
|
+
:acl => @options[:acl],
|
65
|
+
:policy => policy,
|
66
|
+
:signature => signature,
|
67
|
+
"AWSAccessKeyId" => @options[:aws_access_key_id],
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def key
|
72
|
+
@key ||= "uploads/assets/#{SecureRandom.hex}/${filename}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def url
|
76
|
+
"https://#{@options[:bucket]}.s3.amazonaws.com/"
|
77
|
+
end
|
78
|
+
|
79
|
+
def policy
|
80
|
+
Base64.encode64(policy_data.to_json).gsub("\n", "")
|
81
|
+
end
|
82
|
+
|
83
|
+
def policy_data
|
84
|
+
{
|
85
|
+
expiration: @options[:expiration].utc.iso8601,
|
86
|
+
conditions: [
|
87
|
+
["starts-with", "$utf8", ""],
|
88
|
+
["starts-with", "$key", ""],
|
89
|
+
["content-length-range", 0, @options[:max_file_size]],
|
90
|
+
{bucket: @options[:bucket]},
|
91
|
+
{acl: @options[:acl]}
|
92
|
+
]
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
def signature
|
97
|
+
Base64.encode64(
|
98
|
+
OpenSSL::HMAC.digest(
|
99
|
+
OpenSSL::Digest::Digest.new('sha1'),
|
100
|
+
@options[:aws_secret_access_key], policy
|
101
|
+
)
|
102
|
+
).gsub("\n", "")
|
103
|
+
end
|
104
|
+
|
105
|
+
def s3_available?
|
106
|
+
@options[:aws_access_key_id].present? && @options[:aws_secret_access_key].present? && @options[:bucket].present?
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Smithy
|
2
|
+
class Asset < ActiveRecord::Base
|
3
|
+
attr_accessible :name, :file, :file_name, :file_url, :retained_file, :uploaded_file_url
|
4
|
+
|
5
|
+
validates_presence_of :file, :name
|
6
|
+
|
7
|
+
has_many :images, :dependent => :destroy
|
8
|
+
|
9
|
+
file_accessor :file
|
10
|
+
include Smithy::Dragonfly::AssetHelper
|
11
|
+
|
12
|
+
before_validation :set_name
|
13
|
+
before_save :set_file_uid_manually
|
14
|
+
|
15
|
+
default_scope order(:name)
|
16
|
+
|
17
|
+
def file
|
18
|
+
# check for the jquery uploaded file first, just in case one got past the manual check. Also keeps backwards-compatibility
|
19
|
+
if self.uploaded_file_url?
|
20
|
+
dragonfly_attachments[:file].app.datastore = self.class.dragonfly_remote_datastore
|
21
|
+
self.file_url = URI.escape(self.uploaded_file_url)
|
22
|
+
elsif dragonfly_attachments[:file].to_value
|
23
|
+
dragonfly_attachments[:file].app.datastore = self.class.dragonfly_datastore
|
24
|
+
end
|
25
|
+
dragonfly_attachments[:file].to_value
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_liquid
|
29
|
+
{
|
30
|
+
'id' => self.id,
|
31
|
+
'name' => self.name,
|
32
|
+
'content_type' => self.content_type,
|
33
|
+
'file' => self.file,
|
34
|
+
'file_name' => self.file_name,
|
35
|
+
'file_width' => self.file_width,
|
36
|
+
'file_height' => self.file_height,
|
37
|
+
'file_size' => self.file_size,
|
38
|
+
'url' => self.file.url
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def set_content_types
|
44
|
+
set_content_type(self.file, :content_type)
|
45
|
+
end
|
46
|
+
|
47
|
+
# this allows dragonfly to take over management of the uploaded file. We are
|
48
|
+
# assuming that jquery-upload and dragonfly are using the same data storage...
|
49
|
+
def set_file_uid_manually
|
50
|
+
if self.uploaded_file_url? # this means it was uploaded via jquery-upload
|
51
|
+
self.file_uid = URI.parse(self.uploaded_file_url).path.sub(/^\//, '')
|
52
|
+
self.uploaded_file_url = nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_name
|
57
|
+
if self.uploaded_file_url?
|
58
|
+
self.name = File.basename(self.uploaded_file_url, '.*').titleize unless self.name?
|
59
|
+
elsif self.file.present?
|
60
|
+
self.name = File.basename(self.file.name, '.*').titleize unless self.name?
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Smithy
|
2
|
+
class Content < ActiveRecord::Base
|
3
|
+
include Smithy::ContentBlocks::Model
|
4
|
+
|
5
|
+
attr_accessible :content
|
6
|
+
|
7
|
+
validates_presence_of :content
|
8
|
+
|
9
|
+
before_save :render_markdown_content
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def content_block_description
|
13
|
+
"Content is primarily used for adding text-based content to your pages"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def formatted_content
|
18
|
+
self.markdown_content
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_liquid
|
22
|
+
{
|
23
|
+
'id' => self.id,
|
24
|
+
'content' => self.content,
|
25
|
+
'formatted_content' => self.formatted_content
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def render_markdown_content
|
31
|
+
formatter = Smithy::Formatter.new(self.content)
|
32
|
+
self.markdown_content = formatter.render
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Smithy
|
2
|
+
class ContentBlock < ActiveRecord::Base
|
3
|
+
attr_accessible :name, :templates_attributes
|
4
|
+
|
5
|
+
validates_presence_of :name
|
6
|
+
|
7
|
+
has_many :templates, :class_name => "ContentBlockTemplate"
|
8
|
+
has_many :page_contents
|
9
|
+
|
10
|
+
after_save :touch_page_contents
|
11
|
+
|
12
|
+
accepts_nested_attributes_for :templates, :reject_if => lambda {|a| a['name'].blank? || a['content'].blank? }, :allow_destroy => true
|
13
|
+
|
14
|
+
default_scope order(:name)
|
15
|
+
|
16
|
+
def description
|
17
|
+
klass.content_block_description if klass
|
18
|
+
end
|
19
|
+
|
20
|
+
def content_field_names
|
21
|
+
unless @content_field_names
|
22
|
+
if klass.new.respond_to?(:to_liquid)
|
23
|
+
@content_field_names = klass.new.to_liquid.keys
|
24
|
+
else
|
25
|
+
@content_field_names = klass.column_names.delete_if{|column_name| ["id", "created_at", "updated_at"].include?(column_name) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
@content_field_names
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def klass
|
33
|
+
@klass ||= "#{self.name}".safe_constantize || "Smithy::#{self.name}".safe_constantize
|
34
|
+
end
|
35
|
+
|
36
|
+
def touch_page_contents
|
37
|
+
self.page_contents.each(&:touch)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Smithy
|
2
|
+
class ContentBlockTemplate < ActiveRecord::Base
|
3
|
+
attr_accessible :content, :name
|
4
|
+
|
5
|
+
belongs_to :content_block, :touch => true
|
6
|
+
has_many :page_contents
|
7
|
+
|
8
|
+
validates_presence_of :name
|
9
|
+
validates_uniqueness_of :name, :scope => :content_block_id
|
10
|
+
validates_presence_of :content
|
11
|
+
|
12
|
+
after_save :touch_page_contents
|
13
|
+
|
14
|
+
default_scope order(:name)
|
15
|
+
|
16
|
+
def liquid_template
|
17
|
+
@liquid_template ||= ::Liquid::Template.parse(self.content)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def touch_page_contents
|
22
|
+
self.page_contents.each(&:touch)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|