headmin 0.1.1 → 0.2.2

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 (210) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -1
  3. data/Gemfile.lock +24 -2
  4. data/README.md +8 -43
  5. data/app/controllers/concerns/headmin/authentication.rb +0 -8
  6. data/app/controllers/concerns/headmin/pagination.rb +1 -1
  7. data/app/helpers/headmin/admin_helper.rb +4 -4
  8. data/app/models/concerns/headmin/block.rb +11 -0
  9. data/app/models/concerns/headmin/blockable.rb +10 -0
  10. data/app/models/concerns/headmin/field.rb +17 -0
  11. data/app/models/concerns/headmin/fieldable.rb +44 -0
  12. data/app/services/block_service.rb +68 -0
  13. data/app/views/{layouts → examples}/admin.html.erb +0 -0
  14. data/app/views/{layouts/admin → examples}/auth.html.erb +0 -0
  15. data/app/views/headmin/_blocks.html.erb +24 -0
  16. data/app/views/headmin/_breadcrumbs.html.erb +9 -5
  17. data/app/views/headmin/_card.html.erb +48 -0
  18. data/app/views/headmin/_dropdown.html.erb +18 -0
  19. data/app/views/headmin/_filters.html.erb +56 -34
  20. data/app/views/headmin/_form.html.erb +60 -6
  21. data/app/views/headmin/_heading.html.erb +8 -4
  22. data/app/views/headmin/_index.html.erb +9 -8
  23. data/app/views/headmin/_notifications.html.erb +8 -0
  24. data/app/views/headmin/_pagination.html.erb +11 -7
  25. data/app/views/headmin/_popup.html.erb +26 -0
  26. data/app/views/headmin/_table.html.erb +11 -4
  27. data/app/views/headmin/dropdown/_button.html.erb +13 -0
  28. data/app/views/headmin/dropdown/_devise.html.erb +21 -0
  29. data/app/views/headmin/{layout/dropdown → dropdown}/_divider.html.erb +1 -1
  30. data/app/views/headmin/dropdown/_item.html.erb +18 -0
  31. data/app/views/headmin/dropdown/_list.html.erb +11 -0
  32. data/app/views/headmin/dropdown/_locale.html.erb +17 -0
  33. data/app/views/headmin/filters/_date.html.erb +21 -16
  34. data/app/views/headmin/filters/_search.html.erb +18 -18
  35. data/app/views/headmin/filters/_select.html.erb +28 -23
  36. data/app/views/headmin/filters/filter/_button.html.erb +15 -6
  37. data/app/views/headmin/filters/filter/_menu_item.html.erb +2 -2
  38. data/app/views/headmin/filters/filter/_template.html.erb +2 -2
  39. data/app/views/headmin/forms/_actions.html.erb +4 -8
  40. data/app/views/headmin/forms/_base.html.erb +60 -0
  41. data/app/views/headmin/forms/_blocks.html.erb +32 -0
  42. data/app/views/headmin/forms/_checkbox.html.erb +39 -0
  43. data/app/views/headmin/forms/_ckeditor.html.erb +42 -0
  44. data/app/views/headmin/forms/_date.html.erb +45 -0
  45. data/app/views/headmin/forms/_email.html.erb +39 -0
  46. data/app/views/headmin/forms/_file.html.erb +40 -0
  47. data/app/views/headmin/forms/_image.html.erb +55 -0
  48. data/app/views/headmin/forms/_label.html.erb +24 -0
  49. data/app/views/headmin/forms/_number.html.erb +50 -0
  50. data/app/views/headmin/forms/_password.html.erb +69 -0
  51. data/app/views/headmin/forms/_redactorx.html.erb +49 -0
  52. data/app/views/headmin/forms/_repeater.html.erb +133 -0
  53. data/app/views/headmin/forms/_select.html.erb +70 -0
  54. data/app/views/headmin/forms/_text.html.erb +62 -0
  55. data/app/views/headmin/forms/_textarea.html.erb +39 -0
  56. data/app/views/headmin/forms/_url.html.erb +39 -0
  57. data/app/views/headmin/forms/_validation.html.erb +21 -0
  58. data/app/views/headmin/forms/actions/_destroy.html.erb +13 -0
  59. data/app/views/headmin/forms/actions/_save.html.erb +12 -0
  60. data/app/views/headmin/forms/actions/_view.html.erb +15 -0
  61. data/app/views/headmin/forms/fields/_base.html.erb +25 -0
  62. data/app/views/headmin/forms/fields/_file.html.erb +15 -22
  63. data/app/views/headmin/forms/fields/_group.html.erb +38 -0
  64. data/app/views/headmin/forms/fields/_image.html.erb +15 -35
  65. data/app/views/headmin/forms/fields/_list.html.erb +26 -0
  66. data/app/views/headmin/forms/fields/_text.html.erb +15 -37
  67. data/app/views/headmin/forms/repeater/_row.html.erb +51 -0
  68. data/app/views/headmin/heading/_title.html.erb +1 -1
  69. data/app/views/headmin/layout/_body.html.erb +1 -1
  70. data/app/views/headmin/layout/_content.html.erb +1 -1
  71. data/app/views/headmin/layout/_footer.html.erb +1 -1
  72. data/app/views/headmin/layout/_header.html.erb +1 -1
  73. data/app/views/headmin/layout/_main.html.erb +2 -2
  74. data/app/views/headmin/layout/_sidebar.html.erb +1 -1
  75. data/app/views/headmin/layout/sidebar/{_menu.html.erb → _nav.html.erb} +1 -1
  76. data/app/views/headmin/nav/_item.html.erb +21 -0
  77. data/app/views/headmin/nav/item/_devise.html.erb +21 -0
  78. data/app/views/headmin/nav/item/_locale.html.erb +17 -0
  79. data/app/views/headmin/pagination/_per_page.html.erb +18 -0
  80. data/app/views/headmin/{kaminari → pagination/kaminari}/_first_page.html.erb +0 -0
  81. data/app/views/headmin/{kaminari → pagination/kaminari}/_gap.html.erb +0 -0
  82. data/app/views/headmin/{kaminari → pagination/kaminari}/_last_page.html.erb +0 -0
  83. data/app/views/headmin/{kaminari → pagination/kaminari}/_next_page.html.erb +0 -0
  84. data/app/views/headmin/{kaminari → pagination/kaminari}/_page.html.erb +1 -1
  85. data/app/views/headmin/{kaminari → pagination/kaminari}/_paginator.html.erb +0 -0
  86. data/app/views/headmin/{kaminari → pagination/kaminari}/_prev_page.html.erb +0 -0
  87. data/app/views/headmin/table/_actions.html.erb +24 -17
  88. data/app/views/headmin/table/_body.html.erb +12 -10
  89. data/app/views/headmin/table/_foot.html.erb +8 -4
  90. data/app/views/headmin/table/_footer.html.erb +3 -7
  91. data/app/views/headmin/table/_head.html.erb +3 -1
  92. data/app/views/headmin/table/_header.html.erb +3 -7
  93. data/app/views/headmin/table/actions/_action.html.erb +26 -9
  94. data/app/views/headmin/table/actions/_delete.html.erb +11 -7
  95. data/app/views/headmin/table/actions/_export.html.erb +11 -7
  96. data/app/views/headmin/table/body/_association.html.erb +1 -1
  97. data/app/views/headmin/table/body/_boolean.erb +1 -1
  98. data/app/views/headmin/table/body/_currency.html.erb +1 -1
  99. data/app/views/headmin/table/body/_date.html.erb +1 -1
  100. data/app/views/headmin/table/body/_id.html.erb +2 -2
  101. data/app/views/headmin/table/body/_row.html.erb +1 -1
  102. data/app/views/headmin/table/body/_string.html.erb +1 -1
  103. data/app/views/headmin/table/body/_text.html.erb +1 -1
  104. data/app/views/headmin/table/foot/_cell.html.erb +1 -1
  105. data/app/views/headmin/table/foot/_id.html.erb +2 -2
  106. data/app/views/headmin/table/head/_cell.html.erb +1 -1
  107. data/app/views/headmin/table/head/_id.html.erb +3 -3
  108. data/app/views/headmin/views/devise/confirmations/_new.html.erb +9 -0
  109. data/app/views/headmin/views/devise/passwords/_edit.html.erb +12 -0
  110. data/app/views/headmin/views/devise/passwords/_new.html.erb +9 -0
  111. data/app/views/{admin/users/registrations/edit.html.erb → headmin/views/devise/registrations/_edit.html.erb} +5 -5
  112. data/app/views/headmin/views/devise/registrations/_new.html.erb +11 -0
  113. data/app/views/headmin/views/devise/sessions/_new.html.erb +13 -0
  114. data/app/views/{admin/users → headmin/views/devise}/shared/_error_messages.html.erb +0 -0
  115. data/app/views/{admin/users → headmin/views/devise}/shared/_links.html.erb +0 -0
  116. data/app/views/headmin/views/devise/unlocks/_new.html.erb +10 -0
  117. data/config/initializers/customize_input_error.rb +9 -0
  118. data/config/locales/devise/en.yml +65 -0
  119. data/config/locales/en.yml +2 -134
  120. data/config/locales/headmin/filters/en.yml +13 -0
  121. data/config/locales/headmin/filters/nl.yml +13 -0
  122. data/config/locales/headmin/forms/en.yml +34 -0
  123. data/config/locales/headmin/forms/nl.yml +33 -0
  124. data/config/locales/headmin/heading/en.yml +5 -0
  125. data/config/locales/headmin/heading/nl.yml +5 -0
  126. data/config/locales/headmin/layout/en.yml +14 -0
  127. data/config/locales/headmin/layout/nl.yml +14 -0
  128. data/config/locales/headmin/pagination/en.yml +21 -0
  129. data/config/locales/headmin/pagination/nl.yml +21 -0
  130. data/config/locales/headmin/table/en.yml +23 -0
  131. data/config/locales/headmin/table/nl.yml +23 -0
  132. data/config/locales/headmin/views/en.yml +58 -0
  133. data/config/locales/headmin/views/nl.yml +58 -0
  134. data/config/locales/nl.yml +2 -135
  135. data/dist/css/headmin.css +3182 -743
  136. data/dist/js/headmin.js +729 -33
  137. data/docs/README.md +2 -1
  138. data/docs/blocks.md +70 -85
  139. data/docs/devise.md +1 -60
  140. data/docs/fields.md +57 -0
  141. data/headmin.gemspec +1 -0
  142. data/lib/generators/headmin/blocks_generator.rb +19 -0
  143. data/lib/generators/headmin/fields_generator.rb +19 -0
  144. data/lib/generators/templates/migrations/create_blocks.rb +10 -0
  145. data/lib/generators/templates/migrations/create_fields.rb +13 -0
  146. data/lib/generators/templates/models/block.rb +3 -0
  147. data/lib/generators/templates/models/field.rb +3 -0
  148. data/lib/headmin/version.rb +1 -1
  149. data/package.json +6 -6
  150. data/src/js/headmin/controllers/blocks_controller.js +103 -0
  151. data/src/js/headmin/controllers/filters_controller.js +23 -12
  152. data/src/js/headmin/controllers/popup_controller.js +68 -0
  153. data/src/js/headmin/controllers/repeater_controller.js +117 -11
  154. data/src/js/headmin/controllers/table_actions_controller.js +16 -5
  155. data/src/js/headmin/controllers/table_controller.js +84 -1
  156. data/src/js/headmin/headmin.js +29 -56
  157. data/src/scss/headmin/filters.scss +0 -14
  158. data/src/scss/headmin/form.scss +43 -3
  159. data/src/scss/headmin/popup.scss +17 -0
  160. data/src/scss/headmin/table.scss +9 -6
  161. data/src/scss/headmin.scss +7 -4
  162. data/src/scss/vendor/redactorx/override.css +3 -0
  163. data/src/scss/vendor/redactorx/redactorx.css +1460 -0
  164. data/yarn.lock +105 -2210
  165. metadata +108 -62
  166. data/app/controllers/admin/users/confirmations_controller.rb +0 -31
  167. data/app/controllers/admin/users/omniauth_callbacks_controller.rb +0 -31
  168. data/app/controllers/admin/users/passwords_controller.rb +0 -35
  169. data/app/controllers/admin/users/registrations_controller.rb +0 -63
  170. data/app/controllers/admin/users/sessions_controller.rb +0 -28
  171. data/app/controllers/admin/users/unlocks_controller.rb +0 -31
  172. data/app/views/admin/users/confirmations/new.html.erb +0 -9
  173. data/app/views/admin/users/mailer/confirmation_instructions.html.erb +0 -5
  174. data/app/views/admin/users/mailer/email_changed.html.erb +0 -7
  175. data/app/views/admin/users/mailer/password_change.html.erb +0 -3
  176. data/app/views/admin/users/mailer/reset_password_instructions.html.erb +0 -8
  177. data/app/views/admin/users/mailer/unlock_instructions.html.erb +0 -7
  178. data/app/views/admin/users/passwords/edit.html.erb +0 -12
  179. data/app/views/admin/users/passwords/new.html.erb +0 -9
  180. data/app/views/admin/users/registrations/new.html.erb +0 -11
  181. data/app/views/admin/users/sessions/new.html.erb +0 -13
  182. data/app/views/admin/users/unlocks/new.html.erb +0 -10
  183. data/app/views/headmin/forms/_group.html.erb +0 -36
  184. data/app/views/headmin/forms/fields/_checkbox.html.erb +0 -23
  185. data/app/views/headmin/forms/fields/_ckeditor.html.erb +0 -28
  186. data/app/views/headmin/forms/fields/_currency.html.erb +0 -24
  187. data/app/views/headmin/forms/fields/_date.html.erb +0 -36
  188. data/app/views/headmin/forms/fields/_email.html.erb +0 -39
  189. data/app/views/headmin/forms/fields/_label.html.erb +0 -9
  190. data/app/views/headmin/forms/fields/_multiple_select.html.erb +0 -37
  191. data/app/views/headmin/forms/fields/_password.html.erb +0 -39
  192. data/app/views/headmin/forms/fields/_repeater.html.erb +0 -48
  193. data/app/views/headmin/forms/fields/_select.html.erb +0 -36
  194. data/app/views/headmin/forms/fields/_select_tags.html.erb +0 -32
  195. data/app/views/headmin/forms/fields/_textarea.html.erb +0 -29
  196. data/app/views/headmin/forms/fields/_url.html.erb +0 -38
  197. data/app/views/headmin/forms/fields/_validation.html.erb +0 -12
  198. data/app/views/headmin/forms/fields/repeater/_row.html.erb +0 -16
  199. data/app/views/headmin/layout/dropdown/_item.html.erb +0 -17
  200. data/app/views/headmin/layout/header/_account.html.erb +0 -25
  201. data/app/views/headmin/layout/header/_locale.html.erb +0 -19
  202. data/app/views/headmin/layout/sidebar/menu/_account.html.erb +0 -25
  203. data/app/views/headmin/layout/sidebar/menu/_item.html.erb +0 -16
  204. data/app/views/headmin/layout/sidebar/menu/_locale.html.erb +0 -18
  205. data/src/js/headmin/controllers/index_controller.js +0 -79
  206. data/src/js/headmin/controllers/repeater_row_controller.js +0 -54
  207. data/src/scss/vendor/choices/cross-inverse.svg +0 -6
  208. data/src/scss/vendor/choices/cross.svg +0 -6
  209. data/src/scss/vendor/choices/custom.scss +0 -28
  210. data/src/scss/vendor/choices/variables.scss +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9f3322a28300a8474d9e3eb6de7426ffc1e29ce1d335538acecc185b7a0a622
4
- data.tar.gz: c8ed8550f75532b996fe507407abf724f0899e0db61d1881a2320ff97a0fa0fe
3
+ metadata.gz: 5b4489879289d2643f3045d91f28b3530f3c21e5a888246ceb36029106ea0692
4
+ data.tar.gz: 0e161c13ca9f3fd26f96401eefea905cd3858d0c3b3dfe86cd8ce4bda718d8f8
5
5
  SHA512:
6
- metadata.gz: 252e757eb913f233271e7b41f474dada9913446af1ef48cc2b2d55d435e2d5b9dfab8199c18ebbb6a19cd260541ea1c1bc996bf1feecd9d8ee67a779ada5a1d3
7
- data.tar.gz: 0d7c2ec678aea04c6317af5117d91ca622f08754a532d7baa93478925d509bf569783d828ea4b43053aca2d48c427bf6b13fd4e07701c32b8fa363a239efcf39
6
+ metadata.gz: 78d063e6e740edba6d1a849e1bacbff2a8750300848c20134b3e15bc5217b216e53a15be5d923de6671aecf768ce98c41cffa31bbd8939abd42e6a12ee877c7f
7
+ data.tar.gz: c515db4260d09f9a402d8b46d7d8b36acc10a3dbad433248a19716c5b3b59459ee965dfc8a862d8a35137b58aa4b8af734a6ef73a094b425a9f6ee81140a7261
data/Gemfile CHANGED
@@ -8,5 +8,4 @@ gemspec
8
8
  gem "rake", "~> 13.0"
9
9
 
10
10
  gem "minitest", "~> 5.0"
11
-
12
11
  gem "rubocop", "~> 1.7"
data/Gemfile.lock CHANGED
@@ -1,12 +1,30 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- headmin (0.1.0)
4
+ headmin (0.2.1)
5
+ closure_tree (~> 7.3)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
10
+ activemodel (6.1.4.1)
11
+ activesupport (= 6.1.4.1)
12
+ activerecord (6.1.4.1)
13
+ activemodel (= 6.1.4.1)
14
+ activesupport (= 6.1.4.1)
15
+ activesupport (6.1.4.1)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ zeitwerk (~> 2.3)
9
21
  ast (2.4.2)
22
+ closure_tree (7.4.0)
23
+ activerecord (>= 4.2.10)
24
+ with_advisory_lock (>= 4.0.0)
25
+ concurrent-ruby (1.1.9)
26
+ i18n (1.8.10)
27
+ concurrent-ruby (~> 1.0)
10
28
  minitest (5.14.4)
11
29
  parallel (1.20.1)
12
30
  parser (3.0.0.0)
@@ -27,11 +45,15 @@ GEM
27
45
  rubocop-ast (1.4.1)
28
46
  parser (>= 2.7.1.5)
29
47
  ruby-progressbar (1.11.0)
48
+ tzinfo (2.0.4)
49
+ concurrent-ruby (~> 1.0)
30
50
  unicode-display_width (2.0.0)
51
+ with_advisory_lock (4.6.0)
52
+ activerecord (>= 4.2)
53
+ zeitwerk (2.5.1)
31
54
 
32
55
  PLATFORMS
33
56
  x86_64-darwin-19
34
- x86_64-darwin-20
35
57
 
36
58
  DEPENDENCIES
37
59
  headmin!
data/README.md CHANGED
@@ -1,7 +1,10 @@
1
1
  # Headmin
2
2
  A complete library of commonly used components to build an admin interface in your Ruby on Rails project.
3
3
 
4
- For information about different features: [click here](docs/README.md)
4
+ ## Interesting links
5
+ - [Full documentation](docs/README.md)
6
+ - [Rubygems](https://rubygems.org/gems/headmin)
7
+ - [NPM](https://www.npmjs.com/package/headmin)
5
8
 
6
9
  ## Installation
7
10
 
@@ -47,38 +50,6 @@ Finally import Headmin in your stylesheet.
47
50
  ## Development
48
51
  For development purposes it's helpful to have both the test project and Headmin located in the same directory.
49
52
 
50
- There are 2 ways of working locally:
51
- 1. **Configure package managers (preferred)**: setup bundler and yarn to look for local checkouts
52
- 2. **Use relative paths**: refer to Headmin by it's relative path
53
-
54
- ### Solution #1: Configure package managers (preferred)
55
- This is the preferred way because you can develop locally, and deploy in a staging environment without changing configurations.
56
-
57
- Force bundler to use the local gem with:
58
- ```shell
59
- bundle config local.headmin /usr/local/var/www/headmin
60
- ```
61
- In your Gemfile you need to refer to the feature branch you're working on
62
- ```ruby
63
- gem 'headmin', git: 'git@github.com:insiting/headmin.git', branch: 'feature/test'
64
- ```
65
-
66
- Symlink the headmin node module like this.
67
-
68
- In your Headmin directory:
69
- ```shell
70
- yarn link
71
- ```
72
-
73
- In your project directory
74
- ```shell
75
- yarn link headmin
76
- ```
77
-
78
- ### Solution #2: Use relative paths
79
- We don't prefer this solution because you have to switch sources regularly in Gemfile or package.json for each deployment.
80
-
81
-
82
53
  In Gemfile
83
54
  ```ruby
84
55
  gem "headmin", path: "../headmin"
@@ -88,7 +59,7 @@ In package.json
88
59
  ```json
89
60
  {
90
61
  "dependencies": {
91
- "bar": "file:../headmin"
62
+ "bar": "link:../headmin"
92
63
  }
93
64
  }
94
65
  ```
@@ -128,16 +99,10 @@ $ gem tag -p
128
99
  $ gem release
129
100
  ```
130
101
 
131
- Use the generated version number for the node module as well
102
+ Update the node module
132
103
  ```
133
- // In package.json
134
-
135
- {
136
- "name": "headmin",
137
- "version": "{new version number here}",
138
- ...
139
- }
140
-
104
+ # Manually update the version number in package.json
105
+ $ npm publish
141
106
  ```
142
107
 
143
108
  ## Deployment
@@ -3,15 +3,7 @@ module Headmin
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- alias_method :devise_current_user, :current_user
7
6
  before_action :authenticate_admin!
8
-
9
- def current_user
10
- devise_current_user || current_admin
11
- end
12
7
  end
13
-
14
-
15
-
16
8
  end
17
9
  end
@@ -16,7 +16,7 @@ module Headmin
16
16
  end
17
17
 
18
18
  def per_page
19
- length = (params[:per_page] || params[:length]).to_i
19
+ length = params[:per_page].to_i
20
20
  length > 0 ? length : 24
21
21
  end
22
22
  end
@@ -13,14 +13,14 @@ module Headmin
13
13
  content_tag(:i, class: "bi bi-#{icon} #{klass}", data: data) {}
14
14
  end
15
15
 
16
- def menu_item_active?(link)
17
- uri = URI(link)
16
+ def current_url?(url)
17
+ uri = URI(url)
18
18
  path = uri.path
19
19
  query_string = uri.query
20
20
  matches_path = request.path.include?(path)
21
21
  matches_query = uri.query ? request.query_string.include?(query_string) : true
22
- is_root = request.fullpath == link
23
- if link == admin_root_path
22
+ is_root = request.fullpath == url
23
+ if url == admin_root_path
24
24
  is_root
25
25
  else
26
26
  matches_path && matches_query
@@ -0,0 +1,11 @@
1
+ module Headmin
2
+ module Block
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+
7
+ # Associations
8
+ belongs_to :blockable, polymorphic: true, optional: true, touch: true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Headmin
2
+ module Blockable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :blocks, as: :blockable
7
+ accepts_nested_attributes_for :blocks, allow_destroy: true
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ module Headmin
2
+ module Field
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ # Configuration
7
+ has_closure_tree
8
+
9
+ # Associations
10
+ belongs_to :fieldable, polymorphic: true, optional: true, touch: true
11
+ belongs_to :field, optional: true, touch: true
12
+ has_many :fields, foreign_key: "parent_id"
13
+ accepts_nested_attributes_for :fields, allow_destroy: true
14
+ has_one_attached :file
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,44 @@
1
+ module Headmin
2
+ module Fieldable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :fields, as: :fieldable, dependent: :destroy
7
+ accepts_nested_attributes_for :fields, allow_destroy: true
8
+
9
+ def fields_hash
10
+ save_pair(fields.hash_tree)
11
+ end
12
+
13
+ private
14
+
15
+ def save_pair(my_hash, array = false)
16
+ if array
17
+ my_hash.map { |key, value|
18
+ save_pair(value)
19
+ }
20
+ else
21
+ Hash[my_hash.map { |key, value|
22
+ if value.empty?
23
+ case key.field_type
24
+ when 'group'
25
+ [key.name, save_pair(key.hash_tree[key])]
26
+ when 'list'
27
+ [key.name, save_pair(key.hash_tree[key], true)]
28
+ else
29
+ [key.name, return_field_output(key)]
30
+ end
31
+ else
32
+ key.field_type == 'list' ? [key.name, save_pair(value, true)] : [key.name, save_pair(value)]
33
+ end
34
+ }]
35
+ end
36
+ end
37
+
38
+ # returns what a field_type should return, e.g. its value, the file, the object ...
39
+ def return_field_output(key)
40
+ key.field_type == 'image' ? key.file : key.value
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,68 @@
1
+ class BlockService
2
+ def self.block_names(path:)
3
+ form_views(path: path).map do |view|
4
+ filename = File.basename(view, '.html.erb')
5
+
6
+ # Removes leading _ if exists
7
+ filename.sub!(/^_/, '')
8
+ end
9
+ end
10
+
11
+ def self.form_view(name, path:)
12
+ view_by_name(name, form_view_paths(path))
13
+ end
14
+
15
+ def self.frontend_view(name, path:)
16
+ view_by_name(name, frontend_view_paths(path))
17
+ end
18
+
19
+ def self.frontend_views(path:)
20
+ views(frontend_view_paths(path))
21
+ end
22
+
23
+ def self.form_views(path:)
24
+ views(form_view_paths(path))
25
+ end
26
+
27
+ private
28
+
29
+ # Looks for a block view by its name.
30
+ #
31
+ # It will first search in a specified path and will fallback to the default path
32
+ # An exception will be raised if the view is nowhere to be found
33
+ def self.view_by_name(name, paths)
34
+ views = views(paths)
35
+ view = views.find { |view| view.include?("/_#{name}.html.erb") }
36
+
37
+ unless view
38
+ prefixes = paths.map { |path| path.split('app/views/').last }
39
+ raise ActionView::MissingTemplate.new(paths, name, prefixes, true, "headmin") unless view
40
+ end
41
+
42
+ view
43
+ end
44
+
45
+ def self.form_view_paths(path)
46
+ [app_view_path(path), app_view_path('admin/blocks')].uniq
47
+ end
48
+
49
+ def self.frontend_view_paths(path)
50
+ [app_view_path(path), app_view_path('website/blocks')].uniq
51
+ end
52
+
53
+ def self.app_view_path(path)
54
+ base_path = 'app/views'
55
+ [base_path, path].join('/')
56
+ end
57
+
58
+ def self.views(paths)
59
+ paths.map { |path| views_in_path(path) }.flatten
60
+ end
61
+
62
+ def self.views_in_path(path)
63
+ files = Dir.glob("#{path}/*")
64
+ files.map do |file|
65
+ file.split('app/views/').last
66
+ end
67
+ end
68
+ end
File without changes
File without changes
@@ -0,0 +1,24 @@
1
+ <%
2
+ # headmin/blocks
3
+ #
4
+ # ==== Options
5
+ # * <tt>blockable</tt> - Object with blocks association
6
+ # * <tt>path</tt> - Directory where to look for block templates
7
+ #
8
+ # ==== Examples
9
+ # Basic version. This will only look for blocks in 'website/blocks'
10
+ # <%= render "headmin/blocks", blockable: @page %#>
11
+ #
12
+ # Define the path to look for block templates like this:
13
+ # <%= render "headmin/blocks", blockable: @page, path: 'website/pages/blocks' %#>
14
+
15
+ blockable = local_assigns.has_key?(:blockable) ? blockable : nil
16
+ path = local_assigns.has_key?(:path) ? path : nil
17
+ %>
18
+
19
+ <% if blockable && blockable.respond_to?(:blocks) %>
20
+ <% blockable.blocks.order(:position).each do |block| %>
21
+ <% view_path = BlockService.frontend_view(block.name, path: path).gsub('/_', '/') %>
22
+ <%= render view_path, block: block %>
23
+ <% end %>
24
+ <% end %>
@@ -1,8 +1,12 @@
1
- <%#
2
- name: headmin/heading/breadcrumbs
3
- accepts block: no
4
- parameters:
5
- breadcrumbs: Breadcrumbs collection
1
+ <%
2
+ # headmin/breadcrumbs
3
+ #
4
+ # ==== Options
5
+ # * <tt>breadcrumbs</tt> - Object with blocks association
6
+ #
7
+ # ==== Examples
8
+ # Basic version. This will use the publicly available `breadcrumbs` variable
9
+ # <%= render "headmin/breadcrumbs" %#>
6
10
  %>
7
11
 
8
12
  <nav aria-label="breadcrumb">
@@ -0,0 +1,48 @@
1
+ <%
2
+ # headmin/card
3
+ #
4
+ # ==== 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
8
+ #
9
+ # ==== Examples
10
+ # Basic version.
11
+ # <%= render 'headmin/card' do %#>
12
+ # Your content
13
+ # <% end %#>
14
+ #
15
+ # Title and description
16
+ # <%= render 'headmin/card', title: 'Title', description: 'Description' do %#>
17
+ # Your content
18
+ # <% end %#>
19
+
20
+ title = local_assigns.has_key?(:title) ? title : nil
21
+ description = local_assigns.has_key?(:description) ? description : nil
22
+ padded = local_assigns.has_key?(:padded) ? padded : true
23
+ %>
24
+
25
+ <div class="card mb-3 shadow-sm">
26
+
27
+ <% if padded || title || description %>
28
+ <div class="card-body">
29
+ <% if title.present? %>
30
+ <h5 class="card-title"><%= title %></h5>
31
+ <% end %>
32
+
33
+ <% if description.present? %>
34
+ <p class="card-text text-secondary"><%= description %></p>
35
+ <% end %>
36
+
37
+ <!-- Render inside body-->
38
+ <% if padded %>
39
+ <%= yield if block_given? %>
40
+ <% end %>
41
+ </div>
42
+ <% end %>
43
+
44
+ <!-- Render outside body-->
45
+ <% unless padded %>
46
+ <%= yield if block_given? %>
47
+ <% end %>
48
+ </div>
@@ -0,0 +1,18 @@
1
+ <%
2
+ # headmin/dropdown
3
+ #
4
+ # ==== Options
5
+ # * <tt>class</tt> - Custom class names to put on the dropdown
6
+ #
7
+ # ==== Examples
8
+ # Basic version
9
+ # <%= render "headmin/dropdown" do %#>
10
+ # Your content
11
+ # <% end %#>
12
+
13
+ class_names = local_assigns.has_key?(:class) ? local_assigns[:class] : 'btn-group'
14
+ %>
15
+
16
+ <div class="dropdown <%= class_names %>">
17
+ <%= yield %>
18
+ </div>
@@ -1,47 +1,69 @@
1
- <%#
2
- name: headmin/filters
3
- accepts block: yes
4
- parameters:
5
- url: base url to send filter query to
1
+ <%
2
+ # headmin/filters
3
+ #
4
+ # ==== Options
5
+ # * <tt>url</tt> - Base url to send filter query to. Defaults to current URL
6
+ #
7
+ # ==== Examples
8
+ # Basic version
9
+ # <%= render "headmin/filters" %#>
10
+ #
11
+ # With custom URL
12
+ # <%= render "headmin/filters", url: admin_polls_path %#>
13
+
14
+ action = local_assigns.has_key?(:url) ? url : request.url
6
15
  %>
7
- <% action = local_assigns.has_key?(:url) ? url : request.url %>
8
16
 
9
- <form class="h-filters d-flex align-items-center mb-2" action="<%= action %>" data-controller="filters" data-filters-target="form">
10
- <%= yield if block_given? %>
17
+ <form action="<%= action %>" data-controller="filters" data-filters-target="form">
11
18
 
12
19
  <!-- Default parameters (e.g. sorting, pagination) -->
13
- <% default_params.each do |name, value| %>
20
+ <% default_params.except('page').each do |name, value| %>
14
21
  <%= hidden_field_tag(name.to_sym, value) %>
15
22
  <% end %>
16
23
 
17
- <!-- Filter buttons -->
18
- <div class="h-filter-list d-flex" data-filters-target="list">
19
- <%= content_for :filters_buttons %>
20
- </div>
24
+ <%= yield if block_given? %>
21
25
 
22
- <!-- Filter templates -->
23
- <%= content_for :filters_templates %>
26
+ <div class="d-flex flex-column flex-md-row align-content-start align-items-md-center">
27
+ <div class="d-flex align-items-center">
28
+
29
+ <!-- Search -->
30
+ <div class="h-filters-search d-flex my-1 w-100">
31
+ <%= content_for :filters_search %>
24
32
 
25
- <!-- Menu -->
26
- <% if content_for :filters_menu %>
27
- <div class="btn-group">
28
- <button type="button" class="btn btn-link dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
29
- <%= bootstrap_icon('funnel-fill') %>
30
- <%= t('.button') %>
31
- </button>
32
- <ul class="dropdown-menu">
33
- <%= content_for :filters_menu %>
34
- <li><hr class="dropdown-divider"></li>
35
- <li><a class="dropdown-item text-danger" href="#" data-action="click->filters#removeAll"><%= t('.remove_all') %></a></li>
36
- </ul>
33
+ <!-- Separator -->
34
+ <% if content_for(:filters_menu) && content_for(:filters_search) %>
35
+ <div class="vr mx-2"></div>
36
+ <% end %>
37
+ </div>
38
+
39
+ <!-- Menu -->
40
+ <div class="h-filters-menu d-flex align-items-center w-auto my-1">
41
+ <% if content_for :filters_menu %>
42
+ <div class="btn-group">
43
+ <button type="button" class="btn h-btn-outline-light dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
44
+ <%= bootstrap_icon('funnel') %>
45
+ <%= t('.button') %>
46
+ </button>
47
+ <ul class="dropdown-menu">
48
+ <%= content_for :filters_menu %>
49
+ <li>
50
+ <hr class="dropdown-divider">
51
+ </li>
52
+ <li>
53
+ <a class="dropdown-item text-danger" href="#" data-action="click->filters#removeAll"><%= t('.remove_all') %></a>
54
+ </li>
55
+ </ul>
56
+ </div>
57
+ <% end %>
58
+ </div>
37
59
  </div>
38
- <% end %>
39
60
 
40
- <!-- Separator -->
41
- <% if content_for(:filters_menu) && content_for(:filters_search) %>
42
- <span class="separator"></span>
43
- <% end %>
61
+ <!-- Filter list -->
62
+ <div class="h-filter-list d-flex ms-md-1 flex-wrap" data-filters-target="list">
63
+ <%= content_for :filters_buttons %>
64
+ </div>
65
+ </div>
44
66
 
45
- <!-- Search -->
46
- <%= content_for :filters_search %>
67
+ <!-- Filter templates -->
68
+ <%= content_for :filters_templates %>
47
69
  </form>
@@ -1,11 +1,65 @@
1
- <%#
2
- name: headmin/form
3
- accepts block: yes (required)
4
- parameters: model
1
+ <%
2
+ # headmin/form
3
+ #
4
+ # ==== Options
5
+ # * <tt>model<tt> - A model to infer :url and :scope
6
+ # * <tt>scope<tt> - The scope to prefix input field names with
7
+ # * <tt>url<tt> - The URL the form submits to
8
+ # * <tt>format<tt> - The format of the route the form submits to
9
+ # * <tt>namespace<tt> - A namespace for your form to ensure uniqueness of id attributes on form elements
10
+ # * <tt>method<tt> - The method to use when submitting the form
11
+ # * <tt>authenticity_token<tt> - Authenticity token to use in the form
12
+ # * <tt>local<tt> - By default form submits are remote and unobtrusive XHRs
13
+ # * <tt>skip_enforcing_utf8<tt> - If set to true, a hidden input with name utf8 is not output
14
+ # * <tt>builder<tt> - Override the object used to build the form
15
+ # * <tt>html<tt> - Other optional HTML attributes for the form tag
16
+ # * <tt>id<tt> - Optional HTML id attribute
17
+ # * <tt>class<tt> - Optional HTML class attribute
18
+ # * <tt>data<tt> - Optional HTML data attributes
19
+ #
20
+ # === Examples
21
+ # Basic version
22
+ # <%= render 'headmin/form', model: @product do |form| %#>
23
+ # Form content
24
+ # <% end %#>
25
+ #
26
+ # Specify URL to post to
27
+ # <%= render 'headmin/form', model: @product, url: admin_products_path do |form| %#>
28
+ # Form content
29
+ # <% end %#>
30
+
31
+ model = local_assigns.has_key?(:model) ? local_assigns[:model] : nil
32
+ scope = local_assigns.has_key?(:scope) ? local_assigns[:scope] : nil
33
+ url = local_assigns.has_key?(:url) ? local_assigns[:url] : nil
34
+ format = local_assigns.has_key?(:format) ? local_assigns[:format] : nil
35
+
36
+ namespace = local_assigns.has_key?(:namespace) ? namespace : nil
37
+ method = local_assigns.has_key?(:method) ? method : nil
38
+ authenticity_token = local_assigns.has_key?(:authenticity_token) ? authenticity_token : nil
39
+ local = local_assigns.has_key?(:local) ? local : true
40
+ skip_enforcing_utf8 = local_assigns.has_key?(:skip_enforcing_utf8) ? skip_enforcing_utf8 : nil
41
+ builder = local_assigns.has_key?(:builder) ? builder : nil
42
+ html = local_assigns.has_key?(:html) ? html : {}
43
+ id = local_assigns.has_key?(:id) ? id : nil
44
+ option_class = local_assigns.has_key?(:class) ? local_assigns[:class] : nil
45
+ data = local_assigns.has_key?(:data) ? data : nil
46
+
47
+ options = {
48
+ namespace: namespace,
49
+ method: method,
50
+ authenticity_token: authenticity_token,
51
+ local: local,
52
+ skip_enforcing_utf8: skip_enforcing_utf8,
53
+ builder: builder,
54
+ html: html,
55
+ id: id,
56
+ class: option_class,
57
+ data: data
58
+ }
5
59
  %>
6
60
 
7
- <div class="headmin-form container">
8
- <%= form_with model: model do |form| %>
61
+ <div class="container">
62
+ <%= form_with model: model, scope: scope, url: url, format: format, **options do |form| %>
9
63
  <%= yield(form) %>
10
64
  <% end %>
11
65
  </div>
@@ -1,7 +1,11 @@
1
- <%#
2
- name: headmin/heading
3
- accepts block: yes
4
- parameters: none
1
+ <%
2
+ # headmin/heading
3
+ #
4
+ # ==== Examples
5
+ # Basic version
6
+ # <%= render "headmin/heading" do %#>
7
+ # Your content
8
+ # <% end %#>
5
9
  %>
6
10
 
7
11
  <div class="h-heading d-flex flex-column flex-md-row align-items-start align-items-md-end justify-content-between">