katalyst-koi 5.7.1 → 5.8.1

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/builds/katalyst/koi.esm.js +45 -6
  3. data/app/assets/builds/katalyst/koi.js +45 -6
  4. data/app/assets/builds/katalyst/koi.min.js +1 -1
  5. data/app/assets/builds/katalyst/koi.min.js.map +1 -1
  6. data/app/assets/stylesheets/koi/forms/checkboxes.css +2 -2
  7. data/app/assets/stylesheets/koi/forms/combobox.css +2 -2
  8. data/app/assets/stylesheets/koi/forms/index.css +2 -0
  9. data/app/assets/stylesheets/koi/forms/input.css +9 -11
  10. data/app/assets/stylesheets/koi/forms/lexxy.css +53 -0
  11. data/app/assets/stylesheets/koi/forms/radios.css +2 -2
  12. data/app/assets/stylesheets/koi/forms/textarea.css +1 -1
  13. data/app/assets/stylesheets/koi/forms/trix.css +30 -6
  14. data/app/assets/stylesheets/koi/index.css +1 -0
  15. data/app/controllers/admin/active_storage/direct_uploads_controller.rb +9 -0
  16. data/app/controllers/admin/background_jobs_controller.rb +68 -0
  17. data/app/controllers/admin/feature_flags_controller.rb +67 -0
  18. data/app/controllers/admin/recurring_tasks_controller.rb +67 -0
  19. data/app/helpers/admin/background_jobs_helper.rb +15 -0
  20. data/app/helpers/koi/tags/trix_toolbar.rb +64 -0
  21. data/app/javascript/koi/application.js +4 -1
  22. data/app/javascript/koi/utils/lexxy.js +23 -0
  23. data/app/javascript/koi/utils/trix.js +17 -0
  24. data/app/models/background_job.rb +98 -0
  25. data/app/models/feature_flag.rb +128 -0
  26. data/app/models/recurring_task.rb +31 -0
  27. data/app/views/admin/background_jobs/_navigation.html.erb +8 -0
  28. data/app/views/admin/background_jobs/blocked.html.erb +17 -0
  29. data/app/views/admin/background_jobs/completed.html.erb +17 -0
  30. data/app/views/admin/background_jobs/failed.html.erb +26 -0
  31. data/app/views/admin/background_jobs/in_progress.html.erb +17 -0
  32. data/app/views/admin/background_jobs/index.html.erb +22 -0
  33. data/app/views/admin/background_jobs/scheduled.html.erb +17 -0
  34. data/app/views/admin/background_jobs/show.html.erb +41 -0
  35. data/app/views/admin/feature_flags/index.html.erb +14 -0
  36. data/app/views/admin/feature_flags/new.html.erb +14 -0
  37. data/app/views/admin/feature_flags/show.html.erb +30 -0
  38. data/app/views/admin/recurring_tasks/index.html.erb +20 -0
  39. data/app/views/admin/recurring_tasks/show.html.erb +33 -0
  40. data/app/views/layouts/action_text/contents/_content.html.erb +3 -0
  41. data/config/ci.rb +10 -0
  42. data/config/importmap.rb +6 -4
  43. data/config/routes.rb +32 -0
  44. data/lib/generators/koi/admin_route/templates/initializer.rb.tt +4 -3
  45. data/lib/koi/action_text.rb +112 -0
  46. data/lib/koi/config.rb +3 -1
  47. data/lib/koi/engine.rb +23 -0
  48. data/lib/koi/form/builder.rb +27 -12
  49. data/lib/koi/form_builder.rb +2 -0
  50. data/lib/koi/menu.rb +4 -0
  51. data/lib/koi.rb +12 -6
  52. metadata +52 -5
  53. data/lib/koi/form/content.rb +0 -55
@@ -0,0 +1,17 @@
1
+ <%# locals: (collection:, state_counts:) %>
2
+
3
+ <% content_for(:header) do %>
4
+ <h1>In progress jobs</h1>
5
+
6
+ <%= render "navigation", state_counts: %>
7
+ <% end %>
8
+
9
+ <%= table_query_with(collection:) %>
10
+
11
+ <%= table_with(collection:) do |row, job| %>
12
+ <% row.link(:class_name, url: ->(record) { admin_background_job_path(record.active_job_id) }, label: "Job") %>
13
+ <% row.text(:queue_name, label: "Queue") %>
14
+ <% row.datetime(:scheduled_at, label: "Scheduled") %>
15
+ <% end %>
16
+
17
+ <%= table_pagination_with(collection:) %>
@@ -0,0 +1,22 @@
1
+ <%# locals: (collection:, state_counts:) %>
2
+
3
+ <% content_for(:header) do %>
4
+ <h1>Pending jobs</h1>
5
+
6
+ <%= render "navigation", state_counts: %>
7
+ <% end %>
8
+
9
+ <%= table_query_with(collection:) %>
10
+
11
+ <%= table_selection_with(collection:) do %>
12
+ <%= tag.button("Discard", formaction: discard_all_admin_background_jobs_path, formmethod: :delete, class: "button") %>
13
+ <% end %>
14
+
15
+ <%= table_with(collection:) do |row, job| %>
16
+ <% row.select %>
17
+ <% row.link(:class_name, url: ->(record) { admin_background_job_path(record.active_job_id) }, label: "Job") %>
18
+ <% row.text(:queue_name, label: "Queue") %>
19
+ <% row.datetime(:scheduled_at, label: "Scheduled") %>
20
+ <% end %>
21
+
22
+ <%= table_pagination_with(collection:) %>
@@ -0,0 +1,17 @@
1
+ <%# locals: (collection:, state_counts:) %>
2
+
3
+ <% content_for(:header) do %>
4
+ <h1>Scheduled jobs</h1>
5
+
6
+ <%= render "navigation", state_counts: %>
7
+ <% end %>
8
+
9
+ <%= table_query_with(collection:) %>
10
+
11
+ <%= table_with(collection:) do |row, job| %>
12
+ <% row.link(:class_name, url: ->(record) { admin_background_job_path(record.active_job_id) }, label: "Job") %>
13
+ <% row.text(:queue_name, label: "Queue") %>
14
+ <% row.datetime(:scheduled_at, label: "Scheduled") %>
15
+ <% end %>
16
+
17
+ <%= table_pagination_with(collection:) %>
@@ -0,0 +1,41 @@
1
+ <%# locals: (background_job:) %>
2
+
3
+ <% content_for(:header) do %>
4
+ <%= breadcrumb_list do %>
5
+ <li><%= link_to("Background jobs", admin_background_jobs_path) %></li>
6
+ <% end %>
7
+
8
+ <h1><%= background_job %></h1>
9
+
10
+ <%= actions_list do %>
11
+ <% if background_job.failed? %>
12
+ <li><%= link_to("Retry", retry_admin_background_job_path(background_job), data: { turbo_method: :post }) %></li>
13
+ <% end %>
14
+ <% if background_job.discardable? %>
15
+ <li><%= link_to_delete(background_job.job, "Discard", url: discard_admin_background_job_path(background_job)) %></li>
16
+ <% end %>
17
+ <% end %>
18
+ <% end %>
19
+
20
+ <%= summary_table_with(model: background_job) do |row| %>
21
+ <% row.text(:serialized_arguments, label: "Arguments") do |cell| %>
22
+ <code><%= JSON.pretty_generate(cell.value).strip %></code>
23
+ <% end %>
24
+ <% row.text(:job_id) %>
25
+ <% row.text(:queue_name, label: "Queue") %>
26
+ <% row.datetime(:enqueued_at, label: "Enqueued") %>
27
+ <% if background_job.finished? %>
28
+ <% row.datetime(:finished_at, label: "Finished") %>
29
+ <% row.text(:duration, label: "Duration") %>
30
+ <% end %>
31
+ <% if background_job.failed? %>
32
+ <% row.datetime(:updated_at, label: "Last failed") %>
33
+ <% row.text(:failure_reason, label: "Reason") %>
34
+ <% row.text(:backtrace, label: "Stacktrace") do |cell| %>
35
+ <pre><%= cell.value %></pre>
36
+ <% end %>
37
+ <% end %>
38
+ <% row.text(:job, label: "Raw data") do |cell| %>
39
+ <pre><%= JSON.pretty_generate(cell.value.as_json).strip %></pre>
40
+ <% end %>
41
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <%# locals: (collection:) %>
2
+
3
+ <% content_for(:header) do %>
4
+ <h1>Feature flags</h1>
5
+
6
+ <%= actions_list do %>
7
+ <li><%= link_to("New", new_admin_feature_flag_path) %></li>
8
+ <% end %>
9
+ <% end %>
10
+
11
+ <%= table_with(collection:) do |row, feature_flag| %>
12
+ <% row.link(:key, url: ->(record) { admin_feature_flag_path(record) }, label: "Name") %>
13
+ <% row.text(:state, label: "Status") { |cell| cell.value.to_s.humanize } %>
14
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <%# locals: (feature_flag:) %>
2
+
3
+ <% content_for(:header) do %>
4
+ <%= breadcrumb_list do %>
5
+ <li><%= link_to("Feature flags", admin_feature_flags_path) %></li>
6
+ <% end %>
7
+
8
+ <h1>New feature flag</h1>
9
+ <% end %>
10
+
11
+ <%= form_with(model: feature_flag, url: admin_feature_flags_path) do |form| %>
12
+ <%= form.govuk_text_field(:key, label: { text: "Name" }) %>
13
+ <%= form.button("Create", class: "button") %>
14
+ <% end %>
@@ -0,0 +1,30 @@
1
+ <%# locals: (feature_flag:, groups:) %>
2
+
3
+ <% content_for(:header) do %>
4
+ <%= breadcrumb_list do %>
5
+ <li><%= link_to("Feature flags", admin_feature_flags_path) %></li>
6
+ <% end %>
7
+
8
+ <h1><%= feature_flag %></h1>
9
+
10
+ <%= actions_list do %>
11
+ <li><%= link_to_delete(feature_flag, "Delete", url: admin_feature_flag_path(feature_flag)) %></li>
12
+ <% end %>
13
+ <% end %>
14
+
15
+ <%= form_with(model: feature_flag, url: admin_feature_flag_path(feature_flag), method: :patch) do |form| %>
16
+ <%= form.govuk_radio_buttons_fieldset(:state, legend: { text: "Availability" }) do %>
17
+ <%= form.govuk_radio_button(:state, :on, label: { text: "On for everyone" }) %>
18
+ <%= form.govuk_radio_button(:state, :conditional, label: { text: "Conditional" }) do %>
19
+ <% if groups.any? %>
20
+ <%= form.govuk_collection_check_boxes(:groups, groups.map(&:to_s), :to_s, :humanize, legend: { text: "Groups" }) %>
21
+ <% end %>
22
+ <%= form.govuk_number_field(:percentage_of_actors, label: { text: "Percentage of actors" }, min: 0, max: 100) %>
23
+ <%= form.govuk_number_field(:percentage_of_time, label: { text: "Percentage of time" }, min: 0, max: 100) %>
24
+ <%= form.govuk_text_area(:actors, label: { text: "Actors" }, hint: { text: "One flipper id per line, e.g. Admin::User;1" }) %>
25
+ <% end %>
26
+ <%= form.govuk_radio_button(:state, :off, label: { text: "Off for everyone" }) %>
27
+ <% end %>
28
+
29
+ <%= form.button("Save", class: "button") %>
30
+ <% end %>
@@ -0,0 +1,20 @@
1
+ <%# locals: (collection:) %>
2
+
3
+ <% content_for(:header) do %>
4
+ <%= breadcrumb_list do %>
5
+ <li><%= link_to("Background jobs", admin_background_jobs_path) %></li>
6
+ <% end %>
7
+
8
+ <h1>Recurring tasks</h1>
9
+
10
+ <% end %>
11
+
12
+ <%= table_query_with(collection:) %>
13
+
14
+ <%= table_with(collection:) do |row| %>
15
+ <% row.link(:key, url: ->(record) { admin_recurring_task_path(record.key) }, label: "Job name") %>
16
+ <% row.text(:schedule, label: "Schedule") %>
17
+ <% row.datetime(:last_enqueued_time, label: "Last enqueued") %>
18
+ <% end %>
19
+
20
+ <%= table_pagination_with(collection:) %>
@@ -0,0 +1,33 @@
1
+ <%# locals: (recurring_task:, jobs:) %>
2
+
3
+ <% content_for(:header) do %>
4
+ <%= breadcrumb_list do %>
5
+ <li><%= link_to("Recurring tasks", admin_recurring_tasks_path) %></li>
6
+ <% end %>
7
+
8
+ <h1><%= recurring_task %></h1>
9
+
10
+ <%= actions_list do %>
11
+ <li><%= link_to("Run", run_admin_recurring_task_path(recurring_task), data: { turbo_method: :post }) %></li>
12
+ <% end %>
13
+ <% end %>
14
+
15
+ <%= summary_table_with(model: recurring_task) do |row| %>
16
+ <% row.text(:job_class) %>
17
+ <% row.text(:arguments) do |cell| %>
18
+ <code><%= JSON.pretty_generate(cell.value).strip %></code>
19
+ <% end %>
20
+ <% row.text(:schedule) %>
21
+ <% end %>
22
+
23
+ <h2>Jobs</h2>
24
+
25
+ <%= table_with(collection: jobs) do |row| %>
26
+ <% row.link(:job_id, url: ->(record) { admin_background_job_path(record.active_job_id) }, label: "Job") %>
27
+ <% row.datetime(:enqueued_at) %>
28
+ <% row.datetime(:finished_at) %>
29
+ <% row.number(:duration) %>
30
+ <% row.enum(:state) %>
31
+ <% end %>
32
+
33
+ <%= table_pagination_with(collection: jobs) %>
@@ -0,0 +1,3 @@
1
+ <div class="<%= Koi.action_text_editor %>-content">
2
+ <%= yield -%>
3
+ </div>
data/config/ci.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Run using bin/ci
4
+
5
+ CI.run do
6
+ step "Style", "bundle exec rake lint"
7
+ step "Assets: Build", "bundle exec rake build"
8
+ step "Tests: RSpec", "bundle exec rake spec"
9
+ step "Security: Brakeman", "bundle exec rake security"
10
+ end
data/config/importmap.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
4
- pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
5
- pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
3
+ pin "@hotwired/stimulus", to: "stimulus.min.js"
4
+ pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
5
+ pin "@hotwired/turbo-rails", to: "turbo.min.js"
6
6
  pin "@katalyst/koi", to: "katalyst/koi.min.js"
7
- pin "@rails/actiontext", to: "actiontext.js", preload: true
7
+ pin "@rails/actiontext", to: "actiontext.js"
8
+ pin "@rails/activestorage", to: "activestorage.esm.js"
9
+ pin "lexxy"
8
10
  pin "trix"
data/config/routes.rb CHANGED
@@ -16,6 +16,10 @@ Rails.application.routes.draw do
16
16
  resources :device_authorizations, param: :user_code, only: %i[create show update]
17
17
  resources :device_tokens, only: %i[create]
18
18
 
19
+ scope :active_storage, module: :active_storage do
20
+ post :direct_uploads, to: "direct_uploads#create"
21
+ end
22
+
19
23
  resource :profile, only: %i[show edit update], shallow: true do
20
24
  resources :credentials, only: %i[show new create update destroy]
21
25
  resource :otp, only: %i[new create destroy]
@@ -26,6 +30,27 @@ Rails.application.routes.draw do
26
30
  resources :tokens, param: :token, only: %i[show update], token: /[^\/]+/
27
31
  end
28
32
 
33
+ resources :background_jobs, only: %i[index show], param: :active_job_id do
34
+ collection do
35
+ get :scheduled
36
+ get :in_progress
37
+ get :blocked
38
+ get :failed
39
+ get :completed
40
+
41
+ post :retry_all
42
+ delete :discard_all
43
+ end
44
+
45
+ member do
46
+ post :retry
47
+ delete :discard
48
+ end
49
+ end
50
+ resources :recurring_tasks, only: %i[index show], param: :key do
51
+ post :run, on: :member
52
+ end
53
+ resources :feature_flags, except: :edit, param: :key if Object.const_defined?(:Flipper)
29
54
  resources :url_rewrites
30
55
  resources :well_knowns
31
56
 
@@ -35,8 +60,15 @@ Rails.application.routes.draw do
35
60
  scope :admin do
36
61
  mount Katalyst::Content::Engine, at: "content"
37
62
  mount Katalyst::Navigation::Engine, at: "navigation"
63
+
64
+ # @deprecated use /admin/feature_flags instead, remove in 6.0
38
65
  mount Flipper::UI.app(Flipper) => "flipper" if Object.const_defined?("Flipper::UI")
39
66
  end
40
67
 
41
68
  resources :well_knowns, path: ".well-known", param: :name, only: %i[show], name: /.+/
69
+
70
+ # Fallbacks for optional dependencies
71
+ unless Object.const_defined?("HotwireCombobox")
72
+ get "hotwire_combobox", to: ->(_) { [204, {}, []] }, as: nil
73
+ end
42
74
  end
@@ -7,7 +7,8 @@ Koi::Menu.modules = {
7
7
  }
8
8
 
9
9
  Koi::Menu.advanced = {
10
- "Admin Users" => "/admin/admin_users",
11
- "URL Rewriter" => "/admin/url_rewrites",
12
- "Well Knowns" => "/admin/well_knowns",
10
+ "Admin users" => "/admin/admin_users",
11
+ "Background jobs" => "/admin/background_jobs",
12
+ "URL rewriter" => "/admin/url_rewrites",
13
+ "Well knowns" => "/admin/well_knowns",
13
14
  }
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Koi
4
+ module ActionText
5
+ module TagHelper
6
+ using Katalyst::HtmlAttributes::HasHtmlAttributes
7
+
8
+ def koi_trix_toolbar_tag(**)
9
+ Tags::TrixToolbar.new(**).render
10
+ end
11
+
12
+ def koi_rich_textarea_tag(name, value = nil, options = {}, &)
13
+ case Koi.action_text_editor
14
+ when :lexxy
15
+ lexxy_rich_textarea_tag(name, value, options, &)
16
+ when :trix
17
+ options = options.symbolize_keys
18
+ trix_id = options[:id]
19
+
20
+ toolbar = koi_trix_toolbar_tag(id: "trix-toolbar-#{trix_id}")
21
+ editor = trix_rich_textarea_tag(name, value, {
22
+ data: { turbo_permanent: "" },
23
+ toolbar: "trix-toolbar-#{trix_id}",
24
+ trix_id:,
25
+ }.merge_html(options), &)
26
+
27
+ toolbar + editor
28
+ end
29
+ end
30
+ end
31
+
32
+ module FormHelper
33
+ def koi_rich_textarea(...)
34
+ case Koi.action_text_editor
35
+ when :lexxy
36
+ lexxy_rich_textarea(...)
37
+ when :trix
38
+ trix_rich_textarea(...)
39
+ end
40
+ end
41
+ end
42
+
43
+ module FormBuilder
44
+ def koi_rich_textarea(...)
45
+ case Koi.action_text_editor
46
+ when :lexxy
47
+ lexxy_rich_textarea(...)
48
+ when :trix
49
+ trix_rich_textarea(...)
50
+ end
51
+ end
52
+ end
53
+
54
+ module ActionTextTag
55
+ def koi_render(...)
56
+ case Koi.action_text_editor
57
+ when :lexxy
58
+ lexxy_render(...)
59
+ when :trix
60
+ trix_render(...)
61
+ end
62
+ end
63
+ end
64
+
65
+ # Add aliases for trix default methods so that Koi can swap between trix and lexxy based on feature flags.
66
+ def capture_action_text_defaults
67
+ ::ActionText::TagHelper.module_eval do
68
+ alias_method :trix_rich_textarea_tag, :rich_textarea_tag
69
+ alias_method :trix_rich_text_area_tag, :rich_text_area_tag
70
+ end
71
+
72
+ ::ActionView::Helpers::FormHelper.module_eval do
73
+ alias_method :trix_rich_textarea, :rich_textarea
74
+ alias_method :trix_rich_text_area, :rich_text_area
75
+ end
76
+
77
+ ::ActionView::Helpers::FormBuilder.module_eval do
78
+ alias_method :trix_rich_textarea, :rich_textarea
79
+ alias_method :trix_rich_text_area, :rich_textarea
80
+ end
81
+
82
+ ::ActionView::Helpers::Tags::ActionText.module_eval do
83
+ alias_method :trix_render, :render
84
+ end
85
+ end
86
+ module_function :capture_action_text_defaults
87
+
88
+ # Add shims for rich_textarea and friends.
89
+ # This is intended as a migration path and will be removed when Rails 8.2 is released.
90
+ def override_action_text_defaults
91
+ ::ActionText::TagHelper.module_eval do
92
+ alias_method :rich_textarea_tag, :koi_rich_textarea_tag
93
+ alias_method :rich_text_area_tag, :koi_rich_textarea_tag
94
+ end
95
+
96
+ ::ActionView::Helpers::FormHelper.module_eval do
97
+ alias_method :rich_textarea, :koi_rich_textarea
98
+ alias_method :rich_text_area, :koi_rich_textarea
99
+ end
100
+
101
+ ::ActionView::Helpers::FormBuilder.module_eval do
102
+ alias_method :rich_textarea, :koi_rich_textarea
103
+ alias_method :rich_text_area, :koi_rich_textarea
104
+ end
105
+
106
+ ::ActionView::Helpers::Tags::ActionText.module_eval do
107
+ alias_method :render, :koi_render
108
+ end
109
+ end
110
+ module_function :override_action_text_defaults
111
+ end
112
+ end
data/lib/koi/config.rb CHANGED
@@ -4,7 +4,8 @@ require "active_support/core_ext/numeric"
4
4
 
5
5
  module Koi
6
6
  class Config
7
- attr_accessor :admin_name,
7
+ attr_accessor :action_text_editor,
8
+ :admin_name,
8
9
  :authenticate_local_admins,
9
10
  :resource_name_candidates,
10
11
  :admin_stylesheet,
@@ -16,6 +17,7 @@ module Koi
16
17
  :site_name
17
18
 
18
19
  def initialize
20
+ @action_text_editor = nil
19
21
  @admin_name = "Koi"
20
22
  @authenticate_local_admins = Rails.env.development?
21
23
  @resource_name_candidates = %i[title name]
data/lib/koi/engine.rb CHANGED
@@ -5,6 +5,7 @@ require "katalyst/content"
5
5
  require "katalyst-govuk-formbuilder"
6
6
  require "katalyst/navigation"
7
7
  require "katalyst/tables"
8
+ require "lexxy"
8
9
  require "pagy"
9
10
  require "rotp"
10
11
  require "rqrcode"
@@ -39,6 +40,28 @@ module Koi
39
40
  end
40
41
  end
41
42
 
43
+ # Rails 8.0/8.1 shim for allowing flipper swapping between lexxy/trix
44
+ # Rails 8.2 will introduce action_text.editors, not yet implemented.
45
+ initializer "koi.actiontext.initialize", after: "lexxy.initialize" do |app|
46
+ # disable lexxy injection in favour of Koi injection
47
+ app.config.lexxy.override_action_text_defaults = false
48
+
49
+ # Capture ActionText defaults (trix) once
50
+ ActionText.capture_action_text_defaults
51
+
52
+ # Based on Lexxy::Engine's 'lexxy.initialize'
53
+ app.config.to_prepare do
54
+ ::ActionText::TagHelper.prepend(ActionText::TagHelper)
55
+ ::ActionView::Helpers::FormHelper.prepend(ActionText::FormHelper)
56
+ ::ActionView::Helpers::FormBuilder.prepend(ActionText::FormBuilder)
57
+ ::ActionView::Helpers::Tags::ActionText.prepend(ActionText::ActionTextTag)
58
+
59
+ # Install Koi's stubs.
60
+ # In Rails 8.2 this should be replaced by action_text.editors
61
+ ActionText.override_action_text_defaults
62
+ end
63
+ end
64
+
42
65
  initializer "koi.content" do
43
66
  Katalyst::Content.config.base_controller = "Admin::ApplicationController"
44
67
  Katalyst::Content.config.errors_component = "Koi::Content::Editor::ErrorsComponent"
@@ -5,17 +5,15 @@ module Koi
5
5
  module Builder
6
6
  extend ActiveSupport::Concern
7
7
 
8
- included do
9
- delegate_missing_to :@template
10
- end
11
-
12
8
  # Generates a submit button for saving admin resources.
9
+ # @deprecated will be removed in Koi 6.0
13
10
  def admin_save(text = "Save", name: :commit, value: :save, class: "button", **)
14
11
  button(text, name:, value:, class:, **)
15
12
  end
16
13
 
17
14
  # Generates a delete link formatted as a button that will perform a turbo
18
15
  # delete with a confirmation.
16
+ # @deprecated will be removed in Koi 6.0
19
17
  def admin_delete(text = "Delete", url: nil, confirm: "Are you sure?", data: {}, **)
20
18
  return unless object.persisted?
21
19
 
@@ -27,12 +25,14 @@ module Koi
27
25
 
28
26
  # Generates an archive link formatted as a button that will perform a turbo
29
27
  # delete with a confirmation.
28
+ # @deprecated will be removed in Koi 6.0
30
29
  def admin_archive(text = "Archive", **)
31
30
  admin_delete(text, **)
32
31
  end
33
32
 
34
33
  # Generates a discard changes link formatted as a text button that navigates
35
34
  # the user back to the previous page.
35
+ # @deprecated will be removed in Koi 6.0
36
36
  def admin_discard(text = "Discard", url: :back, **)
37
37
  link_to(text, url, class: "button", data: { text_button: "" }, **)
38
38
  end
@@ -59,16 +59,31 @@ module Koi
59
59
  super
60
60
  end
61
61
 
62
- # Use content editor trix setup by default.
62
+ using Katalyst::HtmlAttributes::HasHtmlAttributes
63
+
64
+ # Use Koi's admin direct uploads URL.
65
+ #
66
+ # @api internal
67
+ # @see Lexxy::FormBuilder#lexxy_rich_textarea
68
+ def lexxy_rich_textarea(attribute_name, **attributes, &)
69
+ attributes = {
70
+ class: "lexxy-content",
71
+ data: { direct_upload_url: @template.admin_direct_uploads_url },
72
+ }.merge_html(**attributes)
73
+
74
+ super
75
+ end
76
+
77
+ # Use Koi's admin direct uploads URL.
63
78
  #
64
79
  # @api internal
65
- # @see GOVUKDesignSystemFormBuilder::Builder#govuk_rich_text_area
66
- def govuk_rich_text_area(attribute_name, data: {}, **, &)
67
- data = data.reverse_merge(
68
- direct_upload_url: @template.katalyst_content.direct_uploads_url,
69
- controller: "content--editor--trix",
70
- action: "trix-initialize->content--editor--trix#trixInitialize",
71
- )
80
+ # @see Koi::ActionText::FormBuilder#trix_rich_textarea
81
+ def trix_rich_textarea(attribute_name, **attributes, &)
82
+ attributes = {
83
+ class: "trix-content",
84
+ data: { direct_upload_url: @template.admin_direct_uploads_url },
85
+ }.merge_html(**attributes)
86
+
72
87
  super
73
88
  end
74
89
  end
@@ -4,5 +4,7 @@ module Koi
4
4
  class FormBuilder < ActionView::Helpers::FormBuilder
5
5
  include GOVUKDesignSystemFormBuilder::Builder
6
6
  include Koi::Form::Builder
7
+
8
+ delegate :content_tag, :tag, :safe_join, :link_to, :capture, to: :@template
7
9
  end
8
10
  end
data/lib/koi/menu.rb CHANGED
@@ -27,14 +27,18 @@ module Koi
27
27
  builder.add_menu(title: "Advanced") do |b|
28
28
  b.add_items(advanced)
29
29
 
30
+ # @deprecated use /admin/feature_flags instead, remove in 6.0
30
31
  if Object.const_defined?("Flipper::UI")
31
32
  b.add_link(title: "Flipper", url: context.main_app.admin_root_path.concat("/flipper"),
32
33
  target: :blank)
33
34
  end
35
+
36
+ # @deprecated superseded by /admin/background_jobs for Solid Queue apps, remove in 6.0
34
37
  if Object.const_defined?("Sidekiq::Web")
35
38
  b.add_link(title: "Sidekiq", url: context.main_app.admin_root_path.concat("sidekiq"),
36
39
  target: :blank)
37
40
  end
41
+
38
42
  b.add_button(title: "Clear cache", url: context.main_app.admin_cache_path,
39
43
  http_method: :delete)
40
44
  end
data/lib/koi.rb CHANGED
@@ -1,14 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Koi
4
- extend self
4
+ class << self
5
+ def config
6
+ @config ||= Config.new
7
+ end
5
8
 
6
- def config
7
- @config ||= Config.new
8
- end
9
+ def configure
10
+ yield config
11
+ end
12
+
13
+ def action_text_editor
14
+ return config.action_text_editor if config.action_text_editor.present?
9
15
 
10
- def configure
11
- yield config
16
+ defined?(::Lexxy) && defined?(::Flipper) && Flipper.enabled?(:lexxy, Koi::Current.admin_user) ? :lexxy : :trix
17
+ end
12
18
  end
13
19
  end
14
20