katalyst-content 0.1.2 → 0.2.0

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