alchemy-custom-model 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +147 -0
  4. data/Rakefile +32 -0
  5. data/app/assets/config/alchemy_custom_model_manifest.js +3 -0
  6. data/app/assets/images/alchemy-custom-model/no_image.png +0 -0
  7. data/app/assets/javascripts/alchemy-custom-model/change_language.js +11 -0
  8. data/app/assets/javascripts/alchemy-custom-model/common_init.js +16 -0
  9. data/app/assets/javascripts/alchemy-custom-model/custom_admin_element_editor.js.coffee +25 -0
  10. data/app/assets/javascripts/alchemy-custom-model/custom_tiny_mce.js.coffee.erb +95 -0
  11. data/app/assets/javascripts/alchemy-custom-model/el_finder.js.coffee.erb +241 -0
  12. data/app/assets/javascripts/alchemy-custom-model/elfinder_ui_manifest.js +4 -0
  13. data/app/assets/javascripts/alchemy-custom-model/manifest.js +23 -0
  14. data/app/assets/javascripts/alchemy-custom-model/nested_attributes_sortable.js.coffee +25 -0
  15. data/app/assets/javascripts/alchemy-custom-model/select2filter.js +51 -0
  16. data/app/assets/javascripts/alchemy-custom-model/subobjects.js +98 -0
  17. data/app/assets/javascripts/alchemy-custom-model/total_page_elfinder.js.coffee +15 -0
  18. data/app/assets/stylesheets/alchemy-custom-model/custom_elfinder.css.scss +130 -0
  19. data/app/assets/stylesheets/alchemy-custom-model/custom_style.css.scss +228 -0
  20. data/app/assets/stylesheets/alchemy-custom-model/custom_tiny_mce.scss +6 -0
  21. data/app/assets/stylesheets/alchemy-custom-model/manifest.css +16 -0
  22. data/app/controllers/alchemy/custom/model/admin/base_controller.rb +189 -0
  23. data/app/controllers/alchemy/custom/model/admin/files_controller.rb +106 -0
  24. data/app/controllers/alchemy/pages_controller_decorator.rb +1 -0
  25. data/app/helpers/alchemy/custom/model/admin/base_helper.rb +379 -0
  26. data/app/helpers/alchemy/custom/model/base_helper.rb +18 -0
  27. data/app/helpers/alchemy/custom/model/custom_model_helper.rb +112 -0
  28. data/app/helpers/alchemy/pages_helper_decorator.rb +95 -0
  29. data/app/models/admin_override_to_param.rb +9 -0
  30. data/app/models/application_record.rb +9 -0
  31. data/app/views/alchemy/custom/model/admin/base/_buttons_tool.html.erb +16 -0
  32. data/app/views/alchemy/custom/model/admin/base/_gallery_item.html.erb +4 -0
  33. data/app/views/alchemy/custom/model/admin/base/_language_tree_select.html.erb +9 -0
  34. data/app/views/alchemy/custom/model/admin/base/_search_box.html.erb +19 -0
  35. data/app/views/alchemy/custom/model/admin/base/_seo.html.erb +8 -0
  36. data/app/views/alchemy/custom/model/admin/base/_table.html.erb +33 -0
  37. data/app/views/alchemy/custom/model/admin/base/_title.html.erb +3 -0
  38. data/app/views/alchemy/custom/model/admin/base/edit.html.erb +18 -0
  39. data/app/views/alchemy/custom/model/admin/base/index.html.erb +39 -0
  40. data/app/views/alchemy/custom/model/admin/base/new.html.erb +19 -0
  41. data/app/views/alchemy/custom/model/admin/files/error_notice.json.jbuilder +1 -0
  42. data/app/views/alchemy/custom/model/admin/files/ui.html.erb +13 -0
  43. data/config/initializers/elfinder_abilities.rb +1 -0
  44. data/config/locales/en.yml +11 -0
  45. data/config/locales/it.yml +21 -0
  46. data/config/routes.rb +8 -0
  47. data/lib/alchemy-custom-model.rb +29 -0
  48. data/lib/alchemy/custom/model/el_finder.rb +17 -0
  49. data/lib/alchemy/custom/model/el_finder/ability.rb +16 -0
  50. data/lib/alchemy/custom/model/el_finder/connector.rb +435 -0
  51. data/lib/alchemy/custom/model/el_finder/image.rb +35 -0
  52. data/lib/alchemy/custom/model/el_finder/path_name.rb +220 -0
  53. data/lib/alchemy/custom/model/el_finder/paths.rb +21 -0
  54. data/lib/alchemy/custom/model/el_finder/paths/active_record_reference.rb +50 -0
  55. data/lib/alchemy/custom/model/el_finder/paths/base.rb +298 -0
  56. data/lib/alchemy/custom/model/el_finder/paths/component_file.rb +59 -0
  57. data/lib/alchemy/custom/model/el_finder/paths/component_files.rb +34 -0
  58. data/lib/alchemy/custom/model/el_finder/paths/file.rb +23 -0
  59. data/lib/alchemy/custom/model/el_finder/paths/files.rb +25 -0
  60. data/lib/alchemy/custom/model/el_finder/paths/image.rb +42 -0
  61. data/lib/alchemy/custom/model/el_finder/paths/images.rb +31 -0
  62. data/lib/alchemy/custom/model/el_finder/paths/root.rb +24 -0
  63. data/lib/alchemy/custom/model/el_finder/volumes.rb +18 -0
  64. data/lib/alchemy/custom/model/el_finder/volumes/alchemy_file.rb +197 -0
  65. data/lib/alchemy/custom/model/el_finder/volumes/alchemy_files.rb +51 -0
  66. data/lib/alchemy/custom/model/el_finder/volumes/alchemy_images.rb +69 -0
  67. data/lib/alchemy/custom/model/el_finder/volumes/base.rb +149 -0
  68. data/lib/alchemy/custom/model/el_finder/volumes/component_attribute.rb +130 -0
  69. data/lib/alchemy/custom/model/engine.rb +40 -0
  70. data/lib/alchemy/custom/model/global_id_setter.rb +35 -0
  71. data/lib/alchemy/custom/model/model_decoration.rb +82 -0
  72. data/lib/alchemy/custom/model/pages_controller_dec.rb +132 -0
  73. data/lib/alchemy/custom/model/translation_scope.rb +18 -0
  74. data/lib/alchemy/custom/model/version.rb +7 -0
  75. data/lib/alchemy/touching_decorator.rb +12 -0
  76. data/lib/tasks/alchemy_custom_model_tasks.rake +41 -0
  77. data/vendor/elfinder/css/elfinder.full.css +5117 -0
  78. data/vendor/elfinder/css/elfinder.min.css +9 -0
  79. data/vendor/elfinder/css/theme.css +349 -0
  80. data/vendor/elfinder/js/elfinder.full.js +34270 -0
  81. data/vendor/elfinder/js/elfinder.min.js +25 -0
  82. metadata +194 -0
@@ -0,0 +1,18 @@
1
+ ##
2
+ # Helper generale per gemma
3
+ module Alchemy::Custom::Model
4
+ module BaseHelper
5
+
6
+ include TranslationScope
7
+
8
+
9
+ def print_current_site_language
10
+ content_tag(:div, class: "current_site_language") do
11
+ acm_t(:you_are_editing_site_language,
12
+ site: Alchemy::Site.current.name,
13
+ language: Alchemy::Language.current.name).html_safe
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,112 @@
1
+ module Alchemy::Custom::Model
2
+ module CustomModelHelper
3
+
4
+ def custom_model_page_urlname(obj)
5
+ layout = Alchemy::PageLayout.get_all_by_attributes(custom_model: obj.class.to_s).select {|ly| ly["custom_model_action"] == "show"}.first
6
+ if not layout.blank?
7
+ Alchemy::Language.current.pages.find_by(page_layout: layout["name"]).try(:parent).try(:urlname)
8
+ else
9
+ nil
10
+ end
11
+ end
12
+
13
+ def custom_model_path(obj)
14
+ custom_model_url_builder(obj) do |url|
15
+ alchemy.show_page_path(Alchemy::Language.current.code, url)
16
+ end
17
+ end
18
+
19
+ def custom_model_url(obj)
20
+ custom_model_url_builder(obj) do |url|
21
+ alchemy.show_page_url(Alchemy::Language.current.code, url)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def custom_model_url_builder(obj)
28
+ to_url = custom_model_page_urlname obj
29
+ if not to_url.blank?
30
+
31
+ # Url build with alchemy
32
+ url = to_url
33
+
34
+ # Url build with model method :to_url
35
+ url = obj.to_url if url.nil? and obj.respond_to?(:to_url)
36
+
37
+ # Url builded with friendly id
38
+ if url.nil?
39
+ url = obj.class.to_s.demodulize.parameterize.underscore
40
+ end
41
+
42
+ url += '/'
43
+
44
+ if obj.class.respond_to?(:friendly_id_config)
45
+ url += "#{obj.send(obj.class.friendly_id_config.slug_column)}"
46
+ else
47
+ url += "#{obj.id}"
48
+ end
49
+
50
+ if block_given?
51
+ yield url
52
+ else
53
+ url
54
+ end
55
+ else
56
+ "#no_page_show_custom_model"
57
+ end
58
+ end
59
+
60
+
61
+ # def search_result_page
62
+ # @search_result_page ||= begin
63
+ # page = Alchemy::Page.published.find_by(
64
+ # page_layout: search_result_page_layout['name'],
65
+ # language_id: Alchemy::Language.current.id
66
+ # )
67
+ # if page.nil?
68
+ # logger.warn "\n++++++\nNo published search result page found. Please create one or publish your search result page.\n++++++\n"
69
+ # end
70
+ # page
71
+ # end
72
+ # end
73
+ #
74
+ # def search_result_page_layout
75
+ # page_layout = Alchemy::PageLayout.get_all_by_attributes(searchresults: true).first
76
+ # if page_layout.nil?
77
+ # raise "No searchresults page layout found. Please add page layout with `searchresults: true` into your `page_layouts.yml` file."
78
+ # end
79
+ # page_layout
80
+ # end
81
+
82
+ # def show_svg(path)
83
+ # File.open(path) do |file|
84
+ # raw file.read
85
+ # end
86
+ # end
87
+ # def homepage_path
88
+ # home_page = Alchemy::Page.language_root_for(Alchemy::Language.current)
89
+ # show_alchemy_page_path(home_page)
90
+ # end
91
+
92
+ # @param [Alchemy::File] alchemy_attachment
93
+ # def from_mime_to_extension(alchemy_attachment)
94
+ # mime = MIME::Types[alchemy_attachment.file_mime_type].first
95
+ # I18n.t("estensione_prodotti.#{mime.i18n_key}", default: mime.preferred_extension)
96
+ # end
97
+
98
+ #
99
+ #
100
+ # def extract_video_id_from_link(link)
101
+ # vid_regex = /(?:youtube(?:-nocookie)?\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/
102
+ # link.match(vid_regex).try(:[], 1)
103
+ # end
104
+ #
105
+ # def youtube_video_thumb_url(video_link)
106
+ # video_id = extract_video_id_from_link video_link
107
+ # if not video_id.blank?
108
+ # "https://img.youtube.com/vi/#{video_id}/hqdefault.jpg"
109
+ # end
110
+ # end
111
+ end
112
+ end
@@ -0,0 +1,95 @@
1
+ Alchemy::PagesHelper.module_eval do
2
+
3
+ include Alchemy::Custom::Model::CustomModelHelper
4
+
5
+ def page_title(options = {})
6
+ return "" if !@custom_element.nil? and @custom_element.respond_to? :meta_title and
7
+ @custom_element.meta_title.presence and @page.title.blank?
8
+ options = {
9
+ prefix: "",
10
+ separator: ""
11
+ }.update(options)
12
+ title_parts = [options[:prefix]]
13
+ if response.status == 200
14
+ if !@custom_element.nil? and @custom_element.respond_to? :meta_title
15
+ title_parts << (@custom_element.meta_title.presence || @page.title)
16
+ else
17
+ title_parts << @page.title
18
+ end
19
+ else
20
+ title_parts << response.status
21
+ end
22
+ title_parts.join(options[:separator]).html_safe
23
+ end
24
+
25
+
26
+ def meta_description
27
+
28
+ meta_description = @page.meta_description
29
+
30
+ if !@custom_element.nil? and @custom_element.respond_to? :meta_description
31
+ meta_description = @custom_element.meta_description || @page.meta_description
32
+ end
33
+
34
+ meta_description || Alchemy::Language.current_root_page.try(:meta_description)
35
+
36
+ end
37
+
38
+ def meta_keywords
39
+
40
+ meta_keywords = @page.meta_keywords
41
+
42
+ if !@custom_element.nil? and @custom_element.respond_to? :meta_keywords
43
+ meta_keywords = @custom_element.meta_keywords.presence || @page.meta_keywords
44
+ end
45
+
46
+ meta_keywords || Alchemy::Language.current_root_page.try(:meta_keywords)
47
+
48
+ end
49
+
50
+ def meta_robots
51
+ return "noindex,nofollow" if Rails.env.to_sym != :production
52
+
53
+ if !@custom_element.nil? and @custom_element.respond_to? :robot_index? and @custom_element.respond_to? :robot_follow?
54
+ "#{(@custom_element.robot_index?.presence or @page.robot_index?) ? '' : 'no'}index, #{(@custom_element.robot_follow?.presence || @page.robot_follow?) ? '' : 'no'}follow"
55
+ else
56
+ "#{ @page.robot_index? ? '' : 'no'}index, #{@page.robot_follow? ? '' : 'no'}follow"
57
+
58
+ end
59
+ end
60
+
61
+ def menu_arrow_and_back_control
62
+ bf = ActiveSupport::SafeBuffer.new
63
+ bf << content_tag(:div, class: "back d-block d-xl-none") do
64
+ content_tag(:span) do
65
+ back = ActiveSupport::SafeBuffer.new
66
+ back << fa_icon("angle-left")
67
+ back << ' BACK'
68
+ back
69
+ end
70
+ end
71
+ bf << content_tag(:span, class: "arrow_menu arrow_up") do
72
+ fa_icon("chevron-up")
73
+ end
74
+ bf << content_tag(:span, class: "arrow_menu arrow_down") do
75
+ fa_icon("chevron-down")
76
+ end
77
+ bf
78
+ end
79
+
80
+
81
+ def language_links_by_page(current_page)
82
+ r = []
83
+ Alchemy::Language.on_current_site.published.with_root_page.collect {|lang|
84
+ page = Alchemy::Page.published.with_language(lang.id).where(name: current_page.name).first
85
+ if not page.nil? and lang != Alchemy::Language.current
86
+ url_page = show_page_path_params(page).merge(locale: lang.code)
87
+ r << content_tag(:link, nil, href: url_page[:locale] + '/' + url_page[:urlname], hreflang: lang.code, rel: "alternate")
88
+ end
89
+ }
90
+ r.join().html_safe
91
+ end
92
+
93
+
94
+ end
95
+
@@ -0,0 +1,9 @@
1
+ require 'active_support/concern'
2
+
3
+ module AdminOverrideToParam
4
+
5
+ def to_param
6
+ self.id.to_s
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ module Alchemy
2
+ module Custom
3
+ module Model
4
+ class ApplicationRecord < ActiveRecord::Base
5
+ self.abstract_class = true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ <% if can?(:edit, base_class) %>
2
+ <%= link_to fa_icon("edit"), edit_polymorphic_path(url_namespace(obj)),
3
+ title: t(:edit),
4
+ class: "edit" %>
5
+ <% end %>
6
+
7
+ <% if check_presence_polymorphic_path(url_namespace(obj)+[:clone], action: :new) and can?(:clones, base_class) %>
8
+ <%= link_to_dialog fa_icon("clone"), new_polymorphic_path(url_namespace(obj)+[:clone]),
9
+ title: t(:clone, model: base_class.model_name.human),
10
+ class: "clone" %>
11
+ <% end %>
12
+
13
+
14
+ <% if can?(:destroy, base_class) %>
15
+ <%= delete_button polymorphic_path(url_namespace(obj)), icon: "trash" %>
16
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <div class="gallery_item_blk">
2
+ <%= image_tag(picture.image_file.thumb("100x100#").url) %>
3
+ <%= yield if block_given? %>
4
+ </div>
@@ -0,0 +1,9 @@
1
+ <%- if multi_language? -%>
2
+ <div class="button_with_label">
3
+ <%= select_tag 'change_language',
4
+ options_for_select(Alchemy::Language.on_current_site.map { |l| [l.name, l.id] }, Alchemy::Language.current.id),
5
+ class: 'alchemy_selectbox' %>
6
+ <label><%= Alchemy.t("Language tree") %></label>
7
+ </div>
8
+ <div class="toolbar_spacer"></div>
9
+ <% end %>
@@ -0,0 +1,19 @@
1
+ <% if base_class.respond_to? :fields_for_search %>
2
+ <%
3
+ field_search = base_class.fields_for_search.join("_or_")
4
+ field_search += "_cont"
5
+ %>
6
+ <%= search_form_for @query, url: url, class: 'search_form' do |f| %>
7
+ <div class="search_field">
8
+ <%= render_icon('search') %>
9
+ <%= f.search_field field_search.to_sym,
10
+ class: 'search_input_field',
11
+ placeholder: Alchemy.t(:search) %>
12
+ <%= link_to render_icon(:times, size: 'xs'), url,
13
+ class: 'search_field_clear',
14
+ id: 'search_field_clear',
15
+ title: Alchemy.t(:click_to_show_all),
16
+ style: params.fetch(:q, {}).present? ? 'display: block' : 'display: none' %>
17
+ </div>
18
+ <% end %>
19
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <fieldset>
2
+ <legend><%= t(:seo_fields)%></legend>
3
+ <%= f.input :meta_title %>
4
+ <%= f.input :meta_description %>
5
+ <%= f.input :meta_keywords %>
6
+ <%= f.input :robot_follow %>
7
+ <%= f.input :robot_index %>
8
+ </fieldset>
@@ -0,0 +1,33 @@
1
+ <% if @objects.any? %>
2
+ <table class="<%= "model_#{base_class.name.underscore.gsub("/", "_")}" %> list"
3
+ id="<%= base_class.name.underscore.gsub("/", "_") %>_list">
4
+ <thead>
5
+ <tr>
6
+ <% table_columns.each do |attribute| %>
7
+ <th class="colum_header <%= attribute.to_s %>">
8
+ <%= t(base_class.human_attribute_name(attribute)) %>
9
+ </th>
10
+ <% end %>
11
+ <th class="tools"></th>
12
+ </tr>
13
+ </thead>
14
+ <tbody>
15
+ <% @objects.each do |obj| %>
16
+ <tr>
17
+ <% table_columns.each do |field| %>
18
+ <td class="custom-model-row <%= field.to_s %>">
19
+ <%= render_obj obj, field %>
20
+ </td>
21
+ <% end %>
22
+ <td class="tools">
23
+
24
+ <%= render partial: "buttons_tool", locals: {obj: obj} %>
25
+
26
+
27
+ </td>
28
+ </tr>
29
+ <% end %>
30
+ </tbody>
31
+ </table>
32
+ <% end %>
33
+
@@ -0,0 +1,3 @@
1
+ <h1>
2
+ <%= t(:title_action, action: t(action_name, scope: :actions), model: base_class.model_name.human) %>
3
+ </h1>
@@ -0,0 +1,18 @@
1
+ <% toolbar(
2
+ buttons: [
3
+ {
4
+ icon: "angle-double-left ",
5
+ label: t(:title_action, action: t(:index, scope: :actions), model: base_class.model_name.human),
6
+ url: polymorphic_path(url_namespace),
7
+ title: t(:title_action, action: t(:index, scope: :actions), model: base_class.model_name.human),
8
+ hotkey: 'alt+b',
9
+ dialog: false,
10
+ if_permitted_to: [:index, @obj.class]
11
+ }
12
+
13
+ ],
14
+ search: false
15
+ ) %>
16
+
17
+ <%= render 'title' %>
18
+ <%= render partial: "form", locals: {object: @obj} %>
@@ -0,0 +1,39 @@
1
+ <% content_for(:toolbar) do %>
2
+ <%= render 'alchemy/admin/partials/site_select' %>
3
+ <%= render 'language_tree_select' %>
4
+ <%= print_current_site_language %>
5
+ <%= render partial: 'search_box', locals: {url: polymorphic_path(url_namespace), base_class: base_class} %>
6
+ <% end %>
7
+
8
+ <% toolbar(
9
+ buttons: [
10
+ {
11
+ icon: :plus,
12
+ label: acm_t(:title_action, action: acm_t(:new, scope: :actions), model: base_class.model_name.human),
13
+ url: new_polymorphic_path(url_namespace),
14
+ title: acm_t(:title_action, action: acm_t(:new, scope: :actions), model: base_class.model_name.human),
15
+ hotkey: 'alt+n',
16
+ dialog: false,
17
+ if_permitted_to: [:create, base_class]
18
+ }
19
+ ],
20
+ search: false,
21
+ ) %>
22
+
23
+
24
+ <%= base_container do %>
25
+
26
+ <div id="archive_all" class="resources-table-wrapper">
27
+
28
+ <%= content_tag :h1, "#{@objects.count} #{base_class.model_name.human(count: @objects.count)}", class: 'resources-header' %>
29
+
30
+
31
+ <%= render partial: "table" %>
32
+
33
+ <%= paginate @objects, theme: 'alchemy', hide_per_page_select: true %>
34
+
35
+ </div>
36
+
37
+ <% end %>
38
+
39
+
@@ -0,0 +1,19 @@
1
+ <% toolbar(
2
+ buttons: [
3
+ {
4
+ icon: "angle-double-left ",
5
+ label: acm_t(:title_action, action: t(:index, scope: :actions), model: base_class.model_name.human),
6
+ url: polymorphic_path(url_namespace),
7
+ title: acm_t(:title_action, action: t(:index, scope: :actions), model: base_class.model_name.human),
8
+ hotkey: 'alt+b',
9
+ dialog: false,
10
+ if_permitted_to: [:index, @obj.class]
11
+ }
12
+
13
+ ],
14
+ search: false
15
+ ) %>
16
+
17
+ <%= render 'title' %>
18
+ <%= render 'form', object: @obj %>
19
+
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <%= stylesheet_link_tag 'alchemy/admin/all', media: 'all' %>
5
+ <%= stylesheet_link_tag 'elfinder/css/elfinder.min', media: 'all' %>
6
+ <%= stylesheet_link_tag 'elfinder/css/theme', media: 'all' %>
7
+ <%= javascript_include_tag 'alchemy-custom-model/elfinder_ui_manifest' %>
8
+ <%= csrf_meta_tags %>
9
+ </head>
10
+ <body>
11
+ <%= content_tag(:div, nil, id: 'elfinder', data: {"elfinder-volumes": @volumes.join(',')}) %>
12
+ </body>
13
+ </html>