alchemy-custom-model 0.1.0

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 (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>