ahoy_captain 0.11.1 → 0.76

Sign up to get free protection for your applications and to get access to all the features.
Files changed (190) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -25
  3. data/Rakefile +2 -23
  4. data/app/assets/javascript/ahoy_captain/application.js +4 -4
  5. data/app/assets/javascript/ahoy_captain/controllers/application.js +5 -5
  6. data/app/assets/javascript/ahoy_captain/controllers/application_controller.js +8 -27
  7. data/app/assets/javascript/ahoy_captain/controllers/details_modal_controller.js +5 -5
  8. data/app/assets/javascript/ahoy_captain/controllers/dropdown_label_controller.js +2 -2
  9. data/app/assets/javascript/ahoy_captain/controllers/filter_controller.js +145 -0
  10. data/app/assets/javascript/ahoy_captain/controllers/filter_tag_controller.js +17 -0
  11. data/app/assets/javascript/ahoy_captain/controllers/funnel_chart_controller.js +127 -113
  12. data/app/assets/javascript/ahoy_captain/controllers/index.js +3 -4
  13. data/app/assets/javascript/ahoy_captain/controllers/link_controller.js +43 -0
  14. data/app/assets/javascript/ahoy_captain/controllers/navigation_controller.js +25 -0
  15. data/app/assets/javascript/ahoy_captain/controllers/realtime_controller.js +9 -12
  16. data/app/components/ahoy_captain/dropdown_button_component.html.erb +5 -5
  17. data/app/components/ahoy_captain/dropdown_link_component.html.erb +7 -5
  18. data/app/components/ahoy_captain/dropdown_link_component.rb +0 -4
  19. data/app/components/ahoy_captain/filter/modal_component.html.erb +9 -12
  20. data/app/components/ahoy_captain/filter/select_component.html.erb +19 -23
  21. data/app/components/ahoy_captain/filter/select_component.rb +9 -41
  22. data/app/components/ahoy_captain/filter/tag_component.html.erb +4 -8
  23. data/app/components/ahoy_captain/filter/tag_component.rb +30 -6
  24. data/app/components/ahoy_captain/filter/tag_container_component.html.erb +3 -2
  25. data/app/components/ahoy_captain/filter/tag_container_component.rb +8 -1
  26. data/app/components/ahoy_captain/sticky_nav_component.html.erb +33 -28
  27. data/app/components/ahoy_captain/sticky_nav_component.rb +0 -19
  28. data/app/components/ahoy_captain/table_component.html.erb +37 -4
  29. data/app/components/ahoy_captain/table_component.rb +5 -25
  30. data/app/components/ahoy_captain/tile_component.html.erb +10 -21
  31. data/app/components/ahoy_captain/tile_component.rb +2 -10
  32. data/app/components/ahoy_captain/tooltip_component.html.erb +2 -2
  33. data/app/controllers/ahoy_captain/application_controller.rb +30 -23
  34. data/app/controllers/ahoy_captain/campaigns_controller.rb +10 -2
  35. data/app/controllers/ahoy_captain/cities_controller.rb +24 -0
  36. data/app/controllers/ahoy_captain/countries_controller.rb +24 -0
  37. data/app/controllers/ahoy_captain/devices_controller.rb +6 -3
  38. data/app/controllers/ahoy_captain/entry_pages_controller.rb +4 -2
  39. data/app/controllers/ahoy_captain/exit_pages_controller.rb +4 -3
  40. data/app/controllers/ahoy_captain/filters/base_controller.rb +3 -1
  41. data/app/controllers/ahoy_captain/filters/pages/actions_controller.rb +1 -1
  42. data/app/controllers/ahoy_captain/filters/pages/entry_pages_controller.rb +3 -3
  43. data/app/controllers/ahoy_captain/filters/pages/exit_pages_controller.rb +3 -2
  44. data/app/controllers/ahoy_captain/filters/sources_controller.rb +1 -1
  45. data/app/controllers/ahoy_captain/filters/utms_controller.rb +1 -1
  46. data/app/controllers/ahoy_captain/realtimes_controller.rb +1 -1
  47. data/app/controllers/ahoy_captain/regions_controller.rb +24 -0
  48. data/app/controllers/ahoy_captain/sources_controller.rb +5 -2
  49. data/app/controllers/ahoy_captain/stats/base_controller.rb +0 -142
  50. data/app/controllers/ahoy_captain/stats/bounce_rates_controller.rb +2 -4
  51. data/app/controllers/ahoy_captain/stats/total_pageviews_controller.rb +1 -2
  52. data/app/controllers/ahoy_captain/stats/total_visits_controller.rb +1 -2
  53. data/app/controllers/ahoy_captain/stats/unique_visitors_controller.rb +1 -3
  54. data/app/controllers/ahoy_captain/stats/views_per_visits_controller.rb +8 -3
  55. data/app/controllers/ahoy_captain/stats/visit_durations_controller.rb +1 -2
  56. data/app/controllers/ahoy_captain/top_pages_controller.rb +8 -2
  57. data/app/decorators/ahoy_captain/application_decorator.rb +3 -27
  58. data/app/decorators/ahoy_captain/campaign_decorator.rb +0 -8
  59. data/app/decorators/ahoy_captain/city_decorator.rb +0 -12
  60. data/app/decorators/ahoy_captain/country_decorator.rb +0 -10
  61. data/app/decorators/ahoy_captain/device_decorator.rb +2 -13
  62. data/app/decorators/ahoy_captain/page_decorator.rb +0 -11
  63. data/app/decorators/ahoy_captain/region_decorator.rb +0 -16
  64. data/app/decorators/ahoy_captain/source_decorator.rb +0 -7
  65. data/app/helpers/ahoy_captain/application_helper.rb +3 -60
  66. data/app/models/ahoy_captain/current.rb +9 -0
  67. data/app/models/ahoy_captain/rangeable.rb +3 -0
  68. data/app/models/ahoy_captain/url_helpers.rb +6 -0
  69. data/app/models/concerns/ahoy_captain/range_options.rb +14 -1
  70. data/app/presenters/ahoy_captain/dashboard_presenter.rb +46 -18
  71. data/app/presenters/ahoy_captain/funnel_presenter.rb +29 -32
  72. data/app/presenters/ahoy_captain/goals_presenter.rb +23 -33
  73. data/app/queries/ahoy_captain/application_query.rb +13 -81
  74. data/app/queries/ahoy_captain/entry_pages_query.rb +2 -3
  75. data/app/queries/ahoy_captain/event_query.rb +8 -30
  76. data/app/queries/ahoy_captain/exit_pages_query.rb +4 -6
  77. data/app/queries/ahoy_captain/stats/average_views_per_visit_query.rb +4 -11
  78. data/app/queries/ahoy_captain/stats/average_visit_duration_query.rb +7 -15
  79. data/app/queries/ahoy_captain/stats/bounce_rates_query.rb +7 -24
  80. data/app/queries/ahoy_captain/stats/total_pageviews_query.rb +2 -2
  81. data/app/queries/ahoy_captain/stats/total_visitors_query.rb +2 -2
  82. data/app/queries/ahoy_captain/stats/unique_visitors_query.rb +2 -2
  83. data/app/queries/ahoy_captain/stats/views_per_visit_query.rb +3 -3
  84. data/app/queries/ahoy_captain/stats/visit_duration_query.rb +5 -5
  85. data/app/queries/ahoy_captain/visit_query.rb +13 -12
  86. data/app/views/ahoy_captain/devices/index.html+details.erb +1 -1
  87. data/app/views/ahoy_captain/devices/index.html.erb +2 -2
  88. data/app/views/ahoy_captain/funnels/show.html.erb +2 -5
  89. data/app/views/ahoy_captain/goals/index.html.erb +37 -2
  90. data/app/views/ahoy_captain/layouts/application.html.erb +4 -3
  91. data/app/views/ahoy_captain/realtimes/show.html.erb +1 -1
  92. data/app/views/ahoy_captain/roots/show.html.erb +118 -117
  93. data/app/views/ahoy_captain/stats/base/index.html.erb +1 -38
  94. data/app/views/ahoy_captain/stats/show.html.erb +56 -14
  95. data/config/routes.rb +3 -16
  96. data/lib/ahoy_captain/ahoy/event_methods.rb +75 -36
  97. data/lib/ahoy_captain/ahoy/visit_methods.rb +1 -1
  98. data/lib/ahoy_captain/configuration.rb +7 -18
  99. data/lib/ahoy_captain/engine.rb +0 -22
  100. data/lib/ahoy_captain/goals.rb +4 -16
  101. data/lib/ahoy_captain/period_collection.rb +1 -1
  102. data/lib/ahoy_captain/version.rb +1 -1
  103. data/lib/ahoy_captain.rb +1 -8
  104. data/lib/generators/ahoy_captain/templates/config.rb.tt +3 -50
  105. metadata +17 -185
  106. data/app/assets/javascript/ahoy_captain/controllers/combobox_controller.js +0 -371
  107. data/app/assets/javascript/ahoy_captain/controllers/filter/item_controller.js +0 -12
  108. data/app/assets/javascript/ahoy_captain/controllers/filter_form_controller.js +0 -13
  109. data/app/assets/javascript/ahoy_captain/controllers/filter_modal_controller.js +0 -45
  110. data/app/assets/javascript/ahoy_captain/controllers/frame_link_controller.js +0 -20
  111. data/app/assets/javascript/ahoy_captain/controllers/interval_controller.js +0 -15
  112. data/app/assets/javascript/ahoy_captain/controllers/line_chart_controller.js +0 -251
  113. data/app/assets/javascript/ahoy_captain/controllers/map_controller.js +0 -47
  114. data/app/assets/javascript/ahoy_captain/controllers/predicate_select_controller.js +0 -10
  115. data/app/assets/javascript/ahoy_captain/controllers/properties_controller.js +0 -8
  116. data/app/assets/javascript/ahoy_captain/controllers/property_filter_controller.js +0 -45
  117. data/app/assets/javascript/ahoy_captain/controllers/tile_controller.js +0 -33
  118. data/app/assets/javascript/ahoy_captain/controllers/toggle_controller.js +0 -17
  119. data/app/assets/javascript/ahoy_captain/helpers/chart_utils.js +0 -156
  120. data/app/assets/javascript/ahoy_captain/helpers/countries.js +0 -2261
  121. data/app/assets/javascript/ahoy_captain/helpers/number_formatters.js +0 -55
  122. data/app/components/ahoy_captain/combobox_component.html.erb +0 -33
  123. data/app/components/ahoy_captain/combobox_component.rb +0 -13
  124. data/app/components/ahoy_captain/comparison_link_component.html.erb +0 -17
  125. data/app/components/ahoy_captain/comparison_link_component.rb +0 -44
  126. data/app/components/ahoy_captain/filter/dropdown_component.html.erb +0 -50
  127. data/app/components/ahoy_captain/filter/dropdown_component.rb +0 -51
  128. data/app/components/ahoy_captain/previous_next_component.html.erb +0 -8
  129. data/app/components/ahoy_captain/previous_next_component.rb +0 -11
  130. data/app/components/ahoy_captain/stats/comparable_container_component.html.erb +0 -25
  131. data/app/components/ahoy_captain/stats/comparable_container_component.rb +0 -86
  132. data/app/components/ahoy_captain/stats/container_component.html.erb +0 -15
  133. data/app/components/ahoy_captain/stats/container_component.rb +0 -26
  134. data/app/components/ahoy_captain/tables/devices_table_component.rb +0 -11
  135. data/app/components/ahoy_captain/tables/dynamic_table.rb +0 -13
  136. data/app/components/ahoy_captain/tables/dynamic_table_component.rb +0 -204
  137. data/app/components/ahoy_captain/tables/goals_table_component.rb +0 -17
  138. data/app/components/ahoy_captain/tables/header_component.html.erb +0 -5
  139. data/app/components/ahoy_captain/tables/header_component.rb +0 -18
  140. data/app/components/ahoy_captain/tables/headers/header_component.html.erb +0 -5
  141. data/app/components/ahoy_captain/tables/headers/header_component.rb +0 -16
  142. data/app/components/ahoy_captain/tables/properties_table_component.rb +0 -27
  143. data/app/components/ahoy_captain/tables/row_component.html.erb +0 -4
  144. data/app/components/ahoy_captain/tables/rows/row_component.html.erb +0 -6
  145. data/app/components/ahoy_captain/tables/rows/row_component.rb +0 -40
  146. data/app/controllers/ahoy_captain/exports_controller.rb +0 -14
  147. data/app/controllers/ahoy_captain/filters/goals_controller.rb +0 -9
  148. data/app/controllers/ahoy_captain/filters/properties/names_controller.rb +0 -11
  149. data/app/controllers/ahoy_captain/filters/properties/values_controller.rb +0 -15
  150. data/app/controllers/ahoy_captain/locations/cities_controller.rb +0 -22
  151. data/app/controllers/ahoy_captain/locations/countries_controller.rb +0 -22
  152. data/app/controllers/ahoy_captain/locations/maps_controller.rb +0 -24
  153. data/app/controllers/ahoy_captain/locations/regions_controller.rb +0 -22
  154. data/app/controllers/ahoy_captain/properties_controller.rb +0 -41
  155. data/app/models/ahoy_captain/comparison_mode.rb +0 -72
  156. data/app/models/ahoy_captain/export.rb +0 -48
  157. data/app/models/ahoy_captain/filter_parser.rb +0 -82
  158. data/app/models/ahoy_captain/range_from_params.rb +0 -78
  159. data/app/models/concerns/ahoy_captain/compare_mode.rb +0 -19
  160. data/app/models/concerns/ahoy_captain/limitable.rb +0 -17
  161. data/app/queries/ahoy_captain/campaign_query.rb +0 -14
  162. data/app/queries/ahoy_captain/city_query.rb +0 -11
  163. data/app/queries/ahoy_captain/country_query.rb +0 -10
  164. data/app/queries/ahoy_captain/device_query.rb +0 -10
  165. data/app/queries/ahoy_captain/region_query.rb +0 -11
  166. data/app/queries/ahoy_captain/source_query.rb +0 -10
  167. data/app/queries/ahoy_captain/stats/base_query.rb +0 -18
  168. data/app/queries/ahoy_captain/top_page_query.rb +0 -13
  169. data/app/queries/concerns/ahoy_captain/comparable_queries.rb +0 -25
  170. data/app/queries/concerns/ahoy_captain/comparable_query.rb +0 -138
  171. data/app/queries/concerns/ahoy_captain/lazy_comparable_query.rb +0 -42
  172. data/app/views/ahoy_captain/devices/_table.html.erb +0 -2
  173. data/app/views/ahoy_captain/layouts/shared/_tile_loader.html.erb +0 -12
  174. data/app/views/ahoy_captain/locations/maps/show.html.erb +0 -3
  175. data/app/views/ahoy_captain/properties/_form.html.erb +0 -6
  176. data/app/views/ahoy_captain/properties/index.html.erb +0 -3
  177. data/app/views/ahoy_captain/properties/show.html.erb +0 -6
  178. data/app/views/ahoy_captain/roots/_filters.html.erb +0 -80
  179. data/lib/ahoy_captain/filter_configuration/filter.rb +0 -16
  180. data/lib/ahoy_captain/filter_configuration/filter_collection.rb +0 -48
  181. data/lib/ahoy_captain/filters_configuration.rb +0 -77
  182. data/lib/ahoy_captain/predicate_label.rb +0 -7
  183. data/lib/generators/ahoy_captain/migration_generator.rb +0 -21
  184. data/lib/generators/ahoy_captain/templates/migration.rb.tt +0 -7
  185. /data/app/views/ahoy_captain/{locations/cities → cities}/index.html+details.erb +0 -0
  186. /data/app/views/ahoy_captain/{locations/cities → cities}/index.html.erb +0 -0
  187. /data/app/views/ahoy_captain/{locations/countries → countries}/index.html+details.erb +0 -0
  188. /data/app/views/ahoy_captain/{locations/countries → countries}/index.html.erb +0 -0
  189. /data/app/views/ahoy_captain/{locations/regions → regions}/index.html+details.erb +0 -0
  190. /data/app/views/ahoy_captain/{locations/regions → regions}/index.html.erb +0 -0
@@ -1,371 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus";
2
- import "classnames"
3
-
4
- const debounce = (func, delay) => {
5
- let debounceTimer
6
- return function() {
7
- const context = this
8
- const args = arguments
9
- clearTimeout(debounceTimer)
10
- debounceTimer = setTimeout(() => func.apply(context, args), delay)
11
- }
12
- }
13
-
14
- export default class extends Controller {
15
- static targets = ["input", "list", "option", "container", "select", "highlighted", "box", "selected"];
16
- static classes = ["boxOpen"]
17
- static values = {
18
- options: Array,
19
- isLoading: Boolean,
20
- isOpen: Boolean,
21
- disabled: Boolean,
22
- input: String,
23
- highlightedIndex: Number,
24
- singleOption: Boolean,
25
- freeChoice: { type: Boolean, default: false },
26
- selected: Array,
27
- url: String,
28
- query: String
29
- };
30
-
31
- connect() {
32
- this.isLoadingValue = false;
33
- this.isOpenValue = false;
34
- this.inputValue = '';
35
- this.highlightedIndexValue = 0;
36
- this.clickHandler = this.clickHandler.bind(this)
37
-
38
- this.inputTarget.addEventListener('keydown', this.onKeyDown.bind(this))
39
- this.debouncedFetchOptions = debounce(this.fetchOptions.bind(this), 250);
40
- this.checkDisabledState();
41
- if(this.singleOptionValue) {
42
- this.selectTarget.removeAttribute('multiple')
43
- } else {
44
- this.selectTarget.multiple = true
45
- }
46
-
47
- Object.defineProperty(this.selectTarget, "combobox", {
48
- enumerable: false,
49
- configurable: false,
50
- writable: false,
51
- value: this,
52
- });
53
-
54
- const targetNode = this.selectTarget;
55
- const config = { attributes: true };
56
-
57
- const callback = (mutationList, observer) => {
58
- for (const mutation of mutationList) {
59
- if (mutation.type === "attributes") {
60
- this.handleNameChange()
61
- }
62
- }
63
- };
64
-
65
- const observer = new MutationObserver(callback);
66
- observer.observe(targetNode, config);
67
-
68
-
69
- window.dispatchEvent(new CustomEvent('combobox:init', { detail: { combobox: this } }))
70
- this.search = new URLSearchParams(window.location.search);
71
- this.search.delete(this.selectTarget.name)
72
- }
73
-
74
- handleNameChange() {
75
- if(this.selectTarget.name.includes("_cont]")) {
76
- this.freeChoiceValue = true
77
- } else {
78
- this.freeChoiceValue = false
79
- }
80
- }
81
- checkDisabledState() {
82
- if (this.disabledValue) {
83
- this.element.classList.add('opacity-80', 'cursor-default', 'pointer-events-none');
84
- } else {
85
- this.element.classList.remove('opacity-80', 'cursor-default', 'pointer-events-none')
86
- }
87
- }
88
-
89
- onInput(event) {
90
- this.inputValue = event.target.value;
91
- this.debouncedFetchOptions(this.inputValue);
92
- }
93
-
94
- fetchOptions(query) {
95
- if(this.disabledValue) { return }
96
-
97
- if(this.freeChoiceValue) {
98
- this.isLoadingValue = false;
99
- this.highlightedIndexValue = 0;
100
- this.optionsValue = [{ text: query, value: query }];
101
- this.isOpenValue = true;
102
-
103
- } else {
104
- this.isLoadingValue = true;
105
- this.isOpenValue = true;
106
-
107
- const formData = new FormData(this.selectTarget.form);
108
- const searchParams = new URLSearchParams([...formData.entries()]);
109
-
110
- searchParams.delete(this.selectTarget.name);
111
- searchParams.delete(this.queryValue);
112
- searchParams.set(this.queryValue, query);
113
-
114
- fetch(`${this.urlValue}?${searchParams.toString()}`).then(resp => resp.json()).then(loadedOptions => {
115
- this.isLoadingValue = false;
116
- this.highlightedIndexValue = 0;
117
- this.optionsValue = loadedOptions.map(option => ({ text: option.text, value: option.value }));
118
- });
119
- }
120
- }
121
-
122
- highlight(element) {
123
- const index = parseInt(element.target.dataset.index);
124
- this.highlightIndex(index)
125
- }
126
-
127
- scrollToOption(index) {
128
- const optionElement = this.listTarget.querySelector(`[data-index="${index}"]`);
129
- if (optionElement) {
130
- optionElement.scrollIntoView({ block: 'center' });
131
- }
132
- }
133
-
134
- highlightIndex(index) {
135
- this.highlightedIndexValue = index;
136
- this.scrollToOption(index);
137
- }
138
-
139
- setSelected(values) {
140
- this.selectedValue = values;
141
- }
142
-
143
- setDisabled(value) {
144
- this.disabledValue = value
145
- }
146
-
147
- onKeyDown(event) {
148
- switch (event.key) {
149
- case 'Enter':
150
- if (!this.isOpenValue || this.isLoadingValue || this.optionTargets.length === 0) return;
151
- const option = this.listTarget.querySelector(`[data-index="${this.highlightedIndexValue}"]`);
152
- if(option) {
153
- this.selectOption(option);
154
- }
155
-
156
- event.preventDefault();
157
- break;
158
- case 'Escape':
159
- if (!this.isOpenValue || this.isLoadingValue) return;
160
- this.isOpenValue = false;
161
- this.inputTarget.focus();
162
- event.preventDefault();
163
- break;
164
- case 'ArrowDown':
165
- if(this.isOpenValue) {
166
- this.highlightIndex(this.highlightedIndexValue + 1)
167
- } else {
168
- this.isOpenValue = true
169
- }
170
- break;
171
- case 'ArrowUp':
172
- if(this.isOpenValue) {
173
- this.highlightIndex(this.highlightedIndexValue - 1)
174
- } else {
175
- this.isOpenValue = true
176
- }
177
- break;
178
- }
179
- }
180
-
181
- selectOption(selected) {
182
- let value = null;
183
- if(selected.tagName) {
184
- value = selected.dataset.value;
185
- if(value === undefined) {
186
- value = selected.parentElement.dataset.value
187
- }
188
- } else {
189
- value = selected.target.dataset.value;
190
- if(value === undefined) {
191
- value = selected.target.parentElement.dataset.value
192
- }
193
- }
194
-
195
- const option = this.optionsValue.filter(option => option.value === value)[0];
196
- if(this.singleOptionValue) {
197
- this.selectedValue = [option]
198
- } else {
199
- this.selectedValue = [...this.selectedValue, option]
200
- }
201
- this.isOpenValue = false;
202
- this.inputTarget.value = '';
203
- this.highlightedIndexValue = 0
204
- }
205
-
206
- toggleOpen() {
207
- if (!this.isOpenValue) {
208
- this.debouncedFetchOptions(this.inputValue);
209
- this.inputTarget.focus();
210
- document.addEventListener('click', this.clickHandler)
211
- } else {
212
- this.inputValue = '';
213
- this.isOpenValue = false;
214
- document.removeEventListener('click', this.clickHandler)
215
- }
216
- }
217
-
218
- clickHandler(event) {
219
- if(event.target.classList.contains('combobox-option')) {
220
- return
221
- } else {
222
- this.toggleOpen()
223
- return
224
- }
225
- }
226
-
227
- isOpenValueChanged(current) {
228
- if(current) {
229
- this.boxTarget.classList.add(...this.boxOpenClasses)
230
- } else {
231
- this.boxTarget.classList.remove(...this.boxOpenClasses)
232
-
233
- }
234
- this.listTarget.style.display = current ? 'block' : 'none';
235
- }
236
-
237
- highlightedIndexValueChanged(current, previous) {
238
- const prev = this.listTarget.querySelector(`[data-index="${previous}"]`)
239
- if(prev) {
240
- prev.classList.remove('bg-primary-600', 'text-white')
241
- }
242
- const now = this.listTarget.querySelector(`[data-index="${current}"]`);
243
- if(now) {
244
- now.classList.add('bg-primary-600', 'text-white')
245
- }
246
- }
247
-
248
- renderDropDownContent() {
249
- this.listTarget.innerHTML = "";
250
-
251
- const visibleOptions = this.visibleOptions()
252
- const matchesFound = visibleOptions.length > 0 && visibleOptions.some(option => !this.isOptionDisabled(option))
253
-
254
- if (matchesFound) {
255
- return this.renderOptions(visibleOptions.filter(option => !this.isOptionDisabled(option)))
256
- }
257
-
258
- if(this.isLoadingValue) {
259
- this.listTarget.innerHTML = `<div>Is Loading..</div>`
260
- return
261
- }
262
-
263
- if(this.freeChoiceValue) {
264
- this.listTarget.innerHTML = `<div class="relative cursor-default select-none py-2 px-4 text-gray-700 dark:text-gray-300">Start typing to apply filter</div>`
265
- return
266
- }
267
-
268
- this.listTarget.innerHTML = `<div class="relative cursor-default select-none py-2 px-4 text-gray-700 dark:text-gray-300">
269
- No matches found in the current dashboard. Try selecting a different time range or searching for something different.
270
- </div>`
271
-
272
- }
273
- renderOptions(options) {
274
- options.forEach((option, index) => {
275
- const optionElement = document.createElement("li");
276
- const isHighlighted = this.highlightedIndexValue === index;
277
- optionElement.innerHTML = `<span class="block truncate" data-index="${index}">${option.text}</span>`;
278
- optionElement.className = classNames('combobox-option relative cursor-pointer select-none py-2 px-3 hover:bg-primary-600 hover:text-white', {
279
- 'text-accent-900': !isHighlighted,
280
- 'bg-primary-600 text-white': isHighlighted,
281
- });
282
-
283
- if(isHighlighted) {
284
- optionElement.dataset.comboboxTarget = "option"
285
- }
286
- optionElement.dataset.action = "click->combobox#selectOption"
287
- optionElement.dataset.index = index;
288
- optionElement.dataset.value = option.value
289
- optionElement.id = `combobox-option-${index}`;
290
-
291
- this.listTarget.appendChild(optionElement);
292
- });
293
- }
294
- optionsValueChanged(current, before) {
295
- this.renderDropDownContent()
296
- }
297
-
298
- isOptionDisabled(option) {
299
- const disabled = this.selectedValue.some((val) => val.value === option.value)
300
-
301
- return disabled
302
- }
303
-
304
- visibleOptions() {
305
- const visibleOptions = [...this.optionsValue]
306
- if (this.freeChoiceValue && this.inputTarget.length > 0 && this.optionsValue.every(option => option.value !== this.inputTarget.value)) {
307
- visibleOptions.push({value: this.inputTarget.value, label: this.inputTarget.value, freeChoice: true})
308
- }
309
-
310
- return visibleOptions
311
- }
312
-
313
- selectedValueChanged(current, prev) {
314
- this.renderSelectedValues()
315
- this.renderDropDownContent()
316
- }
317
-
318
- removeOption(e) {
319
- e.stopPropagation()
320
- const option = this.selectTarget.querySelector(`option[value="${e.target.dataset.value}"]`);
321
- option.remove()
322
- const newValues = [];
323
- this.selectTarget.querySelectorAll('option[selected]').forEach(option => {
324
- newValues.push({text: option.text, value: option.value })
325
- })
326
- this.selectedValue = newValues;
327
- this.isOpenValue = false
328
- }
329
-
330
- renderSelectedValues() {
331
- this.selectTarget.innerHTML = ""
332
- this.selectedTarget.innerHTML = ""
333
- this.selectedValue.forEach(value => {
334
- const option = document.createElement('option');
335
- option.text = value.text;
336
- option.value = value.value;
337
- option.setAttribute('selected', 'selected')
338
- this.selectTarget.appendChild(option)
339
-
340
- const el = document.createElement("div");
341
- el.classList.add('text-primary-content', 'bg-primary', 'flex', 'justify-between', 'w-full', 'rounded-sm', 'px-2', 'py-0.5', 'm-0.5', 'text-sm');
342
- el.innerHTML = `<span class="break-all">${option.text}</span><span class="cursor-pointer font-bold ml-1" data-action="click->combobox#removeOption" data-value="${option.value}" >×</span>`;
343
- this.selectedTarget.appendChild(el)
344
- })
345
- var event = new Event('change');
346
- this.selectTarget.dispatchEvent(event);
347
- if(this.selectedValue.length === 0) {
348
- this.selectedTarget.style.display = "none"
349
- } else {
350
- this.selectedTarget.style.display = ""
351
- }
352
- }
353
-
354
- freeChoiceValueChanged(current, prev) {
355
- if(this.selectedValue.filter(value => value.freeChoice).length) {
356
- console.log("free choice changed")
357
- this.setSelected([])
358
- }
359
-
360
- }
361
- disabledValueChanged(current) {
362
- if(current) {
363
- this.isOpenValue = false
364
- this.inputTarget.disabled = true
365
- this.checkDisabledState()
366
- } else {
367
- this.inputTarget.removeAttribute('disabled')
368
- this.checkDisabledState()
369
- }
370
- }
371
- }
@@ -1,12 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus"
2
-
3
- // Connects to data-controller="filter--item"
4
- export default class extends Controller {
5
- static values = {
6
- modal: String
7
- };
8
-
9
- openModal() {
10
- document.getElementById(this.modalValue).showModal()
11
- }
12
- }
@@ -1,13 +0,0 @@
1
- import {Controller} from "@hotwired/stimulus"
2
-
3
- export default class extends Controller {
4
- handleReset(event) {
5
- event.preventDefault();
6
- const openModal = document.querySelector('dialog.modal[open]');
7
- openModal.querySelectorAll('input, select').forEach(element => {
8
- element.value = ""
9
- });
10
- openModal.close()
11
- this.element.requestSubmit()
12
- }
13
- }
@@ -1,45 +0,0 @@
1
- import { Controller } from '@hotwired/stimulus';
2
-
3
- export default class extends Controller {
4
-
5
- // reverts the modal back to its original state if it was simply closed
6
- connect() {
7
- const targetNode = this.element;
8
- const config = { attributes: true, childList: false, subtree: false };
9
- const callback = (mutationList, observer) => {
10
- for (const mutation of mutationList) {
11
- if(mutation.attributeName === "open") {
12
- if(this.element.open) {
13
- if(!this.originalValues) {
14
- this.originalValues = {};
15
- const formElements = this.element.querySelectorAll('select');
16
- formElements.forEach(el => {
17
- if(el.combobox) {
18
- this.originalValues[el.id] = el.combobox.selectedValue;
19
- } else {
20
- this.originalValues[el.id] = el.value;
21
- }
22
- })
23
- }
24
- } else {
25
- const formElements = this.element.querySelectorAll('select');
26
- formElements.forEach(el => {
27
- if(this.originalValues[el.id]) {
28
- if(el.combobox) {
29
- el.combobox.setSelected(this.originalValues[el.id])
30
- } else {
31
- el.value = this.originalValues[el.id]
32
- }
33
- }
34
- })
35
- }
36
- }
37
- }
38
- };
39
-
40
- const observer = new MutationObserver(callback);
41
- observer.observe(targetNode, config);
42
- }
43
-
44
-
45
- }
@@ -1,20 +0,0 @@
1
- import { Controller } from '@hotwired/stimulus';
2
-
3
- export default class extends Controller {
4
- static targets = ["link", "alt"]
5
- static values = {
6
- classes: { type: Array, default: ["text-primary", "font-semibold"] }
7
- }
8
-
9
- connect() {
10
- this.element.addEventListener('click', () => {
11
- const frame = this.element.dataset.turboFrame;
12
- const otherLinks = document.querySelectorAll(`[data-turbo-frame="${frame}"]`);
13
- otherLinks.forEach(link => {
14
- link.classList.remove('text-primary', 'font-semibold');
15
- })
16
-
17
- this.element.classList.add("text-primary", "font-semibold")
18
- })
19
- }
20
- }
@@ -1,15 +0,0 @@
1
- import { Controller } from '@hotwired/stimulus';
2
-
3
- export default class extends Controller {
4
- handleChange(event) {
5
- const url = new URL(event.target.form.action);
6
- const interval = event.target.value;
7
- url.searchParams.set('interval', interval);
8
- event.target.closest('turbo-frame').src = url.href;
9
- document.querySelectorAll('a[data-turbo-frame="chart"]').forEach(el => {
10
- const url = new URL(el.href);
11
- url.searchParams.set('interval', interval);
12
- el.href = url.href
13
- })
14
- }
15
- }