trestle 0.9.9 → 0.10.0.pre

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 (328) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +31 -3
  3. data/.gitignore +3 -0
  4. data/Gemfile +5 -1
  5. data/README.md +2 -1
  6. data/app/assets/bundle/trestle/admin.css +23 -0
  7. data/app/assets/bundle/trestle/admin.js +83 -0
  8. data/app/assets/bundle/trestle/fa-brands-400.ttf +0 -0
  9. data/app/assets/bundle/trestle/fa-brands-400.woff2 +0 -0
  10. data/app/assets/bundle/trestle/fa-regular-400.ttf +0 -0
  11. data/app/assets/bundle/trestle/fa-regular-400.woff2 +0 -0
  12. data/app/assets/bundle/trestle/fa-solid-900.ttf +0 -0
  13. data/app/assets/bundle/trestle/fa-solid-900.woff2 +0 -0
  14. data/app/assets/bundle/trestle/locale/cs.js +110 -0
  15. data/app/assets/bundle/trestle/locale/de.js +116 -0
  16. data/app/assets/bundle/trestle/locale/en.js +329 -0
  17. data/app/assets/bundle/trestle/locale/es-MX.js +109 -0
  18. data/app/assets/bundle/trestle/locale/es.js +109 -0
  19. data/app/assets/bundle/trestle/locale/fr.js +111 -0
  20. data/app/assets/bundle/trestle/locale/ko.js +111 -0
  21. data/app/assets/bundle/trestle/locale/lv.js +109 -0
  22. data/app/assets/bundle/trestle/locale/nl.js +96 -0
  23. data/app/assets/bundle/trestle/locale/pl.js +99 -0
  24. data/app/assets/bundle/trestle/locale/pt-BR.js +98 -0
  25. data/app/assets/bundle/trestle/locale/vi.js +116 -0
  26. data/app/assets/bundle/trestle/locale/zh-CN.js +109 -0
  27. data/app/assets/bundle/trestle/photoswipe-7aa1aec9c3c1fd65c382.digested.js +6 -0
  28. data/app/assets/sprockets/trestle/custom.css +1 -0
  29. data/app/assets/sprockets/trestle/icons/font-awesome.css.erb +32 -0
  30. data/app/assets/sprockets/trestle/manifest.js +4 -0
  31. data/app/assets/stylesheets/trestle/custom.css +6 -1
  32. data/app/controllers/concerns/trestle/controller/helpers.rb +2 -0
  33. data/app/controllers/concerns/trestle/controller/location.rb +1 -6
  34. data/app/controllers/concerns/trestle/controller/modal.rb +23 -0
  35. data/app/controllers/concerns/trestle/controller/turbo.rb +21 -0
  36. data/app/controllers/concerns/trestle/resource/controller/actions.rb +39 -28
  37. data/app/controllers/concerns/trestle/resource/controller/redirection.rb +5 -5
  38. data/app/controllers/trestle/application_controller.rb +2 -1
  39. data/app/helpers/trestle/flash_helper.rb +10 -0
  40. data/app/helpers/trestle/form_helper.rb +3 -2
  41. data/app/helpers/trestle/format_helper.rb +2 -1
  42. data/app/helpers/trestle/i18n_helper.rb +46 -7
  43. data/app/helpers/trestle/modal_helper.rb +34 -0
  44. data/app/helpers/trestle/tab_helper.rb +1 -1
  45. data/app/helpers/trestle/turbo_frame_helper.rb +34 -0
  46. data/app/helpers/trestle/url_helper.rb +7 -4
  47. data/app/views/layouts/trestle/admin.html.erb +16 -18
  48. data/app/views/layouts/trestle/admin.turbo_stream.erb +11 -0
  49. data/app/views/layouts/trestle/modal.html.erb +5 -0
  50. data/app/views/trestle/_i18n.html.erb +12 -0
  51. data/app/views/trestle/_theme.html.erb +15 -0
  52. data/app/views/trestle/application/_header.html.erb +1 -1
  53. data/app/views/trestle/application/_layout.html.erb +6 -3
  54. data/app/views/trestle/application/_modal.html.erb +36 -0
  55. data/app/views/trestle/application/_tabs.html.erb +4 -4
  56. data/app/views/trestle/flash/_alert.html.erb +1 -1
  57. data/app/views/trestle/flash/_debug.html.erb +1 -1
  58. data/app/views/trestle/resource/_form.html.erb +5 -0
  59. data/app/views/trestle/resource/create.turbo_stream.erb +5 -0
  60. data/app/views/trestle/resource/destroy.turbo_stream.erb +1 -0
  61. data/app/views/trestle/resource/edit.html.erb +4 -2
  62. data/app/views/trestle/resource/index.html.erb +12 -10
  63. data/app/views/trestle/resource/new.html.erb +4 -2
  64. data/app/views/trestle/resource/show.html.erb +4 -2
  65. data/app/views/trestle/resource/update.turbo_stream.erb +5 -0
  66. data/app/views/trestle/shared/_sidebar.html.erb +9 -9
  67. data/frontend/css/components/_alerts.scss +19 -17
  68. data/frontend/css/components/_background.scss +7 -35
  69. data/frontend/css/components/_badges.scss +31 -0
  70. data/frontend/css/components/_breadcrumbs.scss +4 -4
  71. data/frontend/css/components/_buttons.scss +5 -4
  72. data/frontend/css/components/_datepicker.scss +12 -8
  73. data/frontend/css/components/_dropdown.scss +23 -3
  74. data/frontend/css/components/{_fields.scss → _forms.scss} +16 -3
  75. data/frontend/css/components/_media-grid.scss +52 -44
  76. data/frontend/css/components/_modal.scss +33 -4
  77. data/frontend/css/components/_pagination.scss +1 -1
  78. data/frontend/css/components/_photoswipe.scss +8 -0
  79. data/frontend/css/components/_popover.scss +1 -0
  80. data/frontend/css/components/_scopes.scss +1 -1
  81. data/frontend/css/components/_select.scss +161 -31
  82. data/frontend/css/components/_table.scss +60 -65
  83. data/frontend/css/components/_tabs.scss +10 -3
  84. data/frontend/css/components/_tags.scss +71 -16
  85. data/frontend/css/components/_toolbars.scss +16 -11
  86. data/frontend/css/components/_turbo.scss +3 -0
  87. data/frontend/css/core/_bootstrap.scss +46 -0
  88. data/frontend/css/core/_dependencies.scss +4 -3
  89. data/frontend/css/core/_functions.scss +39 -0
  90. data/frontend/css/core/_mixins.scss +2 -36
  91. data/frontend/css/core/_theme.scss +258 -0
  92. data/frontend/css/core/_typography.scss +10 -1
  93. data/frontend/css/icons/_fontawesome.scss +3 -15
  94. data/frontend/css/index.scss +12 -6
  95. data/frontend/css/layout/_base.scss +3 -3
  96. data/frontend/css/layout/_content.scss +10 -6
  97. data/frontend/css/layout/_footer.scss +1 -1
  98. data/frontend/css/layout/_header.scss +5 -3
  99. data/frontend/css/layout/_navigation.scss +2 -2
  100. data/frontend/css/layout/_sidebar.scss +19 -9
  101. data/frontend/css/support/_sprockets.scss +2 -0
  102. data/frontend/css/support/_webpack.scss +2 -0
  103. data/frontend/css/variables/_bootstrap.scss +134 -40
  104. data/frontend/css/variables/_maps.scss +15 -0
  105. data/frontend/css/variables/_trestle.scss +55 -26
  106. data/frontend/js/controllers/application_controller.js +17 -0
  107. data/frontend/js/controllers/checkbox_select_controller.js +43 -0
  108. data/frontend/js/controllers/confirm_controller.js +115 -0
  109. data/frontend/js/controllers/confirm_delete_controller.js +11 -0
  110. data/frontend/js/controllers/datepicker_controller.js +12 -0
  111. data/frontend/js/controllers/datetimepicker_controller.js +13 -0
  112. data/frontend/js/controllers/deprecated/init_controller.js +9 -0
  113. data/frontend/js/controllers/flatpickr_controller.js +50 -0
  114. data/frontend/js/controllers/follow_url_controller.js +36 -0
  115. data/frontend/js/controllers/form_error_controller.js +24 -0
  116. data/frontend/js/controllers/form_loading_controller.js +50 -0
  117. data/frontend/js/controllers/gallery_controller.js +10 -0
  118. data/frontend/js/controllers/index.js +19 -0
  119. data/frontend/js/controllers/keyboard_submit_controller.js +25 -0
  120. data/frontend/js/controllers/lightbox_controller.js +160 -0
  121. data/frontend/js/controllers/mobile_sidebar_controller.js +30 -0
  122. data/frontend/js/controllers/modal_controller.js +36 -0
  123. data/frontend/js/controllers/modal_frame_controller.js +11 -0
  124. data/frontend/js/controllers/modal_trigger_controller.js +74 -0
  125. data/frontend/js/{components/navigation.js → controllers/navigation_controller.js} +14 -10
  126. data/frontend/js/controllers/navigation_tooltip_controller.js +32 -0
  127. data/frontend/js/controllers/popover_controller.js +87 -0
  128. data/frontend/js/controllers/reloadable_controller.js +34 -0
  129. data/frontend/js/controllers/select_controller.js +49 -0
  130. data/frontend/js/controllers/sidebar_controller.js +33 -0
  131. data/frontend/js/controllers/tab_errors_controller.js +45 -0
  132. data/frontend/js/controllers/tabs_controller.js +45 -0
  133. data/frontend/js/controllers/timepicker_controller.js +14 -0
  134. data/frontend/js/controllers/toggle_attr_controller.js +27 -0
  135. data/frontend/js/controllers/toggle_class_controller.js +27 -0
  136. data/frontend/js/controllers/tooltip_controller.js +13 -0
  137. data/frontend/js/controllers/wrapper_controller.js +43 -0
  138. data/frontend/js/core/backdrop.js +100 -0
  139. data/frontend/js/core/error_modal.js +65 -0
  140. data/frontend/js/core/fetch.js +32 -0
  141. data/frontend/js/core/i18n.js +24 -10
  142. data/frontend/js/core/modal.js +52 -0
  143. data/frontend/js/core/stream_actions.js +56 -0
  144. data/frontend/js/core/turbo_errors.js +9 -0
  145. data/frontend/js/{core → deprecated}/events.js +1 -8
  146. data/frontend/js/deprecated/tooltip.js +8 -0
  147. data/frontend/js/index.js +28 -40
  148. data/frontend/js/mixins/index.js +5 -0
  149. data/frontend/js/mixins/photoswipe.js +10 -0
  150. data/frontend/js/util/bootstrap.js +93 -0
  151. data/i18n/config.yml +14 -0
  152. data/i18n/environment.rb +8 -0
  153. data/i18n/export +3 -0
  154. data/i18n/template.erb +1 -0
  155. data/lib/generators/trestle/install/install_generator.rb +3 -8
  156. data/lib/generators/trestle/install/templates/trestle.rb.erb +5 -5
  157. data/lib/trestle/color.rb +113 -0
  158. data/lib/trestle/configuration.rb +16 -8
  159. data/lib/trestle/engine.rb +23 -17
  160. data/lib/trestle/form/fields/check_box_helpers.rb +7 -18
  161. data/lib/trestle/form/fields/collection_select.rb +1 -1
  162. data/lib/trestle/form/fields/color_field.rb +4 -0
  163. data/lib/trestle/form/fields/date_field.rb +4 -0
  164. data/lib/trestle/form/fields/date_picker.rb +10 -4
  165. data/lib/trestle/form/fields/date_select.rb +1 -1
  166. data/lib/trestle/form/fields/datetime_field.rb +4 -0
  167. data/lib/trestle/form/fields/datetime_select.rb +1 -1
  168. data/lib/trestle/form/fields/file_field.rb +3 -28
  169. data/lib/trestle/form/fields/form_control.rb +2 -2
  170. data/lib/trestle/form/fields/form_group.rb +1 -1
  171. data/lib/trestle/form/fields/grouped_collection_select.rb +1 -1
  172. data/lib/trestle/form/fields/radio_button_helpers.rb +5 -17
  173. data/lib/trestle/form/fields/range_field.rb +1 -5
  174. data/lib/trestle/form/fields/select.rb +17 -1
  175. data/lib/trestle/form/fields/time_field.rb +4 -0
  176. data/lib/trestle/form/fields/time_select.rb +1 -1
  177. data/lib/trestle/form/fields/time_zone_select.rb +1 -1
  178. data/lib/trestle/form/renderer.rb +3 -0
  179. data/lib/trestle/form.rb +16 -1
  180. data/lib/trestle/resource/toolbar.rb +2 -2
  181. data/lib/trestle/table/actions_column.rb +2 -2
  182. data/lib/trestle/table/row.rb +2 -1
  183. data/lib/trestle/table/select_column.rb +3 -6
  184. data/lib/trestle/table.rb +6 -1
  185. data/lib/trestle/toolbar/item.rb +1 -1
  186. data/lib/trestle/toolbar/menu.rb +3 -6
  187. data/lib/trestle/version.rb +1 -1
  188. data/lib/trestle.rb +2 -23
  189. data/package.json +31 -27
  190. data/trestle.gemspec +2 -3
  191. data/webpack.config.js +10 -10
  192. data/yarn.lock +1456 -1194
  193. metadata +166 -164
  194. data/app/assets/bundle/trestle/bundle.css +0 -12
  195. data/app/assets/bundle/trestle/bundle.js +0 -89
  196. data/app/assets/bundle/trestle/fa-brands-400.eot +0 -0
  197. data/app/assets/bundle/trestle/fa-brands-400.svg +0 -3717
  198. data/app/assets/bundle/trestle/fa-brands-400.woff +0 -0
  199. data/app/assets/bundle/trestle/fa-regular-400.eot +0 -0
  200. data/app/assets/bundle/trestle/fa-regular-400.svg +0 -801
  201. data/app/assets/bundle/trestle/fa-regular-400.woff +0 -0
  202. data/app/assets/bundle/trestle/fa-solid-900.eot +0 -0
  203. data/app/assets/bundle/trestle/fa-solid-900.svg +0 -5034
  204. data/app/assets/bundle/trestle/fa-solid-900.woff +0 -0
  205. data/app/assets/javascripts/trestle/admin.js +0 -3
  206. data/app/assets/javascripts/trestle/i18n.js.erb +0 -8
  207. data/app/assets/stylesheets/trestle/admin.css +0 -2
  208. data/app/assets/stylesheets/trestle/icons/_font-awesome.css.erb +0 -40
  209. data/app/controllers/concerns/trestle/controller/dialog.rb +0 -16
  210. data/app/views/trestle/application/_dialog.html.erb +0 -34
  211. data/frontend/css/components/_color-vars.scss +0 -10
  212. data/frontend/css/components/_custom-forms.scss +0 -35
  213. data/frontend/css/components/_magnific-popup.scss +0 -36
  214. data/frontend/css/components/_turbolinks.scss +0 -3
  215. data/frontend/js/components/confirmation.js +0 -32
  216. data/frontend/js/components/datepicker.js +0 -69
  217. data/frontend/js/components/dialog.js +0 -149
  218. data/frontend/js/components/file.js +0 -7
  219. data/frontend/js/components/form.js +0 -100
  220. data/frontend/js/components/gallery.js +0 -33
  221. data/frontend/js/components/pagination.js +0 -51
  222. data/frontend/js/components/select.js +0 -18
  223. data/frontend/js/components/sidebar.js +0 -75
  224. data/frontend/js/components/table.js +0 -61
  225. data/frontend/js/components/tabs.js +0 -59
  226. data/frontend/js/components/tooltips.js +0 -25
  227. data/frontend/js/core/contexts.js +0 -17
  228. data/frontend/js/core/turbolinks.js +0 -3
  229. data/frontend/js/core/visit.js +0 -16
  230. data/frontend/theme/trestle/_theme.scss +0 -4
  231. data/frontend/theme/trestle/_variables.scss +0 -4
  232. data/frontend/theme/trestle/theme/_defaults.scss +0 -152
  233. data/frontend/theme/trestle/theme/_functions.scss +0 -44
  234. data/frontend/theme/trestle/theme/_variables.scss +0 -15
  235. data/frontend/theme/trestle/theme/bootstrap/_alert.scss +0 -19
  236. data/frontend/theme/trestle/theme/bootstrap/_badge.scss +0 -25
  237. data/frontend/theme/trestle/theme/bootstrap/_buttons.scss +0 -93
  238. data/frontend/theme/trestle/theme/bootstrap/_color-vars.scss +0 -11
  239. data/frontend/theme/trestle/theme/bootstrap/_custom-forms.scss +0 -93
  240. data/frontend/theme/trestle/theme/bootstrap/_dropdown.scss +0 -6
  241. data/frontend/theme/trestle/theme/bootstrap/_forms.scss +0 -6
  242. data/frontend/theme/trestle/theme/bootstrap/_links.scss +0 -7
  243. data/frontend/theme/trestle/theme/bootstrap/_list-group.scss +0 -31
  244. data/frontend/theme/trestle/theme/bootstrap/_nav.scss +0 -6
  245. data/frontend/theme/trestle/theme/bootstrap/_pagination.scss +0 -18
  246. data/frontend/theme/trestle/theme/bootstrap/_progress.scss +0 -3
  247. data/frontend/theme/trestle/theme/bootstrap/_tables.scss +0 -41
  248. data/frontend/theme/trestle/theme/bootstrap/_utilities.scss +0 -3
  249. data/frontend/theme/trestle/theme/bootstrap/utilities/_background.scss +0 -17
  250. data/frontend/theme/trestle/theme/bootstrap/utilities/_borders.scss +0 -5
  251. data/frontend/theme/trestle/theme/bootstrap/utilities/_text.scss +0 -18
  252. data/frontend/theme/trestle/theme/trestle/_background.scss +0 -61
  253. data/frontend/theme/trestle/theme/trestle/_datepicker.scss +0 -58
  254. data/frontend/theme/trestle/theme/trestle/_headers.scss +0 -4
  255. data/frontend/theme/trestle/theme/trestle/_navbar.scss +0 -15
  256. data/frontend/theme/trestle/theme/trestle/_navigation.scss +0 -5
  257. data/frontend/theme/trestle/theme/trestle/_select2.scss +0 -22
  258. data/frontend/theme/trestle/theme/trestle/_tags.scss +0 -12
  259. data/frontend/theme/trestle/theme/trestle/_turbolinks.scss +0 -3
  260. data/frontend/theme/trestle/theme.scss +0 -29
  261. data/lib/generators/trestle/install/templates/_theme.scss +0 -13
  262. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ar-dz.js +0 -0
  263. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ar.js +0 -0
  264. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/at.js +0 -0
  265. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/az.js +0 -0
  266. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/be.js +0 -0
  267. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/bg.js +0 -0
  268. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/bn.js +0 -0
  269. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/bs.js +0 -0
  270. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/cat.js +0 -0
  271. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ckb.js +0 -0
  272. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/cs.js +0 -0
  273. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/cy.js +0 -0
  274. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/da.js +0 -0
  275. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/de.js +0 -0
  276. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/default.js +0 -0
  277. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/eo.js +0 -0
  278. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/es.js +0 -0
  279. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/et.js +0 -0
  280. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/fa.js +0 -0
  281. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/fi.js +0 -0
  282. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/fo.js +0 -0
  283. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/fr.js +0 -0
  284. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ga.js +0 -0
  285. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/gr.js +0 -0
  286. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/he.js +0 -0
  287. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/hi.js +0 -0
  288. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/hr.js +0 -0
  289. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/hu.js +0 -0
  290. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/hy.js +0 -0
  291. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/id.js +0 -0
  292. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/is.js +0 -0
  293. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/it.js +0 -0
  294. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ja.js +0 -0
  295. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ka.js +0 -0
  296. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/km.js +0 -0
  297. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ko.js +0 -0
  298. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/kz.js +0 -0
  299. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/lt.js +0 -0
  300. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/lv.js +0 -0
  301. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/mk.js +0 -0
  302. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/mn.js +0 -0
  303. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ms.js +0 -0
  304. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/my.js +0 -0
  305. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/nl.js +0 -0
  306. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/nn.js +0 -0
  307. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/no.js +0 -0
  308. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/pa.js +0 -0
  309. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/pl.js +0 -0
  310. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/pt.js +0 -0
  311. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ro.js +0 -0
  312. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/ru.js +0 -0
  313. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/si.js +0 -0
  314. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sk.js +0 -0
  315. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sl.js +0 -0
  316. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sq.js +0 -0
  317. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sr-cyr.js +0 -0
  318. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sr.js +0 -0
  319. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/sv.js +0 -0
  320. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/th.js +0 -0
  321. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/tr.js +0 -0
  322. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/uk.js +0 -0
  323. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/uz.js +0 -0
  324. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/uz_latn.js +0 -0
  325. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/vn.js +0 -0
  326. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/zh-tw.js +0 -0
  327. /data/app/assets/bundle/trestle/{flatpickr → locale/flatpickr}/zh.js +0 -0
  328. /data/app/assets/{stylesheets → sprockets}/trestle/_custom.css +0 -0
@@ -0,0 +1,87 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ import { Popover } from 'bootstrap'
4
+
5
+ export default class extends ApplicationController {
6
+ static values = {
7
+ title: { type: String, default: '' },
8
+ content: { type: String, default: '' },
9
+ placement: { type: String, default: 'left' },
10
+ html: { type: Boolean, default: false },
11
+ trigger: { type: String, default: 'click' }
12
+ }
13
+
14
+ static classes = [ "custom" ]
15
+
16
+ initialize () {
17
+ this.boundHide = this.hide.bind(this)
18
+
19
+ this.boundOnShown = this.onShown.bind(this)
20
+ this.boundOnHidden = this.onHidden.bind(this)
21
+ }
22
+
23
+ connect () {
24
+ this.popover = new Popover(this.element, this.popoverOptions)
25
+
26
+ this.element.addEventListener('shown.bs.popover', this.boundOnShown)
27
+ this.element.addEventListener('hidden.bs.popover', this.boundOnHidden)
28
+ }
29
+
30
+ disconnect () {
31
+ this.element.removeEventListener('shown.bs.popover', this.boundOnShown)
32
+ this.element.removeEventListener('hidden.bs.popover', this.boundOnHidden)
33
+
34
+ document.removeEventListener('click', this.boundHide)
35
+
36
+ if (this.popover._isEnabled) {
37
+ this.popover.dispose()
38
+ }
39
+ }
40
+
41
+ show () {
42
+ this.popover.show()
43
+ }
44
+
45
+ toggle () {
46
+ this.popover.toggle()
47
+ }
48
+
49
+ clickWithinPopover (e) {
50
+ return this.popover.tip && this.popover.tip.contains(e.target)
51
+ }
52
+
53
+ hide (e) {
54
+ if (e && this.clickWithinPopover(e)) {
55
+ return
56
+ }
57
+
58
+ this.popover.hide()
59
+ }
60
+
61
+ onShown () {
62
+ document.addEventListener('click', this.boundHide)
63
+ }
64
+
65
+ onHidden () {
66
+ document.removeEventListener('click', this.boundHide)
67
+ }
68
+
69
+ get popoverOptions () {
70
+ return {
71
+ title: this.title,
72
+ content: this.content,
73
+ placement: this.placementValue,
74
+ trigger: this.triggerValue,
75
+ html: this.htmlValue,
76
+ customClass: this.hasCustomClass ? this.customClass : ''
77
+ }
78
+ }
79
+
80
+ get title () {
81
+ return this.titleValue
82
+ }
83
+
84
+ get content () {
85
+ return this.contentValue
86
+ }
87
+ }
@@ -0,0 +1,34 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ export default class extends ApplicationController {
4
+ static values = {
5
+ url: String
6
+ }
7
+
8
+ initialize () {
9
+ this.boundScrollToTop = this.scrollToTop.bind(this)
10
+ }
11
+
12
+ connect () {
13
+ this.element.addEventListener('turbo:frame-load', this.boundScrollToTop)
14
+ }
15
+
16
+ scrollToTop (e) {
17
+ const scrollTarget = this.element.closest('[data-scroll-target]')
18
+ const boundingRect = scrollTarget.getBoundingClientRect()
19
+
20
+ if (scrollTarget && boundingRect.top < 0) {
21
+ scrollTarget.scrollIntoView()
22
+ }
23
+ }
24
+
25
+ reload () {
26
+ if (this.element.src) {
27
+ this.element.reload()
28
+ } else if (this.hasUrlValue) {
29
+ this.element.src = this.urlValue
30
+ } else {
31
+ this.element.src = document.location.href
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,49 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ import $ from 'jquery'
4
+ import 'select2/dist/js/select2.full'
5
+
6
+ // Use Bootstrap theme
7
+ $.fn.select2.defaults.set('theme', 'bootstrap-5')
8
+
9
+ // Copy all classes from select tag to replacement select field (.select2-selection)
10
+ $.fn.select2.defaults.set('containerCssClass', ':all:')
11
+
12
+ // Copy all classes excluding 'form-control'/'form-control-*'/'form-select'/'form-select-*' from select tag to dropdown container (.select2-dropdown)
13
+ $.fn.select2.defaults.set('dropdownCssClass', function (el) {
14
+ return el[0].className.replace(/\s*form-(control|select)(-\w+)?\s*/g, '')
15
+ })
16
+
17
+ export default class extends ApplicationController {
18
+ connect () {
19
+ $(this.element).select2(this.options)
20
+
21
+ $(this.element).on('change.select2', (e) => {
22
+ if (!e.originalEvent) {
23
+ e.preventDefault()
24
+
25
+ const nativeEvent = new CustomEvent('change', {
26
+ bubbles: true,
27
+ cancelable: true
28
+ })
29
+
30
+ e.target.dispatchEvent(nativeEvent)
31
+ }
32
+ })
33
+ }
34
+
35
+ disconnect () {
36
+ $(this.element).select2('destroy')
37
+ $(this.element).off('change.select2')
38
+ }
39
+
40
+ get options () {
41
+ return {
42
+ dropdownParent: this.dropdownParent
43
+ }
44
+ }
45
+
46
+ get dropdownParent () {
47
+ return this.element.closest('.modal')
48
+ }
49
+ }
@@ -0,0 +1,33 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ import cookie from '../core/cookie'
4
+
5
+ export default class extends ApplicationController {
6
+ static targets = ["inner"]
7
+
8
+ connect () {
9
+ this.scrollToActive()
10
+ }
11
+
12
+ toggle () {
13
+ const bodyClasses = document.body.classList
14
+
15
+ if (bodyClasses.contains('sidebar-expanded') || bodyClasses.contains('sidebar-collapsed')) {
16
+ bodyClasses.remove('sidebar-expanded', 'sidebar-collapsed')
17
+ cookie.delete('trestle:sidebar')
18
+ } else if (document.body.clientWidth >= 1200) {
19
+ bodyClasses.add('sidebar-collapsed')
20
+ cookie.set('trestle:sidebar', 'collapsed')
21
+ } else if (document.body.clientWidth >= 768) {
22
+ bodyClasses.add('sidebar-expanded')
23
+ cookie.set('trestle:sidebar', 'expanded')
24
+ }
25
+ }
26
+
27
+ scrollToActive () {
28
+ const active = this.element.getElementsByClassName('active')[0]
29
+ if (active && this.hasInnerTarget) {
30
+ this.innerTarget.scrollTop = active.offsetTop - 100
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,45 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ import { Tab } from 'bootstrap'
4
+
5
+ export default class extends ApplicationController {
6
+ static values = {
7
+ errorSelector: { type: String, default: '.is-invalid:not([type="hidden"])' }
8
+ }
9
+
10
+ connect () {
11
+ this.element.querySelectorAll('.nav-link').forEach((link) => {
12
+ this.updateErrorCount(link)
13
+ })
14
+
15
+ this.focusFirstTabWithErrors()
16
+ }
17
+
18
+ updateErrorCount (link) {
19
+ const pane = document.querySelector(link.getAttribute('href'))
20
+ const errorCount = pane.querySelectorAll(this.errorSelectorValue).length
21
+
22
+ if (errorCount > 0) {
23
+ const badge = this._createErrorBadge(errorCount)
24
+ link.appendChild(badge)
25
+ }
26
+ }
27
+
28
+ focusFirstTabWithErrors () {
29
+ this.element.querySelectorAll('.nav-link').forEach((link) => {
30
+ if (link.querySelector('.badge-danger')) {
31
+ Tab.getOrCreateInstance(link).show()
32
+ return
33
+ }
34
+ })
35
+ }
36
+
37
+ _createErrorBadge (count) {
38
+ const badge = document.createElement('span')
39
+
40
+ badge.classList.add('badge', 'badge-danger', 'badge-pill')
41
+ badge.textContent = count
42
+
43
+ return badge
44
+ }
45
+ }
@@ -0,0 +1,45 @@
1
+ /* global history, location */
2
+
3
+ import ApplicationController from './application_controller'
4
+
5
+ import { navigator } from '@hotwired/turbo'
6
+ import { Tab } from 'bootstrap'
7
+
8
+ export default class extends ApplicationController {
9
+ connect () {
10
+ this.element.querySelectorAll('.nav-link').forEach((link) => {
11
+ link.addEventListener('shown.bs.tab', this.saveActiveTab)
12
+ })
13
+
14
+ this.focusActiveTab()
15
+ }
16
+
17
+ disconnect () {
18
+ this.element.querySelectorAll('.nav-link').forEach((link) => {
19
+ link.removeEventListener('shown.bs.tab', this.saveActiveTab)
20
+ })
21
+ }
22
+
23
+ saveActiveTab (e) {
24
+ const hash = e.target.getAttribute('href')
25
+
26
+ if (hash.substring(0, 1) === '#') {
27
+ const url = `${location.pathname}#!${hash.substring(1)}`
28
+
29
+ history.replaceState({}, null, url)
30
+ navigator.history.replace(new URL(url, location.origin))
31
+ }
32
+ }
33
+
34
+ focusActiveTab () {
35
+ if (location.hash.substring(0, 2) === '#!') {
36
+ const hash = location.hash.substring(2)
37
+ const link = this.element.querySelector(`.nav-link[href='#${hash}']`)
38
+
39
+ if (link) {
40
+ const tab = new Tab(link)
41
+ tab.show()
42
+ }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,14 @@
1
+ import FlatpickrController from './flatpickr_controller'
2
+
3
+ import { i18n } from '../core/i18n'
4
+
5
+ export default class extends FlatpickrController {
6
+ get options () {
7
+ return {
8
+ ...super.options,
9
+ enableTime: true,
10
+ noCalendar: true,
11
+ altFormat: i18n.t('admin.datepicker.formats.time', { defaultValue: 'h:i K' })
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,27 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ export default class extends ApplicationController {
4
+ static targets = ["item"]
5
+
6
+ static values = {
7
+ attribute: String
8
+ }
9
+
10
+ toggle () {
11
+ this.itemTargets.forEach((item) => {
12
+ item[this.attributeValue] = !item[this.attributeValue]
13
+ })
14
+ }
15
+
16
+ set () {
17
+ this.itemTargets.forEach((item) => {
18
+ item[this.attributeValue] = true
19
+ })
20
+ }
21
+
22
+ unset () {
23
+ this.itemTargets.forEach((item) => {
24
+ item[this.attributeValue] = false
25
+ })
26
+ }
27
+ }
@@ -0,0 +1,27 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ export default class extends ApplicationController {
4
+ static targets = ["item"]
5
+
6
+ static values = {
7
+ class: String
8
+ }
9
+
10
+ toggle () {
11
+ this.itemTargets.forEach((item) => {
12
+ item.classList.toggle(this.classValue)
13
+ })
14
+ }
15
+
16
+ add () {
17
+ this.itemTargets.forEach((item) => {
18
+ item.classList.add(this.classValue)
19
+ })
20
+ }
21
+
22
+ remove () {
23
+ this.itemTargets.forEach((item) => {
24
+ item.classList.remove(this.classValue)
25
+ })
26
+ }
27
+ }
@@ -0,0 +1,13 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ import { Tooltip } from 'bootstrap'
4
+
5
+ export default class extends ApplicationController {
6
+ connect () {
7
+ this.tooltip = new Tooltip(this.element)
8
+ }
9
+
10
+ disconnect () {
11
+ this.tooltip.dispose()
12
+ }
13
+ }
@@ -0,0 +1,43 @@
1
+ import ApplicationController from './application_controller'
2
+
3
+ export default class extends ApplicationController {
4
+ static outlets = ['mobile-sidebar']
5
+
6
+ initialize () {
7
+ this.boundStopAnimating = this.stopAnimating.bind(this)
8
+ }
9
+
10
+ connect () {
11
+ this.element.addEventListener('transitionend', this.boundStopAnimating)
12
+ }
13
+
14
+ disconnect () {
15
+ this.element.removeEventListener('transitionend', this.boundStopAnimating)
16
+ }
17
+
18
+ animate () {
19
+ this.element.classList.add('animate')
20
+ }
21
+
22
+ stopAnimating () {
23
+ this.element.classList.remove('animate')
24
+ }
25
+
26
+ hideMobileSidebar (e) {
27
+ const sidebarController = this.mobileSidebarOutlet
28
+
29
+ if (!sidebarController.isExpanded) {
30
+ return
31
+ }
32
+
33
+ const clickInHeader = e.target.closest('.app-header')
34
+ const clickInSidebar = e.target.closest('.app-sidebar')
35
+
36
+ if (!clickInHeader && !clickInSidebar) {
37
+ e.stopPropagation()
38
+ e.preventDefault()
39
+
40
+ sidebarController.hide()
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,100 @@
1
+ import Modal from './modal'
2
+
3
+ import { reflow, execute, executeAfterTransition } from '../util/bootstrap'
4
+
5
+ const Default = {
6
+ className: 'modal-backdrop',
7
+ isAnimated: true
8
+ }
9
+
10
+ const CLASS_NAME_FADE = 'fade'
11
+ const CLASS_NAME_SHOW = 'show'
12
+ const CLASS_NAME_LOADING = 'loading'
13
+
14
+ export default class Backdrop {
15
+ static getInstance () {
16
+ if (!this.instance) {
17
+ this.instance = new Backdrop()
18
+ }
19
+
20
+ return this.instance
21
+ }
22
+
23
+ constructor () {
24
+ this._config = Default
25
+ this._element = null
26
+ this._isAppended = false
27
+ }
28
+
29
+ show (callback) {
30
+ this._append()
31
+
32
+ if (this._config.isAnimated) {
33
+ reflow(this._getElement())
34
+ }
35
+
36
+ this._getElement().classList.add(CLASS_NAME_SHOW)
37
+
38
+ this._emulateAnimation(() => {
39
+ execute(callback)
40
+ })
41
+ }
42
+
43
+ hide (callback) {
44
+ if (Modal.existing.length === 0) {
45
+ this._getElement().classList.remove(CLASS_NAME_SHOW)
46
+ }
47
+
48
+ this._emulateAnimation(() => {
49
+ this.dispose()
50
+ execute(callback)
51
+ Modal.restorePrevious()
52
+ })
53
+ }
54
+
55
+ dispose () {
56
+ if (!this._isAppended) {
57
+ return
58
+ }
59
+
60
+ if (Modal.existing.length === 0) {
61
+ this._element.remove()
62
+ this._isAppended = false
63
+ }
64
+ }
65
+
66
+ loading (isLoading) {
67
+ const el = this._getElement()
68
+ el.classList[isLoading ? 'add' : 'remove'](CLASS_NAME_LOADING)
69
+ }
70
+
71
+ // Private
72
+
73
+ _getElement () {
74
+ if (!this._element) {
75
+ const backdrop = document.createElement('div')
76
+ backdrop.className = this._config.className
77
+ if (this._config.isAnimated) {
78
+ backdrop.classList.add(CLASS_NAME_FADE)
79
+ }
80
+
81
+ this._element = backdrop
82
+ }
83
+
84
+ return this._element
85
+ }
86
+
87
+ _append () {
88
+ if (this._isAppended) {
89
+ return
90
+ }
91
+
92
+ document.body.append(this._getElement())
93
+
94
+ this._isAppended = true
95
+ }
96
+
97
+ _emulateAnimation (callback) {
98
+ executeAfterTransition(callback, this._getElement(), this._config.isAnimated)
99
+ }
100
+ }
@@ -0,0 +1,65 @@
1
+ /* global DOMParser */
2
+
3
+ import { i18n } from '../core/i18n'
4
+
5
+ const TEMPLATE = () => `
6
+ <div class="modal fade error-modal" tabindex="-1" data-controller="modal">
7
+ <div class="modal-dialog modal-xl">
8
+ <div class="modal-content">
9
+ <div class="modal-header">
10
+ <h4 class="modal-title"></h4>
11
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
12
+ </div>
13
+
14
+ <div class="modal-body">
15
+ </div>
16
+
17
+ <div class="modal-footer">
18
+ <button type="button" class="btn btn-light" data-bs-dismiss="modal" aria-label="OK">${i18n.t('admin.buttons.ok', { defaultValue: 'OK' })}</button>
19
+ </div
20
+ </div>
21
+ </div>
22
+ </div>
23
+ `
24
+
25
+ export default class ErrorModal {
26
+ static show ({ title, content }) {
27
+ new ErrorModal({ title, content }).show()
28
+ }
29
+
30
+ constructor ({ title, content }) {
31
+ this.title = title
32
+ this.content = content
33
+ }
34
+
35
+ show () {
36
+ this._append(this._buildModal())
37
+ }
38
+
39
+ // Private
40
+
41
+ _buildModal () {
42
+ const el = this._buildWrapper()
43
+ el.querySelector('.modal-title').textContent = this.title
44
+
45
+ const iframe = this._buildIframe(this.content)
46
+ el.querySelector('.modal-body').append(iframe)
47
+
48
+ return el
49
+ }
50
+
51
+ _buildWrapper () {
52
+ return new DOMParser().parseFromString(TEMPLATE(), 'text/html').body.childNodes[0]
53
+ }
54
+
55
+ _buildIframe () {
56
+ const iframe = document.createElement('iframe')
57
+ iframe.className = 'error-iframe'
58
+ iframe.srcdoc = this.content
59
+ return iframe
60
+ }
61
+
62
+ _append (el) {
63
+ document.getElementById('modal').append(el)
64
+ }
65
+ }
@@ -0,0 +1,32 @@
1
+ /* global fetch */
2
+
3
+ import { renderStreamMessage } from '@hotwired/turbo'
4
+
5
+ import ErrorModal from './error_modal'
6
+
7
+ export function fetchWithErrorHandling (url, options = {}) {
8
+ return fetch(url, options)
9
+ .then(response => {
10
+ if (!response.ok) { throw response }
11
+ return response
12
+ })
13
+ .catch(response => {
14
+ const title = `${response.status} (${response.statusText})`
15
+ response.text().then(content => ErrorModal.show({ title, content }))
16
+ })
17
+ }
18
+
19
+ export function fetchTurboStream (url, options = {}) {
20
+ options = {
21
+ ...options,
22
+
23
+ headers: {
24
+ Accept: 'text/vnd.turbo-stream.html',
25
+ ...options.headers
26
+ }
27
+ }
28
+
29
+ return fetchWithErrorHandling(url, options)
30
+ .then(response => response.text())
31
+ .then(html => renderStreamMessage(html))
32
+ }
@@ -1,20 +1,24 @@
1
+ import { I18n } from 'i18n-js'
1
2
  import flatpickr from 'flatpickr'
2
3
 
3
4
  // Container for i18n translations
4
- export const i18n = {}
5
+ export const i18n = new I18n()
6
+
7
+ function localizeTrestle (locale, fallbacks) {
8
+ // Set up i18n fallbacks
9
+ i18n.enableFallback = true
10
+ i18n.locales.register(locale, [locale, ...fallbacks])
11
+
12
+ // Set current locale
13
+ i18n.locale = locale
14
+ }
5
15
 
6
16
  // Some of Flatpickr's locale names differ from Rails. This maps the Rails I18n locale to their Flatpickr equivalent.
7
17
  const FlatpickrLocaleConversions = { ca: 'cat', el: 'gr', nb: 'no', vi: 'vn' }
8
18
 
9
- // Sets up localization for Trestle and its dependencies, in particular Flatpickr.
10
- // This method accepts a list of locales in descending order of priority.
11
- //
12
- // Trestle.localize('es-MX', 'es', 'en')
13
- //
14
- export function localize () {
15
- for (var i = 0; i < arguments.length; ++i) {
16
- var locale = arguments[i]
17
- var flatpickrLocale = FlatpickrLocaleConversions[locale] || locale
19
+ function localizeFlatpickr (...locales) {
20
+ for (const locale of locales) {
21
+ const flatpickrLocale = FlatpickrLocaleConversions[locale] || locale
18
22
 
19
23
  if (flatpickr.l10ns[flatpickrLocale]) {
20
24
  flatpickr.localize(flatpickr.l10ns[flatpickrLocale])
@@ -22,3 +26,13 @@ export function localize () {
22
26
  }
23
27
  }
24
28
  }
29
+
30
+ // Sets up localization for Trestle and its dependencies, in particular Flatpickr.
31
+ // This method accepts a list of locales in descending order of priority.
32
+ //
33
+ // Trestle.localize('es-MX', 'es', 'en')
34
+ //
35
+ export function localize (locale, ...fallbacks) {
36
+ localizeTrestle(locale, fallbacks)
37
+ localizeFlatpickr(locale, ...fallbacks)
38
+ }