katalyst-koi 4.18.0 → 5.0.0.alpha.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.
- checksums.yaml +4 -4
- data/app/assets/images/koi/icons/add.svg +3 -0
- data/app/assets/images/koi/icons/close.svg +1 -0
- data/app/assets/images/koi/koi.png +0 -0
- data/app/assets/javascripts/koi/controllers/file_field_controller.js +2 -2
- data/app/assets/javascripts/koi/controllers/index.js +0 -3
- data/app/assets/javascripts/koi/controllers/koi/modal_controller.js +40 -0
- data/app/assets/javascripts/koi/controllers/navigation_controller.js +14 -21
- data/app/assets/javascripts/koi/controllers/webauthn_registration_controller.js +4 -1
- data/app/assets/stylesheets/koi/blocks/actions.css +8 -0
- data/app/assets/stylesheets/koi/blocks/application-header.css +15 -0
- data/app/assets/stylesheets/koi/blocks/application-navigation.css +54 -0
- data/app/assets/stylesheets/koi/blocks/button.css +90 -0
- data/app/assets/stylesheets/koi/blocks/flash.css +19 -0
- data/app/assets/stylesheets/koi/blocks/icon.css +15 -0
- data/app/assets/stylesheets/koi/blocks/index.css +13 -0
- data/app/assets/stylesheets/koi/blocks/modal.css +26 -0
- data/app/assets/stylesheets/koi/blocks/navigation.css +23 -0
- data/app/assets/stylesheets/koi/blocks/page-header.css +31 -0
- data/app/assets/stylesheets/koi/blocks/pagy.css +82 -0
- data/app/assets/stylesheets/koi/blocks/prose.css +37 -0
- data/app/assets/stylesheets/koi/blocks/tables/index.css +4 -0
- data/app/assets/stylesheets/koi/{components/_query.scss → blocks/tables/query.css} +13 -13
- data/app/assets/stylesheets/koi/{base/_tables.scss → blocks/tables/table.css} +11 -59
- data/app/assets/stylesheets/koi/compositions/cover.css +17 -0
- data/app/assets/stylesheets/koi/{base/_flow.scss → compositions/flow.css} +1 -1
- data/app/assets/stylesheets/koi/compositions/index.css +4 -0
- data/app/assets/stylesheets/koi/compositions/wrapper.css +11 -0
- data/app/assets/stylesheets/koi/forms/caption.css +22 -0
- data/app/assets/stylesheets/koi/forms/checkboxes.css +153 -0
- data/app/assets/stylesheets/koi/forms/date-input.css +12 -0
- data/app/assets/stylesheets/koi/{components/_document-field.scss → forms/document-field.css} +20 -15
- data/app/assets/stylesheets/koi/forms/errors.css +38 -0
- data/app/assets/stylesheets/koi/forms/fieldset.css +73 -0
- data/app/assets/stylesheets/koi/forms/file-upload.css +20 -0
- data/app/assets/stylesheets/koi/forms/form-group.css +19 -0
- data/app/assets/stylesheets/koi/forms/hint.css +11 -0
- data/app/assets/stylesheets/koi/forms/image-field.css +96 -0
- data/app/assets/stylesheets/koi/forms/index.css +44 -0
- data/app/assets/stylesheets/koi/forms/input.css +194 -0
- data/app/assets/stylesheets/koi/forms/label.css +43 -0
- data/app/assets/stylesheets/koi/forms/password.css +18 -0
- data/app/assets/stylesheets/koi/forms/radios.css +162 -0
- data/app/assets/stylesheets/koi/forms/select.css +18 -0
- data/app/assets/stylesheets/koi/forms/textarea.css +3 -0
- data/app/assets/stylesheets/koi/forms/trix.css +33 -0
- data/app/assets/stylesheets/koi/global/fonts.css +22 -0
- data/app/assets/stylesheets/koi/global/global-styles.css +297 -0
- data/app/assets/stylesheets/koi/global/reset.css +98 -0
- data/app/assets/stylesheets/koi/global/variables.css +97 -0
- data/app/assets/stylesheets/koi/icons.css +14 -0
- data/app/assets/stylesheets/koi/{admin.scss → index.css} +16 -7
- data/app/assets/stylesheets/koi/login.css +26 -0
- data/app/assets/stylesheets/koi/themes/_index.scss +0 -1
- data/app/assets/stylesheets/koi/utilities/index.css +1 -0
- data/app/assets/stylesheets/koi/utilities/visually-hidden.css +18 -0
- data/app/components/concerns/koi/tables/cells.rb +3 -3
- data/app/components/koi/header/edit_component.rb +1 -1
- data/app/components/koi/header/index_component.rb +1 -1
- data/app/components/koi/header/new_component.rb +1 -1
- data/app/components/koi/header/show_component.rb +1 -1
- data/app/components/koi/header_component.html.erb +12 -11
- data/app/components/koi/header_component.rb +4 -2
- data/app/components/koi/table_component.rb +8 -0
- data/app/controllers/admin/admin_users_controller.rb +24 -18
- data/app/controllers/admin/application_controller.rb +1 -3
- data/app/controllers/admin/credentials_controller.rb +18 -14
- data/app/controllers/admin/otps_controller.rb +15 -13
- data/app/controllers/admin/sessions_controller.rb +12 -1
- data/app/controllers/admin/url_rewrites_controller.rb +19 -17
- data/app/controllers/admin/well_knowns_controller.rb +20 -18
- data/app/controllers/concerns/koi/controller.rb +37 -0
- data/app/helpers/koi/form_helper.rb +18 -0
- data/app/helpers/koi/header_helper.rb +122 -0
- data/app/helpers/koi/index_actions_helper.rb +3 -2
- data/app/helpers/koi/modal_helper.rb +71 -0
- data/app/models/admin/user.rb +7 -1
- data/app/models/url_rewrite.rb +1 -9
- data/app/views/admin/admin_users/_form.html+self.erb +8 -0
- data/app/views/admin/admin_users/_form.html.erb +8 -0
- data/app/views/admin/admin_users/archived.html.erb +7 -4
- data/app/views/admin/admin_users/edit.html+self.erb +12 -0
- data/app/views/admin/admin_users/edit.html.erb +13 -8
- data/app/views/admin/admin_users/index.html.erb +10 -5
- data/app/views/admin/admin_users/new.html.erb +8 -8
- data/app/views/admin/admin_users/show.html+self.erb +26 -14
- data/app/views/admin/admin_users/show.html.erb +22 -20
- data/app/views/admin/credentials/_credentials.html+self.erb +8 -6
- data/app/views/admin/credentials/_credentials.html.erb +3 -1
- data/app/views/admin/credentials/create.turbo_stream.erb +4 -3
- data/app/views/admin/credentials/destroy.turbo_stream.erb +4 -2
- data/app/views/admin/credentials/new.html.erb +42 -36
- data/app/views/admin/dashboards/show.html.erb +13 -1
- data/app/views/admin/otps/_form.html.erb +7 -7
- data/app/views/admin/otps/create.turbo_stream.erb +3 -3
- data/app/views/admin/otps/new.html.erb +5 -3
- data/app/views/admin/sessions/new.html.erb +2 -3
- data/app/views/admin/sessions/otp.html.erb +1 -3
- data/app/views/admin/sessions/password.html.erb +1 -3
- data/app/views/admin/tokens/show.html.erb +4 -6
- data/app/views/admin/url_rewrites/_form.html.erb +9 -0
- data/app/views/admin/url_rewrites/edit.html.erb +13 -9
- data/app/views/admin/url_rewrites/index.html.erb +10 -7
- data/app/views/admin/url_rewrites/new.html.erb +8 -8
- data/app/views/admin/url_rewrites/show.html.erb +17 -12
- data/app/views/admin/well_knowns/_form.html.erb +9 -0
- data/app/views/admin/well_knowns/edit.html.erb +13 -9
- data/app/views/admin/well_knowns/index.html.erb +8 -5
- data/app/views/admin/well_knowns/new.html.erb +8 -8
- data/app/views/admin/well_knowns/show.html.erb +14 -13
- data/app/views/katalyst/content/asides/_aside.html+form.erb +6 -4
- data/app/views/katalyst/content/columns/_column.html+form.erb +5 -3
- data/app/views/katalyst/content/contents/_content.html+form.erb +8 -6
- data/app/views/katalyst/content/figures/_figure.html+form.erb +8 -5
- data/app/views/katalyst/content/groups/_group.html+form.erb +5 -3
- data/app/views/katalyst/content/items/_item.html+form.erb +5 -3
- data/app/views/katalyst/content/sections/_section.html+form.erb +5 -3
- data/app/views/katalyst/content/tables/_table.html+form.erb +16 -11
- data/app/views/katalyst/navigation/items/_button.html.erb +6 -12
- data/app/views/katalyst/navigation/items/_heading.html.erb +3 -10
- data/app/views/katalyst/navigation/items/_link.html.erb +6 -11
- data/app/views/katalyst/navigation/menus/edit.html.erb +10 -6
- data/app/views/katalyst/navigation/menus/index.html.erb +4 -2
- data/app/views/katalyst/navigation/menus/new.html.erb +5 -3
- data/app/views/katalyst/navigation/menus/show.html.erb +8 -7
- data/app/views/layouts/koi/_application_header.html.erb +20 -0
- data/app/views/layouts/koi/_application_navigation.html.erb +34 -0
- data/app/views/layouts/koi/_flash.html.erb +6 -3
- data/app/views/layouts/koi/_navigation_header.html.erb +0 -2
- data/app/views/layouts/koi/application.html.erb +22 -27
- data/app/views/layouts/koi/frame.html.erb +1 -3
- data/app/views/layouts/koi/login.html.erb +12 -5
- data/config/locales/koi.en.yml +9 -1
- data/config/routes.rb +1 -1
- data/lib/generators/koi/admin/admin_generator.rb +3 -12
- data/lib/generators/koi/admin_controller/admin_controller_generator.rb +6 -16
- data/lib/generators/koi/admin_controller/templates/controller.rb.tt +82 -18
- data/lib/generators/koi/admin_controller/templates/controller_spec.rb.tt +113 -47
- data/lib/generators/koi/admin_route/admin_route_generator.rb +60 -6
- data/lib/generators/koi/admin_views/USAGE +18 -7
- data/lib/generators/koi/admin_views/admin_views_generator.rb +19 -11
- data/lib/generators/koi/admin_views/templates/_form.html.erb.tt +8 -0
- data/lib/generators/koi/admin_views/templates/archived.html.erb.tt +33 -0
- data/lib/generators/koi/admin_views/templates/edit.html.erb.tt +17 -9
- data/lib/generators/koi/admin_views/templates/index.html.erb.tt +31 -3
- data/lib/generators/koi/admin_views/templates/new.html.erb.tt +8 -8
- data/lib/generators/koi/admin_views/templates/show.html.erb.tt +15 -18
- data/lib/generators/koi/helpers/attribute_helpers.rb +147 -0
- data/lib/generators/koi/helpers/attribute_types.rb +218 -0
- data/lib/generators/koi/helpers/resource_helpers.rb +121 -0
- data/lib/generators/koi/{active_record/active_record_generator.rb → model/model_generator.rb} +1 -1
- data/lib/koi/config.rb +3 -1
- data/lib/koi/engine.rb +0 -9
- data/lib/koi/form/builder.rb +4 -4
- data/lib/koi/form/content.rb +55 -0
- data/lib/koi/form/elements/document.rb +1 -1
- data/lib/koi/form/elements/image.rb +1 -1
- data/lib/koi/form_builder.rb +1 -0
- data/lib/koi/menu.rb +14 -1
- data/spec/factories/admins.rb +1 -1
- metadata +92 -101
- data/app/assets/builds/koi/admin.css +0 -1
- data/app/assets/stylesheets/koi/base/_button.scss +0 -122
- data/app/assets/stylesheets/koi/base/_icon.scss +0 -29
- data/app/assets/stylesheets/koi/base/_index.scss +0 -21
- data/app/assets/stylesheets/koi/base/_input.scss +0 -19
- data/app/assets/stylesheets/koi/base/_link.scss +0 -26
- data/app/assets/stylesheets/koi/base/_list.scss +0 -11
- data/app/assets/stylesheets/koi/base/_typography.scss +0 -160
- data/app/assets/stylesheets/koi/components/_actions-group.scss +0 -7
- data/app/assets/stylesheets/koi/components/_image-field.scss +0 -95
- data/app/assets/stylesheets/koi/components/_index.scss +0 -9
- data/app/assets/stylesheets/koi/components/_pagy.scss +0 -29
- data/app/assets/stylesheets/koi/components/_summary-list.scss +0 -40
- data/app/assets/stylesheets/koi/layouts/_banner.scss +0 -7
- data/app/assets/stylesheets/koi/layouts/_content.scss +0 -40
- data/app/assets/stylesheets/koi/layouts/_flash.scss +0 -41
- data/app/assets/stylesheets/koi/layouts/_header.scss +0 -61
- data/app/assets/stylesheets/koi/layouts/_index.scss +0 -48
- data/app/assets/stylesheets/koi/layouts/_main.scss +0 -23
- data/app/assets/stylesheets/koi/layouts/_navigation.scss +0 -180
- data/app/assets/stylesheets/koi/layouts/_stack.scss +0 -13
- data/app/assets/stylesheets/koi/pages/_index.scss +0 -1
- data/app/assets/stylesheets/koi/pages/_login.scss +0 -46
- data/app/assets/stylesheets/koi/themes/_govuk.scss +0 -56
- data/app/assets/stylesheets/koi/themes/_kpop.scss +0 -5
- data/app/assets/stylesheets/koi/utils/_breakpoints.scss +0 -13
- data/app/assets/stylesheets/koi/utils/_hide.scss +0 -11
- data/app/assets/stylesheets/koi/utils/_index.scss +0 -2
- data/app/assets/stylesheets/koi/utils/_typography.scss +0 -42
- data/app/components/koi/content/editor/item_form_component.html.erb +0 -11
- data/app/components/koi/content/editor/item_form_component.rb +0 -94
- data/app/components/koi/summary_list/attachment_component.rb +0 -47
- data/app/components/koi/summary_list/base.rb +0 -59
- data/app/components/koi/summary_list/boolean_component.rb +0 -15
- data/app/components/koi/summary_list/date_component.rb +0 -17
- data/app/components/koi/summary_list/datetime_component.rb +0 -17
- data/app/components/koi/summary_list/item_component.rb +0 -26
- data/app/components/koi/summary_list/number_component.rb +0 -21
- data/app/components/koi/summary_list/rich_text_component.rb +0 -8
- data/app/components/koi/summary_list/text_component.rb +0 -8
- data/app/components/koi/summary_list_component.html.erb +0 -5
- data/app/components/koi/summary_list_component.rb +0 -75
- data/app/controllers/concerns/koi/controller/is_admin_controller.rb +0 -66
- data/app/helpers/koi/application_helper.rb +0 -7
- data/app/helpers/koi/date_helper.rb +0 -26
- data/app/helpers/koi/definition_list_helper.rb +0 -10
- data/app/views/admin/admin_users/_fields.html+self.erb +0 -3
- data/app/views/admin/admin_users/_fields.html.erb +0 -3
- data/app/views/admin/url_rewrites/_fields.html.erb +0 -4
- data/app/views/admin/well_knowns/_fields.html.erb +0 -6
- data/app/views/layouts/koi/_environment.html.erb +0 -4
- data/app/views/layouts/koi/_header.html.erb +0 -11
- data/app/views/layouts/koi/_navigation.html.erb +0 -23
- data/app/views/layouts/koi/_navigation_collapse.html.erb +0 -3
- data/lib/generators/koi/admin_views/templates/_fields.html.erb.tt +0 -3
- data/lib/generators/koi/helpers/admin_generator_attributes.rb +0 -66
- data/lib/koi/extensions/dartsass.rb +0 -23
- /data/app/assets/stylesheets/koi/{components/_clipboard.scss → blocks/clipboard.css} +0 -0
- /data/app/assets/stylesheets/koi/{components/_index-actions.scss → blocks/index-actions.css} +0 -0
- /data/app/assets/stylesheets/koi/{components/_toolbar.scss → blocks/toolbar.css} +0 -0
- /data/app/assets/stylesheets/koi/{base/_repel.scss → compositions/repel.css} +0 -0
@@ -3,12 +3,20 @@
|
|
3
3
|
require "rails/generators/named_base"
|
4
4
|
require "rails/generators/resource_helpers"
|
5
5
|
|
6
|
+
require_relative "../helpers/attribute_helpers"
|
7
|
+
require_relative "../helpers/resource_helpers"
|
8
|
+
|
6
9
|
module Koi
|
7
10
|
class AdminRouteGenerator < Rails::Generators::NamedBase
|
8
|
-
include
|
11
|
+
include Helpers::AttributeHelpers
|
12
|
+
include Helpers::ResourceHelpers
|
9
13
|
|
10
14
|
source_root File.expand_path("templates", __dir__)
|
11
15
|
|
16
|
+
argument :attributes, type: :array, default: [], banner: "field:type field:type"
|
17
|
+
|
18
|
+
class_option :force, type: :boolean, default: true
|
19
|
+
|
12
20
|
def create_routes
|
13
21
|
return if Pathname.new(destination_root).join("config/routes/admin.rb").exist?
|
14
22
|
|
@@ -16,7 +24,17 @@ module Koi
|
|
16
24
|
end
|
17
25
|
|
18
26
|
def add_route
|
19
|
-
route "resources :#{file_name.pluralize}"
|
27
|
+
route "resources :#{file_name.pluralize}"
|
28
|
+
|
29
|
+
if orderable?
|
30
|
+
resource_route "patch :order, on: :collection"
|
31
|
+
end
|
32
|
+
|
33
|
+
if archivable?
|
34
|
+
resource_route "put :restore, on: :collection"
|
35
|
+
resource_route "put :archive, on: :collection"
|
36
|
+
resource_route "get :archived, on: :collection"
|
37
|
+
end
|
20
38
|
end
|
21
39
|
|
22
40
|
def create_navigation
|
@@ -30,7 +48,7 @@ module Koi
|
|
30
48
|
# Safe because we know that this only called during code generation
|
31
49
|
config = eval(match) # rubocop:disable Security/Eval
|
32
50
|
label = [*regular_class_path.map(&:humanize), human_name.pluralize].join(" ")
|
33
|
-
path =
|
51
|
+
path = route_url
|
34
52
|
config[label] = path
|
35
53
|
config = config.sort.to_h
|
36
54
|
StringIO.new.tap do |io|
|
@@ -55,7 +73,7 @@ module Koi
|
|
55
73
|
|
56
74
|
# See Rails::Generators::Actions
|
57
75
|
# Replaces hard-coded route with admin route file
|
58
|
-
def route(routing_code, namespace:
|
76
|
+
def route(routing_code, namespace: regular_class_path)
|
59
77
|
namespace = Array(namespace)
|
60
78
|
namespace_pattern = route_namespace_pattern(namespace)
|
61
79
|
routing_code = namespace.reverse.reduce(routing_code) do |code, name|
|
@@ -76,10 +94,39 @@ module Koi
|
|
76
94
|
end
|
77
95
|
end
|
78
96
|
|
97
|
+
def resource_route(routing_code, namespace: regular_class_path, resource: "resources :#{file_name.pluralize}")
|
98
|
+
namespace = Array(namespace)
|
99
|
+
resource_pattern = route_namespace_pattern(namespace, resource)
|
100
|
+
block_pattern = /#{resource_pattern}( do)?\n/
|
101
|
+
|
102
|
+
log :route, routing_code
|
103
|
+
|
104
|
+
in_root do
|
105
|
+
resource_match = match_file(route_file, block_pattern)
|
106
|
+
|
107
|
+
if resource_match.captures.last.nil?
|
108
|
+
*, current_indent = resource_match.captures.compact.map(&:length)
|
109
|
+
inject_into_file route_file, " do\n#{' ' * current_indent}end",
|
110
|
+
after: resource_pattern,
|
111
|
+
verbose: false,
|
112
|
+
force: false
|
113
|
+
end
|
114
|
+
|
115
|
+
resource_match = match_file(route_file, block_pattern)
|
116
|
+
|
117
|
+
*, existing_block_indent, _ = resource_match.captures.compact.map(&:length)
|
118
|
+
routing_code = rebase_indentation(routing_code, existing_block_indent + 2)
|
119
|
+
|
120
|
+
inject_into_file route_file, routing_code, after: block_pattern, verbose: true, force: false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
79
124
|
# See Rails::Generators::Actions
|
80
125
|
# Replaces Routes.draw with namespace :admin as the search term
|
81
|
-
def route_namespace_pattern(namespace)
|
82
|
-
|
126
|
+
def route_namespace_pattern(namespace, resource = nil)
|
127
|
+
seed = resource ? route_resource_pattern(namespace, resource) : nil
|
128
|
+
|
129
|
+
namespace.each_with_index.reverse_each.reduce(seed) do |pattern, (name, i)|
|
83
130
|
cummulative_margin = "\\#{i + 1}[ ]{2}"
|
84
131
|
blank_or_indented_line = "^[ ]*\n|^#{cummulative_margin}.*\n"
|
85
132
|
"(?:(?:#{blank_or_indented_line})*?^(#{cummulative_margin})namespace :#{name} do\n#{pattern})?"
|
@@ -88,6 +135,13 @@ module Koi
|
|
88
135
|
end
|
89
136
|
end
|
90
137
|
|
138
|
+
# Generate a regex for the resource block at the appropriate level of nesting
|
139
|
+
def route_resource_pattern(namespace, resource)
|
140
|
+
cummulative_margin = "\\#{namespace.count + 1}[ ]{2}"
|
141
|
+
blank_or_indented_line = "^[ ]*\n|^#{cummulative_margin}.*\n"
|
142
|
+
"(?:(?:#{blank_or_indented_line})*?^(#{cummulative_margin})#{resource})"
|
143
|
+
end
|
144
|
+
|
91
145
|
def route_file
|
92
146
|
"config/routes/admin.rb"
|
93
147
|
end
|
@@ -1,12 +1,23 @@
|
|
1
1
|
Description:
|
2
|
-
Generates
|
2
|
+
Generates Koi admin CRUD views for the given model.
|
3
|
+
|
4
|
+
When run without field:type arguments, the generator will automatically
|
5
|
+
introspect the model's attributes and associations to generate appropriate
|
6
|
+
admin views. This makes it easy to create admin views for existing models
|
7
|
+
or re-generate views when models change.
|
8
|
+
|
9
|
+
Options:
|
10
|
+
--force Overwrite existing view files
|
3
11
|
|
4
12
|
Example:
|
5
|
-
bin/rails generate koi:admin_views
|
13
|
+
bin/rails generate koi:admin_views Product name:string price:integer active:boolean
|
6
14
|
|
7
15
|
This will create:
|
8
|
-
app/views/admin/
|
9
|
-
app/views/admin/
|
10
|
-
app/views/admin/
|
11
|
-
app/views/admin/
|
12
|
-
app/views/admin/
|
16
|
+
app/views/admin/products/_fields.html.erb
|
17
|
+
app/views/admin/products/edit.html.erb
|
18
|
+
app/views/admin/products/index.html.erb
|
19
|
+
app/views/admin/products/new.html.erb
|
20
|
+
app/views/admin/products/show.html.erb
|
21
|
+
|
22
|
+
For existing models, run without field arguments to auto-introspect:
|
23
|
+
bin/rails generate koi:admin_views Product --force
|
@@ -1,38 +1,46 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "rails/generators/named_base"
|
4
|
-
require "rails/generators/resource_helpers"
|
5
4
|
|
6
|
-
require_relative "../helpers/
|
5
|
+
require_relative "../helpers/attribute_helpers"
|
6
|
+
require_relative "../helpers/resource_helpers"
|
7
7
|
|
8
8
|
module Koi
|
9
9
|
class AdminViewsGenerator < Rails::Generators::NamedBase
|
10
|
-
include
|
11
|
-
include Helpers::
|
10
|
+
include Helpers::AttributeHelpers
|
11
|
+
include Helpers::ResourceHelpers
|
12
12
|
|
13
13
|
source_root File.expand_path("templates", __dir__)
|
14
14
|
|
15
15
|
argument :attributes, type: :array, default: [], banner: "field:type field:type"
|
16
16
|
|
17
|
+
class_option :force, type: :boolean, default: true
|
18
|
+
|
17
19
|
def create_root_folder
|
18
20
|
empty_directory File.join("app/views", controller_file_path)
|
19
21
|
end
|
20
22
|
|
21
23
|
def copy_view_files
|
22
24
|
available_views.each do |filename|
|
23
|
-
|
24
|
-
template filename, File.join("app/views", controller_file_path, target)
|
25
|
+
template(filename, File.join("app/views", controller_file_path, filename))
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
29
|
+
def remove_legacy
|
30
|
+
remove_file(File.join("app/views", controller_file_path, "_fields.html.erb"), force: true)
|
31
|
+
end
|
32
|
+
|
28
33
|
private
|
29
34
|
|
30
35
|
def available_views
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
[
|
37
|
+
"index.html.erb",
|
38
|
+
("archived.html.erb" if archivable?),
|
39
|
+
"show.html.erb",
|
40
|
+
"new.html.erb",
|
41
|
+
"edit.html.erb",
|
42
|
+
"_form.html.erb",
|
43
|
+
].compact
|
36
44
|
end
|
37
45
|
end
|
38
46
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<%%# locals: (collection:) %>
|
2
|
+
|
3
|
+
<%% content_for(:header) do %>
|
4
|
+
<%%= breadcrumb_list do %>
|
5
|
+
<li><%%= link_to("<%= human_name.pluralize.titleize %>", <%= admin_index_helper %>) %></li>
|
6
|
+
<%% end %>
|
7
|
+
|
8
|
+
<h1>Archived <%= human_name.pluralize.titleize %></h1>
|
9
|
+
<%% end %>
|
10
|
+
|
11
|
+
<% if query? %>
|
12
|
+
<%%= table_query_with(collection:) %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<%%= table_selection_with(collection:) do %>
|
16
|
+
<%%= tag.button("Restore", formaction: <%= restore_admin_helper %>, formmethod: :put, class: "button") %>
|
17
|
+
<%% end %>
|
18
|
+
|
19
|
+
<%%= table_with(collection:) do |row, <%= singular_name %>| %>
|
20
|
+
<%% row.select %>
|
21
|
+
<%- index_attributes.each_with_index do |attribute, index| -%>
|
22
|
+
<%- if index.zero? -%>
|
23
|
+
<%% row.link :<%= attribute.name %> %>
|
24
|
+
<%- else -%>
|
25
|
+
<%= index_attribute_for attribute %>
|
26
|
+
<%- end -%>
|
27
|
+
<%- end -%>
|
28
|
+
<%% row.date :archived_at %>
|
29
|
+
<%% end %>
|
30
|
+
|
31
|
+
<%- if paginate? -%>
|
32
|
+
<%%= table_pagination_with(collection:) %>
|
33
|
+
<%- end -%>
|
@@ -1,12 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
<%%
|
1
|
+
<%%# locals: (<%= singular_name %>:) %>
|
2
|
+
|
3
|
+
<%% content_for(:header) do %>
|
4
|
+
<%%= breadcrumb_list do %>
|
5
|
+
<li><%%= link_to("<%= human_name.pluralize.titleize %>", <%= admin_index_helper %>) %></li>
|
6
|
+
<li><%%= link_to(<%= singular_name %>, <%= admin_show_helper %>) %></li>
|
7
|
+
<%% end %>
|
4
8
|
|
5
|
-
|
6
|
-
<%%= render "fields", form: %>
|
9
|
+
<h1>Edit <%= human_name.downcase %></h1>
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
<%%= actions_list do %>
|
12
|
+
<%- if archivable? -%>
|
13
|
+
<li><%%= link_to_archive_or_delete(<%= singular_name %>) %></li>
|
14
|
+
<%- else -%>
|
15
|
+
<li><%%= link_to_delete(<%= singular_name %>) %></li>
|
16
|
+
<%- end -%>
|
17
|
+
<%% end %>
|
12
18
|
<%% end %>
|
19
|
+
|
20
|
+
<%%= render("form", <%= singular_name %>:) %>
|
@@ -1,12 +1,35 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
<%%# locals: (collection:) %>
|
2
|
+
|
3
|
+
<%% content_for(:header) do %>
|
4
|
+
<h1><%= human_name.pluralize.titleize %></h1>
|
5
|
+
|
6
|
+
<%%= actions_list do %>
|
7
|
+
<li><%%= link_to("New", <%= new_admin_helper %>) %></li>
|
8
|
+
<%- if archivable? -%>
|
9
|
+
<li><%%= link_to("Archived", <%= archived_admin_helper %>) %></li>
|
10
|
+
<%- end -%>
|
4
11
|
<%% end %>
|
5
12
|
<%% end %>
|
13
|
+
<%- if query? -%>
|
6
14
|
|
7
15
|
<%%= table_query_with(collection:) %>
|
16
|
+
<%- end -%>
|
17
|
+
<%- if selectable? -%>
|
18
|
+
|
19
|
+
<%%= table_selection_with(collection:) do %>
|
20
|
+
<%- if archivable? -%>
|
21
|
+
<%%= tag.button("Archive", formaction: <%= archive_admin_helper %>, formmethod: :put, class: "button") %>
|
22
|
+
<%- end -%>
|
23
|
+
<%% end %>
|
24
|
+
<%- end -%>
|
8
25
|
|
9
26
|
<%%= table_with(collection:) do |row, <%= singular_name %>| %>
|
27
|
+
<%- if orderable? -%>
|
28
|
+
<%% row.ordinal unless collection.filtered? %>
|
29
|
+
<%- end -%>
|
30
|
+
<%- if selectable? -%>
|
31
|
+
<%% row.select %>
|
32
|
+
<%- end -%>
|
10
33
|
<%- index_attributes.each_with_index do |attribute, index| -%>
|
11
34
|
<%- if index.zero? -%>
|
12
35
|
<%% row.link :<%= attribute.name %> %>
|
@@ -15,5 +38,10 @@
|
|
15
38
|
<%- end -%>
|
16
39
|
<%- end -%>
|
17
40
|
<%% end %>
|
41
|
+
<%- if orderable? -%>
|
42
|
+
|
43
|
+
<%%= table_orderable_with(collection:, url: <%= order_admin_helper(type: :path) %>) %>
|
44
|
+
<%- elsif paginate? -%>
|
18
45
|
|
19
46
|
<%%= table_pagination_with(collection:) %>
|
47
|
+
<%- end -%>
|
@@ -1,11 +1,11 @@
|
|
1
|
-
|
2
|
-
<%%= render(Koi::Header::NewComponent.new(model: <%= class_name %>)) %>
|
3
|
-
<%% end %>
|
1
|
+
<%%# locals: (<%= singular_name %>:) %>
|
4
2
|
|
5
|
-
|
6
|
-
<%%=
|
3
|
+
<%% content_for(:header) do %>
|
4
|
+
<%%= breadcrumb_list do %>
|
5
|
+
<li><%%= link_to("<%= human_name.pluralize.titleize %>", <%= admin_index_helper %>) %></li>
|
6
|
+
<%% end %>
|
7
7
|
|
8
|
-
<
|
9
|
-
<%%= form.admin_save %>
|
10
|
-
</div>
|
8
|
+
<h1>New <%= human_name.downcase %></h1>
|
11
9
|
<%% end %>
|
10
|
+
|
11
|
+
<%%= render("form", <%= singular_name %>:) %>
|
@@ -1,22 +1,19 @@
|
|
1
|
-
|
2
|
-
<%%= render(Koi::Header::ShowComponent.new(resource: <%= singular_name %>)) %>
|
3
|
-
<%% end %>
|
1
|
+
<%%# locals: (<%= singular_name %>:) %>
|
4
2
|
|
5
|
-
|
3
|
+
<%% content_for(:header) do %>
|
4
|
+
<%%= breadcrumb_list do %>
|
5
|
+
<li><%%= link_to("<%= human_name.pluralize.titleize %>", <%= admin_index_helper %>) %></li>
|
6
|
+
<%% end %>
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
<%= summary_attribute_for attribute %>
|
13
|
-
<%- end -%>
|
14
|
-
<%- end -%>
|
8
|
+
<h1><%%= <%= singular_name %> %></h1>
|
9
|
+
|
10
|
+
<%%= actions_list do %>
|
11
|
+
<li><%%= link_to("Edit", <%= edit_admin_helper %>) %></li>
|
12
|
+
<%% end %>
|
15
13
|
<%% end %>
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
</div>
|
15
|
+
<%%= summary_table_with(model: <%= singular_name %>) do |row| %>
|
16
|
+
<%- show_attributes.each do |attribute| -%>
|
17
|
+
<%= show_attribute_for(attribute) %>
|
18
|
+
<%- end -%>
|
19
|
+
<%% end %>
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators/resource_helpers"
|
4
|
+
|
5
|
+
require_relative "attribute_types"
|
6
|
+
|
7
|
+
module Koi
|
8
|
+
module Helpers
|
9
|
+
module AttributeHelpers
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
class IntrospectedAttribute < Rails::Generators::GeneratedAttribute
|
13
|
+
attr_reader :association, :attachment, :enum
|
14
|
+
|
15
|
+
def initialize(name, type, association: nil, attachment: nil, enum: nil, **)
|
16
|
+
super(name, type, **)
|
17
|
+
|
18
|
+
@association = association
|
19
|
+
@attachment = attachment
|
20
|
+
@enum = enum
|
21
|
+
end
|
22
|
+
|
23
|
+
def association?
|
24
|
+
@association.present?
|
25
|
+
end
|
26
|
+
|
27
|
+
def attachment?
|
28
|
+
@attachment.present?
|
29
|
+
end
|
30
|
+
|
31
|
+
def enum?
|
32
|
+
@enum.present?
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize(args, *options)
|
37
|
+
super
|
38
|
+
|
39
|
+
load_attributes! if attributes.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
def govuk_input_for(attribute)
|
43
|
+
AttributeTypes.for(attribute).govuk_input
|
44
|
+
end
|
45
|
+
|
46
|
+
def index_attribute_for(attribute)
|
47
|
+
AttributeTypes.for(attribute).index_row
|
48
|
+
end
|
49
|
+
|
50
|
+
def show_attribute_for(attribute)
|
51
|
+
AttributeTypes.for(attribute).show_row
|
52
|
+
end
|
53
|
+
|
54
|
+
def collection_attribute_for(attribute)
|
55
|
+
AttributeTypes.for(attribute).collection_attribute
|
56
|
+
end
|
57
|
+
|
58
|
+
def index_attributes
|
59
|
+
attributes.select { |attribute| index_attribute_for(attribute).present? }
|
60
|
+
end
|
61
|
+
|
62
|
+
def show_attributes
|
63
|
+
attributes.select { |attribute| show_attribute_for(attribute).present? }
|
64
|
+
end
|
65
|
+
|
66
|
+
def default_sort_attribute
|
67
|
+
if orderable?
|
68
|
+
:ordinal
|
69
|
+
elsif (attribute = attributes.find { |attr| attr.type == :string })
|
70
|
+
attribute.name
|
71
|
+
else
|
72
|
+
attributes.first&.name
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def model_class
|
79
|
+
@model_class ||= class_name.safe_constantize
|
80
|
+
end
|
81
|
+
|
82
|
+
def load_attributes!
|
83
|
+
return unless model_class && model_class < ActiveRecord::Base
|
84
|
+
|
85
|
+
load_basic_attributes!
|
86
|
+
load_attachment_attributes!
|
87
|
+
load_rich_text_attributes!
|
88
|
+
load_association_attributes!
|
89
|
+
end
|
90
|
+
|
91
|
+
def load_basic_attributes!
|
92
|
+
model_class.attribute_types.each do |name, type|
|
93
|
+
next if internal_column?(name) || foreign_key_column?(name)
|
94
|
+
|
95
|
+
@attributes << IntrospectedAttribute.new(name, type.type, enum: model_class.defined_enums[name])
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def load_attachment_attributes!
|
100
|
+
return unless model_class.respond_to?(:attachment_reflections)
|
101
|
+
|
102
|
+
model_class.attachment_reflections.each do |name, attachment|
|
103
|
+
@attributes << IntrospectedAttribute.new(name, :attachment, attachment:)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def load_rich_text_attributes!
|
108
|
+
return unless model_class.respond_to?(:rich_text_association_names)
|
109
|
+
|
110
|
+
model_class.rich_text_association_names.each do |name|
|
111
|
+
@attributes << IntrospectedAttribute.new(name.to_s.gsub(/^rich_text_/, "").to_sym, :rich_text)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def load_association_attributes!
|
116
|
+
model_class.reflect_on_all_associations.each do |association|
|
117
|
+
next unless association.macro == :belongs_to
|
118
|
+
|
119
|
+
@attributes << IntrospectedAttribute.new(
|
120
|
+
association.name.to_s,
|
121
|
+
:string, # associations display as text/links
|
122
|
+
association:,
|
123
|
+
)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def attachments?(name)
|
128
|
+
attribute = attributes.find { |attr| attr.name == name }
|
129
|
+
attribute&.attachments?
|
130
|
+
end
|
131
|
+
|
132
|
+
def internal_column?(name)
|
133
|
+
%w[id created_at updated_at].include?(name.to_s)
|
134
|
+
end
|
135
|
+
|
136
|
+
def foreign_key_columns
|
137
|
+
model_class
|
138
|
+
.reflect_on_all_associations(:belongs_to)
|
139
|
+
.map(&:foreign_key)
|
140
|
+
end
|
141
|
+
|
142
|
+
def foreign_key_column?(name)
|
143
|
+
foreign_key_columns.include?(name.to_s)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|