alchemy_cms 4.3.2 → 4.4.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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +92 -0
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +59 -2
  5. data/Gemfile +6 -5
  6. data/README.md +7 -6
  7. data/alchemy_cms.gemspec +4 -2
  8. data/app/assets/config/alchemy_manifest.js +15 -0
  9. data/app/assets/javascripts/alchemy/admin.js +1 -0
  10. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +1 -13
  11. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +1 -1
  12. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +84 -87
  13. data/app/assets/javascripts/alchemy/alchemy.preview.js.coffee +0 -4
  14. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +1 -1
  15. data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee +2 -2
  16. data/app/assets/javascripts/alchemy/page_select.js +41 -0
  17. data/app/assets/javascripts/alchemy/templates/index.js +1 -0
  18. data/app/assets/javascripts/alchemy/templates/page.hbs +9 -0
  19. data/app/assets/stylesheets/alchemy/_mixins.scss +11 -1
  20. data/app/assets/stylesheets/alchemy/admin.scss +3 -0
  21. data/app/assets/stylesheets/alchemy/elements.scss +1 -0
  22. data/app/assets/stylesheets/alchemy/forms.scss +6 -5
  23. data/app/assets/stylesheets/alchemy/labels.scss +6 -0
  24. data/app/assets/stylesheets/alchemy/nodes.scss +154 -0
  25. data/app/assets/stylesheets/alchemy/page-select.scss +30 -0
  26. data/app/assets/stylesheets/alchemy/selects.scss +39 -22
  27. data/app/assets/stylesheets/alchemy/sitemap.scss +0 -33
  28. data/app/assets/stylesheets/alchemy/tags.scss +0 -3
  29. data/app/controllers/alchemy/admin/base_controller.rb +1 -0
  30. data/app/controllers/alchemy/admin/elements_controller.rb +24 -11
  31. data/app/controllers/alchemy/admin/languages_controller.rb +5 -0
  32. data/app/controllers/alchemy/admin/nodes_controller.rb +43 -0
  33. data/app/controllers/alchemy/admin/pages_controller.rb +1 -21
  34. data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
  35. data/app/controllers/alchemy/admin/tags_controller.rb +1 -2
  36. data/app/controllers/alchemy/api/contents_controller.rb +17 -2
  37. data/app/controllers/alchemy/api/elements_controller.rb +26 -1
  38. data/app/controllers/alchemy/api/pages_controller.rb +78 -7
  39. data/app/controllers/alchemy/messages_controller.rb +23 -8
  40. data/app/helpers/alchemy/admin/contents_helper.rb +1 -1
  41. data/app/helpers/alchemy/admin/elements_helper.rb +6 -0
  42. data/app/helpers/alchemy/admin/essences_helper.rb +23 -4
  43. data/app/helpers/alchemy/elements_block_helper.rb +11 -3
  44. data/app/helpers/alchemy/elements_helper.rb +3 -3
  45. data/app/helpers/alchemy/essences_helper.rb +36 -9
  46. data/app/helpers/alchemy/pages_helper.rb +29 -0
  47. data/app/models/alchemy/content.rb +1 -1
  48. data/app/models/alchemy/element.rb +20 -8
  49. data/app/models/alchemy/element/element_contents.rb +6 -4
  50. data/app/models/alchemy/element/presenters.rb +2 -2
  51. data/app/models/alchemy/essence_page.rb +29 -0
  52. data/app/models/alchemy/essence_picture.rb +8 -3
  53. data/app/models/alchemy/language.rb +10 -2
  54. data/app/models/alchemy/node.rb +48 -0
  55. data/app/models/alchemy/page.rb +74 -3
  56. data/app/models/alchemy/page/page_elements.rb +12 -4
  57. data/app/models/alchemy/page/page_natures.rb +6 -0
  58. data/app/models/alchemy/page/page_scopes.rb +1 -1
  59. data/app/models/alchemy/picture.rb +5 -1
  60. data/app/models/concerns/alchemy/content_touching.rb +1 -1
  61. data/app/serializers/alchemy/element_serializer.rb +7 -1
  62. data/app/serializers/alchemy/page_serializer.rb +0 -4
  63. data/app/views/alchemy/_menubar.html.erb +1 -1
  64. data/app/views/alchemy/admin/elements/_element.html.erb +18 -2
  65. data/app/views/alchemy/admin/leave.html.erb +1 -1
  66. data/app/views/alchemy/admin/nodes/_form.html.erb +39 -0
  67. data/app/views/alchemy/admin/nodes/_node.html.erb +87 -0
  68. data/app/views/alchemy/admin/nodes/edit.html.erb +1 -0
  69. data/app/views/alchemy/admin/nodes/index.html.erb +58 -0
  70. data/app/views/alchemy/admin/nodes/new.html.erb +1 -0
  71. data/app/views/alchemy/admin/pages/_anchor_link.html.erb +22 -0
  72. data/app/views/alchemy/admin/pages/_form.html.erb +1 -1
  73. data/app/views/alchemy/admin/pages/_internal_link.html.erb +7 -11
  74. data/app/views/alchemy/admin/pages/_menu_fields.html.erb +33 -0
  75. data/app/views/alchemy/admin/pages/_sitemap.html.erb +0 -7
  76. data/app/views/alchemy/admin/pages/link.html.erb +4 -0
  77. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +7 -3
  78. data/app/views/alchemy/admin/partials/_routes.html.erb +3 -3
  79. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +1 -0
  80. data/app/views/alchemy/essences/_essence_date_view.html.erb +1 -0
  81. data/app/views/alchemy/essences/_essence_file_view.html.erb +1 -0
  82. data/app/views/alchemy/essences/_essence_html_view.html.erb +1 -0
  83. data/app/views/alchemy/essences/_essence_link_view.html.erb +1 -0
  84. data/app/views/alchemy/essences/_essence_page_editor.html.erb +23 -0
  85. data/app/views/alchemy/essences/_essence_page_view.html.erb +5 -0
  86. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +2 -0
  87. data/app/views/alchemy/essences/_essence_picture_view.html.erb +1 -0
  88. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +1 -0
  89. data/app/views/alchemy/essences/_essence_select_editor.html.erb +1 -0
  90. data/app/views/alchemy/essences/_essence_select_view.html.erb +1 -0
  91. data/app/views/alchemy/essences/_essence_text_editor.html.erb +3 -0
  92. data/app/views/alchemy/essences/_essence_text_view.html.erb +1 -0
  93. data/config/alchemy/modules.yml +13 -4
  94. data/config/initializers/assets.rb +1 -13
  95. data/config/locales/alchemy.en.yml +27 -9
  96. data/config/routes.rb +11 -3
  97. data/db/migrate/20191016073858_create_alchemy_essence_pages.rb +8 -0
  98. data/db/migrate/20191029212236_create_alchemy_nodes.rb +24 -0
  99. data/lib/alchemy/admin/locale.rb +1 -1
  100. data/lib/alchemy/auth_accessors.rb +8 -2
  101. data/lib/alchemy/cache_digests/template_tracker.rb +8 -5
  102. data/lib/alchemy/elements_finder.rb +17 -14
  103. data/lib/alchemy/engine.rb +4 -0
  104. data/lib/alchemy/essence.rb +40 -2
  105. data/lib/alchemy/permissions.rb +2 -0
  106. data/lib/alchemy/tasks/tidy.rb +1 -1
  107. data/lib/alchemy/test_support/essence_shared_examples.rb +25 -8
  108. data/lib/alchemy/test_support/factories/essence_page_factory.rb +10 -0
  109. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +5 -0
  110. data/lib/alchemy/test_support/factories/node_factory.rb +21 -0
  111. data/lib/alchemy/version.rb +1 -1
  112. data/lib/rails/generators/alchemy/elements/elements_generator.rb +0 -1
  113. data/lib/rails/generators/alchemy/elements/templates/view.html.erb +3 -3
  114. data/lib/rails/generators/alchemy/elements/templates/view.html.haml +3 -3
  115. data/lib/rails/generators/alchemy/elements/templates/view.html.slim +3 -3
  116. data/lib/rails/generators/alchemy/install/files/{_article_view.html.erb → _article.html.erb} +2 -2
  117. data/lib/rails/generators/alchemy/install/files/application.html.erb +13 -10
  118. data/lib/rails/generators/alchemy/install/install_generator.rb +2 -11
  119. data/lib/rails/generators/alchemy/menus/menus_generator.rb +24 -0
  120. data/lib/rails/generators/alchemy/menus/templates/node.html.erb +19 -0
  121. data/lib/rails/generators/alchemy/menus/templates/node.html.haml +16 -0
  122. data/lib/rails/generators/alchemy/menus/templates/node.html.slim +16 -0
  123. data/lib/rails/generators/alchemy/menus/templates/wrapper.html.erb +8 -0
  124. data/lib/rails/generators/alchemy/menus/templates/wrapper.html.haml +6 -0
  125. data/lib/rails/generators/alchemy/menus/templates/wrapper.html.slim +6 -0
  126. data/lib/rails/generators/alchemy/views/views_generator.rb +1 -1
  127. data/lib/tasks/alchemy/convert.rake +60 -0
  128. metadata +79 -20
  129. data/.rspec +0 -1
  130. data/.travis.yml +0 -28
  131. data/app/models/alchemy/page/page_users.rb +0 -60
  132. data/app/views/alchemy/admin/elements/list.html.erb +0 -16
  133. data/app/views/alchemy/admin/pages/_page_for_links.html.erb +0 -53
  134. data/lib/rails/generators/alchemy/elements/templates/editor.html.erb +0 -9
  135. data/lib/rails/generators/alchemy/elements/templates/editor.html.haml +0 -8
  136. data/lib/rails/generators/alchemy/elements/templates/editor.html.slim +0 -8
  137. data/lib/rails/generators/alchemy/install/files/_article_editor.html.erb +0 -5
  138. data/lib/rails/generators/alchemy/install/files/alchemy.de.yml +0 -31
  139. data/lib/rails/generators/alchemy/install/files/alchemy.es.yml +0 -31
@@ -25,9 +25,13 @@
25
25
 
26
26
  module Alchemy
27
27
  class EssencePicture < BaseRecord
28
- acts_as_essence ingredient_column: 'picture'
28
+ acts_as_essence ingredient_column: :picture, belongs_to: {
29
+ class_name: 'Alchemy::Picture',
30
+ foreign_key: :picture_id,
31
+ inverse_of: :essence_pictures,
32
+ optional: true
33
+ }
29
34
 
30
- belongs_to :picture, optional: true
31
35
  delegate :image_file_width, :image_file_height, :image_file, to: :picture
32
36
  before_save :fix_crop_values
33
37
  before_save :replace_newlines
@@ -75,7 +79,8 @@ module Alchemy
75
79
  {
76
80
  format: picture.default_render_format,
77
81
  crop_from: crop_from.presence,
78
- crop_size: crop_size.presence
82
+ crop_size: crop_size.presence,
83
+ size: content.settings[:size]
79
84
  }.with_indifferent_access
80
85
  end
81
86
 
@@ -20,6 +20,8 @@
20
20
  # locale :string
21
21
  #
22
22
 
23
+ require_dependency 'alchemy/site'
24
+
23
25
  module Alchemy
24
26
  class Language < BaseRecord
25
27
  belongs_to :site
@@ -57,10 +59,16 @@ module Alchemy
57
59
 
58
60
  scope :published, -> { where(public: true) }
59
61
  scope :with_root_page, -> { joins(:pages).where(Page.table_name => {language_root: true}) }
60
- scope :on_site, ->(s) { s ? where(site_id: s.id) : all }
61
- scope :on_current_site, -> { on_site(Site.current) }
62
62
 
63
63
  class << self
64
+ def on_site(site)
65
+ site ? where(site_id: site.id) : all
66
+ end
67
+
68
+ def on_current_site
69
+ on_site(Site.current)
70
+ end
71
+
64
72
  # Store the current language in the current thread.
65
73
  def current=(language)
66
74
  RequestStore.store[:alchemy_current_language] = language
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ class Node < BaseRecord
5
+ VALID_URL_REGEX = /\A(\/|\D[a-z\+\d\.\-]+:)/
6
+
7
+ acts_as_nested_set scope: 'language_id', touch: true
8
+ stampable stamper_class_name: Alchemy.user_class_name
9
+
10
+ belongs_to :language, class_name: 'Alchemy::Language'
11
+ belongs_to :page, class_name: 'Alchemy::Page', optional: true, inverse_of: :nodes
12
+
13
+ validates :name, presence: true, if: -> { page.nil? }
14
+ validates :url, format: { with: VALID_URL_REGEX }, unless: -> { url.nil? }
15
+
16
+ # Returns the name
17
+ #
18
+ # Either the value is stored in the database
19
+ # or, if attached, the values comes from a page.
20
+ def name
21
+ read_attribute(:name).presence || page&.name
22
+ end
23
+
24
+ class << self
25
+ # Returns all root nodes for current language
26
+ def language_root_nodes
27
+ raise 'No language found' if Language.current.nil?
28
+ roots.where(language_id: Language.current.id)
29
+ end
30
+ end
31
+
32
+ # Returns the url
33
+ #
34
+ # Either the value is stored in the database, aka. an external url.
35
+ # Or, if attached, the values comes from a page.
36
+ def url
37
+ page && "/#{page.urlname}" || read_attribute(:url).presence
38
+ end
39
+
40
+ def to_partial_path
41
+ "#{view_folder_name}/wrapper"
42
+ end
43
+
44
+ def view_folder_name
45
+ "alchemy/menus/#{name.parameterize.underscore}"
46
+ end
47
+ end
48
+ end
@@ -79,7 +79,8 @@ module Alchemy
79
79
  :title,
80
80
  :urlname,
81
81
  :visible,
82
- :layoutpage
82
+ :layoutpage,
83
+ :menu_id
83
84
  ]
84
85
 
85
86
  acts_as_nested_set(dependent: :destroy)
@@ -88,10 +89,29 @@ module Alchemy
88
89
 
89
90
  belongs_to :language, optional: true
90
91
 
92
+ belongs_to :creator,
93
+ primary_key: Alchemy.user_class.primary_key,
94
+ class_name: Alchemy.user_class_name,
95
+ foreign_key: :creator_id,
96
+ optional: true
97
+
98
+ belongs_to :updater,
99
+ primary_key: Alchemy.user_class.primary_key,
100
+ class_name: Alchemy.user_class_name,
101
+ foreign_key: :updater_id,
102
+ optional: true
103
+
104
+ belongs_to :locker,
105
+ primary_key: Alchemy.user_class.primary_key,
106
+ class_name: Alchemy.user_class_name,
107
+ foreign_key: :locked_by,
108
+ optional: true
109
+
91
110
  has_one :site, through: :language
92
111
  has_many :site_languages, through: :site, source: :languages
93
112
  has_many :folded_pages
94
113
  has_many :legacy_urls, class_name: 'Alchemy::LegacyPageUrl'
114
+ has_many :nodes, class_name: 'Alchemy::Node', inverse_of: :page
95
115
 
96
116
  validates_presence_of :language, on: :create, unless: :root
97
117
  validates_presence_of :page_layout, unless: :systempage?
@@ -125,16 +145,22 @@ module Alchemy
125
145
  if: :should_create_legacy_url?,
126
146
  unless: :redirects_to_external?
127
147
 
148
+ after_update :attach_to_menu!,
149
+ if: :should_attach_to_menu?
150
+
151
+ after_update -> { nodes.update_all(updated_at: Time.current) }
152
+
128
153
  # Concerns
129
154
  include Alchemy::Page::PageScopes
130
155
  include Alchemy::Page::PageNatures
131
156
  include Alchemy::Page::PageNaming
132
- include Alchemy::Page::PageUsers
133
157
  include Alchemy::Page::PageElements
134
158
 
135
159
  # site_name accessor
136
160
  delegate :name, to: :site, prefix: true, allow_nil: true
137
161
 
162
+ attr_accessor :menu_id
163
+
138
164
  # Class methods
139
165
  #
140
166
  class << self
@@ -387,7 +413,7 @@ module Alchemy
387
413
 
388
414
  def set_restrictions_to_child_pages
389
415
  descendants.each do |child|
390
- child.update_attributes(restricted: restricted?)
416
+ child.update(restricted: restricted?)
391
417
  end
392
418
  end
393
419
 
@@ -488,6 +514,39 @@ module Alchemy
488
514
  attribute_fixed?(:public_until) ? fixed_attributes[:public_until] : self[:public_until]
489
515
  end
490
516
 
517
+ # Returns the name of the creator of this page.
518
+ #
519
+ # If no creator could be found or associated user model
520
+ # does not respond to +#name+ it returns +'unknown'+
521
+ #
522
+ def creator_name
523
+ creator.try(:name) || Alchemy.t('unknown')
524
+ end
525
+
526
+ # Returns the name of the last updater of this page.
527
+ #
528
+ # If no updater could be found or associated user model
529
+ # does not respond to +#name+ it returns +'unknown'+
530
+ #
531
+ def updater_name
532
+ updater.try(:name) || Alchemy.t('unknown')
533
+ end
534
+
535
+ # Returns the name of the user currently editing this page.
536
+ #
537
+ # If no locker could be found or associated user model
538
+ # does not respond to +#name+ it returns +'unknown'+
539
+ #
540
+ def locker_name
541
+ locker.try(:name) || Alchemy.t('unknown')
542
+ end
543
+
544
+ # Menus (aka. root nodes) this page is attached to
545
+ #
546
+ def menus
547
+ @_menus ||= nodes.map(&:root)
548
+ end
549
+
491
550
  private
492
551
 
493
552
  def set_fixed_attributes
@@ -533,5 +592,17 @@ module Alchemy
533
592
  def set_published_at
534
593
  self.published_at = Time.current
535
594
  end
595
+
596
+ def attach_to_menu!
597
+ Alchemy::Node.find(menu_id).children.create!(
598
+ language_id: language_id,
599
+ page_id: id,
600
+ name: name
601
+ )
602
+ end
603
+
604
+ def should_attach_to_menu?
605
+ menu_id && nodes.none?
606
+ end
536
607
  end
537
608
  end
@@ -9,16 +9,24 @@ module Alchemy
9
9
 
10
10
  has_many :all_elements,
11
11
  -> { order(:position) },
12
- class_name: 'Alchemy::Element'
12
+ class_name: 'Alchemy::Element',
13
+ inverse_of: :page
13
14
  has_many :elements,
14
15
  -> { order(:position).not_nested.unfixed.available },
15
- class_name: 'Alchemy::Element'
16
+ class_name: 'Alchemy::Element',
17
+ inverse_of: :page
16
18
  has_many :trashed_elements,
17
19
  -> { Element.trashed.order(:position) },
18
- class_name: 'Alchemy::Element'
20
+ class_name: 'Alchemy::Element',
21
+ inverse_of: :page
19
22
  has_many :fixed_elements,
20
23
  -> { order(:position).fixed.available },
21
- class_name: 'Alchemy::Element'
24
+ class_name: 'Alchemy::Element',
25
+ inverse_of: :page
26
+ has_many :dependent_destroyable_elements,
27
+ -> { not_nested },
28
+ class_name: 'Alchemy::Element',
29
+ dependent: :destroy
22
30
  has_many :contents, through: :elements
23
31
  has_and_belongs_to_many :to_be_swept_elements, -> { distinct },
24
32
  class_name: 'Alchemy::Element',
@@ -55,19 +55,24 @@ module Alchemy
55
55
  end
56
56
 
57
57
  # Returns true or false if the pages definition for config/alchemy/page_layouts.yml contains redirects_to_external: true
58
+ # @deprecated Please use a menu node with an external url instead.
58
59
  def redirects_to_external?
59
60
  !!definition["redirects_to_external"]
60
61
  end
62
+ deprecate redirects_to_external?: 'Please use a menu node with an external url instead.', deprecator: Alchemy::Deprecation
61
63
 
64
+ # @deprecated
62
65
  def has_controller?
63
66
  !PageLayout.get(page_layout).nil? && !PageLayout.get(page_layout)["controller"].blank?
64
67
  end
68
+ deprecate :has_controller?, deprecator: Alchemy::Deprecation
65
69
 
66
70
  # True if page locked_at timestamp and locked_by id are set
67
71
  def locked?
68
72
  locked_by? && locked_at?
69
73
  end
70
74
 
75
+ # @deprecated Please use a menu node with an url pointing to your controller path instead.
71
76
  def controller_and_action
72
77
  if has_controller?
73
78
  {
@@ -76,6 +81,7 @@ module Alchemy
76
81
  }
77
82
  end
78
83
  end
84
+ deprecate controller_and_action: 'Please use a menu node with an url pointing to your controller path instead.', deprecator: Alchemy::Deprecation
79
85
 
80
86
  # Returns a Hash describing the status of the Page.
81
87
  #
@@ -17,7 +17,7 @@ module Alchemy
17
17
 
18
18
  # All locked pages
19
19
  #
20
- scope :locked, -> { where.not(locked_at: nil, locked_by: nil) }
20
+ scope :locked, -> { where.not(locked_at: nil).where.not(locked_by: nil) }
21
21
 
22
22
  # All pages locked by given user
23
23
  #
@@ -30,7 +30,11 @@ module Alchemy
30
30
  include Alchemy::Picture::Transformations
31
31
  include Alchemy::Picture::Url
32
32
 
33
- has_many :essence_pictures, class_name: 'Alchemy::EssencePicture', foreign_key: 'picture_id'
33
+ has_many :essence_pictures,
34
+ class_name: 'Alchemy::EssencePicture',
35
+ foreign_key: 'picture_id',
36
+ inverse_of: :ingredient_association
37
+
34
38
  has_many :contents, through: :essence_pictures
35
39
  has_many :elements, through: :contents
36
40
  has_many :pages, through: :elements
@@ -17,7 +17,7 @@ module Alchemy
17
17
  #
18
18
  def touch_contents
19
19
  return unless respond_to?(:contents)
20
- contents.each(&:touch)
20
+ contents.update_all(updated_at: Time.current)
21
21
  end
22
22
  end
23
23
  end
@@ -10,12 +10,18 @@ module Alchemy
10
10
  :created_at,
11
11
  :updated_at,
12
12
  :ingredients,
13
- :content_ids
13
+ :content_ids,
14
+ :dom_id,
15
+ :display_name
14
16
 
15
17
  has_many :nested_elements
16
18
 
17
19
  def ingredients
18
20
  object.contents.collect(&:serialize)
19
21
  end
22
+
23
+ def display_name
24
+ object.display_name_with_preview_text
25
+ end
20
26
  end
21
27
  end
@@ -16,9 +16,5 @@ module Alchemy
16
16
  :status
17
17
 
18
18
  has_many :elements
19
-
20
- def elements
21
- object.elements.published
22
- end
23
19
  end
24
20
  end
@@ -4,7 +4,7 @@
4
4
  <li><%= link_to Alchemy.t(:to_alchemy), alchemy.admin_dashboard_url %></li>
5
5
  <li><%= link_to Alchemy.t(:edit_page), alchemy.edit_admin_page_url(@page) %></li>
6
6
  <li>
7
- <%= form_tag Alchemy.logout_path, method: 'delete' do %>
7
+ <%= form_tag Alchemy.logout_path, method: Alchemy.logout_method do %>
8
8
  <%= button_tag Alchemy.t(:logout) %>
9
9
  <% end %>
10
10
  </li>
@@ -16,7 +16,23 @@
16
16
  <div id="element_<%= element.id %>_errors" class="element_errors"></div>
17
17
 
18
18
  <div id="element_<%= element.id %>_content" class="element-content-editors">
19
- <%== render_editor(element) %>
19
+ <% element.definition[:message].tap do |message| %>
20
+ <%= render_message(:info, sanitize(message)) if message %>
21
+ <% end %>
22
+ <% element.definition[:warning].tap do |warning| %>
23
+ <%= render_message(:warning, sanitize(warning)) if warning %>
24
+ <% end %>
25
+ <% if lookup_context.exists?("#{element.name}_editor", ["alchemy/elements"], true) %>
26
+ <%= render_editor(element) %>
27
+ <% else %>
28
+ <%= element_editor_for(element) do %>
29
+ <% element.contents.each do |content| %>
30
+ <%= render "alchemy/essences/#{content.essence_partial_name}_editor", {
31
+ content: content
32
+ } %>
33
+ <% end %>
34
+ <% end %>
35
+ <% end %>
20
36
  </div>
21
37
 
22
38
  <% if element.taggable? %>
@@ -38,7 +54,7 @@
38
54
  'droppable-elements' => element.nestable_elements.join(' ')
39
55
  } do %>
40
56
  <%= render partial: 'alchemy/admin/elements/element',
41
- collection: element.all_nested_elements.not_trashed %>
57
+ collection: element.all_nested_elements %>
42
58
  <% end %>
43
59
 
44
60
  <% if element.expanded? || element.fixed? %>
@@ -5,7 +5,7 @@
5
5
  <label><%= Alchemy.t("Do you want to") %></label>
6
6
  <%= link_to Alchemy.t('stay logged in'), alchemy.root_path, class: 'button secondary' %>
7
7
  </p>
8
- <%= form_tag Alchemy.logout_path, method: 'delete', class: 'buttons' do %>
8
+ <%= form_tag Alchemy.logout_path, method: Alchemy.logout_method, class: 'buttons' do %>
9
9
  <label><%= Alchemy.t('or to completely') %></label>
10
10
  <%= button_tag Alchemy.t(:logout), autofocus: true %>
11
11
  <% end %>
@@ -0,0 +1,39 @@
1
+ <%= alchemy_form_for([:admin, node]) do |f| %>
2
+ <%= f.input :name, input_html: {
3
+ autofocus: true,
4
+ value: node.page && node.read_attribute(:name).blank? ? nil : node.name,
5
+ placeholder: node.page ? node.page.name : nil
6
+ } %>
7
+ <% unless node.root? %>
8
+ <%= f.input :page_id, label: Alchemy::Page.model_name.human, input_html: { class: 'alchemy_selectbox' } %>
9
+ <%= f.input :url, input_html: { disabled: node.page }, hint: Alchemy.t(:node_url_hint) %>
10
+ <%= f.input :title %>
11
+ <%= f.input :nofollow %>
12
+ <%= f.input :external %>
13
+ <%= f.hidden_field :parent_id %>
14
+ <% end %>
15
+ <%= f.hidden_field :language_id %>
16
+ <%= f.submit button_label %>
17
+ <% end %>
18
+
19
+ <script>
20
+ $('#node_page_id').alchemyPageSelect({
21
+ placeholder: "<%= Alchemy.t(:search_page) %>",
22
+ url: "<%= alchemy.api_pages_path %>",
23
+ <% if node.page %>
24
+ initialSelection: {
25
+ id: <%= node.page_id %>,
26
+ text: "<%= node.page.name %>",
27
+ url: "/<%= node.page.urlname %>"
28
+ }
29
+ <% end %>
30
+ }).on('change', function(e) {
31
+ if (e.val === '') {
32
+ $('#node_name').removeAttr('placeholder')
33
+ $('#node_url').val('').prop('disabled', false)
34
+ } else {
35
+ $('#node_name').attr('placeholder', e.added.name)
36
+ $('#node_url').val('/' + e.added.urlname).prop('disabled', true)
37
+ }
38
+ })
39
+ </script>