alchemy-custom-model 2.0.3 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
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>