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.
Files changed (222) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/koi/icons/add.svg +3 -0
  3. data/app/assets/images/koi/icons/close.svg +1 -0
  4. data/app/assets/images/koi/koi.png +0 -0
  5. data/app/assets/javascripts/koi/controllers/file_field_controller.js +2 -2
  6. data/app/assets/javascripts/koi/controllers/index.js +0 -3
  7. data/app/assets/javascripts/koi/controllers/koi/modal_controller.js +40 -0
  8. data/app/assets/javascripts/koi/controllers/navigation_controller.js +14 -21
  9. data/app/assets/javascripts/koi/controllers/webauthn_registration_controller.js +4 -1
  10. data/app/assets/stylesheets/koi/blocks/actions.css +8 -0
  11. data/app/assets/stylesheets/koi/blocks/application-header.css +15 -0
  12. data/app/assets/stylesheets/koi/blocks/application-navigation.css +54 -0
  13. data/app/assets/stylesheets/koi/blocks/button.css +90 -0
  14. data/app/assets/stylesheets/koi/blocks/flash.css +19 -0
  15. data/app/assets/stylesheets/koi/blocks/icon.css +15 -0
  16. data/app/assets/stylesheets/koi/blocks/index.css +13 -0
  17. data/app/assets/stylesheets/koi/blocks/modal.css +26 -0
  18. data/app/assets/stylesheets/koi/blocks/navigation.css +23 -0
  19. data/app/assets/stylesheets/koi/blocks/page-header.css +31 -0
  20. data/app/assets/stylesheets/koi/blocks/pagy.css +82 -0
  21. data/app/assets/stylesheets/koi/blocks/prose.css +37 -0
  22. data/app/assets/stylesheets/koi/blocks/tables/index.css +4 -0
  23. data/app/assets/stylesheets/koi/{components/_query.scss → blocks/tables/query.css} +13 -13
  24. data/app/assets/stylesheets/koi/{base/_tables.scss → blocks/tables/table.css} +11 -59
  25. data/app/assets/stylesheets/koi/compositions/cover.css +17 -0
  26. data/app/assets/stylesheets/koi/{base/_flow.scss → compositions/flow.css} +1 -1
  27. data/app/assets/stylesheets/koi/compositions/index.css +4 -0
  28. data/app/assets/stylesheets/koi/compositions/wrapper.css +11 -0
  29. data/app/assets/stylesheets/koi/forms/caption.css +22 -0
  30. data/app/assets/stylesheets/koi/forms/checkboxes.css +153 -0
  31. data/app/assets/stylesheets/koi/forms/date-input.css +12 -0
  32. data/app/assets/stylesheets/koi/{components/_document-field.scss → forms/document-field.css} +20 -15
  33. data/app/assets/stylesheets/koi/forms/errors.css +38 -0
  34. data/app/assets/stylesheets/koi/forms/fieldset.css +73 -0
  35. data/app/assets/stylesheets/koi/forms/file-upload.css +20 -0
  36. data/app/assets/stylesheets/koi/forms/form-group.css +19 -0
  37. data/app/assets/stylesheets/koi/forms/hint.css +11 -0
  38. data/app/assets/stylesheets/koi/forms/image-field.css +96 -0
  39. data/app/assets/stylesheets/koi/forms/index.css +44 -0
  40. data/app/assets/stylesheets/koi/forms/input.css +194 -0
  41. data/app/assets/stylesheets/koi/forms/label.css +43 -0
  42. data/app/assets/stylesheets/koi/forms/password.css +18 -0
  43. data/app/assets/stylesheets/koi/forms/radios.css +162 -0
  44. data/app/assets/stylesheets/koi/forms/select.css +18 -0
  45. data/app/assets/stylesheets/koi/forms/textarea.css +3 -0
  46. data/app/assets/stylesheets/koi/forms/trix.css +33 -0
  47. data/app/assets/stylesheets/koi/global/fonts.css +22 -0
  48. data/app/assets/stylesheets/koi/global/global-styles.css +297 -0
  49. data/app/assets/stylesheets/koi/global/reset.css +98 -0
  50. data/app/assets/stylesheets/koi/global/variables.css +97 -0
  51. data/app/assets/stylesheets/koi/icons.css +14 -0
  52. data/app/assets/stylesheets/koi/{admin.scss → index.css} +16 -7
  53. data/app/assets/stylesheets/koi/login.css +26 -0
  54. data/app/assets/stylesheets/koi/themes/_index.scss +0 -1
  55. data/app/assets/stylesheets/koi/utilities/index.css +1 -0
  56. data/app/assets/stylesheets/koi/utilities/visually-hidden.css +18 -0
  57. data/app/components/concerns/koi/tables/cells.rb +3 -3
  58. data/app/components/koi/header/edit_component.rb +1 -1
  59. data/app/components/koi/header/index_component.rb +1 -1
  60. data/app/components/koi/header/new_component.rb +1 -1
  61. data/app/components/koi/header/show_component.rb +1 -1
  62. data/app/components/koi/header_component.html.erb +12 -11
  63. data/app/components/koi/header_component.rb +4 -2
  64. data/app/components/koi/table_component.rb +8 -0
  65. data/app/controllers/admin/admin_users_controller.rb +24 -18
  66. data/app/controllers/admin/application_controller.rb +1 -3
  67. data/app/controllers/admin/credentials_controller.rb +18 -14
  68. data/app/controllers/admin/otps_controller.rb +15 -13
  69. data/app/controllers/admin/sessions_controller.rb +12 -1
  70. data/app/controllers/admin/url_rewrites_controller.rb +19 -17
  71. data/app/controllers/admin/well_knowns_controller.rb +20 -18
  72. data/app/controllers/concerns/koi/controller.rb +37 -0
  73. data/app/helpers/koi/form_helper.rb +18 -0
  74. data/app/helpers/koi/header_helper.rb +122 -0
  75. data/app/helpers/koi/index_actions_helper.rb +3 -2
  76. data/app/helpers/koi/modal_helper.rb +71 -0
  77. data/app/models/admin/user.rb +7 -1
  78. data/app/models/url_rewrite.rb +1 -9
  79. data/app/views/admin/admin_users/_form.html+self.erb +8 -0
  80. data/app/views/admin/admin_users/_form.html.erb +8 -0
  81. data/app/views/admin/admin_users/archived.html.erb +7 -4
  82. data/app/views/admin/admin_users/edit.html+self.erb +12 -0
  83. data/app/views/admin/admin_users/edit.html.erb +13 -8
  84. data/app/views/admin/admin_users/index.html.erb +10 -5
  85. data/app/views/admin/admin_users/new.html.erb +8 -8
  86. data/app/views/admin/admin_users/show.html+self.erb +26 -14
  87. data/app/views/admin/admin_users/show.html.erb +22 -20
  88. data/app/views/admin/credentials/_credentials.html+self.erb +8 -6
  89. data/app/views/admin/credentials/_credentials.html.erb +3 -1
  90. data/app/views/admin/credentials/create.turbo_stream.erb +4 -3
  91. data/app/views/admin/credentials/destroy.turbo_stream.erb +4 -2
  92. data/app/views/admin/credentials/new.html.erb +42 -36
  93. data/app/views/admin/dashboards/show.html.erb +13 -1
  94. data/app/views/admin/otps/_form.html.erb +7 -7
  95. data/app/views/admin/otps/create.turbo_stream.erb +3 -3
  96. data/app/views/admin/otps/new.html.erb +5 -3
  97. data/app/views/admin/sessions/new.html.erb +2 -3
  98. data/app/views/admin/sessions/otp.html.erb +1 -3
  99. data/app/views/admin/sessions/password.html.erb +1 -3
  100. data/app/views/admin/tokens/show.html.erb +4 -6
  101. data/app/views/admin/url_rewrites/_form.html.erb +9 -0
  102. data/app/views/admin/url_rewrites/edit.html.erb +13 -9
  103. data/app/views/admin/url_rewrites/index.html.erb +10 -7
  104. data/app/views/admin/url_rewrites/new.html.erb +8 -8
  105. data/app/views/admin/url_rewrites/show.html.erb +17 -12
  106. data/app/views/admin/well_knowns/_form.html.erb +9 -0
  107. data/app/views/admin/well_knowns/edit.html.erb +13 -9
  108. data/app/views/admin/well_knowns/index.html.erb +8 -5
  109. data/app/views/admin/well_knowns/new.html.erb +8 -8
  110. data/app/views/admin/well_knowns/show.html.erb +14 -13
  111. data/app/views/katalyst/content/asides/_aside.html+form.erb +6 -4
  112. data/app/views/katalyst/content/columns/_column.html+form.erb +5 -3
  113. data/app/views/katalyst/content/contents/_content.html+form.erb +8 -6
  114. data/app/views/katalyst/content/figures/_figure.html+form.erb +8 -5
  115. data/app/views/katalyst/content/groups/_group.html+form.erb +5 -3
  116. data/app/views/katalyst/content/items/_item.html+form.erb +5 -3
  117. data/app/views/katalyst/content/sections/_section.html+form.erb +5 -3
  118. data/app/views/katalyst/content/tables/_table.html+form.erb +16 -11
  119. data/app/views/katalyst/navigation/items/_button.html.erb +6 -12
  120. data/app/views/katalyst/navigation/items/_heading.html.erb +3 -10
  121. data/app/views/katalyst/navigation/items/_link.html.erb +6 -11
  122. data/app/views/katalyst/navigation/menus/edit.html.erb +10 -6
  123. data/app/views/katalyst/navigation/menus/index.html.erb +4 -2
  124. data/app/views/katalyst/navigation/menus/new.html.erb +5 -3
  125. data/app/views/katalyst/navigation/menus/show.html.erb +8 -7
  126. data/app/views/layouts/koi/_application_header.html.erb +20 -0
  127. data/app/views/layouts/koi/_application_navigation.html.erb +34 -0
  128. data/app/views/layouts/koi/_flash.html.erb +6 -3
  129. data/app/views/layouts/koi/_navigation_header.html.erb +0 -2
  130. data/app/views/layouts/koi/application.html.erb +22 -27
  131. data/app/views/layouts/koi/frame.html.erb +1 -3
  132. data/app/views/layouts/koi/login.html.erb +12 -5
  133. data/config/locales/koi.en.yml +9 -1
  134. data/config/routes.rb +1 -1
  135. data/lib/generators/koi/admin/admin_generator.rb +3 -12
  136. data/lib/generators/koi/admin_controller/admin_controller_generator.rb +6 -16
  137. data/lib/generators/koi/admin_controller/templates/controller.rb.tt +82 -18
  138. data/lib/generators/koi/admin_controller/templates/controller_spec.rb.tt +113 -47
  139. data/lib/generators/koi/admin_route/admin_route_generator.rb +60 -6
  140. data/lib/generators/koi/admin_views/USAGE +18 -7
  141. data/lib/generators/koi/admin_views/admin_views_generator.rb +19 -11
  142. data/lib/generators/koi/admin_views/templates/_form.html.erb.tt +8 -0
  143. data/lib/generators/koi/admin_views/templates/archived.html.erb.tt +33 -0
  144. data/lib/generators/koi/admin_views/templates/edit.html.erb.tt +17 -9
  145. data/lib/generators/koi/admin_views/templates/index.html.erb.tt +31 -3
  146. data/lib/generators/koi/admin_views/templates/new.html.erb.tt +8 -8
  147. data/lib/generators/koi/admin_views/templates/show.html.erb.tt +15 -18
  148. data/lib/generators/koi/helpers/attribute_helpers.rb +147 -0
  149. data/lib/generators/koi/helpers/attribute_types.rb +218 -0
  150. data/lib/generators/koi/helpers/resource_helpers.rb +121 -0
  151. data/lib/generators/koi/{active_record/active_record_generator.rb → model/model_generator.rb} +1 -1
  152. data/lib/koi/config.rb +3 -1
  153. data/lib/koi/engine.rb +0 -9
  154. data/lib/koi/form/builder.rb +4 -4
  155. data/lib/koi/form/content.rb +55 -0
  156. data/lib/koi/form/elements/document.rb +1 -1
  157. data/lib/koi/form/elements/image.rb +1 -1
  158. data/lib/koi/form_builder.rb +1 -0
  159. data/lib/koi/menu.rb +14 -1
  160. data/spec/factories/admins.rb +1 -1
  161. metadata +92 -101
  162. data/app/assets/builds/koi/admin.css +0 -1
  163. data/app/assets/stylesheets/koi/base/_button.scss +0 -122
  164. data/app/assets/stylesheets/koi/base/_icon.scss +0 -29
  165. data/app/assets/stylesheets/koi/base/_index.scss +0 -21
  166. data/app/assets/stylesheets/koi/base/_input.scss +0 -19
  167. data/app/assets/stylesheets/koi/base/_link.scss +0 -26
  168. data/app/assets/stylesheets/koi/base/_list.scss +0 -11
  169. data/app/assets/stylesheets/koi/base/_typography.scss +0 -160
  170. data/app/assets/stylesheets/koi/components/_actions-group.scss +0 -7
  171. data/app/assets/stylesheets/koi/components/_image-field.scss +0 -95
  172. data/app/assets/stylesheets/koi/components/_index.scss +0 -9
  173. data/app/assets/stylesheets/koi/components/_pagy.scss +0 -29
  174. data/app/assets/stylesheets/koi/components/_summary-list.scss +0 -40
  175. data/app/assets/stylesheets/koi/layouts/_banner.scss +0 -7
  176. data/app/assets/stylesheets/koi/layouts/_content.scss +0 -40
  177. data/app/assets/stylesheets/koi/layouts/_flash.scss +0 -41
  178. data/app/assets/stylesheets/koi/layouts/_header.scss +0 -61
  179. data/app/assets/stylesheets/koi/layouts/_index.scss +0 -48
  180. data/app/assets/stylesheets/koi/layouts/_main.scss +0 -23
  181. data/app/assets/stylesheets/koi/layouts/_navigation.scss +0 -180
  182. data/app/assets/stylesheets/koi/layouts/_stack.scss +0 -13
  183. data/app/assets/stylesheets/koi/pages/_index.scss +0 -1
  184. data/app/assets/stylesheets/koi/pages/_login.scss +0 -46
  185. data/app/assets/stylesheets/koi/themes/_govuk.scss +0 -56
  186. data/app/assets/stylesheets/koi/themes/_kpop.scss +0 -5
  187. data/app/assets/stylesheets/koi/utils/_breakpoints.scss +0 -13
  188. data/app/assets/stylesheets/koi/utils/_hide.scss +0 -11
  189. data/app/assets/stylesheets/koi/utils/_index.scss +0 -2
  190. data/app/assets/stylesheets/koi/utils/_typography.scss +0 -42
  191. data/app/components/koi/content/editor/item_form_component.html.erb +0 -11
  192. data/app/components/koi/content/editor/item_form_component.rb +0 -94
  193. data/app/components/koi/summary_list/attachment_component.rb +0 -47
  194. data/app/components/koi/summary_list/base.rb +0 -59
  195. data/app/components/koi/summary_list/boolean_component.rb +0 -15
  196. data/app/components/koi/summary_list/date_component.rb +0 -17
  197. data/app/components/koi/summary_list/datetime_component.rb +0 -17
  198. data/app/components/koi/summary_list/item_component.rb +0 -26
  199. data/app/components/koi/summary_list/number_component.rb +0 -21
  200. data/app/components/koi/summary_list/rich_text_component.rb +0 -8
  201. data/app/components/koi/summary_list/text_component.rb +0 -8
  202. data/app/components/koi/summary_list_component.html.erb +0 -5
  203. data/app/components/koi/summary_list_component.rb +0 -75
  204. data/app/controllers/concerns/koi/controller/is_admin_controller.rb +0 -66
  205. data/app/helpers/koi/application_helper.rb +0 -7
  206. data/app/helpers/koi/date_helper.rb +0 -26
  207. data/app/helpers/koi/definition_list_helper.rb +0 -10
  208. data/app/views/admin/admin_users/_fields.html+self.erb +0 -3
  209. data/app/views/admin/admin_users/_fields.html.erb +0 -3
  210. data/app/views/admin/url_rewrites/_fields.html.erb +0 -4
  211. data/app/views/admin/well_knowns/_fields.html.erb +0 -6
  212. data/app/views/layouts/koi/_environment.html.erb +0 -4
  213. data/app/views/layouts/koi/_header.html.erb +0 -11
  214. data/app/views/layouts/koi/_navigation.html.erb +0 -23
  215. data/app/views/layouts/koi/_navigation_collapse.html.erb +0 -3
  216. data/lib/generators/koi/admin_views/templates/_fields.html.erb.tt +0 -3
  217. data/lib/generators/koi/helpers/admin_generator_attributes.rb +0 -66
  218. data/lib/koi/extensions/dartsass.rb +0 -23
  219. /data/app/assets/stylesheets/koi/{components/_clipboard.scss → blocks/clipboard.css} +0 -0
  220. /data/app/assets/stylesheets/koi/{components/_index-actions.scss → blocks/index-actions.css} +0 -0
  221. /data/app/assets/stylesheets/koi/{components/_toolbar.scss → blocks/toolbar.css} +0 -0
  222. /data/app/assets/stylesheets/koi/{base/_repel.scss → compositions/repel.css} +0 -0
@@ -0,0 +1,218 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Koi
4
+ module Helpers
5
+ module AttributeTypes
6
+ class Base
7
+ attr_reader :attribute
8
+
9
+ def initialize(attribute)
10
+ @attribute = attribute
11
+ end
12
+
13
+ def govuk_input
14
+ nil
15
+ end
16
+
17
+ def index_row
18
+ nil
19
+ end
20
+
21
+ def show_row
22
+ nil
23
+ end
24
+
25
+ def collection_attribute
26
+ nil
27
+ end
28
+ end
29
+
30
+ class StringType < Base
31
+ def govuk_input
32
+ %(<%= form.govuk_text_field :#{attribute.name} %>)
33
+ end
34
+
35
+ def index_row
36
+ %(<% row.text :#{attribute.name} %>)
37
+ end
38
+
39
+ def show_row
40
+ %(<% row.text :#{attribute.name} %>)
41
+ end
42
+
43
+ def collection_attribute
44
+ %(attribute :#{attribute.name}, :string)
45
+ end
46
+ end
47
+
48
+ class IntegerType < Base
49
+ def govuk_input
50
+ %(<%= form.govuk_number_field :#{attribute.name} %>)
51
+ end
52
+
53
+ def index_row
54
+ %(<% row.number :#{attribute.name} %>)
55
+ end
56
+
57
+ def show_row
58
+ %(<% row.number :#{attribute.name} %>)
59
+ end
60
+
61
+ def collection_attribute
62
+ %(attribute :#{attribute.name}, :integer)
63
+ end
64
+ end
65
+
66
+ class BooleanType < Base
67
+ def govuk_input
68
+ %(<%= form.govuk_check_box_field :#{attribute.name} %>)
69
+ end
70
+
71
+ def index_row
72
+ %(<% row.boolean :#{attribute.name} %>)
73
+ end
74
+
75
+ def show_row
76
+ %(<% row.boolean :#{attribute.name} %>)
77
+ end
78
+
79
+ def collection_attribute
80
+ %(attribute :#{attribute.name}, :boolean)
81
+ end
82
+ end
83
+
84
+ class DateType < Base
85
+ def govuk_input
86
+ %(<%= form.govuk_date_field :#{attribute.name} %>)
87
+ end
88
+
89
+ def index_row
90
+ %(<% row.date :#{attribute.name} %>)
91
+ end
92
+
93
+ def show_row
94
+ %(<% row.date :#{attribute.name} %>)
95
+ end
96
+
97
+ def collection_attribute
98
+ %(attribute :#{attribute.name}, :date)
99
+ end
100
+ end
101
+
102
+ class DatetimeType < Base
103
+ def index_row
104
+ %(<% row.datetime :#{attribute.name} %>)
105
+ end
106
+
107
+ def show_row
108
+ %(<% row.datetime :#{attribute.name} %>)
109
+ end
110
+
111
+ def collection_attribute
112
+ %(attribute :#{attribute.name}, :date)
113
+ end
114
+ end
115
+
116
+ class RichTextType < Base
117
+ def govuk_input
118
+ %(<%= form.govuk_rich_text_area :#{attribute.name} %>)
119
+ end
120
+
121
+ def show_row
122
+ %(<% row.rich_text :#{attribute.name} %>)
123
+ end
124
+ end
125
+
126
+ class AttachmentType < Base
127
+ def govuk_input
128
+ %(<%= form.govuk_image_field :#{attribute.name} %>)
129
+ end
130
+
131
+ def show_row
132
+ %(<% row.attachment :#{attribute.name} %>)
133
+ end
134
+ end
135
+
136
+ class AssociationType < Base
137
+ def show_row
138
+ %(<% row.link :#{attribute.name} %>)
139
+ end
140
+ end
141
+
142
+ class EnumType < Base
143
+ def govuk_input
144
+ %(<%= form.govuk_enum_select :#{attribute.name} %>)
145
+ end
146
+
147
+ def index_row
148
+ %(<% row.enum :#{attribute.name} %>)
149
+ end
150
+
151
+ def show_row
152
+ %(<% row.enum :#{attribute.name} %>)
153
+ end
154
+
155
+ def collection_attribute
156
+ %(attribute :#{attribute.name}, :enum)
157
+ end
158
+ end
159
+
160
+ class OrdinalType < Base
161
+ end
162
+
163
+ class ArchivedType < Base
164
+ def show_row
165
+ %(<% row.boolean :archived %>)
166
+ end
167
+ end
168
+
169
+ module GeneratedAttributeExtensions
170
+ refine Rails::Generators::GeneratedAttribute do
171
+ def attachment?
172
+ false
173
+ end
174
+
175
+ def association?
176
+ %i[belongs_to references].include?(type)
177
+ end
178
+
179
+ def enum?
180
+ false
181
+ end
182
+ end
183
+ end
184
+
185
+ TYPES = {
186
+ string: StringType,
187
+ integer: IntegerType,
188
+ boolean: BooleanType,
189
+ date: DateType,
190
+ datetime: DatetimeType,
191
+ rich_text: RichTextType,
192
+ text: StringType,
193
+ attachment: AttachmentType,
194
+ enum: EnumType,
195
+ }.freeze
196
+
197
+ using GeneratedAttributeExtensions
198
+
199
+ def for(attribute)
200
+ if attribute.association?
201
+ AssociationType.new(attribute)
202
+ elsif attribute.attachment?
203
+ AttachmentType.new(attribute)
204
+ elsif attribute.enum?
205
+ EnumType.new(attribute)
206
+ elsif attribute.name == "ordinal"
207
+ OrdinalType.new(attribute)
208
+ elsif attribute.name == "archived_at"
209
+ ArchivedType.new(attribute)
210
+ else
211
+ TYPES.fetch(attribute.type, StringType).new(attribute)
212
+ end
213
+ end
214
+
215
+ module_function :for
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "attribute_types"
4
+
5
+ module Koi
6
+ module Helpers
7
+ module ResourceHelpers
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ include Rails::Generators::ResourceHelpers
12
+
13
+ private
14
+
15
+ def assign_controller_names!(name)
16
+ super
17
+ @controller_class_path = ["admin", *@controller_class_path]
18
+ end
19
+
20
+ def class_name
21
+ candidate = (class_path + [file_name]).map!(&:camelize).join("::")
22
+ if class_path_overlap.any?
23
+ "::#{candidate}"
24
+ else
25
+ candidate
26
+ end
27
+ end
28
+
29
+ def singular_route_name
30
+ parts = controller_class_path
31
+
32
+ # Gradually remove suffix parts from the prefix if they appear at the beginning of singular_table_name
33
+ (0..parts.count).detect do |n|
34
+ trial = parts.drop(n).join("_")
35
+ return "#{parts.take(n).join('_')}_#{singular_table_name}" if singular_table_name.start_with?(trial)
36
+ end
37
+ end
38
+
39
+ def plural_route_name
40
+ parts = controller_class_path
41
+
42
+ # Gradually remove suffix parts from the prefix if they appear at the beginning of plural_table_name
43
+ (0..parts.count).detect do |n|
44
+ trial = parts.drop(n).join("_")
45
+ return "#{parts.take(n).join('_')}_#{plural_table_name}" if plural_table_name.start_with?(trial)
46
+ end
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def archivable?
53
+ model_class&.included_modules&.include?(Koi::Model::Archivable)
54
+ end
55
+
56
+ def orderable?
57
+ attributes_names.include?("ordinal")
58
+ end
59
+
60
+ def paginate?
61
+ !orderable?
62
+ end
63
+
64
+ def selectable?
65
+ archivable?
66
+ end
67
+
68
+ def sortable?
69
+ default_sort_attribute.present?
70
+ end
71
+
72
+ def query?
73
+ true
74
+ end
75
+
76
+ def admin_index_helper(type: :path)
77
+ "#{plural_route_name}_#{type}"
78
+ end
79
+
80
+ def archive_admin_helper(type: :path)
81
+ "archive_#{plural_route_name}_#{type}"
82
+ end
83
+
84
+ def archived_admin_helper(type: :path)
85
+ "archived_#{plural_route_name}_#{type}"
86
+ end
87
+
88
+ def admin_show_helper(identifier = singular_name, type: :path)
89
+ "#{singular_route_name}_#{type}(#{identifier})"
90
+ end
91
+
92
+ def edit_admin_helper(identifier = singular_name, type: :path)
93
+ "edit_#{admin_show_helper(identifier, type:)}"
94
+ end
95
+
96
+ def new_admin_helper(type: :path)
97
+ "new_#{singular_route_name}_#{type}"
98
+ end
99
+
100
+ def order_admin_helper(type: :path)
101
+ "order_#{plural_route_name}_#{type}"
102
+ end
103
+
104
+ def restore_admin_helper(type: :path)
105
+ "restore_#{plural_route_name}_#{type}"
106
+ end
107
+
108
+ def class_path_overlap(controller = controller_class_path, model = class_path)
109
+ return [] unless controller.present? && model.present?
110
+
111
+ limit = [controller.size, model.size].min
112
+
113
+ (1..limit).reverse_each do |size|
114
+ return model.slice(0...size) if controller.slice(size - 1..-1) == model.slice(0...size)
115
+ end
116
+
117
+ []
118
+ end
119
+ end
120
+ end
121
+ end
@@ -3,7 +3,7 @@
3
3
  require "rails/generators/active_record/model/model_generator"
4
4
 
5
5
  module Koi
6
- class ActiveRecordGenerator < ActiveRecord::Generators::ModelGenerator
6
+ class ModelGenerator < ActiveRecord::Generators::ModelGenerator
7
7
  source_root ActiveRecord::Generators::ModelGenerator.source_root
8
8
 
9
9
  def admin_search
data/lib/koi/config.rb CHANGED
@@ -9,9 +9,11 @@ module Koi
9
9
 
10
10
  config_accessor(:admin_name) { "Koi" }
11
11
 
12
+ config_accessor(:authenticate_local_admins) { Rails.env.development? }
13
+
12
14
  config_accessor(:resource_name_candidates) { %i[title name] }
13
15
 
14
- config_accessor(:admin_stylesheet) { "koi/admin" }
16
+ config_accessor(:admin_stylesheet) { "admin" }
15
17
 
16
18
  config_accessor(:document_mime_types) do
17
19
  %w[image/png image/gif image/jpeg image/webp application/pdf audio/*].freeze
data/lib/koi/engine.rb CHANGED
@@ -3,7 +3,6 @@
3
3
  require "importmap-rails"
4
4
  require "katalyst/content"
5
5
  require "katalyst/govuk/formbuilder"
6
- require "katalyst/kpop"
7
6
  require "katalyst/navigation"
8
7
  require "katalyst/tables"
9
8
  require "pagy"
@@ -38,14 +37,6 @@ module Koi
38
37
  Katalyst::Content.config.errors_component = "Koi::Content::Editor::ErrorsComponent"
39
38
  end
40
39
 
41
- # Koi (& katalyst gems) generate css assets in build that are useful for non-sass consumers, but we don't
42
- # want them getting picked up preferentially by dartsass over their similarly named scss counterparts.
43
- initializer "koi.dartsass" do |app|
44
- app.config.after_initialize do
45
- ::Dartsass::Runner.include(Koi::Extensions::Dartsass) if defined?(::Dartsass::Runner)
46
- end
47
- end
48
-
49
40
  initializer "koi.factories", after: "factory_bot.set_factory_paths" do
50
41
  FactoryBot.definition_file_paths << root.join("spec/factories") if defined?(FactoryBot)
51
42
  end
@@ -10,7 +10,7 @@ module Koi
10
10
  end
11
11
 
12
12
  # Generates a submit button for saving admin resources.
13
- def admin_save(text = "Save", name: :commit, value: :save, class: "button button--primary", **)
13
+ def admin_save(text = "Save", name: :commit, value: :save, class: "button", **)
14
14
  button(text, name:, value:, class:, **)
15
15
  end
16
16
 
@@ -20,8 +20,8 @@ module Koi
20
20
  return unless object.persisted?
21
21
 
22
22
  link_to(text, url || url_for(action: :destroy),
23
- class: "button button--secondary",
24
- data: data.reverse_merge(turbo_method: :delete, turbo_confirm: confirm),
23
+ class: "button",
24
+ data: data.reverse_merge(turbo_method: :delete, turbo_confirm: confirm, ghost_button: ""),
25
25
  **)
26
26
  end
27
27
 
@@ -34,7 +34,7 @@ module Koi
34
34
  # Generates a discard changes link formatted as a text button that navigates
35
35
  # the user back to the previous page.
36
36
  def admin_discard(text = "Discard", url: :back, **)
37
- link_to(text, url, class: "button button--text", **)
37
+ link_to(text, url, class: "button", data: { text_button: "" }, **)
38
38
  end
39
39
 
40
40
  # @api internal
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Koi
4
+ module Form
5
+ module Content
6
+ extend ActiveSupport::Concern
7
+
8
+ def content_heading_fieldset
9
+ govuk_fieldset(legend: { text: "Heading", size: "m" }) do
10
+ concat(content_heading_field(label: nil))
11
+ concat(content_heading_style_field)
12
+ end
13
+ end
14
+
15
+ def content_heading_field(args = {})
16
+ govuk_text_field(:heading,
17
+ **{ label: { text: "Heading", size: "s" } }.deep_merge(args))
18
+ end
19
+
20
+ def content_heading_style_field(args = {})
21
+ govuk_collection_radio_buttons(:heading_style,
22
+ Katalyst::Content.config.heading_styles,
23
+ :itself,
24
+ :itself,
25
+ **{ small: true, legend: { text: "Style", size: "s" } }.deep_merge(args))
26
+ end
27
+
28
+ def content_url_field(args = {})
29
+ govuk_text_field(:url,
30
+ **{ label: { text: "URL", size: "s" } }.deep_merge(args))
31
+ end
32
+
33
+ def content_http_method_field(methods, args = {})
34
+ govuk_select(:http_method, methods,
35
+ **{ label: { text: "HTTP method", size: "s" } }.deep_merge(args))
36
+ end
37
+
38
+ def content_target_field(targets, args = {})
39
+ govuk_select(:target, targets,
40
+ **{ label: { text: "HTTP target", size: "s" } }.deep_merge(args))
41
+ end
42
+
43
+ def content_theme_field(args = {})
44
+ govuk_select(:theme, Katalyst::Content.config.themes,
45
+ **{ label: { size: "s" }, options: { include_blank: true } }.deep_merge(args))
46
+ end
47
+ alias_method :content_background_field, :content_theme_field
48
+
49
+ def content_visible_field(args = {})
50
+ govuk_check_box_field(:visible,
51
+ **{ label: { text: "Visible? ", size: "s" }, small: true }.deep_merge(args))
52
+ end
53
+ end
54
+ end
55
+ end
@@ -24,7 +24,7 @@ module Koi
24
24
  options = {}
25
25
  add_option(options, :data, "#{stimulus_controller}_target", "preview")
26
26
  add_option(options, :class, "preview-file")
27
- add_option(options, :class, "hidden") unless preview?
27
+ options[:hidden] = "" unless preview?
28
28
 
29
29
  tag.div(**options) do
30
30
  filename = @builder.object.send(@attribute_name).filename.to_s
@@ -22,7 +22,7 @@ module Koi
22
22
  options = {}
23
23
  add_option(options, :data, "#{stimulus_controller}_target", "preview")
24
24
  add_option(options, :class, "preview-image")
25
- add_option(options, :class, "hidden") unless preview?
25
+ options[:hidden] = "" unless preview?
26
26
 
27
27
  tag.div(**options) do
28
28
  tag.img(src: preview_url, class: "image-thumbnail") + destroy_element_trigger
@@ -4,5 +4,6 @@ module Koi
4
4
  class FormBuilder < ActionView::Helpers::FormBuilder
5
5
  include GOVUKDesignSystemFormBuilder::Builder
6
6
  include Koi::Form::Builder
7
+ include Koi::Form::Content
7
8
  end
8
9
  end
data/lib/koi/menu.rb CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Koi
4
4
  module Menu
5
+ mattr_accessor :quick_links
6
+ @@quick_links = {}
7
+
5
8
  mattr_accessor :priority
6
9
  @@priority = {}
7
10
 
@@ -14,7 +17,7 @@ module Koi
14
17
  def admin_menu(context)
15
18
  builder = Builder.new
16
19
  builder.add_menu(title: "Priority") do |b|
17
- b.add_link(title: "View site", url: "/", target: :blank)
20
+ b.add_link(title: "View website", url: "/", target: :blank)
18
21
  b.add_link(title: "Dashboard", url: context.main_app.admin_dashboard_path)
19
22
  b.add_items(priority)
20
23
  end
@@ -38,6 +41,16 @@ module Koi
38
41
  builder.render
39
42
  end
40
43
 
44
+ def dashboard_menu
45
+ builder = Builder.new
46
+ builder.add_menu(title: "Quick links") do |b|
47
+ b.add_link(title: "View website", url: "/", target: :blank)
48
+ b.add_items(quick_links)
49
+ end
50
+ builder.render
51
+ end
52
+
41
53
  module_function(:admin_menu)
54
+ module_function(:dashboard_menu)
42
55
  end
43
56
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  FactoryBot.define do
4
- factory :admin, class: "Admin::User" do
4
+ factory :admin_user, aliases: %i[admin], class: "Admin::User" do
5
5
  email { Faker::Internet.email }
6
6
  name { Faker::Name.name }
7
7
  password { Faker::Internet.password }