katalyst-content 0.1.2 → 0.2.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/controllers/content/editor/container_controller.js +2 -4
  3. data/app/assets/javascripts/controllers/content/editor/image_field_controller.js +90 -0
  4. data/app/assets/javascripts/controllers/content/editor/trix_controller.js +78 -0
  5. data/app/assets/javascripts/utils/content/editor/item.js +34 -10
  6. data/app/assets/javascripts/utils/content/editor/rules-engine.js +74 -31
  7. data/app/assets/stylesheets/katalyst/content/editor/_figure.scss +12 -0
  8. data/app/assets/stylesheets/katalyst/content/editor/_index.scss +7 -1
  9. data/app/assets/stylesheets/katalyst/content/editor/_item-actions.scss +24 -6
  10. data/app/assets/stylesheets/katalyst/content/editor/_new-items.scss +21 -1
  11. data/app/assets/stylesheets/katalyst/content/editor/_status-bar.scss +10 -0
  12. data/app/assets/stylesheets/katalyst/content/editor/_trix-rails.scss +4 -4
  13. data/app/controllers/katalyst/content/direct_uploads_controller.rb +8 -0
  14. data/app/controllers/katalyst/content/items_controller.rb +1 -1
  15. data/app/helpers/katalyst/content/editor/base.rb +1 -0
  16. data/app/helpers/katalyst/content/editor/container.rb +0 -4
  17. data/app/helpers/katalyst/content/editor/image_field.rb +72 -0
  18. data/app/helpers/katalyst/content/editor/status_bar.rb +12 -3
  19. data/app/helpers/katalyst/content/editor_helper.rb +20 -0
  20. data/app/helpers/katalyst/content/frontend_helper.rb +59 -0
  21. data/app/models/concerns/katalyst/content/container.rb +33 -6
  22. data/app/models/concerns/katalyst/content/version.rb +4 -0
  23. data/app/{helpers/katalyst/content/application_helper.rb → models/katalyst/content/aside.rb} +1 -1
  24. data/app/models/katalyst/content/column.rb +8 -0
  25. data/app/models/katalyst/content/content.rb +4 -0
  26. data/app/models/katalyst/content/figure.rb +41 -0
  27. data/app/models/katalyst/content/group.rb +8 -0
  28. data/app/models/katalyst/content/item.rb +13 -1
  29. data/app/models/katalyst/content/layout.rb +8 -0
  30. data/app/models/katalyst/content/section.rb +8 -0
  31. data/app/views/active_storage/blobs/_blob.html.erb +1 -1
  32. data/app/views/katalyst/content/asides/_aside.html+form.erb +27 -0
  33. data/app/views/katalyst/content/asides/_aside.html.erb +14 -0
  34. data/app/views/katalyst/content/columns/_column.html+form.erb +27 -0
  35. data/app/views/katalyst/content/columns/_column.html.erb +14 -0
  36. data/app/views/katalyst/content/contents/_content.html+form.erb +3 -10
  37. data/app/views/katalyst/content/contents/_content.html.erb +3 -3
  38. data/app/views/katalyst/content/editor/_list_item.html.erb +1 -0
  39. data/app/views/katalyst/content/figures/_figure.html+form.erb +38 -0
  40. data/app/views/katalyst/content/figures/_figure.html.erb +4 -0
  41. data/app/views/katalyst/content/groups/_group.html+form.erb +27 -0
  42. data/app/views/katalyst/content/groups/_group.html.erb +7 -0
  43. data/app/views/katalyst/content/items/_form_errors.html.erb +5 -0
  44. data/app/views/katalyst/content/items/_hidden_fields.html.erb +3 -0
  45. data/app/views/katalyst/content/items/_item.html+form.erb +2 -9
  46. data/app/views/katalyst/content/items/_item.html.erb +3 -3
  47. data/app/views/katalyst/content/sections/_section.html+form.erb +27 -0
  48. data/app/views/katalyst/content/sections/_section.html.erb +7 -0
  49. data/config/locales/en.yml +13 -0
  50. data/config/routes.rb +1 -0
  51. data/db/migrate/20220926061535_add_fields_for_figure_to_katalyst_content_items.rb +7 -0
  52. data/lib/katalyst/content/config.rb +7 -0
  53. data/lib/katalyst/content/version.rb +1 -1
  54. data/spec/factories/katalyst/content/items.rb +30 -4
  55. metadata +42 -4
@@ -17,9 +17,11 @@
17
17
  display: none;
18
18
  grid-area: status;
19
19
  font-weight: bold;
20
+ color: var(--color);
20
21
  }
21
22
 
22
23
  &[data-state="published"] .status-text[data-published],
24
+ &[data-state="unpublished"] .status-text[data-unpublished],
23
25
  &[data-state="draft"] .status-text[data-draft],
24
26
  &[data-state="dirty"] .status-text[data-dirty] {
25
27
  display: unset;
@@ -72,6 +74,14 @@
72
74
  }
73
75
  }
74
76
 
77
+ &[data-state="unpublished"] {
78
+ [value="save"],
79
+ [value="discard"],
80
+ [value="revert"] {
81
+ display: none;
82
+ }
83
+ }
84
+
75
85
  &[data-state="draft"] {
76
86
  [value="save"],
77
87
  [value="discard"] {
@@ -13,12 +13,12 @@
13
13
  }
14
14
 
15
15
  .trix-content
16
- .attachment-gallery.attachment-gallery--2
17
- > action-text-attachment,
16
+ .attachment-gallery.attachment-gallery--2
17
+ > action-text-attachment,
18
18
  .trix-content .attachment-gallery.attachment-gallery--2 > .attachment,
19
19
  .trix-content
20
- .attachment-gallery.attachment-gallery--4
21
- > action-text-attachment,
20
+ .attachment-gallery.attachment-gallery--4
21
+ > action-text-attachment,
22
22
  .trix-content .attachment-gallery.attachment-gallery--4 > .attachment {
23
23
  flex-basis: 50%;
24
24
  max-width: 50%;
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Content
5
+ class DirectUploadsController < ActiveStorage::DirectUploadsController
6
+ end
7
+ end
8
+ end
@@ -14,7 +14,7 @@ module Katalyst
14
14
  end
15
15
 
16
16
  def create
17
- item = @container.items.build(item_params)
17
+ @item = item = @container.items.build(item_params)
18
18
  if item.save
19
19
  render :update, locals: { item: item, previous: @container.items.build(type: item.type) }
20
20
  else
@@ -14,6 +14,7 @@ module Katalyst
14
14
 
15
15
  attr_accessor :template, :container
16
16
 
17
+ delegate :config, to: ::Katalyst::Content
17
18
  delegate_missing_to :template
18
19
 
19
20
  def initialize(template, container)
@@ -29,10 +29,6 @@ module Katalyst
29
29
  add_option(options, :data, :controller, CONTAINER_CONTROLLER)
30
30
  add_option(options, :data, :action, ACTIONS)
31
31
 
32
- # depth = options.delete(:depth) || container.depth
33
- #
34
- # add_option(options, :data, :"#{CONTAINER_CONTROLLER}-max-depth-value", depth) if depth
35
-
36
32
  options
37
33
  end
38
34
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Content
5
+ module Editor
6
+ class ImageField < Base
7
+ IMAGE_FIELD_CONTROLLER = "content--editor--image-field"
8
+
9
+ ACTIONS = <<~ACTIONS.gsub(/\s+/, " ").freeze
10
+ dragover->#{IMAGE_FIELD_CONTROLLER}#dragover
11
+ dragenter->#{IMAGE_FIELD_CONTROLLER}#dragenter
12
+ dragleave->#{IMAGE_FIELD_CONTROLLER}#dragleave
13
+ drop->#{IMAGE_FIELD_CONTROLLER}#drop
14
+ ACTIONS
15
+
16
+ attr_accessor :item, :method
17
+
18
+ def build(item, method, **options, &block)
19
+ self.item = item
20
+ self.method = method
21
+
22
+ tag.div **default_options(**options) do
23
+ concat(capture { yield self }) if block
24
+ end
25
+ end
26
+
27
+ def preview(**options)
28
+ add_option(options, :data, "#{IMAGE_FIELD_CONTROLLER}_target", "preview")
29
+ add_option(options, :class, "hidden") unless preview?
30
+
31
+ tag.div **options do
32
+ image_tag preview_url, class: "image-thumbnail"
33
+ end
34
+ end
35
+
36
+ def file_input_options(options = {})
37
+ add_option(options, :accept, config.image_mime_types.join(","))
38
+ add_option(options, :data, :action, "change->#{IMAGE_FIELD_CONTROLLER}#onUpload")
39
+
40
+ options
41
+ end
42
+
43
+ def hint_text
44
+ t("views.katalyst.content.item.size_hint", max_size: number_to_human_size(config.max_image_size.megabytes))
45
+ end
46
+
47
+ def preview?
48
+ value&.attached? && value&.persisted?
49
+ end
50
+
51
+ def preview_url
52
+ preview? ? main_app.url_for(value) : ""
53
+ end
54
+
55
+ def value
56
+ item.send(method)
57
+ end
58
+
59
+ private
60
+
61
+ def default_options(**options)
62
+ add_option(options, :data, :controller, IMAGE_FIELD_CONTROLLER)
63
+ add_option(options, :data, :action, ACTIONS)
64
+ add_option(options, :data, :"#{IMAGE_FIELD_CONTROLLER}_mime_types_value",
65
+ config.image_mime_types.to_json)
66
+
67
+ options
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -11,6 +11,7 @@ module Katalyst
11
11
  def build(**options)
12
12
  tag.div **default_options(**options) do
13
13
  concat status(:published, last_update: l(container.updated_at, format: :short))
14
+ concat status(:unpublished)
14
15
  concat status(:draft)
15
16
  concat status(:dirty)
16
17
  concat actions
@@ -18,9 +19,17 @@ module Katalyst
18
19
  end
19
20
 
20
21
  def status(state, **options)
21
- tag.span(t("views.katalyst.content.editor.#{state}_html", **options),
22
- class: "status-text",
23
- data: { state => "" })
22
+ status_text = t("views.katalyst.content.editor.#{state}_html", **options)
23
+ html_options = { class: "status-text", data: { state => "", turbo: false } }
24
+
25
+ case state
26
+ when :published
27
+ link_to status_text, url_for(container), **html_options
28
+ when :unpublished, :draft
29
+ link_to status_text, "#{url_for(container)}/preview", **html_options
30
+ else
31
+ tag.span status_text, **html_options
32
+ end
24
33
  end
25
34
 
26
35
  def actions
@@ -37,6 +37,26 @@ module Katalyst
37
37
  def content_editor_status_bar(container:, **options)
38
38
  Editor::StatusBar.new(self, container).build(**options)
39
39
  end
40
+
41
+ def content_editor_rich_text_options(options = {})
42
+ defaults = {
43
+ data: {
44
+ direct_upload_url: direct_uploads_url,
45
+ controller: "content--editor--trix",
46
+ action: "trix-initialize->content--editor--trix#trixInitialize",
47
+ },
48
+ }
49
+ defaults.deep_merge(options)
50
+ end
51
+
52
+ def content_editor_image_field(item:, method:, **options, &block)
53
+ Editor::ImageField.new(self, item.container).build(item, method, **options, &block)
54
+ end
55
+
56
+ # When rendering item forms do not include the controller namespace prefix (katalyst/content)
57
+ def prefix_partial_path_with_controller_namespace
58
+ false
59
+ end
40
60
  end
41
61
  end
42
62
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Content
5
+ module FrontendHelper
6
+ def render_content(version)
7
+ render partial: version.tree.select(&:visible?)
8
+ end
9
+
10
+ def render_content_items(items)
11
+ items = items.select(&:visible?)
12
+ render partial: items if items.any?
13
+ end
14
+
15
+ def content_item_tag(item, **options, &block)
16
+ FrontendBuilder.new(self, item).render(**options, &block)
17
+ end
18
+ end
19
+
20
+ class FrontendBuilder
21
+ attr_accessor :template, :item
22
+
23
+ delegate_missing_to :@template
24
+
25
+ def initialize(template, item)
26
+ self.template = template
27
+ self.item = item
28
+ end
29
+
30
+ def render(**options, &block)
31
+ content_tag tag, **default_options(**options) do
32
+ content_tag :div, &block
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def default_options(**options)
39
+ {
40
+ id: item.heading&.parameterize,
41
+ class: ["content-item", item.model_name.param_key, item.background, options[:class]],
42
+ data: { content_index: item.index, content_depth: item.depth, **options.fetch(:data, {}) },
43
+ **options.except(:class, :data, :root),
44
+ }
45
+ end
46
+
47
+ def tag
48
+ case item
49
+ when Figure
50
+ :figure
51
+ when Section
52
+ :section
53
+ else
54
+ :div
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -20,8 +20,8 @@ module Katalyst
20
20
  inverse_of: :parent,
21
21
  optional: true
22
22
 
23
- delegate :nodes, :items, :tree, to: :published_version, prefix: :published, allow_nil: true
24
- delegate :nodes, :items, :tree, to: :draft_version, prefix: :draft, allow_nil: true
23
+ delegate :nodes, :items, :tree, :text, to: :published_version, prefix: :published, allow_nil: true
24
+ delegate :nodes, :items, :tree, :text, to: :draft_version, prefix: :draft, allow_nil: true
25
25
 
26
26
  has_many :versions,
27
27
  class_name: "#{name}::Version",
@@ -46,18 +46,37 @@ module Katalyst
46
46
  class_name: "Katalyst::Content::Item",
47
47
  dependent: :destroy,
48
48
  validate: true
49
+
50
+ scope :order_by_state, ->(dir) do
51
+ dir = :asc unless %w[asc desc].include?(dir.to_s)
52
+ unpublished = arel_table[:published_version_id].eq(nil)
53
+ draft = arel_table[:published_version_id].not_eq(arel_table[:draft_version_id])
54
+ case_statement = Arel::Nodes::Case.new
55
+ .when(unpublished).then(3)
56
+ .when(draft).then(2)
57
+ .else(1)
58
+ order(case_statement.public_send(dir)).order(updated_at: dir)
59
+ end
60
+
61
+ scope :published, -> { where.not(published_version_id: nil) }
49
62
  end
50
63
 
51
64
  # A resource is in draft mode if it has an unpublished draft or it has no published version.
52
65
  # @return the current state of the resource, either `published` or `draft`
53
66
  def state
54
- if published_version_id && published_version_id == draft_version_id
55
- :published
56
- else
67
+ if !published_version_id
68
+ :unpublished
69
+ elsif published_version_id != draft_version_id
57
70
  :draft
71
+ else
72
+ :published
58
73
  end
59
74
  end
60
75
 
76
+ def published?
77
+ published_version_id.present?
78
+ end
79
+
61
80
  # Promotes the draft version to become the published version
62
81
  def publish!
63
82
  update!(published_version: draft_version)
@@ -70,6 +89,12 @@ module Katalyst
70
89
  self
71
90
  end
72
91
 
92
+ # Sets the currently published version to nil
93
+ def unpublish!
94
+ update!(published_version_id: nil)
95
+ self
96
+ end
97
+
73
98
  # Updates the current draft version with new structure. Attributes should be structural information about the
74
99
  # items, e.g. `{index => {id:, depth:}` or `[{id:, depth:}]`.
75
100
  #
@@ -82,7 +107,9 @@ module Katalyst
82
107
  private
83
108
 
84
109
  def unset_versions
85
- update(draft_version: nil, published_version: nil)
110
+ self.draft_version_id = nil
111
+ self.published_version_id = nil
112
+ save!(validate: false)
86
113
  end
87
114
 
88
115
  # Returns an unsaved copy of draft version for accumulating changes.
@@ -28,6 +28,10 @@ module Katalyst
28
28
  item
29
29
  end
30
30
  end
31
+
32
+ def text
33
+ items.filter_map(&:to_plain_text).join("\n")
34
+ end
31
35
  end
32
36
  end
33
37
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Katalyst
4
4
  module Content
5
- module ApplicationHelper
5
+ class Aside < Layout
6
6
  end
7
7
  end
8
8
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Content
5
+ class Column < Layout
6
+ end
7
+ end
8
+ end
@@ -16,6 +16,10 @@ module Katalyst
16
16
  def self.permitted_params
17
17
  super + %i[content]
18
18
  end
19
+
20
+ def to_plain_text
21
+ [super, content.to_plain_text].compact.join("\n") if visible?
22
+ end
19
23
  end
20
24
  end
21
25
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_storage_validations"
4
+
5
+ module Katalyst
6
+ module Content
7
+ class Figure < Item
8
+ has_one_attached :image
9
+
10
+ validates :image,
11
+ presence: true,
12
+ content_type: config.image_mime_types,
13
+ size: { less_than: config.max_image_size.megabytes }
14
+
15
+ default_scope { with_attached_image }
16
+
17
+ def initialize_dup(source)
18
+ super
19
+
20
+ # if image has changed, duplicate the change, otherwise attach the existing blob
21
+ if source.attachment_changes["image"]
22
+ self.image = source.attachment_changes["image"].attachable
23
+ elsif source.image.attached?
24
+ image.attach(source.image.blob)
25
+ end
26
+ end
27
+
28
+ def self.permitted_params
29
+ super - %i[show_heading] + %i[image caption]
30
+ end
31
+
32
+ alias_attribute :alt, :heading
33
+
34
+ def to_plain_text
35
+ text = ["Image: #{alt}"]
36
+ text << "Caption: #{caption}" if caption.present?
37
+ text.compact.join("\n") if visible?
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Content
5
+ class Group < Layout
6
+ end
7
+ end
8
+ end
@@ -4,10 +4,14 @@ module Katalyst
4
4
  module Content
5
5
  # STI base class for content items
6
6
  class Item < ApplicationRecord
7
+ def self.config
8
+ Katalyst::Content.config
9
+ end
10
+
7
11
  belongs_to :container, polymorphic: true
8
12
 
9
13
  validates :heading, presence: true
10
- validates :background, presence: true, inclusion: { in: Katalyst::Content.config.backgrounds }
14
+ validates :background, presence: true, inclusion: { in: config.backgrounds }
11
15
 
12
16
  after_initialize :initialize_tree
13
17
 
@@ -25,6 +29,14 @@ module Katalyst
25
29
  ]
26
30
  end
27
31
 
32
+ def to_plain_text
33
+ heading if show_heading? && visible?
34
+ end
35
+
36
+ def layout?
37
+ is_a? Layout
38
+ end
39
+
28
40
  private
29
41
 
30
42
  def initialize_tree
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Content
5
+ class Layout < Item
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Content
5
+ class Section < Layout
6
+ end
7
+ end
8
+ end
@@ -1,6 +1,6 @@
1
1
  <figure class="attachment attachment--<%= blob.representable? ? "preview" : "file" %> attachment--<%= blob.filename.extension %>">
2
2
  <% if blob.representable? %>
3
- <%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %>
3
+ <%= image_tag main_app.url_for(blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ])) %>
4
4
  <% end %>
5
5
 
6
6
  <figcaption class="attachment__caption">
@@ -0,0 +1,27 @@
1
+ <%= form_with model: aside, scope: :item, url: path do |form| %>
2
+ <%= render "hidden_fields", form: form %>
3
+ <%= render "form_errors", form: form %>
4
+
5
+ <div class="field">
6
+ <%= form.label :heading %>
7
+ <%= form.text_field :heading %>
8
+ </div>
9
+
10
+ <div class="field">
11
+ <%= form.label :show_heading %>
12
+ <%= form.check_box :show_heading %>
13
+ </div>
14
+
15
+ <div class="field">
16
+ <%= form.label :background %>
17
+ <%= form.select :background, Katalyst::Content.config.backgrounds %>
18
+ </div>
19
+
20
+ <div class="field">
21
+ <%= form.label :visible %>
22
+ <%= form.check_box :visible %>
23
+ </div>
24
+
25
+ <%= form.submit "Done" %>
26
+ <%= link_to "Discard", :back %>
27
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <%= content_item_tag aside do %>
2
+ <%= tag.h3 aside.heading if aside.show_heading? %>
3
+
4
+ <% items = aside.children.select(&:visible?) %>
5
+ <% last = items.pop %>
6
+ <div role="aside-container">
7
+ <div>
8
+ <%= render_content_items items %>
9
+ </div>
10
+ <aside>
11
+ <%= render_content_items [last] %>
12
+ </aside>
13
+ </div>
14
+ <% end %>
@@ -0,0 +1,27 @@
1
+ <%= form_with model: column, scope: :item, url: path do |form| %>
2
+ <%= render "hidden_fields", form: form %>
3
+ <%= render "form_errors", form: form %>
4
+
5
+ <div class="field">
6
+ <%= form.label :heading %>
7
+ <%= form.text_field :heading %>
8
+ </div>
9
+
10
+ <div class="field">
11
+ <%= form.label :show_heading %>
12
+ <%= form.check_box :show_heading %>
13
+ </div>
14
+
15
+ <div class="field">
16
+ <%= form.label :background %>
17
+ <%= form.select :background, Katalyst::Content.config.backgrounds %>
18
+ </div>
19
+
20
+ <div class="field">
21
+ <%= form.label :visible %>
22
+ <%= form.check_box :visible %>
23
+ </div>
24
+
25
+ <%= form.submit "Done" %>
26
+ <%= link_to "Discard", :back %>
27
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <%= content_item_tag column do %>
2
+ <%= tag.h3 column.heading if column.show_heading? %>
3
+
4
+ <% items = column.children.select(&:visible?) %>
5
+ <% last = items.pop %>
6
+ <div class="columns-container">
7
+ <div class="column">
8
+ <%= render_content_items items %>
9
+ </div>
10
+ <div class="column">
11
+ <%= render_content_items [last] %>
12
+ </div>
13
+ </div>
14
+ <% end %>
@@ -1,13 +1,6 @@
1
1
  <%= form_with model: content, scope: :item, url: path do |form| %>
2
- <%= form.hidden_field :container_type %>
3
- <%= form.hidden_field :container_id %>
4
- <%= form.hidden_field :type %>
5
-
6
- <%= tag.div class: "errors" do %>
7
- <% content.errors.full_messages.each do |error| %>
8
- <li class="error"><%= error %></li>
9
- <% end %>
10
- <% end if content.errors.any? %>
2
+ <%= render "hidden_fields", form: form %>
3
+ <%= render "form_errors", form: form %>
11
4
 
12
5
  <div class="field">
13
6
  <%= form.label :heading %>
@@ -31,7 +24,7 @@
31
24
 
32
25
  <div class="field">
33
26
  <%= form.label :content %>
34
- <%= form.rich_text_area :content %>
27
+ <%= form.rich_text_area :content, content_editor_rich_text_options %>
35
28
  </div>
36
29
 
37
30
  <%= form.submit "Done" %>
@@ -1,5 +1,5 @@
1
- <div class="<%= content.background %>">
2
- <%= tag.h2 content.heading if content.show_heading? %>
1
+ <%= content_item_tag content do %>
2
+ <%= tag.h3 content.heading if content.show_heading? %>
3
3
 
4
4
  <%= content.content %>
5
- </div>
5
+ <% end %>
@@ -3,6 +3,7 @@
3
3
  data-content-item-id="<%= item.id %>"
4
4
  data-content-index="<%= item.index %>"
5
5
  data-content-depth="<%= item.depth %>"
6
+ <%= "data-content-layout" if item.layout? %>
6
7
  data-deny-de-nest
7
8
  data-deny-nest
8
9
  data-deny-collapse
@@ -0,0 +1,38 @@
1
+ <%= form_with model: figure, scope: :item, url: path do |form| %>
2
+ <%= render "hidden_fields", form: form %>
3
+ <%= render "form_errors", form: form %>
4
+
5
+ <%= content_editor_image_field item: figure, method: :image do |builder| %>
6
+ <div class="field">
7
+ <%= form.label :image %>
8
+ <div>
9
+ <%= builder.preview class: "image-wrapper" %>
10
+ </div>
11
+ <%= form.file_field :image, **builder.file_input_options %>
12
+ <hint><%= builder.hint_text %></hint>
13
+ </div>
14
+ <% end %>
15
+
16
+ <div class="field">
17
+ <%= form.label :heading %>
18
+ <%= form.text_field :heading %>
19
+ </div>
20
+
21
+ <div class="field">
22
+ <%= form.label :background %>
23
+ <%= form.select :background, Katalyst::Content.config.backgrounds %>
24
+ </div>
25
+
26
+ <div class="field">
27
+ <%= form.label :visible %>
28
+ <%= form.check_box :visible %>
29
+ </div>
30
+
31
+ <div class="field">
32
+ <%= form.label :caption %>
33
+ <%= form.text_field :caption %>
34
+ </div>
35
+
36
+ <%= form.submit "Done" %>
37
+ <%= link_to "Discard", :back %>
38
+ <% end %>