PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.8.5
Independent Analytics – WordPress Analytics Plugin v2.8.5
2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / javascript-source / controllers / filters_controller.js
independent-analytics / javascript-source / controllers Last commit date
campaign_builder_controller.js 2 years ago chart_controller.js 1 year ago chart_geo_controller.js 2 years ago chart_interval_controller.js 2 years ago clipboard_controller.js 2 years ago copy_report_controller.js 2 years ago create_report_controller.js 2 years ago delete_data_controller.js 2 years ago delete_report_controller.js 2 years ago easepick_controller.js 2 years ago export_reports_controller.js 2 years ago filters_controller.js 1 year ago group_controller.js 2 years ago import_reports_controller.js 2 years ago migration_redirect_controller.js 2 years ago modal_controller.js 2 years ago plugin_group_options_controller.js 1 year ago pruner_controller.js 1 year ago quick_stats_controller.js 2 years ago real_time_controller.js 2 years ago rename_report_controller.js 2 years ago report_controller.js 1 year ago reset_analytics_controller.js 2 years ago save_report_controller.js 2 years ago select_input_controller.js 2 years ago set_favorite_report_controller.js 2 years ago sort_controller.js 2 years ago sortable_reports_controller.js 2 years ago table_columns_controller.js 2 years ago woocommerce_settings_controller.js 1 year ago
filters_controller.js
310 lines
1 import {Controller} from "@hotwired/stimulus"
2 import * as easepick from "@easepick/bundle";
3
4 export default class extends Controller {
5 static values = {
6 filters: Array
7 }
8 static targets = [
9 'modal',
10 'modalButton',
11 'blueprint',
12 'filters',
13 'condition',
14 'reset',
15 'inclusion',
16 'column',
17 'operator',
18 'operand',
19 'conditionButtons',
20 'spinner',
21 ]
22
23 appliedConditions = 0
24
25 connect() {
26 document.addEventListener('click', this.maybeClose)
27 document.addEventListener('iawp:filtersChanged', this.updateFilters)
28 document.addEventListener('iawp:fetchingReport', this.onFetchingReport)
29
30 if (this.filtersValue.length > 0) {
31 this.createInitialFilters()
32 this.setResetEnabled(true)
33 } else {
34 this.addCondition()
35 }
36 }
37
38 disconnect() {
39 document.removeEventListener('click', this.maybeClose)
40 document.removeEventListener('iawp:filtersChanged', this.updateFilters)
41 document.removeEventListener('iawp:fetchingReport', this.onFetchingReport)
42 }
43
44 onFetchingReport = () => {
45 const enabledElements = this.element.querySelector('#modal-filters').querySelectorAll('input:not([disabled]), button:not([disabled]), select:not([disabled])')
46
47 enabledElements.forEach(element => element.disabled = true)
48 this.spinnerTarget.classList.remove('hidden')
49
50 document.addEventListener('iawp:fetchedReport', () => {
51 enabledElements.forEach(element => element.disabled = false)
52 this.spinnerTarget.classList.add('hidden')
53 }, {once: true})
54 }
55
56 updateFilters = (event) => {
57 this.filtersTarget.innerHTML = ''
58 this.blueprintTarget.innerHTML = event.detail.filtersTemplateHTML
59 this.conditionButtonsTarget.innerHTML = event.detail.filtersButtonsHTML
60 this.filtersValue = event.detail.filters
61 this.setCount(event.detail.filters.length)
62
63 if (this.filtersValue.length > 0) {
64 this.createInitialFilters()
65 } else {
66 this.addCondition()
67 }
68 }
69
70 createInitialFilters() {
71 this.filtersValue.forEach((filter) => {
72 const element = this.blueprintTarget.content.cloneNode(true)
73 this.filtersTarget.appendChild(element)
74 const condition = this.filtersTarget.lastElementChild
75
76 const inclusionTarget = this.inclusionTargets.find((inclusion) => condition.contains(inclusion))
77 const columnTarget = this.columnTargets.find((column) => condition.contains(column))
78
79 inclusionTarget.value = filter.inclusion
80 columnTarget.value = filter.column
81
82 const type = columnTarget.options[columnTarget.selectedIndex].dataset.type
83
84 // Show the correct operator
85 this.operatorTargets.filter((operator) => {
86 return condition.contains(operator)
87 }).forEach((operator) => {
88 const isMatch = operator.dataset.type === type
89
90 operator.classList.toggle('show', isMatch)
91
92 if(isMatch) {
93 operator.value = filter.operator
94 }
95 })
96
97 // Show the correct operand field
98 this.operandTargets.filter((operand) => {
99 return condition.contains(operand)
100 }).forEach((operand) => {
101 const isMatch = operand.dataset.column === columnTarget.value
102
103 operand.classList.toggle('show', isMatch)
104
105 if(isMatch) {
106 operand.value = filter.operand
107
108 setTimeout(() => {
109 const easepickController = this.application.getControllerForElementAndIdentifier(operand, "easepick")
110
111 if(easepickController) {
112 const start = new easepick.DateTime(filter.operand * 1000);
113 operand.easepick.setDate(start)
114 operand.easepick.gotoDate(start)
115 easepickController.unixTimestampValue = filter.operand
116 }
117 }, 0)
118 }
119 })
120 })
121 }
122
123 maybeClose = (event) => {
124 const isOpen = this.modalTarget.classList.contains('show')
125 const isInComponent = this.element.contains(event.target)
126
127 if (isOpen && !isInComponent) {
128 this.closeModal()
129 }
130 }
131
132 toggleModal(e) {
133 e.preventDefault();
134 const isOpen = this.modalTarget.classList.contains('show')
135 isOpen ? this.closeModal() : this.openModal()
136 }
137
138 openModal() {
139 this.modalTarget.classList.add('show')
140 this.modalButtonTarget.classList.add('open')
141 document.getElementById('iawp-layout').classList.add('modal-open');
142 }
143
144 closeModal() {
145 this.modalTarget.classList.remove('show')
146 this.modalButtonTarget.classList.remove('open')
147 document.getElementById('iawp-layout').classList.remove('modal-open');
148 }
149
150 addCondition() {
151 this.filtersTarget.append(this.blueprintTarget.content.cloneNode(true))
152 this.setResetEnabled(true)
153 }
154
155 removeCondition(e) {
156 e.stopPropagation();
157
158 this.conditionTargets.forEach((condition) => {
159 if (condition.contains(e.target)) {
160 condition.remove()
161 }
162 })
163
164 if (this.conditionTargets.length === 0) {
165 this.addCondition()
166 document.dispatchEvent(
167 new CustomEvent('iawp:changeFilters', {
168 detail: {filters: []}
169 })
170 )
171 this.setResetEnabled(false)
172 }
173
174 if (this.conditionTargets.length === 1) {
175 this.setResetEnabled(false)
176 this.setCount(0)
177 }
178
179 if (this.conditionTargets.length === 0) {
180 this.addCondition()
181 }
182
183 if (this.appliedConditions > 1) {
184 this.apply()
185 }
186 }
187
188 apply({showLoadingOverlay = true} = {}) {
189 let errors = false
190
191 this.conditionTargets.forEach((condition) => {
192 const columnTarget = this.columnTargets.find((column) => condition.contains(column))
193 const operandTarget = this.operandTargets.find((operand) => condition.contains(operand) && operand.classList.contains('show'))
194
195 if (columnTarget.value === '') {
196 columnTarget.classList.add('error')
197 errors = true
198 }
199
200 if (operandTarget && operandTarget.value === '') {
201 operandTarget.classList.add('error')
202 errors = true
203 }
204 })
205
206 if (errors) {
207 return
208 }
209
210 const filters = this.conditionTargets.map((condition) => {
211 const inclusionTarget = this.inclusionTargets.find((inclusion) => condition.contains(inclusion))
212 const columnTarget = this.columnTargets.find((column) => condition.contains(column))
213 const operatorTarget = this.operatorTargets.find((operator) => condition.contains(operator) && operator.classList.contains('show'))
214 const operandTarget = this.operandTargets.find((operand) => condition.contains(operand) && operand.classList.contains('show'))
215 const filter = {
216 inclusion: inclusionTarget.value,
217 column: columnTarget.value,
218 operator: operatorTarget.value,
219 operand: operandTarget.value
220 }
221
222 const easepickController = this.application.getControllerForElementAndIdentifier(operandTarget, "easepick")
223 if (easepickController) {
224 filter.operand = easepickController.unixTimestampValue.toString()
225 }
226
227 return filter
228 })
229
230 this.appliedConditions = filters.length
231 this.setResetEnabled(true)
232 this.setCount(filters.length)
233 this.closeModal()
234
235 document.dispatchEvent(
236 new CustomEvent('iawp:changeFilters', {
237 detail: {
238 filters,
239 showLoadingOverlay
240 }
241 })
242 )
243 }
244
245 reset() {
246 this.conditionTargets.forEach((condition) => {
247 condition.remove()
248 })
249 this.addCondition()
250 this.setResetEnabled(false)
251 this.appliedConditions = 0
252 this.setCount(0)
253 this.closeModal()
254 document.dispatchEvent(
255 new CustomEvent('iawp:changeFilters', {
256 detail: {filters: []}
257 })
258 )
259 }
260
261 setCount(count = 0) {
262 document.getElementById('toolbar').setAttribute('data-filter-count', count);
263 }
264
265 setResetEnabled(enable = true) {
266 if (enable) {
267 this.resetTarget.removeAttribute('disabled')
268 } else {
269 this.resetTarget.setAttribute('disabled', 'disabled')
270 }
271 }
272
273 // Todo - Need to clear anything that's been hidden
274 columnSelect(e) {
275 const condition = this.conditionTargets.find((condition) => condition.contains(e.target))
276 const column = e.target.value
277 const type = e.target.options[e.target.selectedIndex].dataset.type
278
279 // Remove error class
280 e.target.classList.remove('error')
281
282 // Show the correct operator
283 this.operatorTargets.filter((operator) => {
284 return condition.contains(operator)
285 }).forEach((operator) => {
286 const matchingType = operator.dataset.type === type
287 operator.classList.toggle('show', matchingType)
288 })
289
290 // Show the correct operand field
291 this.operandTargets.filter((operand) => {
292 return condition.contains(operand)
293 }).forEach((operand) => {
294 const matchingColumn = operand.dataset.column === column
295 operand.classList.toggle('show', matchingColumn)
296 })
297 }
298
299 operandChange(e) {
300 e.target.classList.remove('error')
301 }
302
303 operandKeyDown(e) {
304 if (e.keyCode === 13) {
305 // Enter key pressed
306 this.apply()
307 }
308 }
309 }
310