alchemy-custom-model 2.1.2 → 3.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 (52) hide show
  1. checksums.yaml +5 -5
  2. data/app/assets/javascripts/alchemy-custom-model/alchemy_custom_model_select.js +62 -0
  3. data/app/assets/javascripts/alchemy-custom-model/common_init.js +17 -14
  4. data/app/assets/javascripts/alchemy-custom-model/el_finder.js.coffee.erb +31 -0
  5. data/app/assets/javascripts/alchemy-custom-model/manifest.js +5 -0
  6. data/app/assets/javascripts/backend/date_picker.js +24 -0
  7. data/app/assets/javascripts/backend/fix_more_image_in_element.js.coffee +10 -0
  8. data/app/assets/javascripts/backend/override_alchemy_selectbox.js +8 -0
  9. data/app/assets/stylesheets/alchemy-custom-model/custom_elfinder.css.scss +20 -2
  10. data/app/assets/stylesheets/alchemy-custom-model/custom_style.css.scss +95 -0
  11. data/app/controllers/alchemy/custom/model/admin/base_controller.rb +16 -14
  12. data/app/controllers/alchemy/custom/model/admin/base_with_globalize_controller.rb +38 -0
  13. data/app/controllers/concerns/alchemy/admin/nodes_controller_dec.rb +55 -0
  14. data/app/helpers/alchemy/custom/model/admin/base_helper.rb +51 -3
  15. data/app/helpers/alchemy/custom/model/custom_model_helper.rb +26 -13
  16. data/app/helpers/alchemy/pages_helper_decorator.rb +38 -0
  17. data/app/models/concerns/alchemy/node_dec.rb +45 -0
  18. data/app/views/alchemy/admin/nodes/_form.html.erb +126 -0
  19. data/app/views/alchemy/admin/nodes/custom_models.json.jbuilder +10 -0
  20. data/app/views/alchemy/admin/nodes/custom_models_methods.json.jbuilder +10 -0
  21. data/app/views/alchemy/admin/pictures/_custom_model_info.html.erb +27 -0
  22. data/app/views/alchemy/admin/pictures/_infos.html.erb +65 -0
  23. data/app/views/alchemy/custom/model/admin/base/_gallery_item.html.erb +7 -2
  24. data/app/views/alchemy/custom/model/admin/base/_search_panel.html.erb +16 -0
  25. data/app/views/alchemy/custom/model/admin/base/_seo.html.erb +5 -5
  26. data/app/views/alchemy/custom/model/admin/base/_show_object.html.erb +30 -0
  27. data/app/views/alchemy/custom/model/admin/base/_show_objects.html.erb +48 -0
  28. data/app/views/alchemy/custom/model/admin/base/_title.html.erb +1 -1
  29. data/app/views/alchemy/custom/model/admin/base/edit.html.erb +2 -2
  30. data/app/views/alchemy/custom/model/admin/base/index.html.erb +6 -5
  31. data/app/views/alchemy/custom/model/admin/base/new.html.erb +2 -2
  32. data/app/views/alchemy/custom/model/admin/base/show.html.erb +5 -48
  33. data/app/views/alchemy/pages/sitemap.xml.erb +16 -0
  34. data/config/locales/it.yml +6 -0
  35. data/config/routes.rb +16 -0
  36. data/db/migrate/20200424184007_add_fields_to_node.rb +8 -0
  37. data/lib/alchemy/custom/model.rb +58 -0
  38. data/lib/alchemy/custom/model/el_finder/paths/active_record_reference.rb +9 -0
  39. data/lib/alchemy/custom/model/engine.rb +7 -1
  40. data/lib/alchemy/custom/model/globalize_model_decoration.rb +26 -0
  41. data/lib/alchemy/custom/model/menu_methods.rb +16 -0
  42. data/lib/alchemy/custom/model/model_decoration.rb +3 -0
  43. data/lib/alchemy/custom/model/model_utils_methods.rb +28 -0
  44. data/lib/alchemy/custom/model/pages_controller_dec.rb +38 -25
  45. data/lib/alchemy/custom/model/picture_used_by.rb +51 -0
  46. data/lib/alchemy/custom/model/sitemap_methods.rb +18 -0
  47. data/lib/alchemy/custom/model/slug_optimizer.rb +23 -0
  48. data/lib/alchemy/custom/model/version.rb +1 -1
  49. data/lib/tasks/alchemy_custom_model_tasks.rake +3 -0
  50. data/vendor/assets/javascripts/flatpickr/i10n/it.js +71 -0
  51. metadata +66 -9
  52. data/lib/alchemy-custom-model.rb +0 -31
@@ -221,9 +221,12 @@ module Alchemy::Custom::Model::Admin::BaseHelper
221
221
  component_id = SecureRandom.hex(10)
222
222
 
223
223
  bf << form.fields_for(field) do |join_record_form|
224
- render(layout: 'gallery_item', locals: {picture: join_record_form.object.picture}) do
224
+ render(layout: 'gallery_item', locals: {picture: join_record_form.object.picture, jr_id: join_record_form.object.id}) do
225
+ sb = ActiveSupport::SafeBuffer.new
225
226
 
226
- join_record_form.hidden_field :position, class: 'gallery_position_counter'
227
+ sb << join_record_form.hidden_field(:position, class: 'gallery_position_counter')
228
+ sb << join_record_form.hidden_field(:_destroy, class: 'gallery_item_destroy_input')
229
+ sb
227
230
 
228
231
  end
229
232
  end
@@ -389,7 +392,7 @@ module Alchemy::Custom::Model::Admin::BaseHelper
389
392
 
390
393
  def order_path(obj = nil, options = {})
391
394
  if obj.nil?
392
- new_polymorphic_path([:admin, base_class.to_s.pluralize.underscore, :order])
395
+ new_polymorphic_path([:admin, base_class.to_s.pluralize.underscore.to_sym, :order])
393
396
  else
394
397
  new_polymorphic_path([:admin, obj, :order])
395
398
  end
@@ -434,4 +437,49 @@ module Alchemy::Custom::Model::Admin::BaseHelper
434
437
  end
435
438
 
436
439
 
440
+ def search_panel(options = {}, &block)
441
+ submit_button = options.fetch(:enable_submit, true)
442
+ klass = options.delete(:class) || []
443
+
444
+ content_tag(:div, class: "search_panel #{klass.join(" ")}", ** options) do
445
+ sb = ActiveSupport::SafeBuffer.new
446
+
447
+ if @query
448
+ sb << content_tag(:div, class:"title") do
449
+ spt = ActiveSupport::SafeBuffer.new
450
+ spt << content_tag(:span, t("search_panel_title"), class:"title_label")
451
+
452
+ #TODO: toggle pannello
453
+ #spt << content_tag(:span, class:"button_toggle") do
454
+ # content_tag(:a,class:"icon_button") do
455
+ # content_tag(:i, nil, class:"icon fa-fw fa-bars fas")
456
+ # end
457
+ #end
458
+ spt
459
+ end
460
+
461
+ sb << simple_form_for(@query, url: polymorphic_path([:admin, @query.klass]), method: :get) do |f|
462
+ sff = ActiveSupport::SafeBuffer.new
463
+
464
+ sff << content_tag(:div, class: "search_fields_group") do
465
+ search_fields = ActiveSupport::SafeBuffer.new
466
+
467
+ search_fields << capture do
468
+ block.call(f)
469
+ end
470
+
471
+ search_fields
472
+ end
473
+ if submit_button
474
+ sff << content_tag(:div, class: "action_buttons") do
475
+ f.submit(::I18n.t('alchemy_ajax_form.submit_search'))
476
+ end
477
+ end
478
+ sff
479
+ end
480
+ end
481
+ sb
482
+ end
483
+ end
484
+
437
485
  end
@@ -2,37 +2,46 @@ module Alchemy::Custom::Model
2
2
  module CustomModelHelper
3
3
 
4
4
  def self.included(mod)
5
- if ::Rails.application.config.action_controller.include_all_helpers!=false
5
+ if ::Rails.application.config.action_controller.include_all_helpers != false
6
6
  raise "Devi definire in config/application.rb config.action_controller.include_all_helpers=false
7
7
  in modo da far funzionare correttamente l'override degli helper come per i controller"
8
8
  end
9
9
  end
10
10
 
11
- def custom_model_page_urlname(obj)
12
- layout = Alchemy::PageLayout.get_all_by_attributes(custom_model: obj.class.to_s).select {|ly| ly["custom_model_action"] == "show"}.first
11
+ def custom_model_page_urlname(obj, language: nil)
12
+ if language.blank?
13
+ language = Alchemy::Language.current
14
+ end
15
+ layout = Alchemy::PageLayout.get_all_by_attributes(custom_model: obj.class.to_s).select { |ly| ly["custom_model_action"] == "show" }.first
13
16
  if not layout.blank?
14
- Alchemy::Language.current.pages.find_by(page_layout: layout["name"]).try(:parent).try(:urlname)
17
+ language.pages.find_by(page_layout: layout["name"]).try(:parent).try(:urlname)
15
18
  else
16
19
  nil
17
20
  end
18
21
  end
19
22
 
20
- def custom_model_path(obj)
21
- custom_model_url_builder(obj) do |url|
22
- alchemy.show_page_path(Alchemy::Language.current.code, url)
23
+ def custom_model_path(obj, options = {})
24
+ language = options.delete(:language)
25
+ custom_model_url_builder(obj, language: language) do |url|
26
+ alchemy.show_page_path(language || Alchemy::Language.current.code, url, options)
23
27
  end
24
28
  end
25
29
 
26
- def custom_model_url(obj)
27
- custom_model_url_builder(obj) do |url|
28
- alchemy.show_page_url(Alchemy::Language.current.code, url)
30
+ def custom_model_url(obj, options = {})
31
+ language = options.delete(:language)
32
+ if language.is_a? String
33
+ language = Alchemy::Language.find_by_code(language)
34
+ end
35
+ custom_model_url_builder(obj, language: language) do |url|
36
+ alchemy.show_page_url(language.code || Alchemy::Language.current.code, url, options)
29
37
  end
30
38
  end
31
39
 
40
+
32
41
  private
33
42
 
34
- def custom_model_url_builder(obj)
35
- to_url = custom_model_page_urlname obj
43
+ def custom_model_url_builder(obj, language: nil)
44
+ to_url = custom_model_page_urlname obj, language: language
36
45
  if not to_url.blank?
37
46
 
38
47
  # Url build with alchemy
@@ -49,11 +58,15 @@ module Alchemy::Custom::Model
49
58
  url += '/'
50
59
 
51
60
  if obj.class.respond_to?(:friendly_id_config)
52
- url += "#{obj.send(obj.class.friendly_id_config.slug_column)}"
61
+ language = Alchemy::Language.current if language.blank?
62
+ Globalize.with_locale(language.language_code.to_sym) do
63
+ url += "#{obj.send(obj.class.friendly_id_config.slug_column)}"
64
+ end
53
65
  else
54
66
  url += "#{obj.id}"
55
67
  end
56
68
 
69
+
57
70
  if block_given?
58
71
  yield url
59
72
  else
@@ -91,5 +91,43 @@ Alchemy::PagesHelper.module_eval do
91
91
  end
92
92
 
93
93
 
94
+ def check_if_active node_or_cm_inst
95
+ if !node_or_cm_inst.is_a? Alchemy::Node
96
+ if node_or_cm_inst.respond_to? :for_menu_matching and node_or_cm_inst.for_menu_matching.include? @custom_element
97
+ return true
98
+ end
99
+ else
100
+ if node_or_cm_inst.custom_model?
101
+ if @custom_element.respond_to? :for_menu_matching and
102
+ @custom_element.for_menu_matching.include? node_or_cm_inst.klass_custom_model
103
+ return true
104
+ end
105
+ elsif node_or_cm_inst.page and node_or_cm_inst.page.self_and_descendants.include? @page
106
+ return true
107
+ end
108
+ end
109
+ false
110
+ end
111
+
112
+ def render_menu_with_language(name, options = {})
113
+ root_node = Alchemy::Node.where(language_id: Alchemy::Language.current.id).roots.find_by(name: name)
114
+ if root_node.nil?
115
+ warning("Menu with name #{name} not found!")
116
+ return
117
+ end
118
+
119
+ options = {
120
+ node_partial_name: "#{root_node.view_folder_name}/node"
121
+ }.merge(options)
122
+
123
+ render(root_node, menu: root_node, node: root_node, options: options)
124
+ rescue ActionView::MissingTemplate => e
125
+ warning <<-WARN
126
+ Menu partial not found for #{name}.
127
+ #{e}
128
+ WARN
129
+ end
130
+
131
+
94
132
  end
95
133
 
@@ -0,0 +1,45 @@
1
+ module Alchemy
2
+ module NodeDec
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+
8
+ validates :custom_model_klass, presence: true, if: -> {
9
+ url.blank? and not parent.nil?
10
+ }
11
+
12
+ before_validation :ensure_page_nil_if_custom_model, on: [:create, :update]
13
+ before_validation :set_site, on: [:create], if: -> {site.nil?}
14
+
15
+ def custom_model?
16
+ !custom_model_klass.blank?
17
+ end
18
+
19
+ def klass_custom_model
20
+ self.custom_model_klass.constantize
21
+ end
22
+
23
+ private
24
+
25
+ def ensure_page_nil_if_custom_model
26
+ if not url.blank? and !custom_model_klass_changed? and !custom_model_method_changed?
27
+ self.custom_model_klass = nil
28
+ self.custom_model_method = nil
29
+ elsif !custom_model_klass.blank? and !url_changed?
30
+ self.page = nil
31
+ self.url = nil
32
+ end
33
+
34
+ end
35
+
36
+ def set_site
37
+ unless self.language.nil?
38
+ self.site = language.site
39
+ end
40
+ end
41
+
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,126 @@
1
+ <%= alchemy_form_for([:admin, node]) do |f| %>
2
+
3
+ <% if node.root? %>
4
+
5
+ <% if Alchemy::Node.respond_to? :available_menu_names %>
6
+ <%= f.input :name,
7
+ collection: Alchemy::Node.available_menu_names.map { |n| [I18n.t(n, scope: [:alchemy, :menu_names]), n] },
8
+ include_blank: false,
9
+ input_html: {class: 'alchemy_selectbox'} %>
10
+ <% else %>
11
+ <%= f.input :name, input_html: {
12
+ autofocus: true,
13
+ value: node.page && node.read_attribute(:name).blank? ? nil : node.name,
14
+ placeholder: node.page ? node.page.name : nil
15
+ } %>
16
+ <% end %>
17
+
18
+ <% else %>
19
+
20
+ <%= f.input :name, as: :string, input_html: {
21
+ autofocus: true,
22
+ value: node.page && node.read_attribute(:name).blank? ? nil : node.name,
23
+ placeholder: node.page ? node.page.name : nil
24
+ } %>
25
+
26
+ <%
27
+ active_klass = (node.errors.keys.include? :custom_model_klass or
28
+ node.custom_model?) ? "ui-tabs-active" : ""
29
+ %>
30
+
31
+ <div class="container_selctor_age_custom_model">
32
+ <div id="tabs_nodes" class="ui-tabs ui-corner-all ui-widget ui-widget-content">
33
+ <ul role="tablist" class="ui-tabs-nav ui-corner-all ui-helper-reset ui-helper-clearfix ui-widget-header">
34
+ <li role="tab" tabindex="0" class="ui-tabs-tab ui-corner-top ui-state-default ui-tab">
35
+ <a href="#pages" role="presentation" tabindex="-1" class="ui-tabs-anchor" id="ui-id-1">
36
+ <%= Alchemy.t(:pages_select) %>
37
+ </a>
38
+ </li>
39
+ <li role="tab" tabindex="1" class="ui-tabs-tab ui-corner-top ui-tab <%= active_klass %>">
40
+ <a href="#custom_models" role="presentation" tabindex="1" class="ui-tabs-anchor" id="ui-id-2">
41
+ <%= Alchemy.t(:custom_models) %>
42
+ </a>
43
+ </li>
44
+ </ul>
45
+ <div id="custom_models" aria-labelledby="legacy_urls_label" role="tabpanel" class="ui-tabs-panel ui-corner-bottom ui-widget-content" aria-hidden="false">
46
+ <%= f.input :custom_model_klass, input_html: {class: 'alchemy_selectbox'} %>
47
+ <%= f.input :custom_model_method, input_html: {class: 'alchemy_selectbox'} %>
48
+ </div>
49
+ <div id="pages" aria-labelledby="ui-id-1" role="tabpanel" class="ui-tabs-panel ui-corner-bottom ui-widget-content" aria-hidden="false">
50
+ <%= f.input :page_id, label: Alchemy::Page.model_name.human, input_html: {class: 'alchemy_selectbox'} %>
51
+ <%= f.input :url, input_html: {disabled: node.page}, hint: Alchemy.t(:node_url_hint) %>
52
+ <%= f.input :title %>
53
+ <%= f.input :nofollow %>
54
+ <%= f.input :external %>
55
+ <%= f.hidden_field :parent_id %>
56
+ </div>
57
+
58
+ </div>
59
+ </div>
60
+
61
+
62
+
63
+
64
+
65
+
66
+ <% end %>
67
+ <% if node.respond_to? :site_id %>
68
+ <%= f.hidden_field :site_id %>
69
+ <% end %>
70
+ <% if node.respond_to? :language_id %>
71
+ <%= f.hidden_field :language_id %>
72
+ <% end %>
73
+ <%= f.submit button_label %>
74
+ <% end %>
75
+
76
+ <script>
77
+
78
+ $("#tabs_nodes").tabs();
79
+
80
+
81
+ $('#node_custom_model_klass').alchemyCustomModelSelect({
82
+ placeholder: "<%= Alchemy.t(:select_custom_model_method) %>",
83
+ url: "<%= alchemy.custom_models_admin_nodes_path %>",
84
+
85
+ }).on("change", function (event) {
86
+ $('#node_custom_model_method').select2('enable');
87
+
88
+ }).on("select2-removed", function (e) {
89
+ $('#node_custom_model_method').val(null).trigger("change");
90
+ })
91
+
92
+
93
+ $('#node_custom_model_method').alchemyCustomModelSelect({
94
+ placeholder: "<%= Alchemy.t(:select_custom_model) %>",
95
+ url: "<%= alchemy.custom_models_methods_admin_nodes_path %>",
96
+ query_params: function (term, page) {
97
+ var klass = $('#node_custom_model_klass').val()
98
+ return {
99
+ custom_model_klass: klass
100
+ }
101
+ }
102
+
103
+ })
104
+
105
+ $('#node_custom_model_method').select2('disable');
106
+
107
+ $('#node_page_id').alchemyPageSelect({
108
+ placeholder: "<%= Alchemy.t(:search_page) %>",
109
+ url: "<%= alchemy.api_pages_path %>",
110
+ <% if node.page %>
111
+ initialSelection: {
112
+ id: <%= node.page_id %>,
113
+ text: "<%= node.page.name %>",
114
+ url: "/<%= node.page.urlname %>"
115
+ }
116
+ <% end %>
117
+ }).on('change', function (e) {
118
+ if (e.val === '') {
119
+ $('#node_name').removeAttr('placeholder')
120
+ $('#node_url').val('').prop('disabled', false)
121
+ } else {
122
+ $('#node_name').attr('placeholder', e.added.name)
123
+ $('#node_url').val('/' + e.added.urlname).prop('disabled', true)
124
+ }
125
+ })
126
+ </script>
@@ -0,0 +1,10 @@
1
+
2
+ json.meta do
3
+ json.total_count @custom_model_klasses.count
4
+ json.page params[:page]
5
+ json.per_page 10
6
+ end
7
+ json.results @custom_model_klasses do |result|
8
+ json.id result
9
+ json.text result
10
+ end
@@ -0,0 +1,10 @@
1
+
2
+ json.meta do
3
+ json.total_count @custom_model_methods.count
4
+ json.page params[:page]
5
+ json.per_page 10
6
+ end
7
+ json.results @custom_model_methods do |result|
8
+ json.id result
9
+ json.text result
10
+ end
@@ -0,0 +1,27 @@
1
+ <div class="picture-usage-info resource_info">
2
+ <h3>
3
+ <%= I18n.t(:image_used_in_this_models, scope: :alchemy_custom_model) %>
4
+ </h3>
5
+ <div id="pictures_page_list">
6
+ <% used_in = Alchemy::Custom::Model::PictureUsedBy.used_by(@picture.id)%>
7
+ <% if used_in.any? %>
8
+ <ul>
9
+ <% used_in.each do |m| %>
10
+ <li>
11
+ <% begin %>
12
+ <h3>
13
+ <%= render_icon 'file-alt' %>
14
+ <p><%= link_to "#{m.model_name.human}, #{m.try(:slug).to_s}", main_app.edit_polymorphic_path([:admin, m]) %></p>
15
+ </h3>
16
+ <% rescue %>
17
+ <% end %>
18
+ </li>
19
+ <% end %>
20
+ </ul>
21
+ <% else %>
22
+ <%= render_message do %>
23
+ <%= Alchemy.t(:picture_not_in_use_yet) %>
24
+ <% end %>
25
+ <% end %>
26
+ </div>
27
+ </div>
@@ -0,0 +1,65 @@
1
+ <div class="resource_info">
2
+ <div class="picture-file-infos">
3
+ <div class="value">
4
+ <label><%= Alchemy::Picture.human_attribute_name(:image_file_name) %></label>
5
+ <p><%= @picture.image_file_name %></p>
6
+ </div>
7
+ <div class="value">
8
+ <label><%= Alchemy::Picture.human_attribute_name(:image_file_dimensions) %></label>
9
+ <p><%= @picture.image_file_dimensions %>px</p>
10
+ </div>
11
+ <div class="value">
12
+ <label><%= Alchemy::Picture.human_attribute_name(:image_file_size) %></label>
13
+ <p><%= number_to_human_size @picture.image_file_size %></p>
14
+ </div>
15
+ </div>
16
+ </div>
17
+
18
+ <div class="picture-usage-info resource_info">
19
+ <h3>
20
+ <%= Alchemy.t(:this_picture_is_used_on_these_pages) %>
21
+ </h3>
22
+ <div id="pictures_page_list">
23
+ <% if @assignments.any? %>
24
+ <ul>
25
+ <% @assignments.group_by(&:page).each do |page, essence_pictures| %>
26
+ <% if page %>
27
+ <li>
28
+ <h3>
29
+ <%= render_icon 'file-alt' %>
30
+ <p><%= link_to page.name, edit_admin_page_path(page) %></p>
31
+ </h3>
32
+ <ul class="list">
33
+ <% essence_pictures.group_by(&:element).each do |element, essence_pictures| %>
34
+ <li class="<%= cycle('even', 'odd') %>">
35
+ <% page_link = link_to element.display_name_with_preview_text,
36
+ edit_admin_page_path(page, anchor: "element_#{element.id}") %>
37
+ <% pictures = essence_pictures.collect do |e|
38
+ e.content.name_for_label
39
+ end.to_sentence %>
40
+ <% if element.public? %>
41
+ <%= render_icon('window-maximize', style: 'regular') %>
42
+ <% else %>
43
+ <%= render_icon('window-close') %>
44
+ <% end %>
45
+ <p>
46
+ <%== Alchemy.t(:pictures_in_page, page: page_link, pictures: pictures) %>
47
+ <em><%= Alchemy::Element.human_attribute_name(:trashed) if element.trashed? %></em>
48
+ </p>
49
+ </li>
50
+ <% end %>
51
+ </ul>
52
+ </li>
53
+ <% end %>
54
+ <% end %>
55
+ </ul>
56
+ <% else %>
57
+ <%= render_message do %>
58
+ <%= Alchemy.t(:picture_not_in_use_yet) %>
59
+ <% end %>
60
+ <% end %>
61
+ </div>
62
+ </div>
63
+
64
+ <%= render partial: "custom_model_info" %>
65
+