alchemy-custom-model 2.0.3 → 2.2.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 (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/alchemy-custom-model/total_page_elfinder.js.coffee +1 -1
  7. data/app/assets/javascripts/backend/date_picker.js +24 -0
  8. data/app/assets/javascripts/backend/fix_more_image_in_element.js.coffee +10 -0
  9. data/app/assets/javascripts/backend/override_alchemy_selectbox.js +8 -0
  10. data/app/assets/stylesheets/alchemy-custom-model/custom_elfinder.css.scss +20 -2
  11. data/app/assets/stylesheets/alchemy-custom-model/custom_style.css.scss +95 -0
  12. data/app/controllers/alchemy/custom/model/admin/base_controller.rb +58 -10
  13. data/app/controllers/alchemy/custom/model/admin/base_with_globalize_controller.rb +38 -0
  14. data/app/controllers/concerns/alchemy/admin/nodes_controller_dec.rb +55 -0
  15. data/app/helpers/alchemy/custom/model/admin/base_helper.rb +50 -2
  16. data/app/helpers/alchemy/custom/model/custom_model_helper.rb +26 -13
  17. data/app/helpers/alchemy/pages_helper_decorator.rb +38 -0
  18. data/app/models/concerns/alchemy/node_dec.rb +45 -0
  19. data/app/views/alchemy/admin/nodes/_form.html.erb +126 -0
  20. data/app/views/alchemy/admin/nodes/custom_models.json.jbuilder +10 -0
  21. data/app/views/alchemy/admin/nodes/custom_models_methods.json.jbuilder +10 -0
  22. data/app/views/alchemy/admin/pictures/_custom_model_info.html.erb +27 -0
  23. data/app/views/alchemy/admin/pictures/_infos.html.erb +65 -0
  24. data/app/views/alchemy/custom/model/admin/base/_gallery_item.html.erb +7 -2
  25. data/app/views/alchemy/custom/model/admin/base/_search_panel.html.erb +16 -0
  26. data/app/views/alchemy/custom/model/admin/base/_seo.html.erb +5 -5
  27. data/app/views/alchemy/custom/model/admin/base/_show_object.html.erb +30 -0
  28. data/app/views/alchemy/custom/model/admin/base/_show_objects.html.erb +48 -0
  29. data/app/views/alchemy/custom/model/admin/base/_title.html.erb +1 -1
  30. data/app/views/alchemy/custom/model/admin/base/edit.html.erb +2 -2
  31. data/app/views/alchemy/custom/model/admin/base/index.html.erb +24 -2
  32. data/app/views/alchemy/custom/model/admin/base/new.html.erb +2 -2
  33. data/app/views/alchemy/custom/model/admin/base/show.html.erb +5 -48
  34. data/app/views/alchemy/pages/sitemap.xml.erb +16 -0
  35. data/config/locales/it.yml +6 -0
  36. data/config/routes.rb +16 -0
  37. data/db/migrate/20200424184007_add_fields_to_node.rb +8 -0
  38. data/lib/alchemy/custom/model.rb +58 -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 +58 -7
  52. data/lib/alchemy-custom-model.rb +0 -31
@@ -0,0 +1,38 @@
1
+ module Alchemy
2
+ module Custom
3
+ module Model
4
+ module Admin
5
+ class BaseWithGlobalizeController < ::Alchemy::Custom::Model::Admin::BaseController
6
+
7
+
8
+ around_action :switch_globalize_locale
9
+ before_action :load_object, except: :index
10
+
11
+
12
+ def index
13
+ @query = base_class.ransack(params[:q])
14
+ @objects = @query.result(distinct: true)
15
+ @objects = @objects.accessible_by(current_ability)
16
+ @total_objects = @objects
17
+ @objects = @objects.page(params[:page]).
18
+ per(params[:per_page] ||
19
+ (base_class::DEFAULT_PER_PAGE if base_class.const_defined? :DEFAULT_PER_PAGE) ||
20
+ 25)
21
+ instance_variable_set "@#{base_class.name.demodulize.underscore.downcase.pluralize}", @objects
22
+ end
23
+
24
+
25
+
26
+ private
27
+
28
+ def switch_globalize_locale(&action)
29
+ locale = Alchemy::Language.current.language_code.to_sym
30
+ Globalize.with_locale(locale, &action)
31
+ end
32
+
33
+
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,55 @@
1
+ module Alchemy
2
+ module Admin
3
+ module NodesControllerDec
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+
8
+ def custom_models
9
+ @custom_model_klasses = Alchemy::Custom::Model.allowed_custom_models_for_menu
10
+ if params[:q] and params[:q][:name]
11
+ @custom_model_klasses = @custom_model_klasses.select { |el| el.match /#{params[:q][:name]}/i }
12
+ end
13
+ @custom_model_klasses = Kaminari.paginate_array(@custom_model_klasses).page(params[:page]).per(params[:per_page] || 10)
14
+
15
+ end
16
+
17
+ def custom_models_methods
18
+ @custom_model_klasses = Alchemy::Custom::Model.allowed_custom_models_for_menu
19
+ @custom_model_methods = []
20
+ if params[:q] and params[:q][:custom_model_klass]
21
+ klass = Alchemy::Custom::Model.allowed_custom_models_for_menu.select { |el| el == params[:q][:custom_model_klass] }.first
22
+ if !klass.nil? and klass.safe_constantize
23
+ klass = klass.constantize
24
+ if klass.respond_to? :menu_generator_methods
25
+ @custom_model_methods = klass.menu_generator_methods
26
+ end
27
+ end
28
+ end
29
+ @custom_model_methods = Kaminari.paginate_array(@custom_model_methods).page(params[:page]).per(params[:per_page] || 10)
30
+ end
31
+
32
+
33
+ private
34
+
35
+ def resource_params
36
+ params.require(:node).permit(
37
+ :site_id,
38
+ :parent_id,
39
+ :language_id,
40
+ :page_id,
41
+ :name,
42
+ :url,
43
+ :title,
44
+ :nofollow,
45
+ :external,
46
+ :custom_model_klass,
47
+ :custom_model_method
48
+ )
49
+ end
50
+
51
+
52
+ end
53
+ end
54
+ end
55
+ end
@@ -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
@@ -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>