panda_cms 0.6.0 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/builds/panda_cms.css +17 -0
  3. data/app/assets/config/panda_cms_manifest.js +1 -0
  4. data/app/components/panda_cms/code_component.rb +3 -1
  5. data/app/components/panda_cms/menu_component.html.erb +3 -0
  6. data/app/components/panda_cms/menu_component.rb +8 -1
  7. data/app/components/panda_cms/page_menu_component.html.erb +7 -5
  8. data/app/components/panda_cms/page_menu_component.rb +3 -1
  9. data/app/components/panda_cms/rich_text_component.html.erb +2 -2
  10. data/app/components/panda_cms/rich_text_component.rb +12 -4
  11. data/app/components/panda_cms/text_component.rb +1 -1
  12. data/app/controllers/panda_cms/admin/block_contents_controller.rb +1 -1
  13. data/app/javascript/panda_cms/@editorjs--editorjs.js +2577 -0
  14. data/app/javascript/panda_cms/controllers/editor_controller.js +247 -0
  15. data/app/javascript/panda_cms/controllers/index.js +10 -7
  16. data/app/javascript/panda_cms/editor/plain_text_editor.js +102 -0
  17. data/app/javascript/panda_cms/editor/resource_loader.js +69 -0
  18. data/app/javascript/panda_cms/editor/rich_text_editor.js +89 -0
  19. data/app/lib/panda_cms/demo_site_generator.rb +8 -9
  20. data/app/lib/panda_cms/editor_js/blocks/alert.rb +32 -0
  21. data/app/lib/panda_cms/editor_js/blocks/base.rb +28 -0
  22. data/app/lib/panda_cms/editor_js/blocks/header.rb +13 -0
  23. data/app/lib/panda_cms/editor_js/blocks/image.rb +34 -0
  24. data/app/lib/panda_cms/editor_js/blocks/list.rb +30 -0
  25. data/app/lib/panda_cms/editor_js/blocks/paragraph.rb +13 -0
  26. data/app/lib/panda_cms/editor_js/blocks/quote.rb +27 -0
  27. data/app/lib/panda_cms/editor_js/blocks/table.rb +48 -0
  28. data/app/lib/panda_cms/editor_js/renderer.rb +120 -0
  29. data/app/models/panda_cms/block_content.rb +12 -2
  30. data/app/views/panda_cms/admin/pages/edit.html.erb +10 -9
  31. data/app/views/panda_cms/shared/_header.html.erb +2 -3
  32. data/app/views/panda_cms/shared/_importmap.html.erb +13 -3
  33. data/config/importmap.rb +3 -1
  34. data/db/migrate/20240315125411_add_status_to_panda_cms_pages.rb +5 -3
  35. data/db/migrate/20241031205109_add_cached_content_to_panda_cms_block_contents.rb +5 -0
  36. data/db/seeds.rb +1 -0
  37. data/lib/panda_cms/engine.rb +44 -8
  38. data/lib/panda_cms/version.rb +1 -1
  39. metadata +89 -103
  40. data/app/javascript/panda_cms/panda_cms_editable.js +0 -248
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d703e97407899867cc2ba819715b0c042aa2bfeb52b550b975d692c755da6b29
4
- data.tar.gz: 8cd9e111ac125f721a800b49e9447972b3c4e429e80441f5c5f7b27d713cfd66
3
+ metadata.gz: 785a3596f68d157ff6e6363a95c507f536554f276fec85626e488cb3e3ca167f
4
+ data.tar.gz: 8847bd7ffd2b09a6e42a2fc7d4444de20f38e42e91616620092caf558ffafe3d
5
5
  SHA512:
6
- metadata.gz: 357cd56e8fcb1ba6f0266c820f516a47b168812843a5b024cb03f65c131a852ae0ff985782f2a048cce6b4170998ba0644b178c9772af41c93e3802993c6de72
7
- data.tar.gz: 72c27644d6b690b93579cf112d5e9eb7b018d9bd02a46ca0bd994a868b71c1f7ed1fae0612821b3d533799d7d3cf67167ec4dd913713b2977bed3578ca8e02e4
6
+ metadata.gz: bf0a5477ebf5c79bd379275f63bbdb0da9e80896ac81372b976f4dc8a02c9635e2799ff6da1325efe4bdb0368e96a4ffef1271c0340344e52dd3e8a3456e61c5
7
+ data.tar.gz: 0bf5912db2be52720903d71be1ab9fba53b873aad9723caf1b3d4b6b9fe1f372cb81eb54b29d3f33874bfea12ecbc072f67497fb359054ac72efa59352c17693
@@ -879,6 +879,10 @@ a.block-link:after {
879
879
  visibility: visible;
880
880
  }
881
881
 
882
+ .collapse {
883
+ visibility: collapse;
884
+ }
885
+
882
886
  .static {
883
887
  position: static;
884
888
  }
@@ -1167,6 +1171,10 @@ a.block-link:after {
1167
1171
  display: grid;
1168
1172
  }
1169
1173
 
1174
+ .contents {
1175
+ display: contents;
1176
+ }
1177
+
1170
1178
  .hidden {
1171
1179
  display: none;
1172
1180
  }
@@ -1341,6 +1349,10 @@ a.block-link:after {
1341
1349
  cursor: pointer;
1342
1350
  }
1343
1351
 
1352
+ .resize {
1353
+ resize: both;
1354
+ }
1355
+
1344
1356
  .list-disc {
1345
1357
  list-style-type: disc;
1346
1358
  }
@@ -2026,6 +2038,11 @@ a.block-link:after {
2026
2038
  --tw-ring-offset-width: 2px;
2027
2039
  }
2028
2040
 
2041
+ .blur {
2042
+ --tw-blur: blur(8px);
2043
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
2044
+ }
2045
+
2029
2046
  .filter {
2030
2047
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
2031
2048
  }
@@ -1,3 +1,4 @@
1
1
  //= link_tree ../builds/ .css
2
2
  //= link_directory ../../javascript/panda_cms .js
3
3
  //= link_directory ../../javascript/panda_cms/controllers .js
4
+ //= link_directory ../../javascript/panda_cms/editor .js
@@ -15,6 +15,8 @@ module PandaCms
15
15
  @options = options || {}
16
16
  @options[:id] ||= "code-#{key.to_s.dasherize}"
17
17
  @editable = editable
18
+
19
+ raise BlockError.new("Key 'code' is not allowed for CodeComponent") if key == :code
18
20
  end
19
21
 
20
22
  def call
@@ -22,7 +24,7 @@ module PandaCms
22
24
  block = PandaCms::Block.find_by(kind: KIND, key: @key, panda_cms_template_id: Current.page.panda_cms_template_id)
23
25
 
24
26
  if block.nil?
25
- raise PandaCms::MissingBlockError("Block with key #{@key} not found") unless Rails.env.production?
27
+ raise PandaCms::MissingBlockError.new("Block with key #{@key} not found for page #{Current.page.title}") unless Rails.env.production?
26
28
  return false
27
29
  end
28
30
 
@@ -1,3 +1,6 @@
1
1
  <% @menu_items.each do |menu_item| %>
2
2
  <a href="<%= menu_item.resolved_link %>" class="<%= menu_item.css_classes %>"><%= menu_item.text %></a>
3
+ <% if @render_page_menu && menu_item.page %>
4
+ <%= render PandaCms::PageMenuComponent.new(page: menu_item.page, start_depth: 1, styles: @page_menu_styles, show_heading: false) %>
5
+ <% end %>
3
6
  <% end %>
@@ -12,12 +12,13 @@ module PandaCms
12
12
  # The "default" key is applied to all menu items. "inactive" and "active" are set based on the
13
13
  # current path.
14
14
  # @return [void]
15
- def initialize(name:, current_path: "", styles: {})
15
+ def initialize(name:, current_path: "", styles: {}, render_page_menu: false, page_menu_styles: {})
16
16
  @menu = PandaCms::Menu.find_by(name: name)
17
17
  @menu_items = @menu.menu_items
18
18
  @menu_items = @menu_items.where("depth <= ?", @menu.depth) if @menu.depth
19
19
  @menu_items = @menu_items.order(:lft)
20
20
  @current_path = current_path.to_s
21
+ @render_page_menu = render_page_menu
21
22
 
22
23
  @menu_items = @menu_items.order(:lft).map do |menu_item|
23
24
  if is_active?(menu_item)
@@ -28,6 +29,12 @@ module PandaCms
28
29
 
29
30
  menu_item
30
31
  end
32
+
33
+ # TODO: Surely don't need this but Current.page isn't working in the component
34
+ if @render_page_menu
35
+ @current_page = PandaCms::Page.find_by(path: @current_path)
36
+ @page_menu_styles = page_menu_styles
37
+ end
31
38
  end
32
39
 
33
40
  def is_active?(menu_item)
@@ -1,10 +1,12 @@
1
1
  <nav class="<%= styles[:container] %>">
2
2
  <ul role="list" class="p-0 m-0">
3
- <li>
4
- <a href="<%= menu_item.page.path %>" class="<%= menu_item.page == PandaCms::Current.page ? styles[:current_page_active] : styles[:current_page_inactive] %>">
5
- <%= menu_item.text %>
6
- </a>
7
- </li>
3
+ <% if @show_heading %>
4
+ <li>
5
+ <a href="<%= menu_item.page.path %>" class="<%= menu_item.page == PandaCms::Current.page ? styles[:current_page_active] : styles[:current_page_inactive] %>">
6
+ <%= menu_item.text %>
7
+ </a>
8
+ </li>
9
+ <% end %>
8
10
  <ul>
9
11
  <% PandaCms::MenuItem.includes(:page).each_with_level(menu_item.descendants) do |submenu_item, level| %>
10
12
  <% next if PandaCms::Current.page == menu_item.page && level > 1 # If we're on the "top" menu item, only show its direct ancestors %>
@@ -6,7 +6,7 @@ module PandaCms
6
6
  attr_accessor :menu_item
7
7
  attr_accessor :styles
8
8
 
9
- def initialize(page:, start_depth:, styles: {})
9
+ def initialize(page:, start_depth:, styles: {}, show_heading: true)
10
10
  @page = page
11
11
 
12
12
  unless @page.nil?
@@ -21,6 +21,8 @@ module PandaCms
21
21
 
22
22
  @menu_item = menu.menu_items.order(:lft)&.first
23
23
 
24
+ @show_heading = show_heading
25
+
24
26
  # Set some default styles for sanity
25
27
  @styles = styles
26
28
  @styles[:indent_with] ||= "pl-2"
@@ -1,6 +1,6 @@
1
1
  <% if @editable %>
2
- <input id="trix_<%= @options[:id] %>" value="<%= @content %>" type="hidden" name="trix_<%= @options[:id] %>" data-editor-block-content-id="<%= @options[:data][:block_content_id] %>" data-editor-type="<%= @options[:data][:mode] %>">
3
- <trix-editor input="trix_<%= @options[:id] %>" class="panda-cms-content"></trix-editor>
2
+ <div class="panda-cms-content" data-editable-previous-data="<%= @content.to_json %>" id="editor-<%= @options[:id] %>" data-editable-kind="rich_text" data-editable-block-content-id="<%= @options[:id] %>" data-editable-page-id="<%= @options[:data][:page_id] %>" style="border: 1px dashed #ccc; outline: none; cursor: pointer; transition: background 500ms linear; background-color: inherit;">
3
+ </div>
4
4
  <% else %>
5
5
  <div class="panda-cms-content"><%= @content %></div>
6
6
  <% end %>
@@ -25,15 +25,23 @@ module PandaCms
25
25
  @editable &&= params[:embed_id].present? && params[:embed_id] == Current.page.id && Current.user.admin?
26
26
  block = PandaCms::Block.find_by(kind: "rich_text", key: @key, panda_cms_template_id: Current.page.panda_cms_template_id)
27
27
  block_content = block.block_contents.find_by(panda_cms_page_id: Current.page.id)
28
- @content = block_content.content
28
+ if block_content.nil?
29
+ block_content = PandaCms::BlockContent.create(block: block, panda_cms_page_id: Current.page.id, content: "")
30
+ end
29
31
 
30
- @options[:id] = "editor_rich_text_#{block_content.id.tr("-", "_")}"
32
+ @content = block_content.cached_content || block_content.content
33
+ @options[:id] = block_content.id
31
34
 
32
35
  if @editable
33
36
  @options[:data] = {
34
- block_content_id: block_content&.id,
35
- mode: "rich-text"
37
+ page_id: Current.page.id,
38
+ mode: "rich_text"
36
39
  }
40
+
41
+ @content = block_content.content
42
+ elsif @content.is_a?(Hash)
43
+ renderer = PandaCms::EditorJs::Renderer.new(@content)
44
+ @content = renderer.render
37
45
  else
38
46
  @content = @content.html_safe
39
47
  end
@@ -24,7 +24,7 @@ module PandaCms
24
24
  content_tag(:span, @content, @options, false) # Don't escape the content
25
25
  rescue
26
26
  if !Rails.env.production? || is_defined?(Sentry)
27
- raise PandaCms::MissingBlockError("Block with key #{@key} not found")
27
+ raise PandaCms::MissingBlockError.new("Block with key #{@key} not found for page #{Current.page.title}")
28
28
  else
29
29
  false
30
30
  end
@@ -11,7 +11,7 @@ module PandaCms
11
11
  # @type PATCH/PUT
12
12
  # @return
13
13
  def update
14
- if @block_content.update(block_content_params)
14
+ if @block_content.update!(content: params[:content])
15
15
  @block_content.page.touch # Update the page's updated_at
16
16
  render json: @block_content, status: :ok
17
17
  else