headmin 0.2.5 → 0.3.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 (264) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -3
  3. data/Gemfile.lock +13 -2
  4. data/README.md +64 -57
  5. data/app/assets/config/headmin_manifest.js +2 -0
  6. data/app/assets/javascripts/headmin/config/i18n.js +11 -0
  7. data/{src/js → app/assets/javascripts}/headmin/controllers/blocks_controller.js +1 -2
  8. data/app/assets/javascripts/headmin/controllers/date_range_controller.js +32 -0
  9. data/app/assets/javascripts/headmin/controllers/dropzone_controller.js +33 -0
  10. data/app/assets/javascripts/headmin/controllers/file_preview_controller.js +244 -0
  11. data/{src/js → app/assets/javascripts}/headmin/controllers/filter_controller.js +13 -7
  12. data/{src/js → app/assets/javascripts}/headmin/controllers/filters_controller.js +1 -1
  13. data/app/assets/javascripts/headmin/controllers/flatpickr_controller.js +39 -0
  14. data/app/assets/javascripts/headmin/controllers/hello_controller.js +7 -0
  15. data/app/assets/javascripts/headmin/controllers/notification_controller.js +8 -0
  16. data/{src/js → app/assets/javascripts}/headmin/controllers/popup_controller.js +1 -2
  17. data/app/assets/javascripts/headmin/controllers/redactorx_controller.js +13 -0
  18. data/{src/js → app/assets/javascripts}/headmin/controllers/repeater_controller.js +8 -9
  19. data/app/assets/javascripts/headmin/controllers/select_controller.js +48 -0
  20. data/app/assets/javascripts/headmin/controllers/table_actions_controller.js +98 -0
  21. data/app/assets/javascripts/headmin/controllers/table_controller.js +110 -0
  22. data/app/assets/javascripts/headmin/index.js +41 -0
  23. data/app/assets/javascripts/headmin.js +15934 -0
  24. data/{src/scss → app/assets/stylesheets}/headmin/filter.scss +0 -0
  25. data/{src/scss → app/assets/stylesheets}/headmin/filters.scss +0 -0
  26. data/{src/scss → app/assets/stylesheets}/headmin/form.scss +55 -2
  27. data/{src/scss → app/assets/stylesheets}/headmin/general.scss +0 -0
  28. data/{src/scss → app/assets/stylesheets}/headmin/layout/body.scss +0 -0
  29. data/{src/scss → app/assets/stylesheets}/headmin/layout/sidebar.scss +0 -0
  30. data/{src/scss → app/assets/stylesheets}/headmin/layout.scss +0 -0
  31. data/{src/scss → app/assets/stylesheets}/headmin/login.scss +0 -0
  32. data/{src/scss/vendor/bootstrap/variables.scss → app/assets/stylesheets/headmin/overrides/bootstrap.scss} +0 -0
  33. data/{src/scss/vendor/redactorx/override.css → app/assets/stylesheets/headmin/overrides/redactorx.css} +0 -0
  34. data/{src/scss → app/assets/stylesheets}/headmin/popup.scss +0 -0
  35. data/app/assets/stylesheets/headmin/syntax.scss +349 -0
  36. data/{src/scss → app/assets/stylesheets}/headmin/table.scss +1 -0
  37. data/app/assets/stylesheets/headmin/thumbnail.scss +20 -0
  38. data/app/assets/stylesheets/headmin/utilities.scss +68 -0
  39. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_accordion.scss +118 -0
  40. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_alert.scss +57 -0
  41. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_badge.scss +29 -0
  42. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_breadcrumb.scss +28 -0
  43. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_button-group.scss +139 -0
  44. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_buttons.scss +111 -0
  45. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_card.scss +216 -0
  46. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_carousel.scss +229 -0
  47. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_close.scss +40 -0
  48. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_containers.scss +41 -0
  49. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_dropdown.scss +240 -0
  50. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_forms.scss +9 -0
  51. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_functions.scss +302 -0
  52. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_grid.scss +33 -0
  53. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_helpers.scss +9 -0
  54. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_images.scss +42 -0
  55. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_list-group.scss +174 -0
  56. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_mixins.scss +43 -0
  57. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_modal.scss +209 -0
  58. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_nav.scss +139 -0
  59. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_navbar.scss +335 -0
  60. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_offcanvas.scss +83 -0
  61. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_pagination.scss +64 -0
  62. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_placeholders.scss +51 -0
  63. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_popover.scss +158 -0
  64. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_progress.scss +48 -0
  65. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_reboot.scss +625 -0
  66. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_root.scss +54 -0
  67. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_spinners.scss +69 -0
  68. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_tables.scss +155 -0
  69. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_toasts.scss +51 -0
  70. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_tooltip.scss +115 -0
  71. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_transitions.scss +27 -0
  72. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_type.scss +104 -0
  73. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_utilities.scss +630 -0
  74. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/_variables.scss +1641 -0
  75. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/bootstrap-grid.scss +67 -0
  76. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/bootstrap-reboot.scss +13 -0
  77. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/bootstrap-utilities.scss +18 -0
  78. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/bootstrap.scss +53 -0
  79. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/forms/_floating-labels.scss +63 -0
  80. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/forms/_form-check.scss +152 -0
  81. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/forms/_form-control.scss +219 -0
  82. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/forms/_form-range.scss +91 -0
  83. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/forms/_form-select.scss +72 -0
  84. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/forms/_form-text.scss +11 -0
  85. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/forms/_input-group.scss +121 -0
  86. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/forms/_labels.scss +36 -0
  87. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/forms/_validation.scss +12 -0
  88. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/helpers/_clearfix.scss +3 -0
  89. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/helpers/_colored-links.scss +12 -0
  90. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/helpers/_position.scss +30 -0
  91. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/helpers/_ratio.scss +26 -0
  92. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/helpers/_stacks.scss +15 -0
  93. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/helpers/_stretched-link.scss +15 -0
  94. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/helpers/_text-truncation.scss +7 -0
  95. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/helpers/_visually-hidden.scss +8 -0
  96. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/helpers/_vr.scss +8 -0
  97. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_alert.scss +11 -0
  98. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_backdrop.scss +14 -0
  99. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_border-radius.scss +78 -0
  100. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_box-shadow.scss +18 -0
  101. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_breakpoints.scss +127 -0
  102. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_buttons.scss +133 -0
  103. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_caret.scss +64 -0
  104. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_clearfix.scss +9 -0
  105. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_color-scheme.scss +7 -0
  106. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_container.scss +9 -0
  107. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_deprecate.scss +10 -0
  108. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_forms.scss +144 -0
  109. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_gradients.scss +47 -0
  110. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_grid.scss +151 -0
  111. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_image.scss +16 -0
  112. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_list-group.scss +24 -0
  113. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_lists.scss +7 -0
  114. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_pagination.scss +31 -0
  115. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_reset-text.scss +17 -0
  116. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_resize.scss +6 -0
  117. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_table-variants.scss +21 -0
  118. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_text-truncate.scss +8 -0
  119. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_transition.scss +26 -0
  120. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_utilities.scss +89 -0
  121. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/mixins/_visually-hidden.scss +29 -0
  122. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/utilities/_api.scss +47 -0
  123. data/app/assets/stylesheets/headmin/vendor/bootstrap/scss/vendor/_rfs.scss +354 -0
  124. data/app/assets/stylesheets/headmin/vendor/flatpickr.css +903 -0
  125. data/{src/scss/vendor/redactorx → app/assets/stylesheets/headmin/vendor}/redactorx.css +0 -0
  126. data/app/assets/stylesheets/headmin/vendor/tom-select-bootstrap.css +537 -0
  127. data/app/assets/stylesheets/headmin.css +13454 -0
  128. data/app/assets/stylesheets/headmin.scss +65 -0
  129. data/app/helpers/headmin/admin_helper.rb +4 -59
  130. data/app/helpers/headmin/bootstrap_helper.rb +31 -0
  131. data/app/helpers/headmin/documentation_helper.rb +35 -0
  132. data/app/helpers/headmin/filter_helper.rb +7 -3
  133. data/app/helpers/headmin/form_helper.rb +40 -0
  134. data/app/helpers/headmin/request_helper.rb +34 -0
  135. data/app/models/concerns/headmin/fieldable.rb +3 -1
  136. data/app/models/headmin/documentation_renderer.rb +32 -0
  137. data/app/models/headmin/form/base.rb +79 -0
  138. data/app/models/headmin/form/text.rb +53 -0
  139. data/app/services/block_service.rb +8 -4
  140. data/app/views/examples/admin.html.erb +1 -1
  141. data/app/views/headmin/_blocks.html.erb +2 -2
  142. data/app/views/headmin/_breadcrumbs.html.erb +1 -1
  143. data/app/views/headmin/_card.html.erb +10 -6
  144. data/app/views/headmin/_dropdown.html.erb +1 -1
  145. data/app/views/headmin/_filters.html.erb +23 -11
  146. data/app/views/headmin/_form.html.erb +14 -14
  147. data/app/views/headmin/_heading.html.erb +1 -1
  148. data/app/views/headmin/_notifications.html.erb +1 -1
  149. data/app/views/headmin/_pagination.html.erb +3 -2
  150. data/app/views/headmin/_popup.html.erb +10 -4
  151. data/app/views/headmin/_table.html.erb +10 -4
  152. data/app/views/headmin/_thumbnail.html.erb +47 -0
  153. data/app/views/headmin/dropdown/_devise.html.erb +20 -10
  154. data/app/views/headmin/dropdown/_list.html.erb +14 -7
  155. data/app/views/headmin/filters/_date.html.erb +9 -13
  156. data/app/views/headmin/filters/_flatpickr.html.erb +57 -0
  157. data/app/views/headmin/filters/_search.html.erb +5 -5
  158. data/app/views/headmin/filters/_select.html.erb +6 -6
  159. data/app/views/headmin/filters/filter/_button.html.erb +7 -7
  160. data/app/views/headmin/filters/filter/_template.html.erb +1 -1
  161. data/app/views/headmin/forms/_actions.html.erb +1 -1
  162. data/app/views/headmin/forms/_base.html.erb +100 -46
  163. data/app/views/headmin/forms/_blocks.html.erb +14 -7
  164. data/app/views/headmin/forms/_checkbox.html.erb +3 -3
  165. data/app/views/headmin/forms/_date.html.erb +30 -34
  166. data/app/views/headmin/forms/_date_range.html.erb +42 -0
  167. data/app/views/headmin/forms/_email.html.erb +35 -26
  168. data/app/views/headmin/forms/_file.html.erb +186 -34
  169. data/app/views/headmin/forms/_flatpickr.html.erb +34 -0
  170. data/app/views/headmin/forms/_flatpickr_range.html.erb +50 -0
  171. data/app/views/headmin/forms/_hidden.html.erb +24 -0
  172. data/app/views/headmin/forms/_image.html.erb +11 -45
  173. data/app/views/headmin/forms/_label.html.erb +18 -12
  174. data/app/views/headmin/forms/_number.html.erb +40 -37
  175. data/app/views/headmin/forms/_password.html.erb +37 -58
  176. data/app/views/headmin/forms/_redactorx.html.erb +8 -7
  177. data/app/views/headmin/forms/_repeater.html.erb +11 -14
  178. data/app/views/headmin/forms/_select.html.erb +43 -45
  179. data/app/views/headmin/forms/_text.html.erb +94 -59
  180. data/app/views/headmin/forms/_textarea.html.erb +37 -26
  181. data/app/views/headmin/forms/_url.html.erb +35 -26
  182. data/app/views/headmin/forms/_validation.html.erb +3 -3
  183. data/app/views/headmin/forms/_video.html.erb +21 -0
  184. data/app/views/headmin/forms/fields/_base.html.erb +3 -3
  185. data/app/views/headmin/forms/fields/_file.html.erb +2 -2
  186. data/app/views/headmin/forms/fields/_group.html.erb +3 -3
  187. data/app/views/headmin/forms/fields/_image.html.erb +2 -2
  188. data/app/views/headmin/forms/fields/_list.html.erb +3 -3
  189. data/app/views/headmin/forms/fields/_text.html.erb +2 -2
  190. data/app/views/headmin/forms/repeater/_row.html.erb +1 -1
  191. data/app/views/headmin/heading/_title.html.erb +1 -1
  192. data/app/views/headmin/layout/_body.html.erb +1 -1
  193. data/app/views/headmin/layout/_content.html.erb +1 -1
  194. data/app/views/headmin/layout/_footer.html.erb +1 -1
  195. data/app/views/headmin/layout/_header.html.erb +1 -1
  196. data/app/views/headmin/layout/_main.html.erb +12 -6
  197. data/app/views/headmin/layout/_sidebar.html.erb +3 -3
  198. data/app/views/headmin/layout/sidebar/_bottom.html.erb +1 -1
  199. data/app/views/headmin/layout/sidebar/_nav.html.erb +1 -1
  200. data/app/views/headmin/nav/_dropdown.html.erb +34 -0
  201. data/app/views/headmin/nav/_item.html.erb +22 -13
  202. data/app/views/headmin/table/_actions.html.erb +35 -11
  203. data/app/views/headmin/table/_body.html.erb +1 -1
  204. data/app/views/headmin/table/_foot.html.erb +1 -1
  205. data/app/views/headmin/table/_footer.html.erb +1 -1
  206. data/app/views/headmin/table/_head.html.erb +1 -1
  207. data/app/views/headmin/table/_header.html.erb +1 -1
  208. data/app/views/headmin/table/actions/_action.html.erb +4 -4
  209. data/app/views/headmin/table/actions/_delete.html.erb +1 -1
  210. data/app/views/headmin/table/actions/_export.html.erb +1 -1
  211. data/app/views/headmin/table/body/_row.html.erb +15 -7
  212. data/app/views/headmin/views/devise/confirmations/_new.html.erb +1 -1
  213. data/app/views/headmin/views/devise/passwords/_edit.html.erb +2 -2
  214. data/app/views/headmin/views/devise/passwords/_new.html.erb +1 -1
  215. data/app/views/headmin/views/devise/registrations/_edit.html.erb +4 -4
  216. data/app/views/headmin/views/devise/registrations/_new.html.erb +3 -3
  217. data/app/views/headmin/views/devise/shared/_links.html.erb +7 -7
  218. data/app/views/headmin/views/devise/unlocks/_new.html.erb +1 -1
  219. data/config/importmap.rb +2 -0
  220. data/config/locales/activerecord/en.yml +9 -0
  221. data/config/locales/activerecord/nl.yml +9 -0
  222. data/config/locales/en.yml +0 -3
  223. data/config/locales/headmin/forms/en.yml +5 -0
  224. data/config/locales/headmin/forms/nl.yml +5 -0
  225. data/config/locales/headmin/popup/en.yml +4 -0
  226. data/config/locales/headmin/popup/nl.yml +4 -0
  227. data/config/locales/headmin/table/en.yml +5 -1
  228. data/config/locales/headmin/table/nl.yml +5 -1
  229. data/config/locales/headmin/thumbnail/en.yml +4 -0
  230. data/config/locales/headmin/thumbnail/nl.yml +4 -0
  231. data/config/locales/headmin/views/en.yml +1 -1
  232. data/config/locales/headmin/views/nl.yml +14 -14
  233. data/config/locales/nl.yml +0 -3
  234. data/docs/blocks.md +0 -7
  235. data/esbuild-css.js +25 -0
  236. data/esbuild-js.js +11 -0
  237. data/headmin.gemspec +4 -1
  238. data/lib/generators/headmin/blocks_generator.rb +4 -1
  239. data/lib/generators/headmin/devise_generator.rb +5 -1
  240. data/lib/generators/headmin/fields_generator.rb +4 -1
  241. data/lib/generators/templates/controllers/auth/confirmations_controller.rb +31 -0
  242. data/lib/generators/templates/controllers/auth/omniauth_callbacks_controller.rb +31 -0
  243. data/lib/generators/templates/controllers/auth/passwords_controller.rb +35 -0
  244. data/lib/generators/templates/controllers/auth/registrations_controller.rb +63 -0
  245. data/lib/generators/templates/controllers/auth/sessions_controller.rb +28 -0
  246. data/lib/generators/templates/controllers/auth/unlocks_controller.rb +31 -0
  247. data/lib/headmin/engine.rb +15 -0
  248. data/lib/headmin/version.rb +1 -1
  249. data/lib/headmin.rb +1 -1
  250. data/package.json +20 -35
  251. data/src/js/headmin.js +1 -1
  252. data/src/scss/headmin.scss +1 -61
  253. data/yarn.lock +443 -5345
  254. metadata +198 -30
  255. data/.nvmrc +0 -1
  256. data/app/controllers/concerns/headmin/ckeditor.rb +0 -27
  257. data/app/views/headmin/forms/_ckeditor.html.erb +0 -42
  258. data/dist/css/headmin.css +0 -12313
  259. data/dist/js/headmin.js +0 -1548
  260. data/src/js/headmin/controllers/table_actions_controller.js +0 -33
  261. data/src/js/headmin/controllers/table_controller.js +0 -119
  262. data/src/js/headmin/headmin.js +0 -141
  263. data/src/scss/headmin/utilities.scss +0 -19
  264. data/webpack.config.js +0 -30
@@ -0,0 +1,65 @@
1
+ // Bootstrap icons
2
+ @import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css");
3
+
4
+ // Bootstrap
5
+ @import "headmin/vendor/bootstrap/scss/functions";
6
+ @import "headmin/vendor/bootstrap/scss/functions";
7
+ @import "headmin/vendor/bootstrap/scss/functions";
8
+ @import "headmin/vendor/bootstrap/scss/variables";
9
+ @import "headmin/vendor/bootstrap/scss/mixins";
10
+ @import "headmin/vendor/bootstrap/scss/utilities";
11
+ @import "headmin/overrides/bootstrap";
12
+ @import "headmin/vendor/bootstrap/scss/root";
13
+ @import "headmin/vendor/bootstrap/scss/reboot";
14
+ @import "headmin/vendor/bootstrap/scss/type";
15
+ @import "headmin/vendor/bootstrap/scss/images";
16
+ @import "headmin/vendor/bootstrap/scss/containers";
17
+ @import "headmin/vendor/bootstrap/scss/grid";
18
+ @import "headmin/vendor/bootstrap/scss/tables";
19
+ @import "headmin/vendor/bootstrap/scss/forms";
20
+ @import "headmin/vendor/bootstrap/scss/buttons";
21
+ @import "headmin/vendor/bootstrap/scss/transitions";
22
+ @import "headmin/vendor/bootstrap/scss/dropdown";
23
+ @import "headmin/vendor/bootstrap/scss/button-group";
24
+ @import "headmin/vendor/bootstrap/scss/nav";
25
+ @import "headmin/vendor/bootstrap/scss/navbar";
26
+ @import "headmin/vendor/bootstrap/scss/card";
27
+ @import "headmin/vendor/bootstrap/scss/accordion";
28
+ @import "headmin/vendor/bootstrap/scss/breadcrumb";
29
+ @import "headmin/vendor/bootstrap/scss/pagination";
30
+ @import "headmin/vendor/bootstrap/scss/badge";
31
+ @import "headmin/vendor/bootstrap/scss/alert";
32
+ @import "headmin/vendor/bootstrap/scss/progress";
33
+ @import "headmin/vendor/bootstrap/scss/list-group";
34
+ @import "headmin/vendor/bootstrap/scss/close";
35
+ @import "headmin/vendor/bootstrap/scss/toasts";
36
+ @import "headmin/vendor/bootstrap/scss/modal";
37
+ @import "headmin/vendor/bootstrap/scss/tooltip";
38
+ @import "headmin/vendor/bootstrap/scss/popover";
39
+ @import "headmin/vendor/bootstrap/scss/carousel";
40
+ @import "headmin/vendor/bootstrap/scss/spinners";
41
+ @import "headmin/vendor/bootstrap/scss/helpers";
42
+ @import "headmin/vendor/bootstrap/scss/utilities/api";
43
+
44
+ // Tom select
45
+ @import "headmin/vendor/tom-select-bootstrap";
46
+
47
+ // Flatpickr
48
+ @import "headmin/vendor/flatpickr";
49
+
50
+ // Redactor
51
+ @import "headmin/vendor/redactorx";
52
+ @import "headmin/overrides/redactorx";
53
+
54
+ // Headmin
55
+ @import "headmin/filters";
56
+ @import "headmin/form";
57
+ @import "headmin/general";
58
+ @import "headmin/layout";
59
+ @import "headmin/login";
60
+ @import "headmin/table";
61
+ @import "headmin/utilities";
62
+ @import "headmin/filter";
63
+ @import "headmin/popup";
64
+ @import "headmin/thumbnail";
65
+ @import "headmin/syntax";
@@ -1,65 +1,10 @@
1
1
  module Headmin
2
2
  module AdminHelper
3
+ include Headmin::BootstrapHelper
3
4
  include Headmin::FilterHelper
5
+ include Headmin::FormHelper
4
6
  include Headmin::NotificationHelper
5
-
6
- def current_model
7
- controller_name.classify.constantize
8
- end
9
-
10
- def bootstrap_icon(icon, options = {})
11
- data = options.has_key?(:data) ? options[:data] : nil
12
- klass = options.has_key?(:class) ? options[:class] : nil
13
- content_tag(:i, class: "bi bi-#{icon} #{klass}", data: data) {}
14
- end
15
-
16
- def current_url?(url)
17
- uri = URI(url)
18
- path = uri.path
19
- query_string = uri.query
20
- matches_path = request.path.include?(path)
21
- matches_query = uri.query ? request.query_string.include?(query_string) : true
22
- is_root = request.fullpath == url
23
- if url == admin_root_path
24
- is_root
25
- else
26
- matches_path && matches_query
27
- end
28
- end
29
-
30
- def form_field_valid?(form, name)
31
- !form.object.errors.has_key?(name)
32
- end
33
-
34
- def form_field_validation_id(form, name)
35
- [form.object_name, name.to_s, 'validation'].join('_').parameterize.underscore
36
- end
37
-
38
- def form_field_validation_class(form, name)
39
- return nil if request.get?
40
- form.object.errors.has_key?(name) ? 'is-invalid' : 'is-valid'
41
- end
42
-
43
- def default_params
44
- params.select { |key, value| is_default_param?(key) }
45
- end
46
-
47
- def add_default_param_key(key)
48
- keys = default_param_keys || []
49
- keys.push(key)
50
- @default_param_keys = keys
51
- end
52
-
53
- def default_param_keys
54
- @default_param_keys ||= [:page, :start, :length, :per_page]
55
- end
56
-
57
- def is_default_param?(key)
58
- default_param_keys.include?(key.to_sym) || is_sort_param_key?(key)
59
- end
60
-
61
- def is_sort_param_key?(key)
62
- key.to_s.include?('sort_')
63
- end
7
+ include Headmin::RequestHelper
8
+ include Headmin::DocumentationHelper
64
9
  end
65
10
  end
@@ -0,0 +1,31 @@
1
+ module Headmin
2
+ module BootstrapHelper
3
+ def bootstrap_icon(icon, options = {})
4
+ tag_name = options.extract!(:tag_name).fetch(:tag_name, :i)
5
+ options[:class] = ['bi', "bi-#{icon}", options.dig(:class)].compact.join(' ')
6
+ content_tag(tag_name, options) {}
7
+ end
8
+
9
+ # References
10
+ # https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
11
+ def bootstrap_icon_for_mime_type(mime_type, options = {})
12
+ type_map = {
13
+ image: %w[image/bmp image/gif image/vnd.microsoft.icon image/jpeg image/png image/svg+xml image/tiff image/webp],
14
+ play: %w[video/mp4 video/mpeg video/ogg video/mp2t video/webm video/3gpp video/3gpp2],
15
+ music: %w[audio/aac audio/midi audio/x-midi audio/mpeg audio/ogg audio/opus audio/wav audio/webm audio/3gpp audio/3gpp2],
16
+ word: %w[application/msword application/vnd.openxmlformats-officedocument.wordprocessingml.document],
17
+ ppt: %w[application/vnd.ms-powerpoint application/vnd.openxmlformats-officedocument.presentationml.presentation],
18
+ excel: %w[application/vnd.ms-excel application/vnd.openxmlformats-officedocument.spreadsheetml.sheet],
19
+ slides: %w[application/vnd.oasis.opendocument.presentation],
20
+ spreadsheet: %w[application/vnd.oasis.opendocument.spreadsheet],
21
+ richtext: %w[application/vnd.oasis.opendocument.text],
22
+ zip: %w[application/zip application/x-7z-compressed application/x-bzip application/x-bzip2 application/gzip application/vnd.rar],
23
+ pdf: %w[application/pdf],
24
+ }
25
+ icon_name = type_map.find{|key, mime_types| mime_types.include?(mime_type)}.first
26
+
27
+ icon = ['file', 'earmark', icon_name].compact.join('-')
28
+ bootstrap_icon(icon, options)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ module Headmin
2
+ module DocumentationHelper
3
+ def extract_documentation(text)
4
+ # Get content inside documentation block
5
+ starts_with = '<% documentation do %>\n'
6
+ ends_with = '\n<% end %>'
7
+ between = text[/#{starts_with}(.*?)#{ends_with}/m, 1]
8
+
9
+ # Remove leading whitespaces from each line
10
+ between.lines.map { |line| line.sub(' ', '') }.join
11
+ end
12
+
13
+ def markdown_to_html(text)
14
+ renderer = Headmin::DocumentationRenderer.new(escape_html: true)
15
+ markdown = Redcarpet::Markdown.new(renderer, tables: true, fenced_code_blocks: true)
16
+ markdown.render(text)
17
+ end
18
+
19
+ def documentation(template = nil)
20
+ # Disable rendering inside block
21
+ return if block_given?
22
+
23
+ # Read contents of template
24
+ content = @lookup_context.find_template(template, nil, true).encode!
25
+
26
+ # Extract documentation
27
+ content = extract_documentation(content)
28
+
29
+ # Convert markdown into HTML
30
+ html = markdown_to_html(content)
31
+
32
+ raw html
33
+ end
34
+ end
35
+ end
@@ -1,11 +1,15 @@
1
1
  module Headmin
2
2
  module FilterHelper
3
3
  def filter_param_exists?(name)
4
- return false unless params.has_key?(name)
4
+ filter_param(name).present?
5
+ end
6
+
7
+ def filter_param(name)
8
+ return nil unless params.has_key?(name)
5
9
  if params[name].is_a?(Array)
6
- params[name].reject { |c| c.empty? }.present?
10
+ params[name].reject { |c| c.empty? }
7
11
  else
8
- params[name].present?
12
+ params[name]
9
13
  end
10
14
  end
11
15
  end
@@ -0,0 +1,40 @@
1
+ module Headmin
2
+ module FormHelper
3
+ def form_field_valid?(form, name)
4
+ !form.object.errors.has_key?(name)
5
+ end
6
+
7
+ def form_field_validation_id(form, name)
8
+ [form.object_name, name.to_s, 'validation'].join('_').parameterize.underscore
9
+ end
10
+
11
+ def form_field_validation_class(form, name)
12
+ return nil if request.get?
13
+ form.object.errors.has_key?(name) ? 'is-invalid' : 'is-valid'
14
+ end
15
+
16
+ def human_attribute_name(attribute)
17
+ attribute.to_s.humanize
18
+ end
19
+
20
+ # Outputs currently present query parameters as hidden fields for a given form
21
+ #
22
+ # https://example.com/products?amount=1&type[]=food&type[]=beverage
23
+ #
24
+ # <%= form.hidden_input :amount, value: 1 %>
25
+ # <%= form.hidden_input :'type[]', value: 'food' %>
26
+ # <%= form.hidden_input :'type[]', value: 'beverage' %>
27
+ def query_parameter_fields(form)
28
+ test = request.query_parameters.map do |name, value|
29
+ if value.is_a?(Array)
30
+ value.map do |value_element|
31
+ form.hidden_field "#{name}[]", value: value_element
32
+ end.join
33
+ else
34
+ form.hidden_field name, value: value
35
+ end
36
+ end
37
+ test.join.html_safe
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,34 @@
1
+ module Headmin
2
+ module RequestHelper
3
+ def current_url?(url)
4
+ uri = URI(url)
5
+ path = uri.path
6
+ query_string = uri.query || ''
7
+ matches_path = request.path.include?(path)
8
+ matches_query = request.query_string.include?(query_string)
9
+ matches_path && matches_query
10
+ end
11
+
12
+ def default_params
13
+ params.select { |key, value| is_default_param?(key) }
14
+ end
15
+
16
+ def add_default_param_key(key)
17
+ keys = default_param_keys || []
18
+ keys.push(key)
19
+ @default_param_keys = keys
20
+ end
21
+
22
+ def default_param_keys
23
+ @default_param_keys ||= [:page, :start, :length, :per_page]
24
+ end
25
+
26
+ def is_default_param?(key)
27
+ default_param_keys.include?(key.to_sym) || is_sort_param_key?(key)
28
+ end
29
+
30
+ def is_sort_param_key?(key)
31
+ key.to_s.include?('sort_')
32
+ end
33
+ end
34
+ end
@@ -7,7 +7,9 @@ module Headmin
7
7
  accepts_nested_attributes_for :fields, allow_destroy: true
8
8
 
9
9
  def fields_hash
10
- parse_hash_tree(fields.hash_tree)
10
+ fields.order(position: :asc).map do |field|
11
+ parse_hash_tree(field.hash_tree)
12
+ end.reduce({}, :merge)
11
13
  end
12
14
 
13
15
  def fields_hash=(hash)
@@ -0,0 +1,32 @@
1
+ module Headmin
2
+ class DocumentationRenderer < Redcarpet::Render::HTML
3
+ def block_code(code, language)
4
+ if language == "erbx"
5
+ "<div class=\"card mb-3\"><div class=\"card-body\">#{render_code(code)}</div><div class=\"card-footer\"><pre><code class=\"h-syntax\">#{highlight_syntax(code, 'erb')}</code></pre></div></div>"
6
+ else
7
+ "<pre><code class=\"h-syntax\">#{highlight_syntax(code, language)}</code></pre></div>"
8
+ end
9
+ end
10
+
11
+ def table(header, body)
12
+ "<table class=\"table table-sm\">#{header}#{body}</table>"
13
+ end
14
+
15
+ private
16
+
17
+ def highlight_syntax(code, language)
18
+ formatter = Rouge::Formatters::HTML.new
19
+ lexer = Rouge::Lexer.find(language)
20
+ formatter.format(lexer.lex(code))
21
+ end
22
+
23
+ def render_code(code)
24
+ ApplicationController.renderer.new(
25
+ 'action_dispatch.request.path_parameters' => {
26
+ controller: 'main',
27
+ action: 'index'
28
+ }
29
+ ).render(inline: code)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,79 @@
1
+ module Headmin
2
+ module Form
3
+ class Base
4
+ def initialize(local_assigns)
5
+ @local_assigns = local_assigns
6
+ end
7
+
8
+ def class_names
9
+ class_names = [@local_assigns[:class]]
10
+ class_names << "form-floating" if float
11
+ class_names << "mb-3 text-start"
12
+ class_names.join(" ")
13
+ end
14
+
15
+ def data
16
+ @local_assigns[:data]
17
+ end
18
+
19
+ def label_options
20
+ {
21
+ attribute: attribute,
22
+ class: "d-block",
23
+ for: id,
24
+ form: form,
25
+ required: required,
26
+ text: label
27
+ }
28
+ end
29
+
30
+ def required
31
+ @local_assigns[:required]
32
+ end
33
+
34
+ def form
35
+ @local_assigns[:form]
36
+ end
37
+
38
+ def id
39
+ @local_assigns[:id]
40
+ end
41
+
42
+ def validation_options
43
+ {
44
+ attribute: attribute,
45
+ form: form
46
+ }
47
+ end
48
+
49
+ def attribute
50
+ @local_assigns[:attribute]
51
+ end
52
+
53
+ def list
54
+ @local_assigns[:list]
55
+ end
56
+
57
+ def list_id
58
+ list ? "#{attribute}_list" : nil
59
+ end
60
+
61
+ def append
62
+ @local_assigns[:append]
63
+
64
+ end
65
+
66
+ def prepend
67
+ @local_assigns[:prepend]
68
+ end
69
+
70
+ def float
71
+ @local_assigns[:float] || false
72
+ end
73
+
74
+ def label
75
+ @local_assigns[:label]
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,53 @@
1
+ module Headmin
2
+ module Form
3
+ class Text
4
+ def initialize(local_assigns)
5
+ @local_assigns = local_assigns
6
+ end
7
+
8
+ def placeholder
9
+ @local_assigns[:float] ? @local_assigns[:placeholder] || attribute : @local_assigns[:placeholder]
10
+ end
11
+
12
+ def attribute
13
+ @local_assigns[:attribute]
14
+ end
15
+
16
+ def form
17
+ @local_assigns[:form]
18
+ end
19
+
20
+ def options
21
+ option_keys = %i(aria autocomplete autofocus data disabled id maxlength minlength list pattern placeholder readonly required spellcheck size value)
22
+ @local_assigns.slice(*option_keys).merge(
23
+ aria: { describedby: form_field_validation_id(form, attribute) },
24
+ class: ["form-control", form_field_validation_class(form, attribute)].join(" "),
25
+ list: @local_assigns[:list] ? "#{attribute}_list" : nil,
26
+ placeholder: placeholder
27
+ )
28
+ end
29
+
30
+ def local_assigns
31
+ @local_assigns
32
+ end
33
+
34
+ def form_field_valid?(form, name)
35
+ return unless form.object
36
+
37
+ !form.object.errors.has_key?(name)
38
+ end
39
+
40
+ def form_field_validation_id(form, name)
41
+ return unless form.object
42
+
43
+ [form.object_name, name.to_s, "validation"].join("_").parameterize.underscore
44
+ end
45
+
46
+ def form_field_validation_class(form, name)
47
+ return unless form.object
48
+
49
+ "is-invalid" if form.object.errors.has_key?(name)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,10 +1,7 @@
1
1
  class BlockService
2
2
  def self.block_names(path:)
3
3
  form_views(path: path).map do |view|
4
- filename = File.basename(view, '.html.erb')
5
-
6
- # Removes leading _ if exists
7
- filename.sub!(/^_/, '')
4
+ view_name(view)
8
5
  end
9
6
  end
10
7
 
@@ -24,6 +21,13 @@ class BlockService
24
21
  views(form_view_paths(path))
25
22
  end
26
23
 
24
+ def self.view_name(view)
25
+ filename = File.basename(view.split('.')[0])
26
+
27
+ # Removes leading _ if exists
28
+ filename.sub(/^_/, '')
29
+ end
30
+
27
31
  private
28
32
 
29
33
  # Looks for a block view by its name.
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html lang="<%= I18n.locale %>" data-controller="headmin">
3
3
  <head>
4
4
  <title>Admin</title>
5
5
  <meta name="viewport" content="width=device-width,initial-scale=1">
@@ -2,8 +2,8 @@
2
2
  # headmin/blocks
3
3
  #
4
4
  # ==== Options
5
- # * <tt>blockable</tt> - Object with blocks association
6
- # * <tt>path</tt> - Directory where to look for block templates
5
+ # * +blockable</tt> - Object with blocks association
6
+ # * +path</tt> - Directory where to look for block templates
7
7
  #
8
8
  # ==== Examples
9
9
  # Basic version. This will only look for blocks in 'website/blocks'
@@ -2,7 +2,7 @@
2
2
  # headmin/breadcrumbs
3
3
  #
4
4
  # ==== Options
5
- # * <tt>breadcrumbs</tt> - Object with blocks association
5
+ # * +breadcrumbs</tt> - Object with blocks association
6
6
  #
7
7
  # ==== Examples
8
8
  # Basic version. This will use the publicly available `breadcrumbs` variable
@@ -1,10 +1,13 @@
1
+ <% warn "[DEPRECATION] `headmin/card` is deprecated. Please use plain Bootstrap markup." %>
1
2
  <%
3
+ # DEPRECATED in 0.3
2
4
  # headmin/card
3
5
  #
4
6
  # ==== Options
5
- # * <tt>title</tt> - Title for card
6
- # * <tt>description</tt> - Description for card
7
- # * <tt>padded</tt> - Set to true if you want to render the block content inside the card-body element
7
+ # * +title</tt> - Title for card
8
+ # * +description</tt> - Description for card
9
+ # * +id</tt> - HTML Id Attribute
10
+ # * +padded</tt> - Set to true if you want to render the block content inside the card-body element
8
11
  #
9
12
  # ==== Examples
10
13
  # Basic version.
@@ -17,12 +20,13 @@
17
20
  # Your content
18
21
  # <% end %#>
19
22
 
23
+ id = local_assigns.has_key?(:id) ? id : nil
20
24
  title = local_assigns.has_key?(:title) ? title : nil
21
25
  description = local_assigns.has_key?(:description) ? description : nil
22
26
  padded = local_assigns.has_key?(:padded) ? padded : true
23
27
  %>
24
28
 
25
- <div class="card mb-3 shadow-sm">
29
+ <div class="card mb-3 shadow-sm" id="<%= id %>">
26
30
 
27
31
  <% if padded || title || description %>
28
32
  <div class="card-body">
@@ -36,13 +40,13 @@
36
40
 
37
41
  <!-- Render inside body-->
38
42
  <% if padded %>
39
- <%= yield if block_given? %>
43
+ <%= yield %>
40
44
  <% end %>
41
45
  </div>
42
46
  <% end %>
43
47
 
44
48
  <!-- Render outside body-->
45
49
  <% unless padded %>
46
- <%= yield if block_given? %>
50
+ <%= yield %>
47
51
  <% end %>
48
52
  </div>
@@ -2,7 +2,7 @@
2
2
  # headmin/dropdown
3
3
  #
4
4
  # ==== Options
5
- # * <tt>class</tt> - Custom class names to put on the dropdown
5
+ # * +class</tt> - Custom class names to put on the dropdown
6
6
  #
7
7
  # ==== Examples
8
8
  # Basic version
@@ -2,16 +2,21 @@
2
2
  # headmin/filters
3
3
  #
4
4
  # ==== Options
5
- # * <tt>url</tt> - Base url to send filter query to. Defaults to current URL
5
+ # * +url</tt> - Base url to send filter query to. Defaults to current URL
6
6
  #
7
7
  # ==== Examples
8
8
  # Basic version
9
- # <%= render "headmin/filters" %#>
9
+ # <%= render "headmin/filters" do %#>
10
+ # <%= render "headmin/filters/select", name: 'color', options: ['red', 'green', 'blue'] %#>
11
+ # <% end %#>
10
12
  #
11
13
  # With custom URL
12
14
  # <%= render "headmin/filters", url: admin_polls_path %#>
13
15
 
14
- action = local_assigns.has_key?(:url) ? url : request.url
16
+ action = local_assigns.has_key?(:url) ? url : request.path
17
+
18
+ # Perform yield in order to capture content blocks
19
+ yield
15
20
  %>
16
21
 
17
22
  <form action="<%= action %>" data-controller="filters" data-filters-target="form">
@@ -21,24 +26,22 @@
21
26
  <%= hidden_field_tag(name.to_sym, value) %>
22
27
  <% end %>
23
28
 
24
- <%= yield if block_given? %>
25
-
26
- <div class="d-flex flex-column flex-md-row align-content-start align-items-md-center">
29
+ <div class="d-flex flex-column flex-md-row align-content-start align-items-md-start">
27
30
  <div class="d-flex align-items-center">
28
31
 
29
32
  <!-- Search -->
30
33
  <div class="h-filters-search d-flex my-1 w-100">
31
- <%= content_for :filters_search %>
34
+ <%= yield :filters_search %>
32
35
 
33
36
  <!-- Separator -->
34
- <% if content_for(:filters_menu) && content_for(:filters_search) %>
37
+ <% if content_for?(:filters_menu) && content_for?(:filters_search) %>
35
38
  <div class="vr mx-2"></div>
36
39
  <% end %>
37
40
  </div>
38
41
 
39
42
  <!-- Menu -->
40
43
  <div class="h-filters-menu d-flex align-items-center w-auto my-1">
41
- <% if content_for :filters_menu %>
44
+ <% if content_for?(:filters_menu) %>
42
45
  <div class="btn-group">
43
46
  <button type="button" class="btn h-btn-outline-light dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
44
47
  <%= bootstrap_icon('funnel') %>
@@ -60,10 +63,19 @@
60
63
 
61
64
  <!-- Filter list -->
62
65
  <div class="h-filter-list d-flex ms-md-1 flex-wrap" data-filters-target="list">
63
- <%= content_for :filters_buttons %>
66
+ <%= yield :filters_buttons %>
64
67
  </div>
65
68
  </div>
66
69
 
67
70
  <!-- Filter templates -->
68
- <%= content_for :filters_templates %>
71
+ <%= yield :filters_templates %>
69
72
  </form>
73
+
74
+
75
+ <%
76
+ # Clears content blocks to make this view reusable
77
+ content_for(:filters_search, flush: true) { concat(nil) }
78
+ content_for(:filters_menu, flush: true) { concat(nil) }
79
+ content_for(:filters_buttons, flush: true) { concat(nil) }
80
+ content_for(:filters_templates, flush: true) { concat(nil) }
81
+ %>