spina-blocks 0.3.1 → 0.5.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +173 -8
  3. data/app/assets/javascripts/spina/controllers/block_collection_controller.js +5 -29
  4. data/app/assets/javascripts/spina/controllers/block_reference_mode_controller.js +55 -0
  5. data/app/assets/javascripts/spina/controllers/content_blocks_controller.js +118 -0
  6. data/app/assets/javascripts/spina/controllers/nested_content_blocks_controller.js +4 -0
  7. data/app/assets/javascripts/spina/utils/dropdown_position.js +30 -0
  8. data/app/controllers/spina/blocks/admin/blocks_controller.rb +22 -4
  9. data/app/controllers/spina/blocks/admin/page_blocks_controller.rb +7 -0
  10. data/app/helpers/spina/blocks/blocks_helper.rb +20 -4
  11. data/app/models/spina/blocks/account_extension.rb +32 -0
  12. data/app/models/spina/blocks/block.rb +27 -1
  13. data/app/models/spina/blocks/inline_block.rb +63 -0
  14. data/app/models/spina/parts/block_reference.rb +109 -1
  15. data/app/models/spina/parts/content_block.rb +18 -0
  16. data/app/models/spina/parts/content_blocks.rb +25 -0
  17. data/app/models/spina/parts/nested_content_blocks.rb +15 -0
  18. data/app/views/spina/admin/parts/block_collections/_form.html.erb +4 -4
  19. data/app/views/spina/admin/parts/block_references/_form.html.erb +118 -10
  20. data/app/views/spina/admin/parts/content_blocks/_fields.html.erb +57 -0
  21. data/app/views/spina/admin/parts/content_blocks/_form.html.erb +73 -0
  22. data/app/views/spina/admin/parts/nested_content_blocks/_form.html.erb +75 -0
  23. data/app/views/spina/admin/pro/search/results/_block.html.erb +2 -2
  24. data/app/views/spina/blocks/admin/blocks/_form.html.erb +9 -5
  25. data/app/views/spina/blocks/admin/blocks/_form_block_settings.html.erb +12 -0
  26. data/app/views/spina/blocks/admin/blocks/index.html.erb +31 -6
  27. data/app/views/spina/blocks/admin/page_blocks/index.html.erb +14 -8
  28. data/config/locales/en.yml +25 -0
  29. data/db/migrate/6_add_custom_block_fields_to_spina_blocks_blocks.rb +14 -0
  30. data/lib/spina/blocks/engine.rb +16 -2
  31. data/lib/spina/blocks/version.rb +1 -1
  32. metadata +21 -3
@@ -0,0 +1,75 @@
1
+ <%#
2
+ Admin form for Spina::Parts::NestedContentBlocks.
3
+ Same as ContentBlocks but uses "nested-content-blocks" Stimulus controller
4
+ to avoid scope conflicts when rendered inside Repeaters or other ContentBlocks.
5
+ Reuses content_blocks/_fields.html.erb for individual block rendering.
6
+ %>
7
+ <% available_templates = f.object.available_templates(current_theme) %>
8
+
9
+ <div class="mt-4" data-controller="nested-content-blocks">
10
+ <label class="block text-sm leading-5 font-medium text-gray-700"><%= f.object.title %></label>
11
+ <% if f.object.hint.present? %>
12
+ <div class="text-gray-400 text-sm mb-2"><%= f.object.hint %></div>
13
+ <% end %>
14
+
15
+ <%# List of existing content blocks %>
16
+ <div data-nested-content-blocks-target="list" class="space-y-3 mb-4">
17
+ <% (f.object.content || []).each do |content_block| %>
18
+ <%= f.fields_for :content, [content_block], child_index: content_block.object_id do |ff| %>
19
+ <%= render "spina/admin/parts/content_blocks/fields", f: ff, stimulus_controller: "nested-content-blocks" %>
20
+ <% end %>
21
+ <% end %>
22
+ </div>
23
+
24
+ <%# Empty state %>
25
+ <div data-nested-content-blocks-target="emptyMessage"
26
+ class="text-sm text-gray-400 italic py-3 text-center"
27
+ style="<%= (f.object.content || []).any? ? 'display:none' : '' %>">
28
+ <%= t('spina.content_blocks.empty') %>
29
+ </div>
30
+
31
+ <%# Add block button with type picker dropdown %>
32
+ <% if available_templates.any? %>
33
+ <div class="relative">
34
+ <button type="button"
35
+ class="btn btn-default text-sm"
36
+ data-action="nested-content-blocks#toggleTypeMenu">
37
+ <svg class="w-4 h-4 mr-1.5 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24">
38
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
39
+ </svg>
40
+ <%= t('spina.content_blocks.add_block') %>
41
+ </button>
42
+
43
+ <div data-nested-content-blocks-target="typeMenu"
44
+ class="absolute z-10 mt-1 w-56 bg-white border border-gray-200 rounded-md shadow-lg py-1"
45
+ style="display:none">
46
+ <% available_templates.each do |template| %>
47
+ <button type="button"
48
+ class="w-full cursor-pointer text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100"
49
+ data-action="nested-content-blocks#addBlock"
50
+ data-block-type="<%= template[:name] %>">
51
+ <%= template[:title] || template[:name].titleize %>
52
+ </button>
53
+ <% end %>
54
+ </div>
55
+ </div>
56
+ <% end %>
57
+
58
+ <%# Pre-rendered templates for each block type (used by Stimulus to clone) %>
59
+ <% available_templates.each do |template| %>
60
+ <%
61
+ content_block = Spina::Parts::ContentBlock.new(
62
+ name: f.object.name,
63
+ block_type: template[:name].to_s
64
+ )
65
+ child_index_placeholder = content_block.object_id.to_s
66
+ %>
67
+ <template data-nested-content-blocks-target="blockTemplate"
68
+ data-block-type="<%= template[:name] %>"
69
+ data-child-index="<%= child_index_placeholder %>">
70
+ <%= f.fields_for(:content, [content_block], child_index: child_index_placeholder) do |ff| %>
71
+ <%= render "spina/admin/parts/content_blocks/fields", f: ff, stimulus_controller: "nested-content-blocks" %>
72
+ <% end %>
73
+ </template>
74
+ <% end %>
75
+ </div>
@@ -1,12 +1,12 @@
1
1
  <%= link_to spina.edit_blocks_admin_block_path(block), class: "block px-2 leading-tight", data: {selected: index.zero?, search_target: "result", action: "mouseenter->search#select", turbo_frame: "_top"} do %>
2
- <div class="flex items-center justify-between w-full px-4 py-3 rounded-md bg-gray-400 bg-opacity-0 <%= 'bg-opacity-25' if index.zero? %>" data-selected-class="bg-opacity-25">
2
+ <div class="flex items-center justify-between w-full px-4 py-3 rounded-md <%= 'bg-gray-400/25' if index.zero? %>" data-selected-class="bg-gray-400/25">
3
3
  <div>
4
4
  <div class="font-medium flex items-center">
5
5
  <%= block.name %>
6
6
  <% unless block.active? %>
7
7
  <div class="opacity-50 text-xs ml-1">(inactive)</div>
8
8
  <% end %>
9
- <div class="flex items-center ml-2 text-xs px-1.5 py-0.5 space-x-1 bg-gray-900 bg-opacity-5 rounded">
9
+ <div class="flex items-center ml-2 text-xs px-1.5 py-0.5 space-x-1 bg-gray-900/5 rounded">
10
10
  <%= heroicon('cube', style: :outline, class: 'w-3 h-3 opacity-50') %>
11
11
  <div class="opacity-75"><%= block.block_template %></div>
12
12
  </div>
@@ -12,11 +12,15 @@
12
12
 
13
13
  <div hidden data-reveal data-transition class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg border border-gray-200 z-30">
14
14
  <div class="rounded-md bg-white shadow-xs py-1">
15
- <%= button_to t('spina.blocks.delete'),
16
- spina.blocks_admin_block_path(@block),
17
- method: :delete,
18
- class: "block w-full text-left px-4 py-2 text-sm leading-5 font-medium text-red-500 cursor-pointer bg-white hover:bg-red-100/50 hover:text-red-500",
19
- form: {data: {controller: "confirm", confirm_message: t('spina.blocks.delete_confirmation')}} %>
15
+ <% if @block.deletable? %>
16
+ <%= button_to t('spina.blocks.delete'),
17
+ spina.blocks_admin_block_path(@block),
18
+ method: :delete,
19
+ class: "block w-full text-left px-4 py-2 text-sm leading-5 font-medium text-red-500 cursor-pointer bg-white hover:bg-red-100/50 hover:text-red-500",
20
+ form: {data: {controller: "confirm", confirm_message: t('spina.blocks.delete_confirmation')}} %>
21
+ <% else %>
22
+ <span class="block px-4 py-2 text-sm leading-5 text-gray-400"><%= t('spina.blocks.cannot_be_deleted') %></span>
23
+ <% end %>
20
24
  </div>
21
25
  </div>
22
26
  </div>
@@ -1,4 +1,16 @@
1
1
  <div class="max-w-5xl grid grid-cols-1 md:grid-cols-3 gap-3 md:gap-6">
2
+ <% if @block.key.present? %>
3
+ <div class="col-span-1 mt-6 md:mt-0">
4
+ <label class="block text-sm font-medium leading-5 text-gray-700">
5
+ <%= Spina::Blocks::Block.human_attribute_name(:key) %>
6
+ </label>
7
+ </div>
8
+
9
+ <div class="col-span-2 mt-1">
10
+ <span class="text-sm text-gray-500 font-mono"><%= @block.key %></span>
11
+ </div>
12
+ <% end %>
13
+
2
14
  <div class="col-span-1 mt-6 md:mt-0">
3
15
  <label class="block text-sm font-medium leading-5 text-gray-700">
4
16
  <%= Spina::Blocks::Block.human_attribute_name(:block_template) %>
@@ -1,7 +1,9 @@
1
1
  <%= render Spina::UserInterface::HeaderComponent.new do |header| %>
2
2
  <% header.with_actions do %>
3
- <% block_templates = current_theme.try(:block_templates) || [] %>
4
- <% if block_templates.any? %>
3
+ <% creatable_templates = (current_theme.try(:block_templates) || []).reject { |bt|
4
+ ((current_theme.try(:custom_blocks) || []).map { |cb| cb[:block_template].to_s }.uniq).include?(bt[:name].to_s)
5
+ } %>
6
+ <% if creatable_templates.any? %>
5
7
  <%= link_to spina.new_blocks_admin_block_path,
6
8
  class: "btn btn-primary",
7
9
  data: {turbo_frame: "modal"} do %>
@@ -16,9 +18,12 @@
16
18
  <nav class="-mb-1 md:-mb-3 mt-4">
17
19
  <div class="relative inline-block" data-controller="reveal" data-reveal-away-value>
18
20
  <button type="button"
19
- class="inline-flex items-center px-3 py-1.5 rounded-md text-sm font-medium bg-white border border-gray-300 text-gray-700 shadow-xs hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
21
+ class="inline-flex items-center cursor-pointer px-3 py-1.5 rounded-md text-sm font-medium bg-white border border-gray-300 text-gray-700 shadow-xs hover:bg-gray-50 focus:outline-hidden focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
20
22
  data-action="reveal#toggle">
21
- <% if @current_block_template.present? %>
23
+ <% if @current_filter == "layout" %>
24
+ <%= heroicon('lock-closed', style: :mini, class: 'h-4 w-4 mr-1.5 -ml-0.5 opacity-75') %>
25
+ <%= t('spina.blocks.layout_blocks') %>
26
+ <% elsif @current_block_template.present? %>
22
27
  <% current_bt = @block_templates.find { |bt| bt[:name].to_s == @current_block_template } %>
23
28
  <%= current_bt ? current_bt[:title] : @current_block_template %>
24
29
  <% else %>
@@ -30,18 +35,33 @@
30
35
 
31
36
  <div hidden data-reveal data-transition class="origin-top-left absolute left-0 mt-2 w-56 rounded-md shadow-lg border border-gray-200 z-30">
32
37
  <div class="rounded-md bg-white shadow-xs py-1">
38
+ <%# "All" filter %>
39
+ <% all_active = @current_block_template.nil? && @current_filter.nil? %>
33
40
  <%= link_to spina.blocks_admin_blocks_path,
34
- class: "flex items-center px-4 py-2 text-sm font-medium leading-5 #{@current_block_template.nil? ? 'text-blue-600 bg-blue-50' : 'text-gray-700 hover:bg-gray-100 hover:text-gray-900'}",
41
+ class: "flex items-center px-4 py-2 text-sm font-medium leading-5 #{all_active ? 'text-blue-600 bg-blue-50' : 'text-gray-700 hover:bg-gray-100 hover:text-gray-900'}",
35
42
  data: {action: "reveal#hide"} do %>
36
43
  <%= heroicon('squares-2x2', class: 'h-4 w-4 mr-2 opacity-75') %>
37
44
  <%= t('spina.blocks.all') %>
38
- <% if @current_block_template.nil? %>
45
+ <% if all_active %>
46
+ <%= heroicon('check', style: :mini, class: 'w-4 h-4 ml-auto opacity-75') %>
47
+ <% end %>
48
+ <% end %>
49
+
50
+ <%# "Layout" filter %>
51
+ <% layout_active = @current_filter == "layout" %>
52
+ <%= link_to spina.blocks_admin_blocks_path(filter: "layout"),
53
+ class: "flex items-center px-4 py-2 text-sm font-medium leading-5 #{layout_active ? 'text-blue-600 bg-blue-50' : 'text-gray-700 hover:bg-gray-100 hover:text-gray-900'}",
54
+ data: {action: "reveal#hide"} do %>
55
+ <%= heroicon('lock-closed', style: :mini, class: 'h-4 w-4 mr-2 opacity-75') %>
56
+ <%= t('spina.blocks.layout_blocks') %>
57
+ <% if layout_active %>
39
58
  <%= heroicon('check', style: :mini, class: 'w-4 h-4 ml-auto opacity-75') %>
40
59
  <% end %>
41
60
  <% end %>
42
61
 
43
62
  <div class="border-t border-gray-100 my-1"></div>
44
63
 
64
+ <%# Template filters %>
45
65
  <% @block_templates.each do |bt| %>
46
66
  <% active = @current_block_template == bt[:name].to_s %>
47
67
  <%= link_to spina.blocks_admin_blocks_path(block_template: bt[:name]),
@@ -84,6 +104,11 @@
84
104
  </div>
85
105
  <% end %>
86
106
  </div>
107
+ <% unless block.deletable? %>
108
+ <div class="pr-4 shrink-0">
109
+ <span class="text-sm font-medium text-blue-500"><%= t('spina.blocks.layout_block') %></span>
110
+ </div>
111
+ <% end %>
87
112
  </li>
88
113
  <% end %>
89
114
  </ul>
@@ -70,14 +70,20 @@
70
70
  </div>
71
71
  <% end %>
72
72
  </div>
73
- <div class="pr-4">
74
- <%= button_to spina.blocks_admin_page_page_block_path(page_id: @page.id, id: page_block.id),
75
- method: :delete,
76
- class: "text-gray-300 hover:text-red-500 transition-colors",
77
- form: {data: {controller: "confirm", confirm_message: t('spina.page_blocks.remove_confirmation')}} do %>
78
- <%= heroicon('x-mark', style: :mini, class: 'w-5 h-5') %>
79
- <% end %>
80
- </div>
73
+ <% if page_block.block.deletable? %>
74
+ <div class="pr-4">
75
+ <%= button_to spina.blocks_admin_page_page_block_path(page_id: @page.id, id: page_block.id),
76
+ method: :delete,
77
+ class: "text-gray-300 hover:text-red-500 transition-colors",
78
+ form: {data: {controller: "confirm", confirm_message: t('spina.page_blocks.remove_confirmation')}} do %>
79
+ <%= heroicon('x-mark', style: :mini, class: 'w-5 h-5') %>
80
+ <% end %>
81
+ </div>
82
+ <% else %>
83
+ <div class="pr-4">
84
+ <span class="text-sm font-medium text-blue-500"><%= t('spina.blocks.layout_block') %></span>
85
+ </div>
86
+ <% end %>
81
87
  </li>
82
88
  <% end %>
83
89
  </ul>
@@ -1,4 +1,16 @@
1
1
  en:
2
+ activerecord:
3
+ attributes:
4
+ spina/blocks/block:
5
+ key: "Key"
6
+ errors:
7
+ models:
8
+ spina/blocks/block:
9
+ attributes:
10
+ base:
11
+ undeletable: "This block is a layout block and cannot be deleted."
12
+ key:
13
+ immutable: "cannot be changed after creation"
2
14
  spina:
3
15
  blocks:
4
16
  title: "Blocks"
@@ -10,6 +22,7 @@ en:
10
22
  deleted: "Block deleted"
11
23
  delete: "Delete block"
12
24
  delete_confirmation: "Are you sure you want to delete this block?"
25
+ cannot_be_deleted: "Block can't be deleted"
13
26
  couldnt_be_saved: "Block couldn't be saved"
14
27
  sorting_saved: "Sorting saved"
15
28
  content: "Content"
@@ -18,15 +31,26 @@ en:
18
31
  category: "Category"
19
32
  no_category: "— No category —"
20
33
  select_block: "— Select block —"
34
+ mode_reference: "Select existing"
35
+ mode_inline: "Fill in here"
36
+ inline_not_editable: "Filled in on this page. Inline editing is switched off for this part, so the content still shows on the site but can't be edited or replaced here."
21
37
  block_type: "Block type"
22
38
  select_block_type: "— Select block type —"
23
39
  no_blocks_yet: "No blocks yet. Create your first block to get started."
24
40
  inactive: "Inactive"
25
41
  uncategorized: "Uncategorized"
26
42
  active_description: "Inactive blocks are hidden from pages."
43
+ layout_block: "Layout"
44
+ layout_blocks: "Layout blocks"
45
+ custom_block_not_found: "Custom block not found. Run rake spina:bootstrap to create it."
27
46
  block_categories:
28
47
  saved: "Category saved"
29
48
  couldnt_be_saved: "Category couldn't be saved"
49
+ content_blocks:
50
+ add_block: "Add block"
51
+ remove: "Remove"
52
+ empty: 'No content blocks yet. Click "Add block" to get started.'
53
+ no_template_found: "Unknown block type: %{type}"
30
54
  page_blocks:
31
55
  title: "Page Blocks"
32
56
  add_block: "Add block"
@@ -34,6 +58,7 @@ en:
34
58
  added: "Block added to page"
35
59
  couldnt_be_added: "Block couldn't be added"
36
60
  removed: "Block removed from page"
61
+ cannot_remove_layout_block: "This layout block cannot be removed from the page."
37
62
  sorting_saved: "Sorting saved"
38
63
  remove_confirmation: "Remove this block from the page?"
39
64
  no_blocks_yet: "No blocks on this page yet. Add blocks from the library to build your page."
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddCustomBlockFieldsToSpinaBlocksBlocks < ActiveRecord::Migration[7.0]
4
+ def change
5
+ unless connection.column_exists?(:spina_blocks_blocks, :deletable)
6
+ add_column(:spina_blocks_blocks, :deletable, :boolean, default: true, null: false)
7
+ end
8
+
9
+ unless connection.column_exists?(:spina_blocks_blocks, :key)
10
+ add_column(:spina_blocks_blocks, :key, :string)
11
+ add_index(:spina_blocks_blocks, :key, unique: true, where: "key IS NOT NULL")
12
+ end
13
+ end
14
+ end
@@ -12,7 +12,7 @@ module Spina
12
12
  end
13
13
 
14
14
  ::Spina::Theme.class_eval do
15
- attr_accessor :block_templates, :block_categories
15
+ attr_accessor :block_templates, :block_categories, :custom_blocks, :content_block_templates
16
16
 
17
17
  unless method_defined?(:initialize_without_blocks)
18
18
  alias_method :initialize_without_blocks, :initialize
@@ -21,6 +21,8 @@ module Spina
21
21
  initialize_without_blocks
22
22
  @block_templates = []
23
23
  @block_categories = []
24
+ @custom_blocks = []
25
+ @content_block_templates = []
24
26
  end
25
27
  end
26
28
  end
@@ -31,11 +33,20 @@ module Spina
31
33
  pin_all_from Spina::Blocks::Engine.root.join("app/assets/javascripts/spina/controllers"),
32
34
  under: "controllers",
33
35
  to: "spina/controllers"
36
+ pin_all_from Spina::Blocks::Engine.root.join("app/assets/javascripts/spina/utils"),
37
+ under: "spina/utils",
38
+ to: "spina/utils"
34
39
  end
35
40
  end
36
41
 
37
42
  initializer "spina.blocks.assets.precompile" do |app|
38
- app.config.assets.precompile += ["spina/controllers/block_collection_controller.js"] if defined?(Sprockets)
43
+ app.config.assets.precompile += [
44
+ "spina/controllers/block_collection_controller.js",
45
+ "spina/controllers/block_reference_mode_controller.js",
46
+ "spina/controllers/content_blocks_controller.js",
47
+ "spina/controllers/nested_content_blocks_controller.js",
48
+ "spina/utils/dropdown_position.js",
49
+ ] if defined?(Sprockets)
39
50
  end
40
51
 
41
52
  initializer "spina.blocks.register_parts" do
@@ -43,6 +54,9 @@ module Spina
43
54
  ::Spina::Part.register(
44
55
  Spina::Parts::BlockReference,
45
56
  Spina::Parts::BlockCollection,
57
+ Spina::Parts::ContentBlocks,
58
+ Spina::Parts::ContentBlock,
59
+ Spina::Parts::NestedContentBlocks,
46
60
  )
47
61
  end
48
62
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Spina
4
4
  module Blocks
5
- VERSION = "0.3.1"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spina-blocks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Kanashchuk
@@ -15,14 +15,20 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '2.0'
18
+ version: '2.21'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '3'
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
22
25
  requirements:
23
26
  - - ">="
24
27
  - !ruby/object:Gem::Version
25
- version: '2.0'
28
+ version: '2.21'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '3'
26
32
  - !ruby/object:Gem::Dependency
27
33
  name: database_cleaner-active_record
28
34
  requirement: !ruby/object:Gem::Requirement
@@ -90,6 +96,10 @@ files:
90
96
  - README.md
91
97
  - Rakefile
92
98
  - app/assets/javascripts/spina/controllers/block_collection_controller.js
99
+ - app/assets/javascripts/spina/controllers/block_reference_mode_controller.js
100
+ - app/assets/javascripts/spina/controllers/content_blocks_controller.js
101
+ - app/assets/javascripts/spina/controllers/nested_content_blocks_controller.js
102
+ - app/assets/javascripts/spina/utils/dropdown_position.js
93
103
  - app/controllers/spina/blocks/admin/blocks_controller.rb
94
104
  - app/controllers/spina/blocks/admin/categories_controller.rb
95
105
  - app/controllers/spina/blocks/admin/page_blocks_controller.rb
@@ -99,14 +109,21 @@ files:
99
109
  - app/models/spina/blocks/application_record.rb
100
110
  - app/models/spina/blocks/block.rb
101
111
  - app/models/spina/blocks/category.rb
112
+ - app/models/spina/blocks/inline_block.rb
102
113
  - app/models/spina/blocks/page_block.rb
103
114
  - app/models/spina/blocks/page_extension.rb
104
115
  - app/models/spina/blocks/search_extension.rb
105
116
  - app/models/spina/parts/block_collection.rb
106
117
  - app/models/spina/parts/block_reference.rb
118
+ - app/models/spina/parts/content_block.rb
119
+ - app/models/spina/parts/content_blocks.rb
120
+ - app/models/spina/parts/nested_content_blocks.rb
107
121
  - app/views/spina/admin/hooks/blocks/_website_secondary_navigation.html.erb
108
122
  - app/views/spina/admin/parts/block_collections/_form.html.erb
109
123
  - app/views/spina/admin/parts/block_references/_form.html.erb
124
+ - app/views/spina/admin/parts/content_blocks/_fields.html.erb
125
+ - app/views/spina/admin/parts/content_blocks/_form.html.erb
126
+ - app/views/spina/admin/parts/nested_content_blocks/_form.html.erb
110
127
  - app/views/spina/admin/pro/search/results/_block.html.erb
111
128
  - app/views/spina/blocks/admin/blocks/_button_block_content.html.erb
112
129
  - app/views/spina/blocks/admin/blocks/_button_block_settings.html.erb
@@ -128,6 +145,7 @@ files:
128
145
  - db/migrate/2_create_spina_blocks_blocks.rb
129
146
  - db/migrate/3_create_spina_blocks_page_blocks.rb
130
147
  - db/migrate/5_rename_title_to_name_in_spina_blocks_blocks.rb
148
+ - db/migrate/6_add_custom_block_fields_to_spina_blocks_blocks.rb
131
149
  - lib/generators/spina/blocks/install_generator.rb
132
150
  - lib/spina-blocks.rb
133
151
  - lib/spina/blocks/engine.rb