adminterface 0.0.0 → 0.2.3

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 (271) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +1 -1
  3. data/README.md +69 -0
  4. data/Rakefile +43 -0
  5. data/app/assets/config/adminterface_manifest.js +1 -0
  6. data/app/assets/stylesheets/adminterface/_base.scss +20 -0
  7. data/app/assets/stylesheets/adminterface/_print.scss +56 -0
  8. data/app/assets/stylesheets/adminterface/components/_active_admin_comment.scss +19 -0
  9. data/app/assets/stylesheets/adminterface/components/_all.scss +24 -0
  10. data/app/assets/stylesheets/adminterface/components/_aside.scss +28 -0
  11. data/app/assets/stylesheets/adminterface/components/_attributes_table.scss +19 -0
  12. data/app/assets/stylesheets/adminterface/components/_comments.scss +7 -0
  13. data/app/assets/stylesheets/adminterface/components/_divider.scss +28 -0
  14. data/app/assets/stylesheets/adminterface/components/_filters.scss +27 -0
  15. data/app/assets/stylesheets/adminterface/components/_flash.scss +4 -0
  16. data/app/assets/stylesheets/adminterface/components/_footer.scss +4 -0
  17. data/app/assets/stylesheets/adminterface/components/_form.scss +219 -0
  18. data/app/assets/stylesheets/adminterface/components/_header.scss +30 -0
  19. data/app/assets/stylesheets/adminterface/components/_index.scss +1 -0
  20. data/app/assets/stylesheets/adminterface/components/_index_as_grid.scss +5 -0
  21. data/app/assets/stylesheets/adminterface/components/_index_as_table.scss +1 -0
  22. data/app/assets/stylesheets/adminterface/components/_index_footer.scss +19 -0
  23. data/app/assets/stylesheets/adminterface/components/_modal_dialog.scss +4 -0
  24. data/app/assets/stylesheets/adminterface/components/_pagination.scss +3 -0
  25. data/app/assets/stylesheets/adminterface/components/_panel.scss +21 -0
  26. data/app/assets/stylesheets/adminterface/components/_sidebar.scss +13 -0
  27. data/app/assets/stylesheets/adminterface/components/_site_title.scss +17 -0
  28. data/app/assets/stylesheets/adminterface/components/_table_for.scss +37 -0
  29. data/app/assets/stylesheets/adminterface/components/_table_tools.scss +19 -0
  30. data/app/assets/stylesheets/adminterface/components/_thumbnail.scss +29 -0
  31. data/app/assets/stylesheets/adminterface/components/_title_bar.scss +36 -0
  32. data/app/assets/stylesheets/adminterface/components/inputs/_all.scss +2 -0
  33. data/app/assets/stylesheets/adminterface/components/inputs/_password.scss +28 -0
  34. data/app/assets/stylesheets/adminterface/components/inputs/_text.scss +30 -0
  35. data/app/assets/stylesheets/adminterface/helpers/_aa_icon.scss +1 -0
  36. data/app/assets/stylesheets/adminterface/helpers/_all.scss +2 -0
  37. data/app/assets/stylesheets/adminterface/helpers/_pointer.scss +1 -0
  38. data/app/assets/stylesheets/adminterface/layouts/_all.scss +4 -0
  39. data/app/assets/stylesheets/adminterface/layouts/_base.scss +5 -0
  40. data/app/assets/stylesheets/adminterface/layouts/_logged_in.scss +30 -0
  41. data/app/assets/stylesheets/adminterface/layouts/_logged_out.scss +14 -0
  42. data/app/assets/stylesheets/adminterface/layouts/types/_all.scss +4 -0
  43. data/app/assets/stylesheets/adminterface/layouts/types/_mixins.scss +195 -0
  44. data/app/assets/stylesheets/adminterface/layouts/types/_navigation_aside.scss +33 -0
  45. data/app/assets/stylesheets/adminterface/layouts/types/_navigation_sidebar.scss +15 -0
  46. data/app/assets/stylesheets/adminterface/layouts/types/_navigation_top.scss +33 -0
  47. data/app/assets/stylesheets/adminterface/mixins/_all.scss +3 -0
  48. data/app/assets/stylesheets/adminterface/mixins/_layouts.scss +38 -0
  49. data/app/assets/stylesheets/adminterface/mixins/_utilities.scss +39 -0
  50. data/app/assets/stylesheets/adminterface/mixins/_variables.scss +100 -0
  51. data/app/assets/stylesheets/adminterface/placeholders/_aa_icon.scss +10 -0
  52. data/app/assets/stylesheets/adminterface/placeholders/_all.scss +3 -0
  53. data/app/assets/stylesheets/adminterface/placeholders/_background.scss +5 -0
  54. data/app/assets/stylesheets/adminterface/placeholders/_typography.scss +11 -0
  55. data/app/assets/stylesheets/adminterface/vendors/_all.scss +4 -0
  56. data/app/assets/stylesheets/adminterface/vendors/bootstrap/_all.scss +6 -0
  57. data/app/assets/stylesheets/adminterface/vendors/bootstrap/_variables.scss +51 -0
  58. data/app/assets/stylesheets/adminterface/vendors/bootstrap/components/_buttons.scss +5 -0
  59. data/app/assets/stylesheets/adminterface/vendors/bootstrap/components/_dropdowns.scss +28 -0
  60. data/app/assets/stylesheets/adminterface/vendors/bootstrap/components/_navs.scss +25 -0
  61. data/app/assets/stylesheets/adminterface/vendors/bootstrap/components/form/_labels.scss +5 -0
  62. data/app/assets/stylesheets/adminterface/vendors/bootstrap/content/_tables.scss +2 -0
  63. data/app/assets/stylesheets/adminterface/vendors/bootstrap/content/_typography.scss +2 -0
  64. data/app/assets/stylesheets/adminterface/vendors/flatpickr/_all.scss +2 -0
  65. data/app/assets/stylesheets/adminterface/vendors/flatpickr/_variables.scss +7 -0
  66. data/app/assets/stylesheets/adminterface/vendors/flatpickr/main.scss +50 -0
  67. data/app/assets/stylesheets/adminterface/vendors/tom_select/_all.scss +1 -0
  68. data/app/assets/stylesheets/adminterface/vendors/tom_select/_main.scss +6 -0
  69. data/app/assets/stylesheets/adminterface/vendors/trix/_actiontext.scss +36 -0
  70. data/app/assets/stylesheets/adminterface/vendors/trix/_all.scss +3 -0
  71. data/app/assets/stylesheets/adminterface/vendors/trix/_trix_editor.scss +86 -0
  72. data/app/assets/stylesheets/adminterface/vendors/trix/_variables.scss +31 -0
  73. data/app/javascript/adminterface/base.js +14 -0
  74. data/app/javascript/adminterface/config.js +129 -0
  75. data/app/javascript/adminterface/initializers/batch_actions.js +9 -0
  76. data/app/javascript/adminterface/initializers/bootstrap.js +29 -0
  77. data/app/javascript/adminterface/initializers/confirm_dialog.js +23 -0
  78. data/app/javascript/adminterface/initializers/detached_dropdown.js +16 -0
  79. data/app/javascript/adminterface/initializers/drawer_menu_item_toggler.js +15 -0
  80. data/app/javascript/adminterface/initializers/filters.js +23 -0
  81. data/app/javascript/adminterface/initializers/has_many.js +7 -0
  82. data/app/javascript/adminterface/initializers/header_toggler.js +10 -0
  83. data/app/javascript/adminterface/initializers/index.js +2 -0
  84. data/app/javascript/adminterface/initializers/per_page.js +12 -0
  85. data/app/javascript/adminterface/initializers/plugins/flatpickr.js +24 -0
  86. data/app/javascript/adminterface/initializers/plugins/input_counter.js +21 -0
  87. data/app/javascript/adminterface/initializers/plugins/password_visibility.js +23 -0
  88. data/app/javascript/adminterface/initializers/plugins/tom_select.js +24 -0
  89. data/app/javascript/adminterface/lib/__tests__/checkbox_toggler.html +5 -0
  90. data/app/javascript/adminterface/lib/__tests__/checkbox_toggler.spec.js +110 -0
  91. data/app/javascript/adminterface/lib/__tests__/detached_dropdown.spec.js +69 -0
  92. data/app/javascript/adminterface/lib/__tests__/filters.spec.js +150 -0
  93. data/app/javascript/adminterface/lib/__tests__/has_many.html +14 -0
  94. data/app/javascript/adminterface/lib/__tests__/has_many.spec.js +224 -0
  95. data/app/javascript/adminterface/lib/__tests__/utils.spec.js +280 -0
  96. data/app/javascript/adminterface/lib/batch_actions.js +106 -0
  97. data/app/javascript/adminterface/lib/checkbox_toggler.js +55 -0
  98. data/app/javascript/adminterface/lib/confirm_dialog.js +113 -0
  99. data/app/javascript/adminterface/lib/detached_dropdown.js +34 -0
  100. data/app/javascript/adminterface/lib/filters.js +34 -0
  101. data/app/javascript/adminterface/lib/has_many.js +125 -0
  102. data/app/javascript/adminterface/lib/header_toggler.js +54 -0
  103. data/app/javascript/adminterface/lib/input.js +108 -0
  104. data/app/javascript/adminterface/lib/inputs/base/groupish.js +55 -0
  105. data/app/javascript/adminterface/lib/inputs/base/pluginish.js +63 -0
  106. data/app/javascript/adminterface/lib/inputs/base_input.js +87 -0
  107. data/app/javascript/adminterface/lib/inputs/boolean_input.js +30 -0
  108. data/app/javascript/adminterface/lib/inputs/check_boxes_input.js +14 -0
  109. data/app/javascript/adminterface/lib/inputs/choices_input.js +96 -0
  110. data/app/javascript/adminterface/lib/inputs/color_input.js +14 -0
  111. data/app/javascript/adminterface/lib/inputs/country_input.js +90 -0
  112. data/app/javascript/adminterface/lib/inputs/datalist_input.js +41 -0
  113. data/app/javascript/adminterface/lib/inputs/date_picker_input.js +11 -0
  114. data/app/javascript/adminterface/lib/inputs/datetime_picker_input.js +11 -0
  115. data/app/javascript/adminterface/lib/inputs/hidden_input.js +21 -0
  116. data/app/javascript/adminterface/lib/inputs/password_input.js +13 -0
  117. data/app/javascript/adminterface/lib/inputs/radio_input.js +13 -0
  118. data/app/javascript/adminterface/lib/inputs/select_input.js +68 -0
  119. data/app/javascript/adminterface/lib/inputs/string_input.js +13 -0
  120. data/app/javascript/adminterface/lib/inputs/switch_input.js +9 -0
  121. data/app/javascript/adminterface/lib/inputs/text_input.js +12 -0
  122. data/app/javascript/adminterface/lib/inputs/time_picker_input.js +13 -0
  123. data/app/javascript/adminterface/lib/inputs/time_zone_input.js +66 -0
  124. data/app/javascript/adminterface/lib/per_page.js +18 -0
  125. data/app/javascript/adminterface/lib/plugins/input_counter.js +94 -0
  126. data/app/javascript/adminterface/lib/plugins/password_visibility.js +70 -0
  127. data/app/javascript/adminterface/lib/table_checkbox_toggler.js +47 -0
  128. data/app/javascript/adminterface/lib/utils.js +148 -0
  129. data/app/views/active_admin/devise/confirmations/new.html.erb +19 -0
  130. data/app/views/active_admin/devise/passwords/edit.html.erb +21 -0
  131. data/app/views/active_admin/devise/passwords/new.html.erb +19 -0
  132. data/app/views/active_admin/devise/registrations/new.html.erb +24 -0
  133. data/app/views/active_admin/devise/sessions/new.html.erb +23 -0
  134. data/app/views/active_admin/devise/shared/_links.html.erb +25 -0
  135. data/app/views/active_admin/devise/shared/_omniauth.html.erb +10 -0
  136. data/app/views/active_admin/devise/unlocks/new.html.erb +19 -0
  137. data/app/views/kaminari/active_admin/_first_page.html.erb +11 -0
  138. data/app/views/kaminari/active_admin/_gap.html.erb +12 -0
  139. data/app/views/kaminari/active_admin/_last_page.html.erb +11 -0
  140. data/app/views/kaminari/active_admin/_next_page.html.erb +11 -0
  141. data/app/views/kaminari/active_admin/_page.html.erb +12 -0
  142. data/app/views/kaminari/active_admin/_paginator.html.erb +27 -0
  143. data/app/views/kaminari/active_admin/_prev_page.html.erb +11 -0
  144. data/app/views/layouts/active_admin_logged_out.html.erb +56 -0
  145. data/config/locales/active_admin.en.yml +25 -0
  146. data/lib/adminterface/callable.rb +7 -0
  147. data/lib/adminterface/configs.rb +76 -0
  148. data/lib/adminterface/data/base.rb +11 -0
  149. data/lib/adminterface/data/countries.rb +44 -0
  150. data/lib/adminterface/data/time_zones.rb +31 -0
  151. data/lib/adminterface/data.rb +6 -0
  152. data/lib/adminterface/encryption/encryptor.rb +26 -0
  153. data/lib/adminterface/engine.rb +22 -0
  154. data/lib/adminterface/extensions/base_controller.rb +59 -0
  155. data/lib/adminterface/extensions/batch_actions/resource_extension.rb +64 -0
  156. data/lib/adminterface/extensions/batch_actions/views/batch_action_selector.rb +48 -0
  157. data/lib/adminterface/extensions/batch_actions/views/selection_cells.rb +39 -0
  158. data/lib/adminterface/extensions/dsl.rb +13 -0
  159. data/lib/adminterface/extensions/dynamic_settings_node.rb +26 -0
  160. data/lib/adminterface/extensions/filters/forms.rb +76 -0
  161. data/lib/adminterface/extensions/form_builder.rb +165 -0
  162. data/lib/adminterface/extensions/inputs/base/active_admin_config.rb +21 -0
  163. data/lib/adminterface/extensions/inputs/base/choices.rb +33 -0
  164. data/lib/adminterface/extensions/inputs/base/groupish.rb +50 -0
  165. data/lib/adminterface/extensions/inputs/base/html.rb +15 -0
  166. data/lib/adminterface/extensions/inputs/base/labelling.rb +15 -0
  167. data/lib/adminterface/extensions/inputs/base/pluginish.rb +56 -0
  168. data/lib/adminterface/extensions/inputs/base/stringish.rb +19 -0
  169. data/lib/adminterface/extensions/inputs/base/wrapping.rb +25 -0
  170. data/lib/adminterface/extensions/inputs/base.rb +19 -0
  171. data/lib/adminterface/extensions/inputs/boolean_input.rb +42 -0
  172. data/lib/adminterface/extensions/inputs/check_boxes_input.rb +34 -0
  173. data/lib/adminterface/extensions/inputs/color_input.rb +29 -0
  174. data/lib/adminterface/extensions/inputs/country_input.rb +33 -0
  175. data/lib/adminterface/extensions/inputs/datalist_input.rb +26 -0
  176. data/lib/adminterface/extensions/inputs/date_picker_input.rb +30 -0
  177. data/lib/adminterface/extensions/inputs/date_select_input.rb +7 -0
  178. data/lib/adminterface/extensions/inputs/datetime_picker_input.rb +19 -0
  179. data/lib/adminterface/extensions/inputs/datetime_select_input.rb +7 -0
  180. data/lib/adminterface/extensions/inputs/email_input.rb +23 -0
  181. data/lib/adminterface/extensions/inputs/file_input.rb +19 -0
  182. data/lib/adminterface/extensions/inputs/filters/base/search_method_select.rb +37 -0
  183. data/lib/adminterface/extensions/inputs/filters/base.rb +3 -0
  184. data/lib/adminterface/extensions/inputs/filters/boolean_input.rb +4 -0
  185. data/lib/adminterface/extensions/inputs/filters/check_boxes_input.rb +12 -0
  186. data/lib/adminterface/extensions/inputs/filters/date_picker_input.rb +4 -0
  187. data/lib/adminterface/extensions/inputs/filters/date_range_input.rb +50 -0
  188. data/lib/adminterface/extensions/inputs/filters/select_input.rb +4 -0
  189. data/lib/adminterface/extensions/inputs/number_input.rb +23 -0
  190. data/lib/adminterface/extensions/inputs/password_input.rb +23 -0
  191. data/lib/adminterface/extensions/inputs/phone_input.rb +23 -0
  192. data/lib/adminterface/extensions/inputs/radio_input.rb +41 -0
  193. data/lib/adminterface/extensions/inputs/range_input.rb +22 -0
  194. data/lib/adminterface/extensions/inputs/rich_text_area_input.rb +21 -0
  195. data/lib/adminterface/extensions/inputs/search_input.rb +23 -0
  196. data/lib/adminterface/extensions/inputs/select_input.rb +33 -0
  197. data/lib/adminterface/extensions/inputs/string_input.rb +19 -0
  198. data/lib/adminterface/extensions/inputs/switch_input.rb +11 -0
  199. data/lib/adminterface/extensions/inputs/text_input.rb +27 -0
  200. data/lib/adminterface/extensions/inputs/time_picker_input.rb +19 -0
  201. data/lib/adminterface/extensions/inputs/time_select_input.rb +7 -0
  202. data/lib/adminterface/extensions/inputs/time_zone_input.rb +33 -0
  203. data/lib/adminterface/extensions/inputs/url_input.rb +23 -0
  204. data/lib/adminterface/extensions/menu_item.rb +16 -0
  205. data/lib/adminterface/extensions/namespace_settings.rb +30 -0
  206. data/lib/adminterface/extensions/orm/active_record/comments/views/active_admin_comments.rb +122 -0
  207. data/lib/adminterface/extensions/resource/action_items.rb +117 -0
  208. data/lib/adminterface/extensions/sidebar_section.rb +35 -0
  209. data/lib/adminterface/extensions/view_helpers/alert_helper.rb +38 -0
  210. data/lib/adminterface/extensions/view_helpers/component_helper.rb +23 -0
  211. data/lib/adminterface/extensions/views/action_items.rb +39 -0
  212. data/lib/adminterface/extensions/views/columns.rb +59 -0
  213. data/lib/adminterface/extensions/views/components/active_admin_form.rb +47 -0
  214. data/lib/adminterface/extensions/views/components/attributes_table.rb +28 -0
  215. data/lib/adminterface/extensions/views/components/blank_slate.rb +19 -0
  216. data/lib/adminterface/extensions/views/components/dropdown_menu.rb +58 -0
  217. data/lib/adminterface/extensions/views/components/icon.rb +26 -0
  218. data/lib/adminterface/extensions/views/components/index_list.rb +43 -0
  219. data/lib/adminterface/extensions/views/components/menu.rb +18 -0
  220. data/lib/adminterface/extensions/views/components/menu_item.rb +69 -0
  221. data/lib/adminterface/extensions/views/components/paginated_collection.rb +52 -0
  222. data/lib/adminterface/extensions/views/components/panel.rb +71 -0
  223. data/lib/adminterface/extensions/views/components/scopes.rb +53 -0
  224. data/lib/adminterface/extensions/views/components/sidebar_section.rb +39 -0
  225. data/lib/adminterface/extensions/views/components/site_title.rb +36 -0
  226. data/lib/adminterface/extensions/views/components/status_tag.rb +26 -0
  227. data/lib/adminterface/extensions/views/components/table_for.rb +23 -0
  228. data/lib/adminterface/extensions/views/components/tabs.rb +101 -0
  229. data/lib/adminterface/extensions/views/footer.rb +27 -0
  230. data/lib/adminterface/extensions/views/header.rb +60 -0
  231. data/lib/adminterface/extensions/views/index_as_grid.rb +53 -0
  232. data/lib/adminterface/extensions/views/index_as_table.rb +77 -0
  233. data/lib/adminterface/extensions/views/pages/base.rb +165 -0
  234. data/lib/adminterface/extensions/views/pages/form.rb +27 -0
  235. data/lib/adminterface/extensions/views/pages/index.rb +136 -0
  236. data/lib/adminterface/extensions/views/pages/page.rb +18 -0
  237. data/lib/adminterface/extensions/views/title_bar.rb +74 -0
  238. data/lib/adminterface/fixtures/components.yml +73 -0
  239. data/lib/adminterface/fixtures/css_classes.yml +107 -0
  240. data/lib/adminterface/initializers/batch_actions.rb +15 -0
  241. data/lib/adminterface/initializers/comments.rb +13 -0
  242. data/lib/adminterface/initializers/configurations.rb +38 -0
  243. data/lib/adminterface/initializers/formtastic.rb +58 -0
  244. data/lib/adminterface/initializers/resource.rb +20 -0
  245. data/lib/adminterface/initializers/view_helpers.rb +14 -0
  246. data/lib/adminterface/initializers/views.rb +39 -0
  247. data/lib/adminterface/license.rb +18 -0
  248. data/lib/adminterface/licensing/base.rb +99 -0
  249. data/lib/adminterface/licensing/commercial.rb +7 -0
  250. data/lib/adminterface/licensing/notice.rb +54 -0
  251. data/lib/adminterface/licensing/personal.rb +13 -0
  252. data/lib/adminterface/public.pem +9 -0
  253. data/lib/adminterface/version.rb +3 -0
  254. data/lib/adminterface.rb +55 -0
  255. data/lib/generators/adminterface/comments/comments_generator.rb +33 -0
  256. data/lib/generators/adminterface/comments/templates/README +13 -0
  257. data/lib/generators/adminterface/comments/templates/active_admin_comment_action_text.rb +18 -0
  258. data/lib/generators/adminterface/comments/templates/migrations/drop_body_for_active_admin_comments.rb.erb +28 -0
  259. data/lib/generators/adminterface/configs/configs_generator.rb +19 -0
  260. data/lib/generators/adminterface/configs/templates/README +33 -0
  261. data/lib/generators/adminterface/install/install_generator.rb +39 -0
  262. data/lib/generators/adminterface/install/templates/dashboard.rb +32 -0
  263. data/lib/generators/adminterface/views/views_generator.rb +15 -0
  264. data/lib/generators/adminterface/webpacker/templates/README +27 -0
  265. data/lib/generators/adminterface/webpacker/templates/active_admin.js +12 -0
  266. data/lib/generators/adminterface/webpacker/templates/active_admin.scss +8 -0
  267. data/lib/generators/adminterface/webpacker/templates/print.scss +3 -0
  268. data/lib/generators/adminterface/webpacker/webpacker_generator.rb +69 -0
  269. data/lib/tasks/adminterface_tasks.rake +4 -0
  270. metadata +291 -10
  271. data/lib/name.rb +0 -1
@@ -0,0 +1,29 @@
1
+ /* global adminterface */
2
+ import { Popover, Tooltip } from 'bootstrap'
3
+
4
+ const initBootstrap = function (element) {
5
+ const popoverTriggerList = [].slice.call(element.querySelectorAll('[data-bs-toggle="popover"]'))
6
+ const tooltipTriggerList = [].slice.call(element.querySelectorAll('[data-bs-toggle="tooltip"]'))
7
+
8
+ popoverTriggerList.map((el) => {
9
+ const instance = new Popover(el)
10
+ adminterface.addObserver(el, instance, instance.constructor.name)
11
+ return instance
12
+ })
13
+
14
+ tooltipTriggerList.map((el) => {
15
+ const instance = new Tooltip(el)
16
+ adminterface.addObserver(el, instance, instance.constructor.name)
17
+ return instance
18
+ })
19
+ }
20
+
21
+ document.addEventListener('DOMContentLoaded', () => {
22
+ initBootstrap(document)
23
+ })
24
+
25
+ document.addEventListener('confirm_dialog:before_open', (el) => {
26
+ initBootstrap(el.detail.dialogForm)
27
+ })
28
+
29
+ export default initBootstrap
@@ -0,0 +1,23 @@
1
+ import Rails from '@rails/ujs'
2
+ import ConfirmDialog from '../lib/confirm_dialog'
3
+
4
+ let __SkipConfirmation = false
5
+
6
+ Rails.confirm = function (message, element) {
7
+ const options = JSON.parse(element.dataset.aaConfirmDialog || '{}')
8
+ const inputs = JSON.parse(element.dataset.inputs || '{}')
9
+
10
+ if (__SkipConfirmation) return true
11
+
12
+ function onConfirm () {
13
+ __SkipConfirmation = true
14
+ element.click()
15
+ __SkipConfirmation = false
16
+ }
17
+
18
+ /* eslint-disable no-new */
19
+ new ConfirmDialog(message, inputs, options, onConfirm)
20
+ /* eslint-enable no-new */
21
+
22
+ return false
23
+ }
@@ -0,0 +1,16 @@
1
+ import DetachedDropdown from '../lib/detached_dropdown'
2
+
3
+ const initDetachedDropdown = function (element) {
4
+ const dropdownTriggerList = [].slice.call(element.querySelectorAll('.dropdown'))
5
+ dropdownTriggerList.map((el) => new DetachedDropdown(el, {}))
6
+ }
7
+
8
+ document.addEventListener('DOMContentLoaded', () => {
9
+ initDetachedDropdown(document.getElementById('active_admin_content'))
10
+ })
11
+
12
+ document.addEventListener('confirm_dialog:before_open', (el) => {
13
+ initDetachedDropdown(el.detail.dialogForm)
14
+ })
15
+
16
+ export default initDetachedDropdown
@@ -0,0 +1,15 @@
1
+ import { Dropdown } from 'bootstrap'
2
+
3
+ document.addEventListener('DOMContentLoaded', () => {
4
+ const shouldToggle =
5
+ document.body.classList.contains('layout-navigation-sidebar') ||
6
+ document.body.classList.contains('layout-navigation-aside')
7
+
8
+ if (shouldToggle) {
9
+ document.querySelectorAll('#header .dropdown-toggle.active').forEach((element) => {
10
+ const dropdown = Dropdown.getOrCreateInstance(element)
11
+ dropdown.show()
12
+ element.blur()
13
+ })
14
+ }
15
+ })
@@ -0,0 +1,23 @@
1
+ /* global adminterface */
2
+ import Filters from '../lib/filters'
3
+
4
+ document.addEventListener('DOMContentLoaded', () => {
5
+ const clearFilterBtn = document.querySelector('.clear_filters_btn')
6
+ const filterForm = document.querySelector('.filter_form')
7
+ const selectAndSearch = [].slice.call(document.querySelectorAll('.filter_form_field.select_and_search select'))
8
+
9
+ if (clearFilterBtn) {
10
+ clearFilterBtn.addEventListener('click', Filters._clearForm)
11
+ adminterface.addObserver(clearFilterBtn, { events: { click: Filters._clearForm } }, 'filters.clear')
12
+ }
13
+
14
+ if (filterForm) {
15
+ filterForm.addEventListener('submit', Filters._disableEmptyInputFields)
16
+ adminterface.addObserver(filterForm, { events: { submit: Filters._disableEmptyInputFields } }, 'filters.submit')
17
+ }
18
+
19
+ selectAndSearch.forEach((el) => {
20
+ el.addEventListener('change', Filters._setSearchType)
21
+ adminterface.addObserver(el, { events: { change: Filters._setSearchType } }, 'filters.selectAndSearch')
22
+ })
23
+ })
@@ -0,0 +1,7 @@
1
+ import HasMany from '../lib/has_many'
2
+
3
+ document.addEventListener('DOMContentLoaded', () => {
4
+ const hasManyTriggerList = [].slice.call(document.querySelectorAll('.has_many_container'))
5
+
6
+ hasManyTriggerList.map((el) => new HasMany(el))
7
+ })
@@ -0,0 +1,10 @@
1
+ import HeaderToggler from '../lib/header_toggler'
2
+
3
+ document.addEventListener('DOMContentLoaded', () => {
4
+ const togglerTriggerList = [].slice.call(document.querySelectorAll('[data-aa-header-toggler]'))
5
+ togglerTriggerList.map((el) => {
6
+ const options = JSON.parse(el.dataset.aaHeaderToggler || '{}')
7
+
8
+ return new HeaderToggler(el, options)
9
+ })
10
+ })
@@ -0,0 +1,2 @@
1
+ const initializers = require.context('.', true, /\.js$/)
2
+ initializers.keys().forEach(initializers)
@@ -0,0 +1,12 @@
1
+ /* global adminterface */
2
+ import PerPage from '../lib/per_page'
3
+
4
+ document.addEventListener('DOMContentLoaded', () => {
5
+ const target = document.querySelector('.pagination_per_page select')
6
+
7
+ if (target) {
8
+ target.addEventListener('change', PerPage._update)
9
+
10
+ adminterface.addObserver(target, { events: { change: PerPage._update } }, 'perPage')
11
+ }
12
+ })
@@ -0,0 +1,24 @@
1
+ /* global adminterface */
2
+ import flatpickr from 'flatpickr'
3
+
4
+ const initFlatpickr = (element) => {
5
+ const flatpickrTriggerList = [].slice.call(element.querySelectorAll('[data-aa-flatpickr]'))
6
+
7
+ flatpickrTriggerList.map((el) => {
8
+ const options = JSON.parse(el.dataset.aaFlatpickr || '{}')
9
+ const instance = flatpickr(el, options)
10
+
11
+ adminterface.addObserver(el, instance, 'flatpickr')
12
+ return instance
13
+ })
14
+ }
15
+
16
+ document.addEventListener('DOMContentLoaded', () => {
17
+ initFlatpickr(document)
18
+ })
19
+
20
+ document.addEventListener('confirm_dialog:before_open', (el) => {
21
+ initFlatpickr(el.detail.dialogForm)
22
+ })
23
+
24
+ export default initFlatpickr
@@ -0,0 +1,21 @@
1
+ import InputCounter from '../../lib/plugins/input_counter'
2
+
3
+ const initInputCounter = function (element) {
4
+ const inputCounterTriggerList = [].slice.call(element.querySelectorAll('[data-aa-input-counter]'))
5
+
6
+ inputCounterTriggerList.map((el) => {
7
+ const options = JSON.parse(el.dataset.aaInputCounter || '{}')
8
+
9
+ return new InputCounter(el, options)
10
+ })
11
+ }
12
+
13
+ document.addEventListener('DOMContentLoaded', () => {
14
+ initInputCounter(document)
15
+ })
16
+
17
+ document.addEventListener('confirm_dialog:before_open', (el) => {
18
+ initInputCounter(el.detail.dialogForm)
19
+ })
20
+
21
+ export default initInputCounter
@@ -0,0 +1,23 @@
1
+ import PasswordVisibility from '../../lib/plugins/password_visibility'
2
+ import initBootstrap from '../bootstrap'
3
+
4
+ const initPasswordVisibility = function (element) {
5
+ const visibilityTriggerList = [].slice.call(element.querySelectorAll('[data-aa-password-visibility]'))
6
+ visibilityTriggerList.map((el) => {
7
+ const options = JSON.parse(el.dataset.aaPasswordVisibility || '{}')
8
+ const instance = new PasswordVisibility(el, options)
9
+
10
+ initBootstrap(instance.eventTarget)
11
+ return instance
12
+ })
13
+ }
14
+
15
+ document.addEventListener('DOMContentLoaded', () => {
16
+ initPasswordVisibility(document)
17
+ })
18
+
19
+ document.addEventListener('confirm_dialog:before_open', (el) => {
20
+ initPasswordVisibility(el.detail.dialogForm)
21
+ })
22
+
23
+ export default initPasswordVisibility
@@ -0,0 +1,24 @@
1
+ /* global adminterface */
2
+ import TomSelect from 'tom-select'
3
+
4
+ const initTomSelect = function (element) {
5
+ const tomSelectTriggerList = [].slice.call(element.querySelectorAll('[data-aa-tom-select]'))
6
+
7
+ tomSelectTriggerList.map((el) => {
8
+ const options = JSON.parse(el.dataset.aaTomSelect || '{}')
9
+ const instance = new TomSelect(el, options)
10
+
11
+ adminterface.addObserver(el, instance, instance.constructor.name)
12
+ return instance
13
+ })
14
+ }
15
+
16
+ document.addEventListener('DOMContentLoaded', () => {
17
+ initTomSelect(document)
18
+ })
19
+
20
+ document.addEventListener('confirm_dialog:before_open', (el) => {
21
+ initTomSelect(el.detail.dialogForm)
22
+ })
23
+
24
+ export default initTomSelect
@@ -0,0 +1,5 @@
1
+ <div id="find-me">
2
+ <input type="checkbox" class="toggle_all" checked>
3
+ <input type="checkbox" class="toggle_one" checked>
4
+ <input type="checkbox" class="toggle_two" checked>
5
+ </div>
@@ -0,0 +1,110 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import CheckboxTogglerClass from '../checkbox_toggler'
4
+
5
+ describe('CheckboxToggler', () => {
6
+ const html = fs.readFileSync(path.resolve(__dirname, './checkbox_toggler.html'))
7
+ const container = '#find-me'
8
+ const options = 'options'
9
+
10
+ beforeEach(() => {
11
+ document.documentElement.innerHTML = html.toString()
12
+ })
13
+
14
+ afterEach(() => {
15
+ jest.restoreAllMocks()
16
+ })
17
+
18
+ test('constructor initiates correctly', () => {
19
+ const spyOnInit = jest.spyOn(CheckboxTogglerClass.prototype, '_init')
20
+ const spyOnBind = jest.spyOn(CheckboxTogglerClass.prototype, '_bind')
21
+
22
+ const CheckboxToggler = new CheckboxTogglerClass(container, options)
23
+
24
+ expect(CheckboxToggler.options).toStrictEqual(options)
25
+ expect(CheckboxToggler.container).toStrictEqual(container)
26
+
27
+ expect(spyOnInit).toHaveBeenCalledTimes(1)
28
+ expect(spyOnBind).toHaveBeenCalledTimes(1)
29
+ })
30
+
31
+ test('init throws error if container is null', () => {
32
+ expect(() => { new CheckboxTogglerClass(null, options) }).toThrow( // eslint-disable-line no-new
33
+ 'Container element not found'
34
+ )
35
+ })
36
+
37
+ test('init throws error if toggle checkbox missing', () => {
38
+ const element = document.createElement('div')
39
+ element.id = 'find-me'
40
+ document.documentElement.innerHTML = element.outerHTML
41
+
42
+ expect(() => { new CheckboxTogglerClass(container, options) }).toThrow( // eslint-disable-line no-new
43
+ '"toggle all" checkbox not found'
44
+ )
45
+ })
46
+
47
+ test('init sets $container, $toggleAllCheckbox, $checkboxes', () => {
48
+ const $container = document.querySelector(container)
49
+ const $toggleAllCheckbox = $container.querySelector('.toggle_all')
50
+ const $checkboxes = $container.querySelectorAll('input[type="checkbox"]:not(.toggle_all)')
51
+ const CheckboxToggler = new CheckboxTogglerClass(container, options)
52
+
53
+ expect(CheckboxToggler.$container).toStrictEqual($container)
54
+ expect(CheckboxToggler.$toggleAllCheckbox).toStrictEqual($toggleAllCheckbox)
55
+ expect(CheckboxToggler.$checkboxes).toStrictEqual($checkboxes)
56
+ })
57
+
58
+ test('bind triggers addEventListener', () => {
59
+ const CheckboxToggler = new CheckboxTogglerClass(container, options)
60
+ const spyOnCheckboxesAddEvent = jest.spyOn(
61
+ CheckboxToggler.$checkboxes[0], 'addEventListener'
62
+ )
63
+ const spyOnToggleAllCheckboxAddEvent = jest.spyOn(
64
+ CheckboxToggler.$toggleAllCheckbox, 'addEventListener'
65
+ )
66
+
67
+ CheckboxToggler._bind()
68
+
69
+ expect(spyOnCheckboxesAddEvent).toHaveBeenCalledTimes(1)
70
+ expect(spyOnCheckboxesAddEvent).toHaveBeenCalledWith(
71
+ 'change',
72
+ expect.any(Function)
73
+ )
74
+
75
+ expect(spyOnToggleAllCheckboxAddEvent).toHaveBeenCalledTimes(1)
76
+ expect(spyOnToggleAllCheckboxAddEvent).toHaveBeenCalledWith(
77
+ 'change',
78
+ expect.any(Function)
79
+ )
80
+ })
81
+
82
+ test('didChangeCheckbox sets toggleAllCheckbox checked to true when all checked', () => {
83
+ const CheckboxToggler = new CheckboxTogglerClass(container, options)
84
+ CheckboxToggler._didChangeCheckbox()
85
+
86
+ expect(CheckboxToggler.$toggleAllCheckbox.checked).toBeTruthy()
87
+ expect(CheckboxToggler.$toggleAllCheckbox.indeterminate).toBeFalsy()
88
+ })
89
+
90
+ test('didChangeCheckbox sets toggleAllCheckbox checked to false when some checked', () => {
91
+ const inputElementToggleTwo = document.querySelector('input.toggle_two')
92
+ inputElementToggleTwo.checked = false
93
+
94
+ const CheckboxToggler = new CheckboxTogglerClass(container, options)
95
+ CheckboxToggler._didChangeCheckbox()
96
+
97
+ expect(CheckboxToggler.$toggleAllCheckbox.checked).toBeFalsy()
98
+ expect(CheckboxToggler.$toggleAllCheckbox.indeterminate).toBeTruthy()
99
+ })
100
+
101
+ test('didChangeToggleAllCheckbox', () => {
102
+ const CheckboxToggler = new CheckboxTogglerClass(container, options)
103
+ const setting = CheckboxToggler._didChangeToggleAllCheckbox()
104
+
105
+ expect(setting).toBeTruthy()
106
+ CheckboxToggler.$checkboxes.forEach(el => {
107
+ expect(el.checked).toStrictEqual(setting)
108
+ })
109
+ })
110
+ })
@@ -0,0 +1,69 @@
1
+ import DetachedDropdownClass from '../detached_dropdown'
2
+
3
+ describe('DetachedDropdown', () => {
4
+ const element = document.createElement('div')
5
+ const options = {
6
+ title: '.title-menu'
7
+ }
8
+
9
+ beforeEach(() => {
10
+ global.adminterface = {
11
+ addObserver: jest.fn()
12
+ }
13
+ })
14
+
15
+ test('constructor initiates properties and call bind correctly', () => {
16
+ const spyOnBind = jest.spyOn(DetachedDropdownClass.prototype, '_bind')
17
+ spyOnBind.mockImplementation(() => {})
18
+ const DetachedDropdown = new DetachedDropdownClass(element, options)
19
+
20
+ expect(DetachedDropdown.element).toEqual(element)
21
+ expect(DetachedDropdown.options).toEqual({
22
+ menu: '.dropdown-menu',
23
+ ...options
24
+ })
25
+ expect(spyOnBind).toHaveBeenCalledTimes(1)
26
+ spyOnBind.mockRestore()
27
+ })
28
+
29
+ test('bind method calls adminterface correctly', () => {
30
+ const DetachedDropdown = new DetachedDropdownClass(element, options)
31
+
32
+ expect(global.adminterface.addObserver).toHaveBeenCalledWith(
33
+ element,
34
+ DetachedDropdown,
35
+ DetachedDropdown.constructor.name
36
+ )
37
+ })
38
+
39
+ test('bind method add event listener correctly', () => {
40
+ const DetachedDropdown = new DetachedDropdownClass(element, options)
41
+ const spyOnAddEventListener = jest.spyOn(
42
+ DetachedDropdown.element,
43
+ 'addEventListener'
44
+ )
45
+ DetachedDropdown._bind()
46
+
47
+ expect(spyOnAddEventListener).toHaveBeenCalledTimes(2)
48
+ expect(spyOnAddEventListener.mock.calls).toEqual([
49
+ ['show.bs.dropdown', expect.any(Function)],
50
+ ['hidden.bs.dropdown', expect.any(Function)]
51
+ ])
52
+ })
53
+
54
+ test('append method calls native WEB API append correctly', () => {
55
+ const testDiv = document.createElement('div')
56
+ const testP = document.createElement('p')
57
+ testDiv.append('Some text', testP)
58
+
59
+ const DetachedDropdown = new DetachedDropdownClass(element, options)
60
+ const spyOnAppend = jest.spyOn(document.body, 'append')
61
+
62
+ DetachedDropdown._append(document.body, testP)
63
+
64
+ expect(spyOnAppend).toHaveBeenCalledTimes(1)
65
+ expect(spyOnAppend).toHaveBeenCalledWith(
66
+ testP.parentElement.removeChild(testP)
67
+ )
68
+ })
69
+ })
@@ -0,0 +1,150 @@
1
+ import Filters from '../filters'
2
+ import * as utilModule from '../utils'
3
+
4
+ describe('Filters', () => {
5
+ const mockURL = '?city=tokyo&country=japan'
6
+ const mockEvent = {
7
+ preventDefault: () => {}
8
+ }
9
+
10
+ const spyOnLocation = jest.spyOn(window, 'location', 'get')
11
+ spyOnLocation.mockImplementation(() => ({ search: mockURL }))
12
+
13
+ const regex = /^(q\[|q%5B|q%5b|page|utf8|commit)/
14
+ const params = utilModule
15
+ .queryStringToParams()
16
+ .filter(({ name }) => !name.match(regex))
17
+
18
+ const mockElementList = [
19
+ {
20
+ value: '',
21
+ disabled: false,
22
+ type: 'input'
23
+ }
24
+ ]
25
+
26
+ let spyOnQueryStringToParams
27
+ let spyOnHasTurbolinks
28
+ let spyOnTurbolinksVisit
29
+ let spyOnToQueryString
30
+ let spyOnQuerySelectorAll
31
+ let spyOnSerializeArray
32
+ let spyOnClosest
33
+ let spyOnQuerySelector
34
+
35
+ beforeEach(() => {
36
+ document.body.innerHTML =
37
+ '<div class="filter_form_field">' +
38
+ ' <input />' +
39
+ '</div>'
40
+
41
+ spyOnQueryStringToParams = jest.spyOn(utilModule, 'queryStringToParams')
42
+
43
+ spyOnHasTurbolinks = jest.spyOn(utilModule, 'hasTurbolinks')
44
+
45
+ spyOnTurbolinksVisit = jest.spyOn(utilModule, 'turbolinksVisit')
46
+
47
+ spyOnToQueryString = jest.spyOn(utilModule, 'toQueryString')
48
+
49
+ spyOnQuerySelectorAll = jest.spyOn(document, 'querySelectorAll')
50
+ spyOnQuerySelectorAll.mockImplementation(() => [...mockElementList])
51
+
52
+ spyOnSerializeArray = jest.spyOn(utilModule, 'serializeArray')
53
+ spyOnSerializeArray.mockImplementation(() => [])
54
+
55
+ spyOnClosest = jest.spyOn(document.documentElement, 'closest')
56
+ spyOnClosest.mockImplementation(() => ({
57
+ querySelector: (selector) => document.querySelector(selector)
58
+ }))
59
+
60
+ spyOnQuerySelector = jest.spyOn(document, 'querySelector')
61
+
62
+ Filters.querySelectorAll = document.querySelectorAll
63
+ Filters.closest = document.documentElement.closest
64
+ Filters.value = 'test value'
65
+ })
66
+
67
+ afterEach(() => {
68
+ jest.clearAllMocks()
69
+ })
70
+
71
+ test('clearForm: triggers queryStringToParams', () => {
72
+ Filters._clearForm(mockEvent)
73
+
74
+ expect(spyOnQueryStringToParams).toHaveBeenCalledTimes(1)
75
+ })
76
+
77
+ test('clearForm: hasTurbolinks true triggers turbolinksVisit', () => {
78
+ spyOnHasTurbolinks.mockImplementation(() => true)
79
+ spyOnTurbolinksVisit.mockImplementation(params => params)
80
+ Filters._clearForm(mockEvent)
81
+
82
+ expect(spyOnTurbolinksVisit).toHaveBeenCalledTimes(1)
83
+ expect(spyOnTurbolinksVisit).toHaveBeenCalledWith(params)
84
+ })
85
+
86
+ test('clearForm: hasTurbolinks false triggers toQueryString', () => {
87
+ spyOnHasTurbolinks.mockImplementation(() => false)
88
+ Filters._clearForm(mockEvent)
89
+
90
+ expect(spyOnToQueryString).toHaveBeenCalledTimes(1)
91
+ expect(spyOnToQueryString).toHaveBeenCalledWith(params)
92
+ })
93
+
94
+ test('disableEmptyInputFields triggers querySelectorAll', () => {
95
+ const mockSelectors = 'input, textarea, select, button'
96
+
97
+ Filters._disableEmptyInputFields(mockEvent)
98
+
99
+ expect(spyOnQuerySelectorAll).toHaveBeenCalledTimes(1)
100
+ expect(spyOnQuerySelectorAll).toHaveBeenCalledWith(mockSelectors)
101
+ })
102
+
103
+ test('disableEmptyInputFields triggers serializeArray', () => {
104
+ Filters._disableEmptyInputFields(mockEvent)
105
+
106
+ expect(spyOnSerializeArray).toHaveBeenCalledTimes(1)
107
+ expect(spyOnSerializeArray).toHaveBeenCalledWith(Filters)
108
+ })
109
+
110
+ test('disableEmptyInputFields sets element list disable value to true', () => {
111
+ Filters._disableEmptyInputFields(mockEvent)
112
+
113
+ const disabledList = mockElementList.filter(el => el.disabled)
114
+ expect(disabledList).toHaveLength(1)
115
+ })
116
+
117
+ test('disableEmptyInputFields triggers turboLinksVisit if hasTurbolinks true', () => {
118
+ spyOnHasTurbolinks.mockImplementation(() => true)
119
+ Filters._disableEmptyInputFields(mockEvent)
120
+
121
+ expect(spyOnTurbolinksVisit).toHaveBeenCalledTimes(1)
122
+ expect(spyOnTurbolinksVisit).toHaveBeenCalledWith([])
123
+ })
124
+
125
+ test('disableEmptyInputFields does not trigger turboLinksVisit if hasTurbolinks false', () => {
126
+ spyOnHasTurbolinks.mockImplementation(() => false)
127
+ Filters._disableEmptyInputFields(mockEvent)
128
+
129
+ expect(spyOnTurbolinksVisit).not.toHaveBeenCalled()
130
+ })
131
+
132
+ test('setSearchType calls DOM API closest and querySelector', () => {
133
+ Filters._setSearchType()
134
+
135
+ expect(spyOnClosest).toHaveBeenCalledTimes(1)
136
+ expect(spyOnClosest).toHaveBeenCalledWith('.filter_form_field')
137
+
138
+ expect(spyOnQuerySelector).toHaveBeenCalledTimes(1)
139
+ expect(spyOnQuerySelector).toHaveBeenCalledWith('input')
140
+ })
141
+
142
+ test('setSearchType sets element name correctly', () => {
143
+ const $element = document.querySelector('input')
144
+ expect($element.name).toEqual('')
145
+
146
+ Filters._setSearchType()
147
+
148
+ expect($element.name).toEqual(`q[${Filters.value}]`)
149
+ })
150
+ })
@@ -0,0 +1,14 @@
1
+ <div data-sortable="address">
2
+ <form class="has-many-list">
3
+ <fieldset class="has_many_fields">
4
+ <input type="checkbox" name="[_destroy]" checked>
5
+ <input type="text" name="[address]" value="Tokyo">
6
+ <a class="button has_many_remove"></a>
7
+ <a
8
+ class="button has_many_add"
9
+ data-html="<div></div>"
10
+ data-placeholder="script"
11
+ ></a>
12
+ </fieldset>
13
+ </form>
14
+ </div>