spreefinery_themes 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/app/assets/images/jstree/file.png +0 -0
  2. data/app/assets/images/jstree/folder.png +0 -0
  3. data/app/assets/javascripts/code_mirror_manager.coffee +105 -0
  4. data/app/assets/javascripts/editor.coffee +3 -0
  5. data/app/assets/javascripts/files_manager.coffee +41 -0
  6. data/app/assets/javascripts/jstree_manager.coffee +177 -0
  7. data/app/assets/javascripts/themes.coffee +21 -0
  8. data/app/assets/stylesheets/editor.css +40 -0
  9. data/app/assets/stylesheets/themes.css +50 -0
  10. data/app/controllers/refinery/themes/admin/editor_controller.rb +73 -0
  11. data/app/controllers/refinery/themes/admin/themes_controller.rb +60 -0
  12. data/app/controllers/refinery/themes/theme_controller.rb +12 -0
  13. data/app/decorators/action_view_decorator.rb +6 -0
  14. data/app/decorators/application_controller_decorator.rb +7 -0
  15. data/app/decorators/base_controller_decorator.rb +4 -0
  16. data/app/decorators/drops_decorator.rb +33 -0
  17. data/app/decorators/liquid_strainer_decorator.rb +23 -0
  18. data/app/decorators/refinery_admin_pages_controller_decorator.rb +6 -0
  19. data/app/decorators/refinery_pages_controller_decorator.rb +17 -0
  20. data/app/decorators/refinery_sessions_controller_decorator.rb +3 -0
  21. data/app/decorators/spree_base_controller_decorator.rb +3 -0
  22. data/app/decorators/spree_checkout_controller_decorator.rb +42 -0
  23. data/app/decorators/template_renderer_decorator.rb +25 -0
  24. data/app/helpers/refinery/themes/admin/themes_helper.rb +9 -0
  25. data/app/liquid/blocks/capture_variable.rb +36 -0
  26. data/app/liquid/blocks/content_for.rb +55 -0
  27. data/app/liquid/blocks/rss.rb +27 -0
  28. data/app/liquid/blocks/with_scope.rb +55 -0
  29. data/app/liquid/drops/address_drop.rb +5 -0
  30. data/app/liquid/drops/country_drop.rb +5 -0
  31. data/app/liquid/drops/form_builder_drop.rb +15 -0
  32. data/app/liquid/drops/image_drop.rb +5 -0
  33. data/app/liquid/drops/line_item_drop.rb +41 -0
  34. data/app/liquid/drops/menu_item_drop.rb +17 -0
  35. data/app/liquid/drops/option_type_drop.rb +5 -0
  36. data/app/liquid/drops/option_value_drop.rb +3 -0
  37. data/app/liquid/drops/order_drop.rb +19 -0
  38. data/app/liquid/drops/page_drop.rb +5 -0
  39. data/app/liquid/drops/page_part_drop.rb +18 -0
  40. data/app/liquid/drops/post_category_drop.rb +5 -0
  41. data/app/liquid/drops/post_comment_drop.rb +5 -0
  42. data/app/liquid/drops/post_drop.rb +21 -0
  43. data/app/liquid/drops/product_drop.rb +81 -0
  44. data/app/liquid/drops/product_property_drop.rb +5 -0
  45. data/app/liquid/drops/property_drop.rb +5 -0
  46. data/app/liquid/drops/role_drop.rb +5 -0
  47. data/app/liquid/drops/spree_money_drop.rb +10 -0
  48. data/app/liquid/drops/state_drop.rb +6 -0
  49. data/app/liquid/drops/taxon_drop.rb +24 -0
  50. data/app/liquid/drops/taxonomy_drop.rb +6 -0
  51. data/app/liquid/drops/user_drop.rb +22 -0
  52. data/app/liquid/drops/variant_drop.rb +24 -0
  53. data/app/liquid/filters/filters.rb +128 -0
  54. data/app/liquid/filters/protected.rb +28 -0
  55. data/app/liquid/filters/rails_filters.rb +73 -0
  56. data/app/liquid/tags/rails_tags.rb +63 -0
  57. data/app/liquid/tags/refinery_tags.rb +33 -0
  58. data/app/liquid/tags/spree_tags.rb +164 -0
  59. data/app/models/file_manager.rb +206 -0
  60. data/app/models/refinery/themes/theme.rb +79 -0
  61. data/app/views/refinery/admin/_dialog_success.html.erb +5 -0
  62. data/app/views/refinery/shared/_menu_branch.html.erb +30 -0
  63. data/app/views/refinery/shared/_pages_menu.html.erb +14 -0
  64. data/app/views/refinery/themes/admin/editor/_editor_actions.html.erb +9 -0
  65. data/app/views/refinery/themes/admin/editor/file.html.erb +50 -0
  66. data/app/views/refinery/themes/admin/editor/index.html.erb +15 -0
  67. data/app/views/refinery/themes/admin/editor/upload_file.html.erb +16 -0
  68. data/app/views/refinery/themes/admin/shared/_actions.html.erb +19 -0
  69. data/app/views/refinery/themes/admin/shared/_theme_assets.html.erb +6 -0
  70. data/app/views/refinery/themes/admin/themes/index.html.erb +58 -0
  71. data/app/views/refinery/themes/admin/themes/upload.html.erb +17 -0
  72. data/app/views/spree/products/_variants.html.erb +19 -0
  73. data/config/initializers/liquid_engine.rb +8 -0
  74. data/config/initializers/refinery/core.rb +4 -0
  75. data/config/initializers/refinery/pages.rb +9 -0
  76. data/config/locales/en.yml +14 -0
  77. data/config/routes.rb +42 -0
  78. data/lib/action_view/template/handlers/liquid.rb +88 -0
  79. data/lib/editable.rb +26 -0
  80. data/lib/hash.rb +5 -0
  81. data/lib/liquid/base_drop.rb +62 -0
  82. data/lib/spreefinery/engine.rb +46 -0
  83. data/lib/spreefinery_themes.rb +21 -0
  84. data/readme.md +27 -0
  85. metadata +178 -0
@@ -0,0 +1,206 @@
1
+ class FileManager
2
+
3
+ def initialize(root, parent=nil)
4
+ @root = root
5
+ @parent = parent
6
+ end
7
+
8
+ def dirs(path=".")
9
+ path = "" if path.nil?
10
+ @path = File.join(File.expand_path(@root), path)
11
+ if File.exists?(@path)
12
+ Dir.entries(@path).sort {|a,b| a <=> b}.inject([]) do |ary, folder|
13
+ ary << {
14
+ :attr => { :fullpath => File.join(@parent, folder), :rel => 'folder'},
15
+ :data => folder,
16
+ :state => Dir[Rails.root.join("themes/#{Refinery::Themes::Theme.current_theme_key}/#{@parent}/#{folder}/*")].empty? ? 'leaf' : 'closed'
17
+ } if File.directory?(File.join(@path, folder)) && folder[0,1] != "."
18
+ ary
19
+ end
20
+ end
21
+ end
22
+
23
+ def files(path=".")
24
+ path = "" if path.nil?
25
+ @path = File.join(File.expand_path(@root), path)
26
+ if File.exists?(@path)
27
+ Dir.entries(@path).sort {|a,b| a <=> b}.inject([]) do |ary, file|
28
+ ary << {:attr => {:fullpath => "#{@parent}/#{file}", :rel => 'default'}, :data => file, :state => 'leaf'} if File.file?(File.join(@path, file))
29
+ ary
30
+ end
31
+ end
32
+ end
33
+
34
+
35
+ def self.create_file(parent_dir, filename)
36
+ content_type = Editable.mime_for filename
37
+ target_name = self.slugify(filename)
38
+
39
+ if filename_ext = File.extname(filename)
40
+ target_name = self.slugify(filename[0..-(filename_ext.length+1)]) + filename_ext
41
+ end
42
+
43
+ return {:notice => "Files of this type (#{filename_ext}) are not allowed!"} unless self.allowed_content_type?(filename_ext)
44
+
45
+ target = File.join(Rails.root, 'themes', Refinery::Themes::Theme.current_theme_key, parent_dir, target_name)
46
+
47
+ begin
48
+ File.open(target, 'w+') do |file|
49
+ file.write('')
50
+ end
51
+ rescue SystemCallError => boom
52
+ return {:notice => "Error: #{boom}"}
53
+ end
54
+
55
+ if File.exist?(target)
56
+ result = {:status => 1,
57
+ :fullpath => File.join(parent_dir, target_name),
58
+ :notice => ('File "%s" was successfully added' % File.basename(target_name)),
59
+ :node_name => target_name
60
+ }
61
+ else
62
+ result = {:notice => 'File "%s" could not be uploaded' % File.basename(target_name)}
63
+ end
64
+ result
65
+ end
66
+
67
+ def self.save_file(file_name, content)
68
+ file = File.join(Rails.root, "themes", Refinery::Themes::Theme.current_theme_key, file_name)
69
+
70
+ begin
71
+ File.open(file, 'w+b') do |f|
72
+ f.write(content)
73
+ end
74
+ rescue SystemCallError => boom
75
+ return {:notice => "Error: #{boom}"}, :layout => false
76
+ end
77
+
78
+ File.read(file)
79
+ end
80
+
81
+
82
+ # remove dir
83
+ def self.remove_dir(fullpath)
84
+ begin
85
+ Dir.rmdir(File.join(Rails.root, 'themes', Refinery::Themes::Theme.current_theme_key, fullpath))
86
+ return {:status => 1, :notice => ('Directory "%s" was successfully removed' % fullpath)}
87
+ rescue SystemCallError => boom
88
+ return {:notice => "Error: #{boom}"}
89
+ end
90
+ end
91
+
92
+ # remove file
93
+ def self.remove_file(fullpath)
94
+ begin
95
+ File.delete(File.join(Rails.root, 'themes', Refinery::Themes::Theme.current_theme_key, fullpath))
96
+ notice = 'File "%s" was successfully removed' % fullpath
97
+ return {:status => 1, :notice => notice}
98
+ rescue SystemCallError => boom
99
+ return {:notice => "Error: #{boom}"}
100
+ end
101
+ end
102
+
103
+
104
+ # rename dir
105
+ def self.rename_dir(fullpath, new_name)
106
+ target_name = slugify(new_name)
107
+ segments = fullpath.split("/")
108
+ segments.pop
109
+ dir_path = segments.join('/')
110
+
111
+ begin
112
+ File.rename(File.join(Rails.root, 'themes', Refinery::Themes::Theme.current_theme_key, fullpath),
113
+ File.join(Rails.root, 'themes', Refinery::Themes::Theme.current_theme_key, dir_path, target_name))
114
+ rescue SystemCallError => boom
115
+ return {:notice => "Error: #{boom}"}
116
+ end
117
+
118
+ {
119
+ :status => 1,
120
+ :fullpath => File.join(dir_path, target_name),
121
+ :notice => ('Directory "%s" was successfully renamed' % target_name),
122
+ :node_name => target_name
123
+ }
124
+
125
+ end
126
+
127
+
128
+ # rename file
129
+ def self.rename_file(fullpath, new_name)
130
+ content_type = Editable.mime_for new_name
131
+ target_name = self.slugify(new_name)
132
+ if filename_ext = File.extname(new_name)
133
+ target_name = self.slugify(new_name[0..-(filename_ext.length+1)]) + filename_ext
134
+ end
135
+
136
+ unless FileManager.allowed_content_type?(filename_ext)
137
+ return {:notice => "Files of this type (#{filename_ext}) are not allowed!"}
138
+ end
139
+
140
+ dir_path = File.dirname(fullpath)
141
+
142
+ begin
143
+ File.rename(File.join(Rails.root, 'themes', Refinery::Themes::Theme.current_theme_key, fullpath),
144
+ File.join(Rails.root, 'themes',Refinery::Themes::Theme.current_theme_key, dir_path, target_name))
145
+ rescue SystemCallError => boom
146
+ return {:notice => "Error: #{boom}"}
147
+ end
148
+
149
+ {
150
+ :status => 1,
151
+ :fullpath => File.join(dir_path, target_name),
152
+ :notice => ('File "%s" was successfully renamed' % File.basename(target_name)),
153
+ :node_name => target_name
154
+ }
155
+
156
+ end
157
+
158
+ # create dir
159
+ def self.create_dir(parent_dir, dir_name)
160
+ slugged_name = slugify(dir_name)
161
+ path = File.join(Rails.root, 'themes', Refinery::Themes::Theme.current_theme_key, parent_dir)
162
+ create_path = File.join(path, slugged_name)
163
+
164
+ if self.secured_path?(path) && !File.exist?(create_path) && FileUtils.mkdir(create_path)
165
+ result = {:status => 1,
166
+ :fullpath => File.join(parent_dir, slugged_name),
167
+ :notice => ('Directory "%s" was successfully created' % slugged_name),
168
+ :node_name => slugged_name
169
+ }
170
+ else
171
+ result = {:notice => 'Directory "%s" could not be created' % slugged_name}
172
+ end
173
+
174
+ result
175
+
176
+ end
177
+
178
+ def self.unzip_file (file)
179
+ require 'zip/zip'
180
+
181
+ Zip::ZipFile.open(file) { |zip_file|
182
+ zip_file.each { |f|
183
+ f_path=File.join(Rails.root.join('themes'), f.name)
184
+ FileUtils.mkdir_p(File.dirname(f_path))
185
+ zip_file.extract(f, f_path) unless File.exist?(f_path)
186
+ }
187
+ }
188
+ end
189
+
190
+ def self.allowed_content_type?(type)
191
+ return true unless Editable.mime_for(".#{type}").eql?('unknown_type')
192
+ return false if Editable.mime_for(".#{type}").eql?('unknown_type')
193
+ end
194
+
195
+
196
+ private
197
+
198
+ def self.secured_path?(file_path)
199
+ File.exist?(file_path) && !File.dirname(file_path).index(Rails.root.join('themes').to_s).nil?
200
+ end
201
+
202
+ def self.slugify(value)
203
+ value.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n, '').to_s.downcase.gsub(/[']+/, '').gsub(/\W+/, ' ').strip.gsub(' ', '-')
204
+ end
205
+
206
+ end
@@ -0,0 +1,79 @@
1
+ require 'open-uri'
2
+
3
+ module Refinery
4
+ module Themes
5
+ class Theme < Refinery::Core::BaseModel
6
+
7
+ attr_accessible :name, :description, :position
8
+
9
+ def default_assigns(str)
10
+ yaml = YAML::load(str)["assigns"] || false
11
+ return {} unless yaml
12
+ assigns = extract_assigns(yaml, :vars)
13
+ extract_assigns(yaml, :collections).each do |k, v|
14
+ assigns[k] = Collection.find_by_key v
15
+ end
16
+ return assigns
17
+ end
18
+
19
+
20
+ class << self
21
+ include ActionController::DataStreaming
22
+
23
+ attr_accessor :content_type, :headers
24
+
25
+ def current_theme_key
26
+ ::Refinery::Setting.find_or_set(:current_theme, "default")
27
+ end
28
+
29
+ def current_theme_config
30
+ config_for(current_theme_key)
31
+ end
32
+
33
+ def default_layout
34
+ ::Refinery::Setting.find_or_set(:default_layout, "site")
35
+ end
36
+
37
+ def theme_path(theme_dir=current_theme_key)
38
+ Rails.root.join("themes/#{theme_dir}")
39
+ end
40
+
41
+ def layout_raw(file_name)
42
+ File.read(theme_path.join("layouts/#{file_name}.liquid"))
43
+ end
44
+
45
+ def all
46
+ Dir.glob(Rails.root.join("themes", "*")).collect { |dir|
47
+ config_for(dir.split("/").last)
48
+ }
49
+ end
50
+
51
+ def config_for(key)
52
+ YAML::load(File.open(theme_path(key).join("config/config.yml")))
53
+ end
54
+
55
+ def layouts
56
+ layouts_list(theme_path.join("views/layouts", "*.liquid"))
57
+ end
58
+
59
+ def templates
60
+ templates_list(theme_path.join("views/refinery/pages/", "*.liquid"))
61
+ end
62
+
63
+ private
64
+
65
+ def layouts_list(path)
66
+ Dir.glob(path).collect { |file|
67
+ file.split("/").last.gsub(/.liquid/, "")
68
+ }
69
+ end
70
+
71
+ def templates_list(path)
72
+ Dir.glob(path).collect { |file|
73
+ file.split("/").last.gsub(/.liquid/, "")
74
+ }
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,5 @@
1
+ <head>
2
+ <script>parent.window.location.reload()</script>
3
+ </head>
4
+ <body>
5
+ </body>
@@ -0,0 +1,30 @@
1
+ <%#TODO migrate to liquid %>
2
+ <%
3
+ have_children = ((children = menu_branch.children unless hide_children).present? &&
4
+ (!local_assigns[:menu_levels] || menu_branch.ancestors.length < local_assigns[:menu_levels]))
5
+
6
+ css = menu_branch_css(local_assigns)
7
+ css << 'dropdown' if have_children
8
+
9
+ if !!local_assigns[:apply_css] and css.any?
10
+ css = "class='#{css.join(' ')}'".html_safe
11
+ end
12
+ -%>
13
+
14
+
15
+ <li<%= ['', css].compact.join(' ').gsub(/\ *$/, '').html_safe %>>
16
+ <% if have_children -%>
17
+ <%= link_to("#{menu_branch.title}<b class=\"caret\"></b>".html_safe, refinery.url_for(menu_branch.url), class: 'dropdown-toggle', 'data-toggle' => 'dropdown') -%>
18
+ <ul class="dropdown-menu">
19
+ <%= render :partial => '/refinery/shared/menu_branch', :collection => children,
20
+ :locals => {
21
+ :apply_css => local_assigns[:apply_css],
22
+ :hide_children => !!hide_children,
23
+ :menu_levels => local_assigns[:menu_levels]
24
+ } -%>
25
+ </ul>
26
+ <% else %>
27
+ <%= link_to(menu_branch.title, refinery.url_for(menu_branch.url)) -%>
28
+ <% end -%>
29
+ </li>
30
+
@@ -0,0 +1,14 @@
1
+ <%
2
+ # Collect the root items.
3
+ # ::Refinery::Menu is smart enough to remember all of the items in the original collection.
4
+ if (roots = local_assigns[:roots] || (collection ||= refinery_menu_pages).roots).present?
5
+ hide_children = Refinery::Core.menu_hide_children if hide_children.nil?
6
+ -%>
7
+ <%= render :partial => '/refinery/shared/menu_branch', :collection => roots,
8
+ :locals => {
9
+ :hide_children => hide_children,
10
+ :sibling_count => (roots.length - 1),
11
+ :menu_levels => local_assigns[:menu_levels],
12
+ :apply_css => true #if you don't care about class='first' class='last' or class='selected' set apply_css to false for speed.
13
+ } -%>
14
+ <% end -%>
@@ -0,0 +1,9 @@
1
+ <% content_for :actions do %>
2
+ <div class="mmenu">
3
+ <input type="button" class="button" id="refresh" value="Refresh"/>
4
+ <input type="button" class="button" id="add_folder" value="Add Root Folder"/>
5
+ </div>
6
+ <br>
7
+
8
+ <div id="jsTree" class="jsTree jstree-apple"></div>
9
+ <% end %>
@@ -0,0 +1,50 @@
1
+ <div class="form-actions">
2
+ <div class="form-actions-left">
3
+ <a href="javascript:CodeMirrorManager.autoFormatSelection()" class="button">Autoformat</a>
4
+ <a href="javascript:CodeMirrorManager.commentSelection(true)" class="button">Comment</a>
5
+ <a href="javascript:CodeMirrorManager.commentSelection(false)" class="button">Uncomment</a>
6
+ </div>
7
+ <div class="form-actions-right">
8
+ Select a theme:
9
+ <select onchange="CodeMirrorManager.selectTheme()" id=select>
10
+ <option selected>default</option>
11
+ <option>ambiance</option>
12
+ <option>blackboard</option>
13
+ <option>cobalt</option>
14
+ <option>eclipse</option>
15
+ <option>elegant</option>
16
+ <option>erlang-dark</option>
17
+ <option>lesser-dark</option>
18
+ <option>monokai</option>
19
+ <option>neat</option>
20
+ <option>night</option>
21
+ <option>rubyblue</option>
22
+ <option>solarized dark</option>
23
+ <option>solarized light</option>
24
+ <option>twilight</option>
25
+ <option>vibrant-ink</option>
26
+ <option>xq-dark</option>
27
+ </select>
28
+ </div>
29
+ </div>
30
+
31
+ <textarea cols="20" rows="20" id="editor"><%= raw @content %></textarea>
32
+ <form method="post" id="form_for_file" enctype="multipart/form-data" class="edit_file"
33
+ action="<%= save_file_themes_admin_editor_url %>" accept-charset="UTF-8">
34
+ <div style="margin: 0pt; padding: 0pt; display: inline;">
35
+ <input type="hidden" value="✓" name="utf8">
36
+ <input type="hidden" value="<%= @related_path %>" name="file_name">
37
+ <input type="hidden" id="file_content" name="file_content">
38
+ <%= token_tag(nil) %>
39
+ </div>
40
+ </form>
41
+
42
+ <div class="form-actions">
43
+ <div class="form-actions-right">
44
+ <%= image_tag "spinner.gif", :style => "display:none", :id => 'spinner', :class => "spinner" %>
45
+ <input class="button" type="submit" value="Save" name="commit" id="file_submit">
46
+ </div>
47
+ </div>
48
+
49
+ <!--<iframe id=preview></iframe>-->
50
+ <%= javascript_tag "var codeMirrorManager = new CodeMirrorManager('editor', '#{@content_type}');" %>
@@ -0,0 +1,15 @@
1
+ <%= render :partial => "refinery/themes/admin/shared/theme_assets" %>
2
+ <%= render 'editor_actions' %>
3
+ <%= render "refinery/themes/admin/shared/actions" %>
4
+
5
+ <% content_for :javascripts do %>
6
+ <%= javascript_include_tag "/assets/editor" %>
7
+ <% end %>
8
+ <% content_for :stylesheets do %>
9
+ <%= stylesheet_link_tag '/assets/editor' %>
10
+ <% end %>
11
+
12
+ <section class="clearfix one_list" id='records'>
13
+ <div class="fullwidth" id="code"><h2>Select any file from tree...</h2></div>
14
+ </section>
15
+
@@ -0,0 +1,16 @@
1
+ <%= render :partial => "refinery/themes/admin/shared/theme_assets" %>
2
+ <section class="clearfix one_list" id="records">
3
+ <%= form_tag(upload_themes_admin_editor_path, :multipart => true) do |f| %>
4
+ <%= hidden_field_tag 'path', @path %>
5
+ <div class='field'>
6
+ <label for="file">Select File:</label>
7
+ <%= file_field_tag 'file', class: 'widest' %>
8
+ </div>
9
+ <div class="form-actions">
10
+ <div class="form-actions-right"><%= submit_tag "Upload" %></div>
11
+ </div>
12
+ <% end %>
13
+ </section>
14
+
15
+
16
+
@@ -0,0 +1,19 @@
1
+ <aside id='actions'>
2
+ <ul>
3
+ <li>
4
+ <%= link_to t('refinery.themes.admin.themes.actions.browse'), refinery.themes_admin_themes_path,
5
+ :class => 'page_copy_icon' %>
6
+ </li>
7
+ <li>
8
+ <%= link_to t('refinery.themes.admin.themes.actions.upload'), refinery.upload_themes_admin_themes_path,
9
+ :class => 'add_icon' %>
10
+ </li>
11
+ <li>
12
+ <%= link_to t('refinery.themes.admin.themes.actions.editor'), refinery.root_themes_admin_editor_url,
13
+ :class => 'folder_icon' %>
14
+ </li>
15
+ </ul>
16
+ <%= yield :actions %>
17
+ </aside>
18
+
19
+ <% content_for :stylesheets, stylesheet_link_tag('refinery/blog/backend') %>