katalyst-koi 4.7.3 → 4.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/builds/koi/admin.css +201 -150
  3. data/app/assets/builds/koi/admin.css.map +1 -1
  4. data/app/assets/javascripts/koi/controllers/index_actions_controller.js +0 -8
  5. data/app/assets/javascripts/koi/controllers/pagy_nav_controller.js +21 -0
  6. data/app/assets/stylesheets/koi/base/_index.scss +1 -0
  7. data/app/assets/stylesheets/koi/base/_tables.scss +15 -0
  8. data/app/assets/stylesheets/koi/components/_index.scss +0 -1
  9. data/app/components/concerns/koi/tables/cells.rb +85 -0
  10. data/app/components/koi/header/edit_component.rb +1 -1
  11. data/app/components/koi/header/show_component.rb +1 -1
  12. data/app/components/koi/summary_list/date_component.rb +2 -2
  13. data/app/components/koi/summary_list/datetime_component.rb +2 -2
  14. data/app/components/koi/summary_list/number_component.rb +2 -2
  15. data/app/components/koi/summary_table_component.rb +7 -0
  16. data/app/components/koi/table_component.rb +7 -0
  17. data/app/components/koi/tables/cells/enum_component.rb +27 -0
  18. data/app/components/koi/tables/table_component.rb +2 -54
  19. data/app/controllers/admin/admin_users_controller.rb +2 -2
  20. data/app/controllers/admin/sessions_controller.rb +8 -10
  21. data/app/controllers/admin/tokens_controller.rb +15 -13
  22. data/app/controllers/admin/url_rewrites_controller.rb +2 -2
  23. data/app/controllers/concerns/koi/controller/has_attachments.rb +1 -1
  24. data/app/controllers/concerns/koi/controller/is_admin_controller.rb +6 -4
  25. data/app/controllers/concerns/koi/controller/json_web_token.rb +1 -1
  26. data/app/helpers/koi/definition_list_helper.rb +2 -2
  27. data/app/helpers/koi/index_actions_helper.rb +2 -4
  28. data/app/helpers/koi/pagy.rb +15 -0
  29. data/app/models/url_rewrite.rb +1 -1
  30. data/app/views/admin/credentials/_credentials.html.erb +1 -1
  31. data/config/initializers/extensions.rb +1 -1
  32. data/config/initializers/flipper.rb +1 -1
  33. data/config/initializers/pagy.rb +2 -0
  34. data/config/locales/koi.en.yml +4 -0
  35. data/db/migrate/20130509235316_add_url_rewriter.rb +1 -1
  36. data/db/migrate/20230531063707_update_admin_users.rb +6 -3
  37. data/db/seeds.rb +1 -1
  38. data/lib/generators/koi/admin/admin_generator.rb +7 -1
  39. data/lib/generators/koi/admin_controller/admin_controller_generator.rb +6 -2
  40. data/lib/generators/koi/admin_controller/templates/controller.rb.tt +51 -53
  41. data/lib/generators/koi/admin_controller/templates/controller_spec.rb.tt +1 -1
  42. data/lib/generators/koi/admin_views/admin_views_generator.rb +8 -23
  43. data/lib/generators/koi/admin_views/templates/edit.html.erb.tt +1 -1
  44. data/lib/generators/koi/admin_views/templates/index.html.erb.tt +7 -7
  45. data/lib/generators/koi/admin_views/templates/new.html.erb.tt +1 -1
  46. data/lib/generators/koi/admin_views/templates/show.html.erb.tt +8 -4
  47. data/lib/govuk_design_system_formbuilder/elements/document.rb +5 -5
  48. data/lib/govuk_design_system_formbuilder/elements/image.rb +5 -5
  49. data/lib/koi/form_builder.rb +12 -12
  50. data/lib/koi/menu/builder.rb +6 -6
  51. metadata +9 -4
  52. data/app/assets/stylesheets/koi/components/_index-table.scss +0 -147
  53. data/app/assets/stylesheets/koi/components/index-table/_ordinal.scss +0 -38
@@ -0,0 +1,21 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class PagyNavController extends Controller {
4
+ connect() {
5
+ document.addEventListener("shortcut:page-prev", this.prevPage);
6
+ document.addEventListener("shortcut:page-next", this.nextPage);
7
+ }
8
+
9
+ disconnect() {
10
+ document.removeEventListener("shortcut:page-prev", this.prevPage);
11
+ document.removeEventListener("shortcut:page-next", this.nextPage);
12
+ }
13
+
14
+ nextPage = () => {
15
+ this.element.querySelector("a:last-child").click();
16
+ };
17
+
18
+ prevPage = () => {
19
+ this.element.querySelector("a:first-child").click();
20
+ };
21
+ }
@@ -3,6 +3,7 @@
3
3
  @use "input";
4
4
  @use "link";
5
5
  @use "list";
6
+ @use "tables";
6
7
  @use "typography";
7
8
 
8
9
  .button--primary {
@@ -0,0 +1,15 @@
1
+ @use "katalyst/tables";
2
+
3
+ :where(th.type-enum, td.type-enum) {
4
+ width: var(--width-small);
5
+ }
6
+
7
+ :where(td.type-enum span) {
8
+ --background-color: var(--site-primary-light);
9
+ --color: var(--site-on-primary);
10
+ background: var(--background-color);
11
+ color: var(--color);
12
+ border-radius: 0.25rem;
13
+ font-size: var(--paragraph--small);
14
+ padding: 0.25rem 0.5rem;
15
+ }
@@ -3,6 +3,5 @@
3
3
  @use "document-field";
4
4
  @use "image-field";
5
5
  @use "index-actions";
6
- @use "index-table";
7
6
  @use "pagy";
8
7
  @use "summary-list";
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Koi
4
+ module Tables
5
+ module Cells
6
+ # Generates a column that links to the record's show page (by default).
7
+ #
8
+ # @param column [Symbol] the column's name, called as a method on the record
9
+ # @param label [String|nil] the label to use for the column header
10
+ # @param heading [boolean] if true, data cells will use `th` tags
11
+ # @param url [Symbol|String|Proc] arguments for url_For, defaults to the record
12
+ # @param link [Hash] options to be passed to the link_to helper
13
+ # @param ** [Hash] HTML attributes to be added to column cells
14
+ # @param & [Proc] optional block to alter the cell content
15
+ #
16
+ # If a block is provided, it will be called with the link cell component as an argument.
17
+ # @yieldparam cell [Katalyst::Tables::Cells::LinkComponent] the cell component
18
+ #
19
+ # @return [void]
20
+ #
21
+ # @example Render a column containing the record's title, linked to its show page
22
+ # <% row.link :title %> # => <td><a href="/admin/post/15">About us</a></td>
23
+ # @example Render a column containing the record's title, linked to its edit page
24
+ # <% row.link :title, url: :edit_admin_post_path do |cell| %>
25
+ # Edit <%= cell %>
26
+ # <% end %>
27
+ # # => <td><a href="/admin/post/15/edit">Edit About us</a></td>
28
+ def link(column, label: nil, heading: false, url: [:admin, record], link: {}, **, &)
29
+ with_cell(Tables::Cells::LinkComponent.new(
30
+ collection:, row:, column:, record:, label:, heading:, url:, link:, **,
31
+ ), &)
32
+ end
33
+
34
+ # Generates a column from an enum value rendered as a tag.
35
+ # The target attribute must be defined as an `enum` in the model.
36
+ #
37
+ # @param column [Symbol] the column's name, called as a method on the record.
38
+ # @param label [String|nil] the label to use for the column header
39
+ # @param heading [boolean] if true, data cells will use `th` tags
40
+ # @param ** [Hash] HTML attributes to be added to column cells
41
+ # @param & [Proc] optional block to wrap the cell content
42
+ #
43
+ # When rendering an enum value, the component will check for translations
44
+ # using the key `active_record.attributes.[model]/[column].[value]`,
45
+ # e.g. `active_record.attributes.banner/status.published`.
46
+ #
47
+ # If a block is provided, it will be called with the cell component as an argument.
48
+ # @yieldparam cell [Katalyst::Tables::CellComponent] the cell component
49
+ #
50
+ # @return [void]
51
+ #
52
+ # @example Render a generic text column for any value that supports `to_s`
53
+ # <% row.enum :status %>
54
+ # <%# label => <th>Status</th> %>
55
+ # <%# data => <td class="type-enum"><span data-enum="status" data-value="published">Published</span></td> %>
56
+ def enum(column, label: nil, heading: false, **, &)
57
+ with_cell(Tables::Cells::EnumComponent.new(
58
+ collection:, row:, column:, record:, label:, heading:, **,
59
+ ), &)
60
+ end
61
+
62
+ # Generates a column that renders an ActiveStorage attachment as a downloadable link.
63
+ #
64
+ # @param column [Symbol] the column's name, called as a method on the record
65
+ # @param label [String|nil] the label to use for the column header
66
+ # @param heading [boolean] if true, data cells will use `th` tags
67
+ # @param variant [Symbol] the variant to use when rendering the image (default :thumb)
68
+ # @param ** [Hash] HTML attributes to be added to column cells
69
+ # @param & [Proc] optional block to alter the cell content
70
+ #
71
+ # If a block is provided, it will be called with the attachment cell component as an argument.
72
+ # @yieldparam cell [Katalyst::Tables::Cells::AttachmentComponent] the cell component
73
+ #
74
+ # @return [void]
75
+ #
76
+ # @example Render a column containing a download link to the record's background image
77
+ # <% row.attachment :background %> # => <td><a href="...">background.png</a></td>
78
+ def attachment(column, label: nil, heading: false, variant: :thumb, **, &)
79
+ with_cell(Tables::Cells::AttachmentComponent.new(
80
+ collection:, row:, column:, record:, label:, heading:, variant:, **,
81
+ ), &)
82
+ end
83
+ end
84
+ end
85
+ end
@@ -36,7 +36,7 @@ module Koi
36
36
 
37
37
  def resource_title
38
38
  title = Koi.config.resource_name_candidates.reduce(nil) do |name, key|
39
- name || resource.respond_to?(key) && resource.public_send(key)
39
+ name || (resource.public_send(key) if resource.respond_to?(key))
40
40
  end
41
41
 
42
42
  title.presence || resource.model_name.human
@@ -29,7 +29,7 @@ module Koi
29
29
 
30
30
  def title
31
31
  title = Koi.config.resource_name_candidates.reduce(@title) do |name, key|
32
- name || resource.respond_to?(key) && resource.public_send(key)
32
+ name || (resource.public_send(key) if resource.respond_to?(key))
33
33
  end
34
34
 
35
35
  title.presence || resource.model_name.human
@@ -3,8 +3,8 @@
3
3
  module Koi
4
4
  module SummaryList
5
5
  class DateComponent < Base
6
- def initialize(model, attribute, format: :admin, **options)
7
- super(model, attribute, **options)
6
+ def initialize(model, attribute, format: :admin, **)
7
+ super(model, attribute, **)
8
8
 
9
9
  @format = format
10
10
  end
@@ -3,8 +3,8 @@
3
3
  module Koi
4
4
  module SummaryList
5
5
  class DatetimeComponent < Base
6
- def initialize(model, attribute, format: :admin, **options)
7
- super(model, attribute, **options)
6
+ def initialize(model, attribute, format: :admin, **)
7
+ super(model, attribute, **)
8
8
 
9
9
  @format = format
10
10
  end
@@ -3,8 +3,8 @@
3
3
  module Koi
4
4
  module SummaryList
5
5
  class NumberComponent < Base
6
- def initialize(model, attribute, format: :admin, **options)
7
- super(model, attribute, **options)
6
+ def initialize(model, attribute, format: :admin, **)
7
+ super(model, attribute, **)
8
8
 
9
9
  @format = format
10
10
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Koi
4
+ class SummaryTableComponent < Katalyst::SummaryTableComponent
5
+ include Tables::Cells
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Koi
4
+ class TableComponent < Katalyst::TableComponent
5
+ include Tables::Cells
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Koi
4
+ module Tables
5
+ module Cells
6
+ # Displays an enum value using data inferred from the model.
7
+ class EnumComponent < Katalyst::Tables::CellComponent
8
+ def rendered_value
9
+ if (value = self.value).present?
10
+ label = t(i18n_enum_label_key(value), default: value)
11
+ tag.span(label, data: { enum: column, value: })
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def default_html_attributes
18
+ { class: "type-enum" }
19
+ end
20
+
21
+ def i18n_enum_label_key(value)
22
+ "active_record.attributes.#{collection.model_name.i18n_key}/#{column}.#{value}"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,61 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # @deprecated prefer Koi::TableComponent
3
4
  module Koi
4
5
  module Tables
5
- class TableComponent < Katalyst::TableComponent
6
- # Generates a column that links to the record's show page (by default).
7
- #
8
- # @param column [Symbol] the column's name, called as a method on the record
9
- # @param label [String|nil] the label to use for the column header
10
- # @param heading [boolean] if true, data cells will use `th` tags
11
- # @param url [Symbol|String|Proc] arguments for url_For, defaults to the record
12
- # @param link [Hash] options to be passed to the link_to helper
13
- # @param ** [Hash] HTML attributes to be added to column cells
14
- # @param & [Proc] optional block to alter the cell content
15
- #
16
- # If a block is provided, it will be called with the link cell component as an argument.
17
- # @yieldparam cell [Katalyst::Tables::Cells::LinkComponent] the cell component
18
- #
19
- # @return [void]
20
- #
21
- # @example Render a column containing the record's title, linked to its show page
22
- # <% row.link :title %> # => <td><a href="/admin/post/15">About us</a></td>
23
- # @example Render a column containing the record's title, linked to its edit page
24
- # <% row.link :title, url: :edit_admin_post_path do |cell| %>
25
- # Edit <%= cell %>
26
- # <% end %>
27
- # # => <td><a href="/admin/post/15/edit">Edit About us</a></td>
28
- def link(column, label: nil, heading: false, url: [:admin, record], link: {}, **, &)
29
- with_cell(Tables::Cells::LinkComponent.new(
30
- collection:, row:, column:, record:, label:, heading:, url:, link:, **,
31
- ), &)
32
- end
33
-
34
- # Generates a column that renders an ActiveStorage attachment as a downloadable link.
35
- #
36
- # @param column [Symbol] the column's name, called as a method on the record
37
- # @param label [String|nil] the label to use for the column header
38
- # @param heading [boolean] if true, data cells will use `th` tags
39
- # @param variant [Symbol] the variant to use when rendering the image (default :thumb)
40
- # @param ** [Hash] HTML attributes to be added to column cells
41
- # @param & [Proc] optional block to alter the cell content
42
- #
43
- # If a block is provided, it will be called with the attachment cell component as an argument.
44
- # @yieldparam cell [Katalyst::Tables::Cells::AttachmentComponent] the cell component
45
- #
46
- # @return [void]
47
- #
48
- # @example Render a column containing a download link to the record's background image
49
- # <% row.attachment :background %> # => <td><a href="...">background.png</a></td>
50
- def attachment(column, label: nil, heading: false, variant: :thumb, **, &)
51
- with_cell(Tables::Cells::AttachmentComponent.new(
52
- collection:, row:, column:, record:, label:, heading:, variant:, **,
53
- ), &)
54
- end
55
-
56
- def default_html_attributes
57
- { class: "index-table" }
58
- end
6
+ class TableComponent < ::Koi::TableComponent
59
7
  end
60
8
  end
61
9
  end
@@ -32,7 +32,7 @@ module Admin
32
32
  if admin.save
33
33
  redirect_to admin_admin_user_path(admin)
34
34
  else
35
- render :new, locals: { admin: }, status: :unprocessable_entity
35
+ render :new, locals: { admin: }, status: :unprocessable_content
36
36
  end
37
37
  end
38
38
 
@@ -40,7 +40,7 @@ module Admin
40
40
  if admin.update(admin_user_params)
41
41
  redirect_to action: :show
42
42
  else
43
- render :edit, locals: { admin: }, status: :unprocessable_entity
43
+ render :edit, locals: { admin: }, status: :unprocessable_content
44
44
  end
45
45
  end
46
46
 
@@ -15,23 +15,17 @@ module Admin
15
15
  end
16
16
 
17
17
  def create
18
- if (admin_user = webauthn_authenticate!)
18
+ if (admin_user = webauthn_authenticate! || params_authenticate!)
19
19
  record_sign_in!(admin_user)
20
20
 
21
21
  session[:admin_user_id] = admin_user.id
22
22
 
23
- redirect_to admin_dashboard_path, notice: "You have been logged in"
24
- elsif (admin_user = Admin::User.authenticate_by(session_params.slice(:email, :password)))
25
- record_sign_in!(admin_user)
26
-
27
- session[:admin_user_id] = admin_user.id
28
-
29
- redirect_to admin_dashboard_path, notice: "You have been logged in"
23
+ redirect_to admin_dashboard_path, notice: I18n.t("koi.auth.login")
30
24
  else
31
25
  admin_user = Admin::User.new(session_params.slice(:email, :password))
32
26
  admin_user.errors.add(:email, "Invalid email or password")
33
27
 
34
- render :new, status: :unprocessable_entity, locals: { admin_user: }
28
+ render :new, status: :unprocessable_content, locals: { admin_user: }
35
29
  end
36
30
  end
37
31
 
@@ -40,7 +34,7 @@ module Admin
40
34
 
41
35
  session[:admin_user_id] = nil
42
36
 
43
- redirect_to admin_dashboard_path, notice: "You have been logged out"
37
+ redirect_to admin_dashboard_path, notice: I18n.t("koi.auth.logout")
44
38
  end
45
39
 
46
40
  private
@@ -49,6 +43,10 @@ module Admin
49
43
  params.require(:admin).permit(:email, :password, :response)
50
44
  end
51
45
 
46
+ def params_authenticate!
47
+ Admin::User.authenticate_by(session_params.slice(:email, :password))
48
+ end
49
+
52
50
  def update_last_sign_in(admin_user)
53
51
  return if admin_user.current_sign_in_at.blank?
54
52
 
@@ -7,6 +7,18 @@ module Admin
7
7
  skip_before_action :authenticate_admin, only: %i[show update]
8
8
  before_action :set_token, only: %i[show update]
9
9
 
10
+ def show
11
+ return redirect_to new_admin_session_path, notice: I18n.t("koi.auth.token_invalid") if @token.blank?
12
+
13
+ admin = Admin::User.find(@token[:admin_id])
14
+
15
+ if token_utilised?(admin, @token)
16
+ return redirect_to new_admin_session_path, notice: I18n.t("koi.auth.token_invalid")
17
+ end
18
+
19
+ render locals: { admin:, token: params[:token] }, layout: "koi/login"
20
+ end
21
+
10
22
  def create
11
23
  admin = Admin::User.find(params[:id])
12
24
  token = encode_token(admin_id: admin.id, exp: 5.minutes.from_now.to_i, iat: Time.current.to_i)
@@ -17,7 +29,9 @@ module Admin
17
29
  def update
18
30
  return redirect_to admin_dashboard_path, status: :see_other if admin_signed_in?
19
31
 
20
- return redirect_to new_admin_session_path, status: :see_other, notice: "invalid token" if @token.blank?
32
+ if @token.blank?
33
+ return redirect_to new_admin_session_path, status: :see_other, notice: I18n.t("koi.auth.token_invalid")
34
+ end
21
35
 
22
36
  admin = Admin::User.find(@token[:admin_id])
23
37
  sign_in_admin(admin)
@@ -25,18 +39,6 @@ module Admin
25
39
  redirect_to admin_admin_user_path(admin)
26
40
  end
27
41
 
28
- def show
29
- return redirect_to new_admin_session_path, notice: "Token invalid or consumed already" if @token.blank?
30
-
31
- admin = Admin::User.find(@token[:admin_id])
32
-
33
- if token_utilised?(admin, @token)
34
- return redirect_to new_admin_session_path, notice: "Token invalid or consumed already"
35
- end
36
-
37
- render locals: { admin:, token: params[:token] }, layout: "koi/login"
38
- end
39
-
40
42
  private
41
43
 
42
44
  def set_token
@@ -29,7 +29,7 @@ module Admin
29
29
  if @url_rewrite.save
30
30
  redirect_to admin_url_rewrite_path(@url_rewrite)
31
31
  else
32
- render :new, status: :unprocessable_entity, locals: { url_rewrite: @url_rewrite }
32
+ render :new, status: :unprocessable_content, locals: { url_rewrite: @url_rewrite }
33
33
  end
34
34
  end
35
35
 
@@ -39,7 +39,7 @@ module Admin
39
39
  if @url_rewrite.save
40
40
  redirect_to admin_url_rewrite_path(@url_rewrite)
41
41
  else
42
- render :edit, status: :unprocessable_entity, locals: { url_rewrite: @url_rewrite }
42
+ render :edit, status: :unprocessable_content, locals: { url_rewrite: @url_rewrite }
43
43
  end
44
44
  end
45
45
 
@@ -15,7 +15,7 @@ module Koi
15
15
  # redirect_to [:admin, @document], status: :see_other
16
16
  # else
17
17
  # store_attachments(@document)
18
- # render :new, status: :unprocessable_entity
18
+ # render :new, status: :unprocessable_content
19
19
  # end
20
20
  # end
21
21
  #
@@ -15,15 +15,17 @@ module Koi
15
15
  include HasAdminUsers
16
16
  include HasAttachments
17
17
  include Katalyst::Tables::Backend
18
- include Pagy::Backend
18
+ include ::Pagy::Backend
19
19
 
20
20
  default_form_builder "Koi::FormBuilder"
21
- default_table_component Koi::Tables::TableComponent
21
+ default_table_component Koi::TableComponent
22
+ default_summary_table_component Koi::SummaryTableComponent
22
23
 
23
24
  helper Katalyst::GOVUK::Formbuilder::Frontend
24
25
  helper Katalyst::Navigation::FrontendHelper
25
26
  helper Katalyst::Tables::Frontend
26
- helper Pagy::Frontend
27
+ helper ::Pagy::Frontend
28
+ helper Koi::Pagy::Frontend
27
29
  helper IndexActionsHelper
28
30
  helper :all
29
31
 
@@ -43,7 +45,7 @@ module Koi
43
45
  return if admin_signed_in? || !Rails.env.development?
44
46
 
45
47
  session[:admin_user_id] =
46
- Admin::User.where(email: %W[#{ENV['USER']}@katalyst.com.au admin@katalyst.com.au]).first&.id
48
+ Admin::User.where(email: %W[#{ENV.fetch('USER', nil)}@katalyst.com.au admin@katalyst.com.au]).first&.id
47
49
  end
48
50
 
49
51
  def authenticate_admin
@@ -13,7 +13,7 @@ module Koi
13
13
 
14
14
  def decode_token(token)
15
15
  payload = JWT.decode(token, SECRET_KEY)[0]
16
- HashWithIndifferentAccess.new(payload)
16
+ ActiveSupport::HashWithIndifferentAccess.new(payload)
17
17
  rescue JWT::DecodeError
18
18
  nil
19
19
  end
@@ -3,8 +3,8 @@
3
3
  module Koi
4
4
  module DefinitionListHelper
5
5
  # @deprecated This method is deprecated and will be removed in Koi 5.
6
- def definition_list(**options, &block)
7
- render Koi::SummaryListComponent.new(**options), &block
6
+ def definition_list(**, &)
7
+ render(Koi::SummaryListComponent.new(**), &)
8
8
  end
9
9
  end
10
10
  end
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Koi
4
4
  module IndexActionsHelper
5
- def koi_index_actions(search: false, create: false, &block)
6
- IndexActionsBuilder.new(self, search:, create:).render(&block)
5
+ def koi_index_actions(search: false, create: false, &)
6
+ IndexActionsBuilder.new(self, search:, create:).render(&)
7
7
  end
8
8
  end
9
9
 
@@ -85,8 +85,6 @@ module Koi
85
85
  ("shortcut:cancel@document->index-actions#clear" if search?),
86
86
  ("shortcut:create@document->index-actions#create" if create?),
87
87
  ("shortcut:search@document->index-actions#search" if search?),
88
- "shortcut:page-prev@document->index-actions#prevPage",
89
- "shortcut:page-next@document->index-actions#nextPage",
90
88
  ].compact.join(" ")
91
89
  end
92
90
 
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Koi
4
+ # Koi Pagy extensions
5
+ module Pagy
6
+ module Frontend
7
+ private
8
+
9
+ # @overload nav_aria_label() to add stimulus controller to pagy_nav
10
+ def nav_aria_label(pagy, aria_label: nil)
11
+ "#{super} data-controller='pagy-nav'"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -14,7 +14,7 @@ class UrlRewrite < ApplicationRecord
14
14
  attribute :status_code, :integer, default: 303
15
15
 
16
16
  validates :from, :to, presence: true
17
- validates :from, format: { with: %r{\A/.*\z}, message: "should start with /" }
17
+ validates :from, format: { with: %r{\A/.*\z}, message: "should start with /" } # rubocop:disable Rails/I18nLocaleTexts
18
18
 
19
19
  scope :active, -> { where(active: true) }
20
20
  scope :alphabetical, -> { order(from: :asc) }
@@ -1,4 +1,4 @@
1
- <%= table_with(id: dom_id(admin, :credentials), collection: admin.credentials, class: "index-table") do |t, c| %>
1
+ <%= table_with(id: dom_id(admin, :credentials), collection: admin.credentials) do |t, c| %>
2
2
  <% t.text :nickname %>
3
3
  <% t.number :sign_count %>
4
4
  <% t.cell :actions, label: "" do %>
@@ -5,6 +5,6 @@ ActiveSupport.on_load(:action_view) do
5
5
  # https://github.com/rails/rails/issues/50916
6
6
  ActionView::AbstractRenderer::ObjectRendering.define_method(
7
7
  :merge_prefix_into_object_path,
8
- Koi::Extensions::ObjectRendering.instance_method(:merge_prefix_into_object_path)
8
+ Koi::Extensions::ObjectRendering.instance_method(:merge_prefix_into_object_path),
9
9
  )
10
10
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Register koi admin roles with flipper for easy toggling
4
4
 
5
- return unless Object.const_defined?("Flipper")
5
+ return unless Object.const_defined?(:Flipper)
6
6
 
7
7
  Flipper.register(:admins) do |flipper, _context|
8
8
  flipper.actor.is_a?(Admin::User) && !flipper.actor.archived?
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Pagy::I18n.load({ locale: "en", filepath: Koi::Engine.root.join("config/locales/pagy.en.yml") })
@@ -8,6 +8,10 @@ en:
8
8
  default: "%Y-%m-%d"
9
9
  admin: "%e %B %Y"
10
10
  koi:
11
+ auth:
12
+ login: "You have been logged in"
13
+ logout: "You have been logged out"
14
+ token_invalid: "Token invalid or consumed already"
11
15
  labels:
12
16
  new: New
13
17
  search: Search
@@ -5,7 +5,7 @@ class AddUrlRewriter < ActiveRecord::Migration[4.2]
5
5
  create_table :url_rewrites do |t|
6
6
  t.text :from
7
7
  t.text :to
8
- t.boolean :active, default: true
8
+ t.boolean :active, default: true, null: false
9
9
 
10
10
  t.timestamps
11
11
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class UpdateAdminUsers < ActiveRecord::Migration[7.0]
2
- class Admin < ActiveRecord::Base; end
4
+ class Admin < ApplicationRecord; end
3
5
 
4
6
  def up
5
7
  add_column :admins, :name, :string
@@ -21,14 +23,15 @@ class UpdateAdminUsers < ActiveRecord::Migration[7.0]
21
23
  def down
22
24
  add_column :admins, :first_name, :string
23
25
  add_column :admins, :last_name, :string
24
- add_column :admins, :reset_password_token, :string, index: { unique: true }
26
+ add_column :admins, :reset_password_token, :string
27
+ add_index :admins, :reset_password_token, unique: true
25
28
  add_column :admins, :reset_password_sent_at, :datetime
26
29
  add_column :admins, :remember_created_at, :datetime
27
30
  add_column :admins, :locked_at, :datetime
28
31
  add_column :admins, :role, :string
29
32
 
30
33
  Admin.all.each do |admin|
31
- admin.first_name, admin.last_name = admin.name.split(' ', 2)
34
+ admin.first_name, admin.last_name = admin.name.split(" ", 2)
32
35
  admin.save!
33
36
  end
34
37
 
data/db/seeds.rb CHANGED
@@ -5,5 +5,5 @@ if Rails.env.development? && !ENV["CI"]
5
5
  Admin::User.create_with(
6
6
  name: `id -F`.strip,
7
7
  password: "password",
8
- ).find_or_create_by(email: "#{ENV['USER']}@katalyst.com.au")
8
+ ).find_or_create_by(email: "#{ENV.fetch('USER', nil)}@katalyst.com.au")
9
9
  end
@@ -13,7 +13,13 @@ module Koi
13
13
  remove_hook_for(:scaffold_controller)
14
14
  remove_hook_for(:resource_route)
15
15
 
16
- hook_for :admin_controller, in: :koi, as: :admin, type: :boolean, default: true
16
+ hook_for :admin_controller, in: :koi, as: :admin, type: :boolean, default: true do |instance, controller|
17
+ args, opts, config = @_initializer
18
+ opts ||= {}
19
+
20
+ # setting model_name so that generators will use the controller_class_path
21
+ instance.invoke controller, args, { model_name: instance.name, **opts }, config
22
+ end
17
23
 
18
24
  Rails::Generators::ModelGenerator.hook_for :admin_search, type: :boolean, default: true
19
25
  Rails::Generators::ModelGenerator.hook_for :ordinal_scope, type: :boolean, default: true