headmin 0.3.2 → 0.4.0

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 (186) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +27 -0
  3. data/.gitignore +14 -0
  4. data/.nvmrc +1 -0
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +24 -0
  7. data/Gemfile +8 -5
  8. data/Gemfile.lock +197 -25
  9. data/README.md +9 -1
  10. data/Rakefile +1 -7
  11. data/app/assets/images/document.docx +0 -0
  12. data/app/assets/images/document.pdf +0 -0
  13. data/app/assets/images/image.jpg +0 -0
  14. data/app/assets/images/spreadsheet.xls +0 -0
  15. data/app/assets/images/video.mp4 +0 -0
  16. data/app/assets/javascripts/headmin/config/i18n.js +9 -9
  17. data/app/assets/javascripts/headmin/controllers/autocomplete_controller.js +255 -0
  18. data/app/assets/javascripts/headmin/controllers/blocks_controller.js +74 -79
  19. data/app/assets/javascripts/headmin/controllers/date_range_controller.js +24 -24
  20. data/app/assets/javascripts/headmin/controllers/dropzone_controller.js +23 -25
  21. data/app/assets/javascripts/headmin/controllers/file_preview_controller.js +237 -237
  22. data/app/assets/javascripts/headmin/controllers/filter_controller.js +44 -44
  23. data/app/assets/javascripts/headmin/controllers/filters_controller.js +57 -61
  24. data/app/assets/javascripts/headmin/controllers/flatpickr_controller.js +29 -29
  25. data/app/assets/javascripts/headmin/controllers/hello_controller.js +3 -3
  26. data/app/assets/javascripts/headmin/controllers/notification_controller.js +7 -6
  27. data/app/assets/javascripts/headmin/controllers/popup_controller.js +51 -52
  28. data/app/assets/javascripts/headmin/controllers/redactorx_controller.js +36 -9
  29. data/app/assets/javascripts/headmin/controllers/repeater_controller.js +122 -125
  30. data/app/assets/javascripts/headmin/controllers/select_controller.js +40 -39
  31. data/app/assets/javascripts/headmin/controllers/table_actions_controller.js +88 -77
  32. data/app/assets/javascripts/headmin/controllers/table_controller.js +103 -89
  33. data/app/assets/javascripts/headmin/index.js +38 -39
  34. data/app/assets/javascripts/headmin.js +287 -732
  35. data/app/assets/stylesheets/headmin/forms/autocomplete.scss +21 -0
  36. data/app/assets/stylesheets/headmin/forms/file.scss +46 -0
  37. data/app/assets/stylesheets/headmin/forms/repeater.scss +62 -0
  38. data/app/assets/stylesheets/headmin/forms/search.scss +12 -0
  39. data/app/assets/stylesheets/headmin/forms.scss +11 -0
  40. data/app/assets/stylesheets/headmin/general.scss +5 -0
  41. data/app/assets/stylesheets/headmin/overrides/bootstrap.scss +5 -3
  42. data/app/assets/stylesheets/headmin/overrides/redactorx.scss +74 -0
  43. data/app/assets/stylesheets/headmin/popup.scss +1 -0
  44. data/app/assets/stylesheets/headmin/syntax.scss +36 -349
  45. data/app/assets/stylesheets/headmin/table.scss +1 -1
  46. data/app/assets/stylesheets/headmin/utilities/buttons.scss +19 -0
  47. data/app/assets/stylesheets/headmin/utilities/dropzone.scss +72 -0
  48. data/app/assets/stylesheets/headmin/utilities.scss +2 -68
  49. data/app/assets/stylesheets/headmin/vendor/tom-select-bootstrap.css +1 -2
  50. data/app/assets/stylesheets/headmin.css +206 -206
  51. data/app/assets/stylesheets/headmin.scss +1 -1
  52. data/app/controllers/concerns/headmin/authentication.rb +1 -1
  53. data/app/controllers/concerns/headmin/searchable.rb +1 -1
  54. data/app/controllers/concerns/headmin/sortable.rb +7 -7
  55. data/app/helpers/headmin/admin_helper.rb +1 -2
  56. data/app/helpers/headmin/bootstrap_helper.rb +2 -24
  57. data/app/helpers/headmin/filter_helper.rb +1 -1
  58. data/app/helpers/headmin/form_helper.rb +5 -11
  59. data/app/helpers/headmin/notification_helper.rb +21 -21
  60. data/app/helpers/headmin/request_helper.rb +3 -3
  61. data/app/models/concerns/headmin/block.rb +1 -2
  62. data/app/models/concerns/headmin/blockable.rb +2 -2
  63. data/app/models/concerns/headmin/field.rb +2 -1
  64. data/app/models/concerns/headmin/fieldable.rb +8 -8
  65. data/app/models/concerns/headmin/form/autocompletable.rb +38 -0
  66. data/app/models/concerns/headmin/form/hintable.rb +19 -0
  67. data/app/models/concerns/headmin/form/input_groupable.rb +23 -0
  68. data/app/models/concerns/headmin/form/labelable.rb +33 -0
  69. data/app/models/concerns/headmin/form/listable.rb +28 -0
  70. data/app/models/concerns/headmin/form/placeholderable.rb +13 -0
  71. data/app/models/concerns/headmin/form/validatable.rb +40 -0
  72. data/app/models/concerns/headmin/form/wrappable.rb +21 -0
  73. data/app/models/headmin/.DS_Store +0 -0
  74. data/app/models/headmin/blocks_view.rb +15 -0
  75. data/app/models/headmin/form/blocks_view.rb +29 -0
  76. data/app/models/headmin/form/checkbox_view.rb +52 -0
  77. data/app/models/headmin/form/date_range_view.rb +25 -0
  78. data/app/models/headmin/form/date_view.rb +45 -0
  79. data/app/models/headmin/form/email_view.rb +48 -0
  80. data/app/models/headmin/form/file_view.rb +116 -0
  81. data/app/models/headmin/form/flatpickr_range_view.rb +102 -0
  82. data/app/models/headmin/form/flatpickr_view.rb +37 -0
  83. data/app/models/headmin/form/hidden_view.rb +10 -0
  84. data/app/models/headmin/form/hint_view.rb +6 -0
  85. data/app/models/headmin/form/input_group_view.rb +19 -0
  86. data/app/models/headmin/form/label_view.rb +24 -0
  87. data/app/models/headmin/form/number_view.rb +49 -0
  88. data/app/models/headmin/form/password_view.rb +44 -0
  89. data/app/models/headmin/form/redactorx_view.rb +59 -0
  90. data/app/models/headmin/form/search_view.rb +48 -0
  91. data/app/models/headmin/form/select_view.rb +62 -0
  92. data/app/models/headmin/form/switch_view.rb +23 -0
  93. data/app/models/headmin/form/text_view.rb +48 -0
  94. data/app/models/headmin/form/textarea_view.rb +44 -0
  95. data/app/models/headmin/form/url_view.rb +48 -0
  96. data/app/models/headmin/form/wrapper_view.rb +19 -0
  97. data/app/models/headmin/form/wysiwyg_view.rb +17 -0
  98. data/app/models/headmin/thumbnail_view.rb +66 -0
  99. data/app/models/view_model.rb +58 -0
  100. data/app/views/headmin/_blocks.html.erb +13 -9
  101. data/app/views/headmin/_heading.html.erb +7 -1
  102. data/app/views/headmin/_thumbnail.html.erb +5 -39
  103. data/app/views/headmin/dropdown/_item.html.erb +1 -1
  104. data/app/views/headmin/forms/_autocomplete.html.erb +11 -0
  105. data/app/views/headmin/forms/_blocks.html.erb +16 -17
  106. data/app/views/headmin/forms/_checkbox.html.erb +24 -29
  107. data/app/views/headmin/forms/_datalist.html.erb +3 -0
  108. data/app/views/headmin/forms/_date.html.erb +24 -24
  109. data/app/views/headmin/forms/_date_range.html.erb +19 -21
  110. data/app/views/headmin/forms/_email.html.erb +27 -32
  111. data/app/views/headmin/forms/_errors.html.erb +2 -3
  112. data/app/views/headmin/forms/_file.html.erb +84 -181
  113. data/app/views/headmin/forms/_flatpickr.html.erb +19 -20
  114. data/app/views/headmin/forms/_flatpickr_range.html.erb +28 -37
  115. data/app/views/headmin/forms/_hidden.html.erb +9 -10
  116. data/app/views/headmin/forms/_hint.html.erb +16 -0
  117. data/app/views/headmin/forms/_input_group.html.erb +21 -0
  118. data/app/views/headmin/forms/_label.html.erb +5 -13
  119. data/app/views/headmin/forms/_number.html.erb +23 -35
  120. data/app/views/headmin/forms/_password.html.erb +21 -30
  121. data/app/views/headmin/forms/_redactorx.html.erb +21 -40
  122. data/app/views/headmin/forms/_repeater.html.erb +55 -60
  123. data/app/views/headmin/forms/_search.html.erb +43 -0
  124. data/app/views/headmin/forms/_select.html.erb +24 -49
  125. data/app/views/headmin/forms/_switch.html.erb +29 -0
  126. data/app/views/headmin/forms/_text.html.erb +42 -96
  127. data/app/views/headmin/forms/_textarea.html.erb +21 -32
  128. data/app/views/headmin/forms/_url.html.erb +26 -31
  129. data/app/views/headmin/forms/_validation.html.erb +10 -13
  130. data/app/views/headmin/forms/_wrapper.html.erb +9 -0
  131. data/app/views/headmin/forms/_wysiwyg.html.erb +28 -0
  132. data/app/views/headmin/forms/autocomplete/_item.html.erb +3 -0
  133. data/app/views/headmin/forms/autocomplete/_list.html.erb +3 -0
  134. data/app/views/headmin/forms/fields/_group.html.erb +6 -4
  135. data/app/views/headmin/forms/repeater/_row.html.erb +4 -4
  136. data/app/views/headmin/nav/item/_devise.html.erb +1 -1
  137. data/app/views/headmin/table/_actions.html.erb +1 -1
  138. data/app/views/headmin/table/actions/_action.html.erb +2 -1
  139. data/app/views/headmin/table/actions/_delete.html.erb +1 -1
  140. data/app/views/headmin/views/devise/registrations/_edit.html.erb +2 -2
  141. data/bin/console +0 -1
  142. data/config/initializers/customize_input_error.rb +4 -4
  143. data/config/locales/headmin/forms/en.yml +0 -11
  144. data/config/locales/headmin/forms/nl.yml +0 -11
  145. data/esbuild-css.js +18 -18
  146. data/esbuild-js.js +8 -8
  147. data/headmin.gemspec +1 -3
  148. data/lib/generators/headmin/blocks_generator.rb +8 -8
  149. data/lib/generators/headmin/devise_generator.rb +4 -4
  150. data/lib/generators/headmin/fields_generator.rb +9 -9
  151. data/lib/generators/templates/controllers/auth/confirmations_controller.rb +1 -3
  152. data/lib/generators/templates/controllers/auth/omniauth_callbacks_controller.rb +1 -3
  153. data/lib/generators/templates/controllers/auth/passwords_controller.rb +1 -3
  154. data/lib/generators/templates/controllers/auth/registrations_controller.rb +1 -3
  155. data/lib/generators/templates/controllers/auth/sessions_controller.rb +1 -3
  156. data/lib/generators/templates/controllers/auth/unlocks_controller.rb +1 -3
  157. data/lib/generators/templates/models/block.rb +1 -1
  158. data/lib/headmin/engine.rb +6 -6
  159. data/lib/headmin/version.rb +1 -3
  160. data/lib/headmin.rb +0 -2
  161. data/package-lock.json +5359 -0
  162. data/package.json +13 -7
  163. data/view_model_benchmark.rb +74 -0
  164. data/yarn-error.log +367 -0
  165. data/yarn.lock +1448 -161
  166. metadata +69 -25
  167. data/.rubocop.yml +0 -13
  168. data/app/assets/stylesheets/headmin/form.scss +0 -132
  169. data/app/assets/stylesheets/headmin/overrides/redactorx.css +0 -3
  170. data/app/helpers/headmin/documentation_helper.rb +0 -35
  171. data/app/models/headmin/documentation_renderer.rb +0 -32
  172. data/app/models/headmin/form/base.rb +0 -79
  173. data/app/models/headmin/form/text.rb +0 -53
  174. data/app/services/block_service.rb +0 -72
  175. data/app/views/headmin/_card.html.erb +0 -52
  176. data/app/views/headmin/forms/_actions.html.erb +0 -28
  177. data/app/views/headmin/forms/_base.html.erb +0 -114
  178. data/app/views/headmin/forms/_image.html.erb +0 -21
  179. data/app/views/headmin/forms/_video.html.erb +0 -21
  180. data/app/views/headmin/forms/actions/_destroy.html.erb +0 -13
  181. data/app/views/headmin/forms/actions/_save.html.erb +0 -12
  182. data/app/views/headmin/forms/actions/_view.html.erb +0 -15
  183. data/docs/blocks-and-fields.md +0 -54
  184. data/docs/blocks.md +0 -48
  185. data/docs/devise.md +0 -41
  186. data/docs/fields.md +0 -79
@@ -0,0 +1,255 @@
1
+ /* global fetch */
2
+ import { Controller } from '@hotwired/stimulus'
3
+
4
+ export default class extends Controller {
5
+ static get targets () {
6
+ return ['input', 'dropdown', 'dropdownItem']
7
+ }
8
+
9
+ static get values () {
10
+ return {
11
+ url: String
12
+ }
13
+ }
14
+
15
+ connect () {
16
+ // Focus
17
+ this.inputTarget.addEventListener('focus', (event) => {
18
+ this.show()
19
+ })
20
+
21
+ // Typing
22
+ this.inputTarget.addEventListener('keydown', (event) => {
23
+ this.handleKeydown(event)
24
+ })
25
+
26
+ // Clicked outside dropdown
27
+ document.addEventListener('click', (event) => {
28
+ this.handleOutsideClick(event)
29
+ })
30
+ }
31
+
32
+ handleKeydown (event) {
33
+ this.show()
34
+
35
+ const keyCode = parseInt(event.keyCode, 10)
36
+ if (this.isArrowKey(keyCode)) {
37
+ this.handleArrowKey(keyCode)
38
+ } else if (this.isEnterKey(keyCode)) {
39
+ this.selectActiveItem()
40
+ } else {
41
+ this.handleTextKey()
42
+ }
43
+ }
44
+
45
+ selectActiveItem () {
46
+ this.activeItem().click()
47
+ }
48
+
49
+ isEnterKey (keyCode) {
50
+ return keyCode === 13
51
+ }
52
+
53
+ handleArrowKey (keyCode) {
54
+ switch (keyCode) {
55
+ case 38:
56
+ this.handleArrowUp()
57
+ break
58
+ case 40:
59
+ this.handleArrowDown()
60
+ break
61
+ default:
62
+ }
63
+ }
64
+
65
+ handleArrowUp () {
66
+ this.selectPreviousItem()
67
+ }
68
+
69
+ handleArrowDown () {
70
+ this.selectNextItem()
71
+ }
72
+
73
+ selectNextItem () {
74
+ const next = this.nextItem()
75
+ this.deselectAll()
76
+ next.classList.add('active')
77
+ }
78
+
79
+ nextItem () {
80
+ const current = this.activeItem()
81
+
82
+ // Select first item if nothing selected
83
+ if (!this.hasSelectedItem()) {
84
+ return this.firstItem()
85
+ }
86
+
87
+ if (this.isItemLast(current)) {
88
+ return this.firstItem()
89
+ } else {
90
+ const index = this.itemIndex(current)
91
+ return this.itemAtIndex(index + 1)
92
+ }
93
+ }
94
+
95
+ selectPreviousItem () {
96
+ const previous = this.previousItem()
97
+ this.deselectAll()
98
+ previous.classList.add('active')
99
+ }
100
+
101
+ previousItem () {
102
+ const current = this.activeItem()
103
+
104
+ // Select last item if nothing selected
105
+ if (!this.hasSelectedItem()) {
106
+ return this.lastItem()
107
+ }
108
+
109
+ if (this.isItemFirst(current)) {
110
+ return this.lastItem()
111
+ } else {
112
+ const index = this.itemIndex(current)
113
+ return this.itemAtIndex(index - 1)
114
+ }
115
+ }
116
+
117
+ deselectAll () {
118
+ this.dropdownItemTargets.forEach(dropdownItem => {
119
+ dropdownItem.classList.remove('active')
120
+ })
121
+ }
122
+
123
+ itemAtIndex (index) {
124
+ return this.dropdownItemTargets[index]
125
+ }
126
+
127
+ firstItem () {
128
+ return this.itemAtIndex(0)
129
+ }
130
+
131
+ lastItem () {
132
+ return this.itemAtIndex(this.dropdownItemTargets.length - 1)
133
+ }
134
+
135
+ hasSelectedItem () {
136
+ return this.activeItem() !== undefined
137
+ }
138
+
139
+ activeItem () {
140
+ return this.dropdownItemTargets.find((item) => {
141
+ return item.classList.contains('active')
142
+ })
143
+ }
144
+
145
+ isItemLast (item) {
146
+ return this.itemIndex(item) === this.dropdownItemTargets.length - 1
147
+ }
148
+
149
+ isItemFirst (item) {
150
+ return this.itemIndex(item) === 0
151
+ }
152
+
153
+ itemIndex (item) {
154
+ return Array.from(this.dropdownItemTargets).indexOf(item)
155
+ }
156
+
157
+ handleTextKey () {
158
+ // 1. fetch info
159
+ this.fetchCollection().then((html) => {
160
+ // 2. render html
161
+ this.renderCollection(html)
162
+ }).then(() => {
163
+ // 3. sort by relevance
164
+ // ...
165
+ // 4. Highlight
166
+ this.highlight()
167
+ })
168
+ }
169
+
170
+ show () {
171
+ if (this.isDropdownEmpty()) {
172
+ this.dropdownTarget.classList.remove('d-none')
173
+ } else {
174
+ this.hide()
175
+ }
176
+ }
177
+
178
+ hide () {
179
+ this.dropdownTarget.classList.add('d-none')
180
+ }
181
+
182
+ isDropdownEmpty () {
183
+ return this.dropdownTarget.textContent.trim().length > 0
184
+ }
185
+
186
+ isArrowKey (keyCode) {
187
+ const arrowKeyCodes = [37, 38, 39, 40]
188
+ return arrowKeyCodes.includes(keyCode)
189
+ }
190
+
191
+ fetchCollection () {
192
+ if (this.isRemote()) {
193
+ return fetch(this.urlValue).then((response) => {
194
+ return response.text()
195
+ }).catch((error) => {
196
+ console.error('The URL you provided for the autocomplete collection didn\'t return a successful result', error)
197
+ })
198
+ } else {
199
+ return Promise.resolve(this.dropdownTarget.innerHTML)
200
+ }
201
+ }
202
+
203
+ renderCollection (html) {
204
+ this.dropdownTarget.innerHTML = html
205
+ }
206
+
207
+ isRemote () {
208
+ return this.hasUrlValue
209
+ }
210
+
211
+ highlight () {
212
+ const query = this.value()
213
+ this.dropdownItemTargets.forEach(dropdownItem => {
214
+ let text = dropdownItem.innerHTML
215
+
216
+ // Clean up past results
217
+ text = text.replace(/<mark.*?>(.*?)<\/mark>/ig, '$1')
218
+
219
+ // Highlight query
220
+ const regex2 = new RegExp(`(${query})`, 'gi')
221
+ text = text.replace(regex2, '<mark>$1</mark>')
222
+
223
+ dropdownItem.innerHTML = text
224
+ })
225
+ }
226
+
227
+ select (event) {
228
+ this.inputTarget.value = event.target.getAttribute('value')
229
+ this.hide()
230
+ }
231
+
232
+ value () {
233
+ return this.inputTarget.value
234
+ }
235
+
236
+ numberOfCharacters () {
237
+ return this.value().length
238
+ }
239
+
240
+ handleOutsideClick (event) {
241
+ if (!this.isClickedInside(event)) {
242
+ this.hide()
243
+ }
244
+ }
245
+
246
+ isClickedInside (event) {
247
+ if (!event) {
248
+ return false
249
+ }
250
+ const inInput = this.inputTarget.contains(event.target)
251
+ const inDropdown = this.dropdownTarget.contains(event.target)
252
+
253
+ return (inInput || inDropdown)
254
+ }
255
+ }
@@ -1,102 +1,97 @@
1
- import {Controller} from "@hotwired/stimulus"
2
- import Sortable from "sortablejs";
1
+ import { Controller } from '@hotwired/stimulus'
2
+ import Sortable from 'sortablejs'
3
3
 
4
4
  export default class extends Controller {
5
- static get targets() {
6
- return ["templateBlock", "block", "blocks", "templateEmpty", "button", "buttons"]
7
- }
8
-
9
- connect() {
10
- new Sortable(this.blocksTarget, {
11
- onEnd: () => {
12
- this.reorderPositions()
13
- }
14
- })
15
-
16
- this.toggleEmpty()
17
- }
5
+ static get targets () {
6
+ return ['templateBlock', 'block', 'blocks', 'templateEmpty', 'button', 'buttons']
7
+ }
18
8
 
19
- toggleEmpty() {
20
- if(this.blockCount() > 0) {
21
- const empty = this.blocksTarget.querySelector('#blocks-empty')
22
- if(empty) {
23
- empty.remove()
24
- }
25
- } else {
26
- const empty = this.templateEmptyTarget.innerHTML
27
- this.blocksTarget.insertAdjacentHTML('beforeend', empty)
28
- }
9
+ connect () {
10
+ Sortable.create(this.blocksTarget, {
11
+ onEnd: () => {
12
+ this.reorderPositions()
13
+ }
14
+ })
15
+
16
+ this.toggleEmpty()
17
+ }
18
+
19
+ toggleEmpty () {
20
+ if (this.blockCount() > 0) {
21
+ const empty = this.blocksTarget.querySelector('#blocks-empty')
22
+ if (empty) {
23
+ empty.remove()
24
+ }
25
+ } else {
26
+ const empty = this.templateEmptyTarget.innerHTML
27
+ this.blocksTarget.insertAdjacentHTML('beforeend', empty)
29
28
  }
29
+ }
30
30
 
31
- add(event) {
32
- event.preventDefault()
33
- const blockType = event.target.dataset.type
34
- let html = this.templateBlockTargets.filter(blockTarget => blockTarget.id === blockType)[0].innerHTML
35
-
36
- html = this.setPosition(html)
37
-
38
- const element = this.blocksTarget.querySelector(`li[data-position='${event.target.dataset.position}']`)
31
+ add (event) {
32
+ event.preventDefault()
33
+ const blockType = event.target.dataset.type
34
+ let html = this.templateBlockTargets.filter(blockTarget => blockTarget.id === blockType)[0].innerHTML
39
35
 
40
- if (element) {
41
- element.insertAdjacentHTML('afterend', html)
42
- }
43
- else {
44
- this.blocksTarget.insertAdjacentHTML('afterbegin', html)
45
- }
36
+ html = this.setPosition(html)
46
37
 
47
- // Dispatch an event
48
- this.blocksTarget.dispatchEvent(new CustomEvent('headmin:reinit', {bubbles: true}))
38
+ const element = this.blocksTarget.querySelector(`li[data-position='${event.target.dataset.position}']`)
49
39
 
50
- this.reorderPositions()
51
- this.toggleEmpty()
40
+ if (element) {
41
+ element.insertAdjacentHTML('afterend', html)
42
+ } else {
43
+ this.blocksTarget.insertAdjacentHTML('afterbegin', html)
52
44
  }
53
45
 
54
- remove(event) {
55
- event.preventDefault()
46
+ this.reorderPositions()
47
+ this.toggleEmpty()
48
+ }
56
49
 
57
- const block = event.target.closest(".list-group-item")
58
- const destroyInput = block.querySelector("input[name*='_destroy']")
50
+ remove (event) {
51
+ event.preventDefault()
59
52
 
60
- if (destroyInput) {
61
- destroyInput.value = 1
62
- block.style.display = 'none'
63
- } else {
64
- block.remove()
65
- }
53
+ const block = event.target.closest('.list-group-item')
54
+ const destroyInput = block.querySelector("input[name*='_destroy']")
66
55
 
67
- this.reorderPositions()
68
- this.toggleEmpty()
56
+ if (destroyInput) {
57
+ destroyInput.value = 1
58
+ block.style.display = 'none'
59
+ } else {
60
+ block.remove()
69
61
  }
70
62
 
71
- setPosition(html) {
72
- const position = this.retrieveLastPosition() + 1
63
+ this.reorderPositions()
64
+ this.toggleEmpty()
65
+ }
73
66
 
74
- const regex = new RegExp('99999', "g");
75
- return html.replace(regex, position)
76
- }
67
+ setPosition (html) {
68
+ const position = this.retrieveLastPosition() + 1
77
69
 
78
- retrieveLastPosition() {
79
- const blocks = Array.from(this.blockTargets)
80
- if (blocks.length < 1) {
81
- return 0
82
- }
70
+ return html.replace(/99999/g, position)
71
+ }
83
72
 
84
- const lastBlock = blocks.slice(-1)[0]
85
- return parseInt(lastBlock.querySelector("[name*='position']").value)
73
+ retrieveLastPosition () {
74
+ const blocks = Array.from(this.blockTargets)
75
+ if (blocks.length < 1) {
76
+ return 0
86
77
  }
87
78
 
88
- reorderPositions() {
89
- for (let [index, block] of this.blockTargets.entries()) {
90
- this.changePositionInfo(block, index)
91
- }
92
- }
79
+ const lastBlock = blocks.slice(-1)[0]
80
+ return parseInt(lastBlock.querySelector("[name*='position']").value)
81
+ }
93
82
 
94
- changePositionInfo(block, index) {
95
- block.setAttribute("data-position", index)
96
- block.querySelector("input[name*='position']").value = index
83
+ reorderPositions () {
84
+ for (const [index, block] of this.blockTargets.entries()) {
85
+ this.changePositionInfo(block, index)
97
86
  }
87
+ }
98
88
 
99
- blockCount() {
100
- return this.blockTargets.length;
101
- }
102
- }
89
+ changePositionInfo (block, index) {
90
+ block.setAttribute('data-position', index)
91
+ block.querySelector("input[name*='position']").value = index
92
+ }
93
+
94
+ blockCount () {
95
+ return this.blockTargets.length
96
+ }
97
+ }
@@ -1,32 +1,32 @@
1
- import {Controller} from "@hotwired/stimulus"
1
+ import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  export default class extends Controller {
4
- static get targets() {
5
- return ["dateInput", "startDateInput", "endDateInput"]
6
- }
4
+ static get targets () {
5
+ return ['dateInput', 'startDateInput', 'endDateInput']
6
+ }
7
7
 
8
- update(event) {
9
- const flatpickr = event.target._flatpickr
10
- const startDate = flatpickr.selectedDates[0]
11
- const endDate = flatpickr.selectedDates[1]
8
+ update (event) {
9
+ const flatpickr = event.target._flatpickr
10
+ const startDate = flatpickr.selectedDates[0]
11
+ const endDate = flatpickr.selectedDates[1]
12
12
 
13
- this.setStartDateInputValue(this.formatDate(startDate))
14
- this.setEndDateInputValue(this.formatDate(endDate))
15
- }
13
+ this.setStartDateInputValue(this.formatDate(startDate))
14
+ this.setEndDateInputValue(this.formatDate(endDate))
15
+ }
16
16
 
17
- setStartDateInputValue(value) {
18
- this.startDateInputTarget.value = value
19
- }
17
+ setStartDateInputValue (value) {
18
+ this.startDateInputTarget.value = value
19
+ }
20
20
 
21
- setEndDateInputValue(value) {
22
- this.endDateInputTarget.value = value
23
- }
21
+ setEndDateInputValue (value) {
22
+ this.endDateInputTarget.value = value
23
+ }
24
24
 
25
- formatDate(date) {
26
- if(date instanceof Date) {
27
- return date.toLocaleDateString('nl-BE', {day: '2-digit', month: '2-digit', year: 'numeric'})
28
- } else {
29
- return null;
30
- }
25
+ formatDate (date) {
26
+ if (date instanceof Date) {
27
+ return date.toLocaleDateString('nl-BE', { day: '2-digit', month: '2-digit', year: 'numeric' })
28
+ } else {
29
+ return null
31
30
  }
32
- }
31
+ }
32
+ }
@@ -1,33 +1,31 @@
1
- import {Controller} from "@hotwired/stimulus"
1
+ import { Controller } from '@hotwired/stimulus'
2
2
 
3
3
  // References:
4
4
  // https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API
5
5
 
6
6
  export default class extends Controller {
7
- static get targets() {
8
- return ["input"]
9
- }
7
+ static get targets () {
8
+ return ['input']
9
+ }
10
10
 
11
- connect() {
12
- this.element.classList.add('h-dropzone')
11
+ connect () {
12
+ // Drag
13
+ this.inputTarget.addEventListener('dragover', (event) => {
14
+ this.element.classList.add('focus')
15
+ })
16
+ this.inputTarget.addEventListener('dragleave', (event) => {
17
+ this.element.classList.remove('focus')
18
+ })
19
+ this.inputTarget.addEventListener('drop', (event) => {
20
+ this.element.classList.remove('focus')
21
+ })
13
22
 
14
- // Drag
15
- this.inputTarget.addEventListener('dragover', (event) => {
16
- this.element.classList.add('dragover')
17
- })
18
- this.inputTarget.addEventListener('dragleave', (event) => {
19
- this.element.classList.remove('dragover')
20
- })
21
- this.inputTarget.addEventListener('drop', (event) => {
22
- this.element.classList.remove('dragover')
23
- })
24
-
25
- // Focus
26
- this.inputTarget.addEventListener('focusin', (event) => {
27
- this.element.classList.add('active')
28
- })
29
- this.inputTarget.addEventListener('focusout', (event) => {
30
- this.element.classList.remove('active')
31
- })
32
- }
23
+ // Focus
24
+ this.inputTarget.addEventListener('focusin', (event) => {
25
+ this.element.classList.add('focus')
26
+ })
27
+ this.inputTarget.addEventListener('focusout', (event) => {
28
+ this.element.classList.remove('focus')
29
+ })
30
+ }
33
31
  }