katalyst-navigation 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +29 -5
  3. data/app/assets/builds/katalyst/navigation.esm.js +911 -0
  4. data/app/assets/builds/katalyst/navigation.js +911 -0
  5. data/app/assets/builds/katalyst/navigation.min.js +2 -0
  6. data/app/assets/builds/katalyst/navigation.min.js.map +1 -0
  7. data/app/assets/config/katalyst-navigation.js +1 -1
  8. data/app/components/katalyst/navigation/editor/base_component.rb +48 -0
  9. data/app/components/katalyst/navigation/editor/errors_component.html.erb +12 -0
  10. data/app/components/katalyst/navigation/editor/errors_component.rb +15 -0
  11. data/app/components/katalyst/navigation/editor/item_component.html.erb +27 -0
  12. data/app/components/katalyst/navigation/editor/item_component.rb +30 -0
  13. data/app/components/katalyst/navigation/editor/item_editor_component.rb +51 -0
  14. data/app/components/katalyst/navigation/editor/new_item_component.html.erb +14 -0
  15. data/app/components/katalyst/navigation/editor/new_item_component.rb +49 -0
  16. data/app/components/katalyst/navigation/editor/new_items_component.html.erb +3 -0
  17. data/app/components/katalyst/navigation/editor/new_items_component.rb +20 -0
  18. data/app/{views/katalyst/navigation/menus/_list_item.html.erb → components/katalyst/navigation/editor/row_component.html.erb} +1 -1
  19. data/{lib/katalyst/navigation/version.rb → app/components/katalyst/navigation/editor/row_component.rb} +4 -1
  20. data/app/{helpers/katalyst/navigation/editor/status_bar.rb → components/katalyst/navigation/editor/status_bar_component.rb} +17 -13
  21. data/app/components/katalyst/navigation/editor/table_component.html.erb +11 -0
  22. data/app/components/katalyst/navigation/editor/table_component.rb +36 -0
  23. data/app/components/katalyst/navigation/editor_component.html.erb +9 -0
  24. data/app/components/katalyst/navigation/editor_component.rb +47 -0
  25. data/app/controllers/concerns/katalyst/navigation/has_navigation.rb +5 -14
  26. data/app/controllers/katalyst/navigation/items_controller.rb +24 -12
  27. data/app/controllers/katalyst/navigation/menus_controller.rb +25 -13
  28. data/app/helpers/katalyst/navigation/frontend_helper.rb +7 -7
  29. data/app/javascript/navigation/application.js +30 -0
  30. data/app/{assets/javascripts/controllers → javascript}/navigation/editor/item_controller.js +1 -1
  31. data/app/{assets/javascripts/utils → javascript}/navigation/editor/menu.js +1 -1
  32. data/app/{assets/javascripts/controllers → javascript}/navigation/editor/menu_controller.js +3 -3
  33. data/app/models/katalyst/navigation/menu.rb +2 -0
  34. data/app/models/katalyst/navigation/types/nodes_type.rb +2 -2
  35. data/app/views/katalyst/navigation/items/_button.html.erb +6 -0
  36. data/app/views/katalyst/navigation/items/_form_errors.html.erb +5 -0
  37. data/app/views/katalyst/navigation/items/_heading.html.erb +1 -0
  38. data/app/views/katalyst/navigation/items/_link.html.erb +11 -0
  39. data/app/views/katalyst/navigation/items/edit.html.erb +4 -3
  40. data/app/views/katalyst/navigation/items/edit.turbo_stream.erb +3 -0
  41. data/app/views/katalyst/navigation/items/new.html.erb +1 -1
  42. data/app/views/katalyst/navigation/items/update.turbo_stream.erb +2 -5
  43. data/app/views/katalyst/navigation/menus/edit.html.erb +1 -1
  44. data/app/views/katalyst/navigation/menus/index.html.erb +1 -1
  45. data/app/views/katalyst/navigation/menus/show.html.erb +3 -13
  46. data/config/importmap.rb +1 -4
  47. data/lib/katalyst/navigation/config.rb +4 -0
  48. data/lib/katalyst/navigation/engine.rb +1 -1
  49. data/lib/katalyst/navigation.rb +6 -1
  50. data/spec/factories/katalyst/navigation/menus.rb +1 -1
  51. metadata +93 -27
  52. data/app/controllers/katalyst/navigation/base_controller.rb +0 -12
  53. data/app/helpers/katalyst/navigation/editor/base.rb +0 -41
  54. data/app/helpers/katalyst/navigation/editor/errors.rb +0 -24
  55. data/app/helpers/katalyst/navigation/editor/item.rb +0 -62
  56. data/app/helpers/katalyst/navigation/editor/list.rb +0 -41
  57. data/app/helpers/katalyst/navigation/editor/menu.rb +0 -47
  58. data/app/helpers/katalyst/navigation/editor/new_item.rb +0 -53
  59. data/app/helpers/katalyst/navigation/editor_helper.rb +0 -52
  60. data/app/views/katalyst/navigation/menus/_item.html.erb +0 -15
  61. data/app/views/katalyst/navigation/menus/_new_item.html.erb +0 -3
  62. data/app/views/katalyst/navigation/menus/_new_items.html.erb +0 -5
  63. /data/app/{assets/javascripts/utils → javascript}/navigation/editor/item.js +0 -0
  64. /data/app/{assets/javascripts/controllers → javascript}/navigation/editor/list_controller.js +0 -0
  65. /data/app/{assets/javascripts/controllers → javascript}/navigation/editor/new_item_controller.js +0 -0
  66. /data/app/{assets/javascripts/utils → javascript}/navigation/editor/rules-engine.js +0 -0
  67. /data/app/{assets/javascripts/controllers → javascript}/navigation/editor/status_bar_controller.js +0 -0
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Katalyst
4
- module Navigation
5
- class BaseController < ActionController::Base
6
- include Katalyst::Tables::Backend
7
-
8
- helper Katalyst::Navigation::EditorHelper
9
- helper Katalyst::Tables::Frontend
10
- end
11
- end
12
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Katalyst
4
- module Navigation
5
- module Editor
6
- class Base
7
- MENU_CONTROLLER = "navigation--editor--menu"
8
- LIST_CONTROLLER = "navigation--editor--list"
9
- ITEM_CONTROLLER = "navigation--editor--item"
10
- STATUS_BAR_CONTROLLER = "navigation--editor--status-bar"
11
- NEW_ITEM_CONTROLLER = "navigation--editor--new-item"
12
-
13
- ATTRIBUTES_SCOPE = "menu[items_attributes][]"
14
- TURBO_FRAME = "navigation--editor--item-frame"
15
-
16
- attr_accessor :template, :menu
17
-
18
- delegate_missing_to :template
19
-
20
- def initialize(template, menu)
21
- self.template = template
22
- self.menu = menu
23
- end
24
-
25
- def menu_form_id
26
- dom_id(menu, :items)
27
- end
28
-
29
- private
30
-
31
- def add_option(options, key, *path)
32
- if path.length > 1
33
- add_option(options[key] ||= {}, *path)
34
- else
35
- options[key] = [options[key], *path].compact.join(" ")
36
- end
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Katalyst
4
- module Navigation
5
- module Editor
6
- class Errors < Base
7
- def build(**options)
8
- turbo_frame_tag dom_id(menu, :errors) do
9
- next unless menu.errors.any?
10
-
11
- tag.div(class: "navigation-errors", **options) do
12
- tag.h2("Errors in navigation") +
13
- tag.ul(class: "errors") do
14
- menu.errors.each do |error|
15
- concat(tag.li(error.message))
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Katalyst
4
- module Navigation
5
- module Editor
6
- class Item < Base
7
- attr_accessor :item
8
-
9
- def build(item, **options, &block)
10
- self.item = item
11
- tag.div **default_options(id: dom_id(item), **options) do
12
- concat(capture { yield self }) if block
13
- concat fields(item)
14
- end
15
- end
16
-
17
- def accordion_actions
18
- tag.div role: "toolbar", data: { tree_accordion_controls: "" } do
19
- concat tag.span(role: "button", value: "collapse",
20
- data: { action: "click->#{MENU_CONTROLLER}#collapse", title: "Collapse tree" })
21
- concat tag.span(role: "button", value: "expand",
22
- data: { action: "click->#{MENU_CONTROLLER}#expand", title: "Expand tree" })
23
- end
24
- end
25
-
26
- def item_actions
27
- tag.div role: "toolbar", data: { tree_controls: "" } do
28
- concat tag.span(role: "button", value: "de-nest",
29
- data: { action: "click->#{MENU_CONTROLLER}#deNest", title: "Outdent" })
30
- concat tag.span(role: "button", value: "nest",
31
- data: { action: "click->#{MENU_CONTROLLER}#nest", title: "Indent" })
32
- concat link_to("", edit_item_link,
33
- role: "button", title: "Edit", value: "edit",
34
- data: { turbo_frame: TURBO_FRAME })
35
- concat tag.span(role: "button", value: "remove",
36
- data: { action: "click->#{MENU_CONTROLLER}#remove", title: "Remove" })
37
- end
38
- end
39
-
40
- def edit_item_link
41
- item.persisted? ? edit_menu_item_path(item.menu, item) : new_menu_item_path(item.menu, type: item.type)
42
- end
43
-
44
- def fields(item)
45
- template.fields(ATTRIBUTES_SCOPE, model: item, index: nil, skip_default_ids: true) do |f|
46
- concat f.hidden_field(:id)
47
- concat f.hidden_field(:depth)
48
- concat f.hidden_field(:index)
49
- end
50
- end
51
-
52
- private
53
-
54
- def default_options(options)
55
- add_option(options, :data, :controller, ITEM_CONTROLLER)
56
-
57
- options
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Katalyst
4
- module Navigation
5
- module Editor
6
- class List < Base
7
- ACTIONS = <<~ACTIONS.gsub(/\s+/, " ").freeze
8
- dragstart->#{LIST_CONTROLLER}#dragstart
9
- dragover->#{LIST_CONTROLLER}#dragover
10
- dragenter->#{LIST_CONTROLLER}#dragenter
11
- dragleave->#{LIST_CONTROLLER}#dragleave
12
- drop->#{LIST_CONTROLLER}#drop
13
- dragend->#{LIST_CONTROLLER}#dragend
14
- ACTIONS
15
-
16
- def build(options, &_block)
17
- tag.ol **default_options(id: menu_form_id, **options) do
18
- yield self
19
- end
20
- end
21
-
22
- def items(*items)
23
- render partial: "katalyst/navigation/menus/item",
24
- layout: "katalyst/navigation/menus/list_item",
25
- collection: items,
26
- as: :item
27
- end
28
-
29
- private
30
-
31
- def default_options(options)
32
- add_option(options, :data, :controller, LIST_CONTROLLER)
33
- add_option(options, :data, :action, ACTIONS)
34
- add_option(options, :data, :"#{MENU_CONTROLLER}_target", "menu")
35
-
36
- options
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Katalyst
4
- module Navigation
5
- module Editor
6
- class Menu < Base
7
- ACTIONS = <<~ACTIONS.gsub(/\s+/, " ").freeze
8
- submit->#{MENU_CONTROLLER}#reindex
9
- navigation:drop->#{MENU_CONTROLLER}#drop
10
- navigation:reindex->#{MENU_CONTROLLER}#reindex
11
- navigation:reset->#{MENU_CONTROLLER}#reset
12
- ACTIONS
13
-
14
- def build(options)
15
- form_with(model: menu, **default_options(id: menu_form_id, **options)) do |form|
16
- concat hidden_input
17
- concat errors
18
- concat(capture { yield form })
19
- end
20
- end
21
-
22
- private
23
-
24
- # Hidden input ensures that if the menu is empty then the controller
25
- # receives an empty array.
26
- def hidden_input
27
- tag.input(type: "hidden", name: "#{Item::ATTRIBUTES_SCOPE}[id]")
28
- end
29
-
30
- def errors
31
- Editor::Errors.new(self, menu).build
32
- end
33
-
34
- def default_options(options)
35
- add_option(options, :data, :controller, MENU_CONTROLLER)
36
- add_option(options, :data, :action, ACTIONS)
37
-
38
- depth = options.delete(:depth) || menu.depth
39
-
40
- add_option(options, :data, :"#{MENU_CONTROLLER}-max-depth-value", depth) if depth
41
-
42
- options
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Katalyst
4
- module Navigation
5
- module Editor
6
- class NewItem < Base
7
- ACTIONS = <<~ACTIONS.gsub(/\s+/, " ").freeze
8
- dragstart->#{NEW_ITEM_CONTROLLER}#dragstart
9
- ACTIONS
10
-
11
- def build(item, **options, &block)
12
- capture do
13
- concat(tag.div(**default_options(options)) do
14
- concat capture(&block)
15
- concat item_template(item)
16
- end)
17
- concat turbo_replace_placeholder(item)
18
- end
19
- end
20
-
21
- # Remove items that are incomplete when rendering new items, this
22
- # causes incomplete items to be removed from the list when the user
23
- # cancels adding a new item by pressing 'discard' in the new item form.
24
- def turbo_replace_placeholder(item)
25
- turbo_stream.replace dom_id(item) do
26
- navigation_editor_item(item: item, data: { delete: "" })
27
- end
28
- end
29
-
30
- # Template is stored inside the new item dom, and copied into drag
31
- # events when the user initiates drag so that it can be copied into the
32
- # editor list on drop.
33
- def item_template(item)
34
- tag.template data: { "#{NEW_ITEM_CONTROLLER}-target" => "template" } do
35
- navigation_editor_items(item: item)
36
- end
37
- end
38
-
39
- private
40
-
41
- def default_options(options)
42
- add_option(options, :draggable, true)
43
- add_option(options, :role, "listitem")
44
- add_option(options, :data, :turbo_frame, TURBO_FRAME)
45
- add_option(options, :data, :controller, NEW_ITEM_CONTROLLER)
46
- add_option(options, :data, :action, ACTIONS)
47
-
48
- options
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Katalyst
4
- module Navigation
5
- module EditorHelper
6
- def navigation_editor_new_items(menu)
7
- Katalyst::Navigation.config.items.map do |item_class|
8
- item_class = item_class.safe_constantize if item_class.is_a?(String)
9
- item_class.new(menu: menu)
10
- end
11
- end
12
-
13
- def navigation_editor_menu(menu:, **options, &block)
14
- Editor::Menu.new(self, menu).build(options, &block)
15
- end
16
-
17
- def navigation_editor_list(menu:, items: menu.draft_items, **options)
18
- Editor::List.new(self, menu).build(options) do |list|
19
- list.items(*items) if items.present?
20
- end
21
- end
22
-
23
- # Generate items without their list wrapper, similar to form_with/fields
24
- def navigation_editor_items(item:, menu: item.menu)
25
- Editor::List.new(self, menu).items(item)
26
- end
27
-
28
- # Generate a turbo stream fragment that will show structural errors to the user.
29
- def navigation_editor_errors(menu:, **options)
30
- turbo_stream.replace(dom_id(menu, :errors),
31
- Editor::Errors.new(self, menu).build(**options))
32
- end
33
-
34
- # Generate a new item template.
35
- def navigation_editor_new_item(item:, menu: item.menu, **options, &block)
36
- Editor::NewItem.new(self, menu).build(item, **options, &block)
37
- end
38
-
39
- def navigation_editor_item(item:, menu: item.menu, **options, &block)
40
- Editor::Item.new(self, menu).build(item, **options, &block)
41
- end
42
-
43
- def navigation_editor_item_fields(item:, menu: item.menu)
44
- Editor::Item.new(self, menu).fields(item)
45
- end
46
-
47
- def navigation_editor_status_bar(menu:, **options)
48
- Editor::StatusBar.new(self, menu).build(**options)
49
- end
50
- end
51
- end
52
- end
@@ -1,15 +0,0 @@
1
- <%= navigation_editor_item item: item do |builder| %>
2
- <div class="tree" data-invisible="<%= !item.visible? %>">
3
- <%= builder.accordion_actions %>
4
-
5
- <span role="img" value="<%= item.model_name.param_key %>" title="Type"></span>
6
- <h4 class="title" title="<%= item.title %>"><%= item.title %></h4>
7
- <span role="img" value="invisible" title="Hidden"></span>
8
- </div>
9
-
10
- <div class="url">
11
- <%= link_to item.url || "", item.url || "", data: { turbo: false } %>
12
- </div>
13
-
14
- <%= builder.item_actions %>
15
- <% end %>
@@ -1,3 +0,0 @@
1
- <%= navigation_editor_new_item item: item, data: { item_type: item.model_name.param_key } do %>
2
- <%= item.model_name.human %>
3
- <% end %>
@@ -1,5 +0,0 @@
1
- <%= turbo_frame_tag "navigation--editor--item-frame" do %>
2
- <div class="navigation--editor--new-items" role="listbox">
3
- <%= render partial: "katalyst/navigation/menus/new_item", collection: navigation_editor_new_items(menu), as: :item %>
4
- </div>
5
- <% end %>