vinsol_spree_themes 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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +36 -0
  3. data/.ruby-version +1 -0
  4. data/Appraisals +16 -0
  5. data/Gemfile +9 -0
  6. data/Gemfile.lock +386 -0
  7. data/LICENSE +26 -0
  8. data/README.md +250 -0
  9. data/Rakefile +21 -0
  10. data/app/assets/javascripts/spree/backend/codemirror/codemirror.js +9351 -0
  11. data/app/assets/javascripts/spree/backend/codemirror/css-hint.js +60 -0
  12. data/app/assets/javascripts/spree/backend/codemirror/fullscreen.js +41 -0
  13. data/app/assets/javascripts/spree/backend/codemirror/html-hint.js +348 -0
  14. data/app/assets/javascripts/spree/backend/codemirror/javascript-hint.js +155 -0
  15. data/app/assets/javascripts/spree/backend/codemirror/javascript.js +813 -0
  16. data/app/assets/javascripts/spree/backend/codemirror/markdown.js +796 -0
  17. data/app/assets/javascripts/spree/backend/codemirror/ruby.js +295 -0
  18. data/app/assets/javascripts/spree/backend/codemirror/show-hint.js +438 -0
  19. data/app/assets/javascripts/spree/backend/editor.js +11 -0
  20. data/app/assets/javascripts/spree/backend/jquery.treemenu.js +87 -0
  21. data/app/assets/javascripts/spree/backend/main.js +26 -0
  22. data/app/assets/javascripts/spree/backend/spree_themes.js +2 -0
  23. data/app/assets/javascripts/spree/backend/template.js +51 -0
  24. data/app/assets/javascripts/spree/backend/theme.js +17 -0
  25. data/app/assets/javascripts/spree/frontend/spree_themes.js +2 -0
  26. data/app/assets/stylesheets/spree/backend/codemirror/codemirror.css +340 -0
  27. data/app/assets/stylesheets/spree/backend/codemirror/fullscreen.css +6 -0
  28. data/app/assets/stylesheets/spree/backend/codemirror/show-hint.css +36 -0
  29. data/app/assets/stylesheets/spree/backend/editor.css +7 -0
  30. data/app/assets/stylesheets/spree/backend/jquery.treemenu.css +8 -0
  31. data/app/assets/stylesheets/spree/backend/spree_themes.css +7 -0
  32. data/app/assets/stylesheets/spree/backend/style.css +239 -0
  33. data/app/assets/stylesheets/spree/backend/template_editor.css +39 -0
  34. data/app/assets/stylesheets/spree/frontend/spree_themes.css +6 -0
  35. data/app/assets/stylesheets/spree/frontend/theme_preview.css +9 -0
  36. data/app/controllers/spree/admin/themes_controller.rb +80 -0
  37. data/app/controllers/spree/admin/themes_preview_controller.rb +30 -0
  38. data/app/controllers/spree/admin/themes_templates_controller.rb +60 -0
  39. data/app/controllers/spree/fragment_cache_controller.rb +13 -0
  40. data/app/controllers/spree/store_controller_decorator.rb +37 -0
  41. data/app/helpers/spree/base_helper_decorator.rb +45 -0
  42. data/app/models/spree/theme.rb +153 -0
  43. data/app/models/spree/themes_template.rb +67 -0
  44. data/app/models/spree/themes_template/cache_resolver.rb +37 -0
  45. data/app/overrides/spree/add_preview_bar_to_store.html.rb +6 -0
  46. data/app/overrides/spree/add_theme_meta_details_to_store.html.rb +6 -0
  47. data/app/overrides/spree/admin/add_themes_tab.html.rb +6 -0
  48. data/app/services/assets_precompiler_service.rb +86 -0
  49. data/app/services/file_generator_service.rb +29 -0
  50. data/app/services/template_generator_service.rb +101 -0
  51. data/app/services/zip_file_builder.rb +87 -0
  52. data/app/services/zip_file_extractor.rb +52 -0
  53. data/app/views/spree/admin/shared/_theme_menu_button.html.erb +5 -0
  54. data/app/views/spree/admin/themes/_themes.html.erb +44 -0
  55. data/app/views/spree/admin/themes/_upload.html.erb +17 -0
  56. data/app/views/spree/admin/themes/index.html.erb +50 -0
  57. data/app/views/spree/admin/themes_templates/_editor.html.erb +29 -0
  58. data/app/views/spree/admin/themes_templates/_template.html.erb +12 -0
  59. data/app/views/spree/admin/themes_templates/edit.html.erb +13 -0
  60. data/app/views/spree/admin/themes_templates/edit.js.erb +1 -0
  61. data/app/views/spree/admin/themes_templates/index.html.erb +27 -0
  62. data/app/views/spree/admin/themes_templates/new.html.erb +56 -0
  63. data/app/views/spree/shared/_preview_bar.html.erb +7 -0
  64. data/app/views/spree/shared/_theme_metadata.html.erb +9 -0
  65. data/bin/rails +7 -0
  66. data/config/initializers/assets.rb +24 -0
  67. data/config/initializers/sprockets.rb +85 -0
  68. data/config/locales/en.yml +52 -0
  69. data/config/routes.rb +22 -0
  70. data/db/migrate/20170628072452_vinsol_spree_themes_create_themes_and_themes_templates_table.rb +24 -0
  71. data/gemfiles/spree_3_1.gemfile +8 -0
  72. data/gemfiles/spree_3_2.gemfile +9 -0
  73. data/gemfiles/spree_master.gemfile +9 -0
  74. data/lib/generators/themes/default.zip +0 -0
  75. data/lib/generators/vinsol_spree_themes/install/install_generator.rb +50 -0
  76. data/lib/tasks/sync_templates.rake +47 -0
  77. data/lib/vinsol_spree_themes.rb +3 -0
  78. data/lib/vinsol_spree_themes/engine.rb +22 -0
  79. data/lib/vinsol_spree_themes/factories.rb +6 -0
  80. data/lib/vinsol_spree_themes/version.rb +18 -0
  81. data/spec/spec_helper.rb +93 -0
  82. data/vinsol_spree_themes.gemspec +43 -0
  83. metadata +374 -0
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/layouts/spree_application',
3
+ name: 'add_preview_bar_to_store',
4
+ insert_before: '[data-hook="body"]',
5
+ partial: 'spree/shared/preview_bar'
6
+ )
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/layouts/spree_application',
3
+ name: 'add_theme_meta_details_to_store',
4
+ insert_bottom: '[data-hook="inside_head"]',
5
+ partial: 'spree/shared/theme_metadata'
6
+ )
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/shared/_main_menu',
3
+ name: 'add_themes_tab',
4
+ insert_before: 'div.spree-version',
5
+ partial: 'spree/admin/shared/theme_menu_button'
6
+ )
@@ -0,0 +1,86 @@
1
+ class AssetsPrecompilerService
2
+
3
+ attr_reader :theme, :env, :manifest
4
+
5
+ PUBLIC_PRECOMPILED_ASSET_PATH = File.join('public', 'assets', 'vinsol_spree_theme')
6
+ PUBLIC_PRECOMPILED_ASSET_PATH_FOR_PREVIEW = File.join('public', 'assets', 'preview_vinsol_spree_theme')
7
+ THEME_PATH = File.join('public', 'vinsol_spree_themes')
8
+ CURRENT_THEME_PATH = File.join(THEME_PATH, 'current')
9
+
10
+ def initialize(theme)
11
+ @theme = theme
12
+ end
13
+
14
+ def minify(options= {})
15
+ options.merge!({ precompile: true }) unless options.key?(:precompile)
16
+ build_environment
17
+ build_manifest
18
+ options[:precompile] ? assets_precompile : manifest
19
+ end
20
+
21
+ def copy_assets
22
+ source_path = File.join(CURRENT_THEME_PATH, 'precompiled_assets', '.')
23
+
24
+ FileUtils.rm_r(PUBLIC_PRECOMPILED_ASSET_PATH) if File.exists?(PUBLIC_PRECOMPILED_ASSET_PATH)
25
+ FileUtils.mkdir_p(PUBLIC_PRECOMPILED_ASSET_PATH)
26
+ FileUtils.cp_r(source_path, PUBLIC_PRECOMPILED_ASSET_PATH)
27
+ end
28
+
29
+ def copy_preview_assets
30
+ source_path = File.join(theme_path, 'precompiled_assets', '.')
31
+
32
+ FileUtils.rm_r(PUBLIC_PRECOMPILED_ASSET_PATH_FOR_PREVIEW) if File.exists?(PUBLIC_PRECOMPILED_ASSET_PATH_FOR_PREVIEW)
33
+ FileUtils.mkdir_p(PUBLIC_PRECOMPILED_ASSET_PATH_FOR_PREVIEW)
34
+ FileUtils.cp_r(source_path, PUBLIC_PRECOMPILED_ASSET_PATH_FOR_PREVIEW)
35
+ end
36
+
37
+ private
38
+
39
+ def build_environment
40
+ @env ||= Sprockets::Environment.new()
41
+ prepend_stylesheet_path
42
+ prepend_javascript_path
43
+ prepend_images_path
44
+ prepend_fonts_path
45
+ set_compressors
46
+ end
47
+
48
+ def build_manifest
49
+ @manifest ||= Sprockets::Manifest.new(env, File.join(theme_path, 'precompiled_assets'))
50
+ end
51
+
52
+ def prepend_stylesheet_path
53
+ env.prepend_path(File.join(source_asset_path, 'stylesheets'))
54
+ end
55
+
56
+ def prepend_javascript_path
57
+ env.prepend_path(File.join(source_asset_path, 'javascripts'))
58
+ end
59
+
60
+ def prepend_images_path
61
+ env.prepend_path(File.join(source_asset_path, 'images'))
62
+ end
63
+
64
+ def prepend_fonts_path
65
+ env.prepend_path(File.join(source_asset_path, 'fonts'))
66
+ end
67
+
68
+ def set_compressors
69
+ env.js_compressor = Rails.application.config.assets.js_compressor
70
+ env.css_compressor = Rails.application.config.assets.css_compressor
71
+ end
72
+
73
+ def assets_precompile
74
+ manifest.clobber
75
+ manifest.compile('*')
76
+ end
77
+
78
+ def source_asset_path
79
+ theme.published? ? CURRENT_THEME_PATH : theme_path
80
+ end
81
+
82
+ def theme_path
83
+ File.join(THEME_PATH, theme.name)
84
+ end
85
+
86
+ end
@@ -0,0 +1,29 @@
1
+ class FileGeneratorService
2
+
3
+ attr_reader :template, :theme
4
+
5
+ def initialize(template)
6
+ @template = template
7
+ @theme = template.theme
8
+ end
9
+
10
+ def self.create(template)
11
+ new(template).send :create
12
+ end
13
+
14
+ private
15
+
16
+ def create
17
+ FileUtils.mkdir_p(output_directory)
18
+ File.open(filepath, 'w+') { |file| file.puts(template.body) }
19
+ end
20
+
21
+ def filepath
22
+ File.join(template.path, template.name)
23
+ end
24
+
25
+ def output_directory
26
+ File.dirname(filepath)
27
+ end
28
+
29
+ end
@@ -0,0 +1,101 @@
1
+ class TemplateGeneratorService
2
+
3
+ DEFAULT_LOCALE = 'en'
4
+ FILE_EXTENSIONS = { css: '.css', scss: '.scss', js: '.js', yml: '.yml' }
5
+ IMAGE_EXTENSIONS = ['.png', '.gif', '.jpeg', '.jpg']
6
+ FONT_EXTENSIONS = ['.woff', '.ttf', '.svg', '.eot', '.woff2', '.otf']
7
+
8
+ attr_reader :filepath, :theme_template, :theme
9
+
10
+ def initialize(filepath, theme)
11
+ @filepath = filepath
12
+ @theme = theme
13
+ @theme_template = build_template
14
+ end
15
+
16
+ def generate
17
+ return nil if(image_file?(filepath) || font_directory?(filepath))
18
+ theme_template.assign_attributes(template_attributes)
19
+ theme_template.save
20
+ end
21
+
22
+ private
23
+
24
+ def build_template
25
+ @theme.templates.find_or_initialize_by(path: get_path, name: file_name)
26
+ end
27
+
28
+ def template_attributes
29
+ {
30
+ body: File.read(filepath),
31
+ path: get_path,
32
+ partial: is_partial?,
33
+ handler: get_handler,
34
+ format: get_format,
35
+ locale: DEFAULT_LOCALE,
36
+ theme_id: theme.id,
37
+ name: file_name
38
+ }
39
+ end
40
+
41
+ def get_path
42
+ File.dirname(filepath)
43
+ end
44
+
45
+ def is_partial?
46
+ file_name.starts_with?('_')
47
+ end
48
+
49
+ def get_handler
50
+ return nil if assets_file?(filepath) || yml_files?(filepath)
51
+ File.extname(filepath).gsub('.', '')
52
+ end
53
+
54
+ def get_format
55
+ return nil if assets_file?(filepath) || yml_files?(filepath)
56
+ # In spree few `.js.erb` files related to google are rendered in html format.
57
+ script_embeded_partial? ? 'html' : format
58
+ end
59
+
60
+ def script_embeded_partial?
61
+ is_partial? && format.eql?('js')
62
+ end
63
+
64
+ def file_name
65
+ File.basename(filepath)
66
+ end
67
+
68
+ def format
69
+ file_name_without_ext.split('.')[-1]
70
+ end
71
+
72
+ def file_name_without_ext
73
+ File.basename(filepath, get_handler)
74
+ end
75
+
76
+ def stylesheet_file?(filename)
77
+ File.extname(filename) == FILE_EXTENSIONS[:css] || FILE_EXTENSIONS[:scss]
78
+ end
79
+
80
+ def javascript_file?(filename)
81
+ File.extname(filename) == FILE_EXTENSIONS[:js]
82
+ end
83
+
84
+ def assets_file?(filename)
85
+ stylesheet_file?(filename) || javascript_file?(filename)
86
+ end
87
+
88
+ # FIX_ME_PG:- considering all images used in themes to be kept in images directory. Later invalidate using file content-type.
89
+ def image_file?(filename)
90
+ file_name == 'snapshot.png' || get_path.split('/').include?('images') && IMAGE_EXTENSIONS.include?(File.extname(filename))
91
+ end
92
+
93
+ def font_directory?(filename)
94
+ get_path.split('/').include?('fonts') && FONT_EXTENSIONS.include?(File.extname(filename))
95
+ end
96
+
97
+ def yml_files?(filename)
98
+ File.extname(filename) == FILE_EXTENSIONS[:yml]
99
+ end
100
+
101
+ end
@@ -0,0 +1,87 @@
1
+ require 'zip'
2
+
3
+ class ZipFileBuilder
4
+
5
+ THEMES_PATH = File.join('public', 'vinsol_spree_themes')
6
+ INVALID_DIRECTORIES = ['.', '..', 'precompiled_assets']
7
+
8
+ attr_reader :theme, :entries, :input_path, :output_path, :zip, :name
9
+
10
+ def initialize(theme)
11
+ @theme = theme
12
+ @name = name
13
+ input_theme_directory_path
14
+ output_zip_file_path
15
+ end
16
+
17
+ def archive
18
+ remove
19
+ @entries = get_directory_content(input_theme_directory_path)
20
+ delete_non_zip_content(@entries)
21
+ build_zip_file
22
+ end
23
+
24
+ def remove
25
+ File.delete(output_path) if File.exist?(output_path)
26
+ end
27
+
28
+ def name
29
+ "#{ theme.name }.zip"
30
+ end
31
+
32
+ private
33
+
34
+ def input_theme_directory_path
35
+ @input_path = File.join(THEMES_PATH, theme.name)
36
+ end
37
+
38
+ def output_zip_file_path
39
+ @output_path = File.join('tmp', name)
40
+ end
41
+
42
+ def get_directory_content(directory_path)
43
+ Dir.entries(directory_path)
44
+ end
45
+
46
+ def delete_non_zip_content(entries)
47
+ INVALID_DIRECTORIES.each { |dir| entries.delete(dir) }
48
+ end
49
+
50
+ def build_zip_file
51
+ open_zip_file
52
+ write_entries('', entries)
53
+ zip.close();
54
+ end
55
+
56
+ def open_zip_file
57
+ @zip = Zip::File.open(output_path, Zip::File::CREATE)
58
+ end
59
+
60
+ def write_entries(path, entries)
61
+ entries.each do |e|
62
+ zip_path = path == '' ? e : File.join(path, e)
63
+ filepath = File.join(input_path, zip_path)
64
+
65
+ if File.directory?(filepath)
66
+ build_sub_directory(zip_path, filepath)
67
+ else
68
+ build_file_to_zip(zip_path, filepath)
69
+ end
70
+ end
71
+ end
72
+
73
+ def build_sub_directory(zip_path, filepath)
74
+ zip.mkdir(zip_path)
75
+ subdir_entries = get_directory_content(filepath);
76
+ delete_non_zip_content(subdir_entries)
77
+
78
+ write_entries(zip_path, subdir_entries)
79
+ end
80
+
81
+ def build_file_to_zip(zip_path, filepath)
82
+ zip.get_output_stream(zip_path) do |file|
83
+ file.puts(File.open(filepath, "rb").read())
84
+ end
85
+ end
86
+
87
+ end
@@ -0,0 +1,52 @@
1
+ require 'zip'
2
+
3
+ class ZipFileExtractor
4
+
5
+ OUTPUT_PATH = File.join('public', 'vinsol_spree_themes')
6
+ IGNORED_FILES_REGEX = /\/(\.|__)/
7
+
8
+ attr_reader :file_path, :theme
9
+
10
+ def initialize(file_path, theme)
11
+ @file_path = file_path
12
+ @theme = theme
13
+ end
14
+
15
+ def extract
16
+ FileUtils.mkdir_p(OUTPUT_PATH)
17
+ parse_file
18
+ end
19
+
20
+ private
21
+
22
+ def parse_file
23
+ Zip::File.open(file_path) do |zip_file|
24
+ zip_file.each do |file|
25
+ filepath = File.join(output_path, file.name)
26
+ next if filepath =~ IGNORED_FILES_REGEX
27
+ unless File.exist?(filepath)
28
+ FileUtils::mkdir_p(File.dirname(filepath))
29
+ zip_file.extract(file, filepath)
30
+ end
31
+ generate_template(filepath) if File.file?(filepath)
32
+ end
33
+ end
34
+ end
35
+
36
+ def output_path
37
+ @output_path ||= File.join(OUTPUT_PATH, file_name)
38
+ end
39
+
40
+ def file_name
41
+ @file_name ||= File.basename(file_path, file_extension)
42
+ end
43
+
44
+ def file_extension
45
+ File.extname(file_path)
46
+ end
47
+
48
+ def generate_template(filepath)
49
+ TemplateGeneratorService.new(filepath, theme).generate
50
+ end
51
+
52
+ end
@@ -0,0 +1,5 @@
1
+ <% if can? :admin, Spree::Theme %>
2
+ <ul class="nav nav-sidebar">
3
+ <%= tab Spree.t(:vinsol_spree_themes), url: admin_themes_path, icon: 'picture' %>
4
+ </ul>
5
+ <% end %>
@@ -0,0 +1,44 @@
1
+ <!-- LISTING ALL THE THEMES -->
2
+ <div class="themes-container">
3
+
4
+ <% sorted_themes(@themes).each do |theme| %>
5
+ <div class="theme theme-col col-md-4 col-sm-6 <%= theme.state %>">
6
+ <div class="theme-block">
7
+ <div class="thumbnail cmn-height-block">
8
+ <%= link_to image_tag(snapshot_path(theme)), admin_theme_templates_path(theme), class: 'img-responsive theme-image' %>
9
+ </div>
10
+
11
+ <div class="theme-content">
12
+ <div class="theme-name-area">
13
+ <h2 class="theme-name"><%= theme.name %></h2>
14
+
15
+ <div class="btn-group dropup">
16
+ <button type="button" class="btn btn-danger dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="glyphicon glyphicon-option-horizontal more-action-glyphicon"></i></button>
17
+
18
+ <div class="dropdown-menu">
19
+ <% if theme.drafted? %>
20
+ <%= link_to Spree.t('actions.compiled'), state_change_admin_theme_path(theme, state: 'compiled'), method: :patch, class: 'dropdown-item' %>
21
+ <% elsif theme.compiled? %>
22
+ <%= link_to Spree.t('actions.published'), state_change_admin_theme_path(theme, state: 'published'), method: :patch, class: 'dropdown-item' %>
23
+ <% end %>
24
+
25
+ <% unless theme.published? %>
26
+ <%= link_to 'Delete', admin_theme_path(theme), method: :delete, class: 'dropdown-item', data: { confirm: 'Are you sure?' } %>
27
+ <% end %>
28
+
29
+ <%= link_to Spree.t('actions.download'), download_admin_theme_path(theme), method: :patch, class: 'dropdown-item action-download' %>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ </div>
34
+
35
+ <div class="theme-action-view">
36
+ <%= link_to Spree.t(:templates), admin_theme_templates_path(theme) , class: 'btn btn-primary btn-sm' %>
37
+ <%= link_to Spree.t('actions.preview'), admin_theme_preview_path(theme_id: theme), class: 'btn btn-info btn-sm', target: '_blank' %>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ <% end %>
42
+ </div>
43
+
44
+ <%= paginate @themes %>
@@ -0,0 +1,17 @@
1
+ <%= form_for @theme, url: upload_admin_themes_path, method: :post do |f| %>
2
+ <div class="updload-theme-panel col-md-4 col-sm-6" data-hook="theme-file-upload-form">
3
+ <div class="upload-theme-col">
4
+ <label class="cmn-height-block text-center">
5
+ <%= f.file_field :template_file, class: 'form-control' %>
6
+ <div class="file-btn-helper">
7
+ <i class="glyphicon glyphicon-upload upload-icon"></i><br />
8
+ ADD NEW THEME
9
+ </div>
10
+ </label>
11
+ </div>
12
+ </div>
13
+
14
+ <div class="form-actions hidden" data-hook="buttons">
15
+ <%= f.submit Spree.t('actions.upload'), class: 'btn-success' %>
16
+ </div>
17
+ <% end %>