PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.14.10
Independent Analytics – WordPress Analytics Plugin v2.14.10
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
overview 1 year ago campaign_builder_controller.js 1 year ago chart_controller.js 2 months ago chart_interval_controller.js 2 years ago clipboard_controller.js 1 year ago copy_report_controller.js 2 years ago create_report_controller.js 1 year ago delete_data_controller.js 1 year ago delete_report_controller.js 2 years ago easepick_controller.js 2 years ago examiner_controller.js 2 months ago examiner_header_controller.js 11 months ago export_overview_controller.js 9 months ago export_reports_controller.js 2 years ago filters_controller.js 6 months ago group_controller.js 2 years ago import_reports_controller.js 2 years ago journey_controller.js 6 months ago map_controller.js 9 months ago migration_redirect_controller.js 2 years ago modal_controller.js 2 years ago pause_emails_controller.js 6 months ago pie_chart_controller.js 6 months ago plugin_group_options_controller.js 1 year ago pruner_controller.js 5 months ago quick_stats_controller.js 1 year ago real_time_controller.js 6 months ago refresh_overview_controller.js 1 year ago rename_report_controller.js 2 years ago report_controller.js 2 months ago reset_analytics_controller.js 1 year ago reset_overview_controller.js 1 year 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 tooltip_controller.js 6 months ago woocommerce_settings_controller.js 1 year ago
filters_controller.js
318 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 filterLogic: String
8 }
9 static targets = [
10 'modal',
11 'modalButton',
12 'blueprint',
13 'filters',
14 'condition',
15 'reset',
16 'inclusion',
17 'column',
18 'operator',
19 'operand',
20 'conditionButtons',
21 'spinner',
22 'filterLogic'
23 ]
24
25 appliedConditions = 0
26
27 connect() {
28 document.addEventListener('click', this.maybeClose)
29 document.addEventListener('iawp:filtersChanged', this.updateFilters)
30 document.addEventListener('iawp:fetchingReport', this.onFetchingReport)
31
32 if (this.filtersValue.length > 0) {
33 this.createInitialFilters()
34 this.setResetEnabled(true)
35 } else {
36 this.addCondition()
37 }
38 }
39
40 disconnect() {
41 document.removeEventListener('click', this.maybeClose)
42 document.removeEventListener('iawp:filtersChanged', this.updateFilters)
43 document.removeEventListener('iawp:fetchingReport', this.onFetchingReport)
44 }
45
46 onFetchingReport = () => {
47 const enabledElements = this.element.querySelector('#modal-filters').querySelectorAll('input:not([disabled]), button:not([disabled]), select:not([disabled])')
48
49 enabledElements.forEach(element => element.disabled = true)
50 this.spinnerTarget.classList.remove('hidden')
51
52 document.addEventListener('iawp:fetchedReport', () => {
53 enabledElements.forEach(element => element.disabled = false)
54 this.spinnerTarget.classList.add('hidden')
55 }, {once: true})
56 }
57
58 updateFilters = (event) => {
59 this.filtersTarget.innerHTML = ''
60 this.blueprintTarget.innerHTML = event.detail.filtersTemplateHTML
61 this.conditionButtonsTarget.innerHTML = event.detail.filtersButtonsHTML
62 this.filtersValue = event.detail.filters
63 this.setCount(event.detail.filters.length)
64
65 if (this.filtersValue.length > 0) {
66 this.createInitialFilters()
67 } else {
68 this.addCondition()
69 }
70 }
71
72 createInitialFilters() {
73 this.filtersValue.forEach((filter) => {
74 const element = this.blueprintTarget.content.cloneNode(true)
75 this.filtersTarget.appendChild(element)
76 const condition = this.filtersTarget.lastElementChild
77
78 const inclusionTarget = this.inclusionTargets.find((inclusion) => condition.contains(inclusion))
79 const columnTarget = this.columnTargets.find((column) => condition.contains(column))
80
81 inclusionTarget.value = filter.inclusion
82 columnTarget.value = filter.column
83
84 const type = columnTarget.options[columnTarget.selectedIndex].dataset.type
85
86 // Show the correct operator
87 this.operatorTargets.filter((operator) => {
88 return condition.contains(operator)
89 }).forEach((operator) => {
90 const isMatch = operator.dataset.type === type
91
92 operator.classList.toggle('show', isMatch)
93
94 if(isMatch) {
95 operator.value = filter.operator
96 }
97 })
98
99 // Show the correct operand field
100 this.operandTargets.filter((operand) => {
101 return condition.contains(operand)
102 }).forEach((operand) => {
103 const isMatch = operand.dataset.column === columnTarget.value
104
105 operand.classList.toggle('show', isMatch)
106
107 if(isMatch) {
108 operand.value = filter.operand
109
110 setTimeout(() => {
111 const easepickController = this.application.getControllerForElementAndIdentifier(operand, "easepick")
112
113 if(easepickController) {
114 const start = new easepick.DateTime(filter.operand * 1000);
115 operand.easepick.setDate(start)
116 operand.easepick.gotoDate(start)
117 easepickController.unixTimestampValue = filter.operand
118 }
119 }, 0)
120 }
121 })
122 })
123 }
124
125 maybeClose = (event) => {
126 const isOpen = this.modalTarget.classList.contains('show')
127 const isInComponent = this.element.contains(event.target)
128
129 if (isOpen && !isInComponent) {
130 this.closeModal()
131 }
132 }
133
134 toggleModal(e) {
135 e.preventDefault();
136 const isOpen = this.modalTarget.classList.contains('show')
137 isOpen ? this.closeModal() : this.openModal()
138 }
139
140 openModal() {
141 this.modalTarget.classList.add('show')
142 this.modalButtonTarget.classList.add('open')
143 document.getElementById('iawp-layout').classList.add('modal-open');
144 }
145
146 closeModal() {
147 this.modalTarget.classList.remove('show')
148 this.modalButtonTarget.classList.remove('open')
149 document.getElementById('iawp-layout').classList.remove('modal-open');
150 }
151
152 addCondition() {
153 this.filtersTarget.append(this.blueprintTarget.content.cloneNode(true))
154 this.setResetEnabled(true)
155 }
156
157 removeCondition(e) {
158 e.stopPropagation();
159
160 this.conditionTargets.forEach((condition) => {
161 if (condition.contains(e.target)) {
162 condition.remove()
163 }
164 })
165
166 if (this.conditionTargets.length === 0) {
167 this.addCondition()
168 document.dispatchEvent(
169 new CustomEvent('iawp:changeFilters', {
170 detail: {filters: []}
171 })
172 )
173 this.setResetEnabled(false)
174 }
175
176 if (this.conditionTargets.length === 1) {
177 this.setResetEnabled(false)
178 this.setCount(0)
179 }
180
181 if (this.conditionTargets.length === 0) {
182 this.addCondition()
183 }
184
185 if (this.appliedConditions > 1) {
186 this.apply()
187 }
188 }
189
190 apply({showLoadingOverlay = true} = {}) {
191 let errors = false
192
193 this.conditionTargets.forEach((condition) => {
194 const columnTarget = this.columnTargets.find((column) => condition.contains(column))
195 const operandTarget = this.operandTargets.find((operand) => condition.contains(operand) && operand.classList.contains('show'))
196
197 if (columnTarget.value === '') {
198 columnTarget.classList.add('error')
199 errors = true
200 }
201
202 if (operandTarget && operandTarget.value === '') {
203 operandTarget.classList.add('error')
204 errors = true
205 }
206 })
207
208 if (errors) {
209 return
210 }
211
212 const filters = this.conditionTargets.map((condition) => {
213 const inclusionTarget = this.inclusionTargets.find((inclusion) => condition.contains(inclusion))
214 const columnTarget = this.columnTargets.find((column) => condition.contains(column))
215 const operatorTarget = this.operatorTargets.find((operator) => condition.contains(operator) && operator.classList.contains('show'))
216 const operandTarget = this.operandTargets.find((operand) => condition.contains(operand) && operand.classList.contains('show'))
217 const filter = {
218 inclusion: inclusionTarget.value,
219 column: columnTarget.value,
220 operator: operatorTarget.value,
221 operand: operandTarget.value
222 }
223
224 const easepickController = this.application.getControllerForElementAndIdentifier(operandTarget, "easepick")
225 if (easepickController) {
226 filter.operand = easepickController.unixTimestampValue.toString()
227 }
228
229 return filter
230 })
231
232 this.appliedConditions = filters.length
233 this.setResetEnabled(true)
234 this.setCount(filters.length)
235 this.closeModal()
236
237 document.dispatchEvent(
238 new CustomEvent('iawp:changeFilters', {
239 detail: {
240 filters,
241 filterLogic: this.filterLogicValue,
242 showLoadingOverlay
243 }
244 })
245 )
246 }
247
248 reset() {
249 this.filterLogicTarget.value = 'and'
250 this.conditionTargets.forEach((condition) => {
251 condition.remove()
252 })
253 this.addCondition()
254 this.setResetEnabled(false)
255 this.appliedConditions = 0
256 this.setCount(0)
257 this.closeModal()
258 document.dispatchEvent(
259 new CustomEvent('iawp:changeFilters', {
260 detail: {filters: []}
261 })
262 )
263 }
264
265 setCount(count = 0) {
266 document.getElementById('toolbar').setAttribute('data-filter-count', count);
267 }
268
269 setResetEnabled(enable = true) {
270 if (enable) {
271 this.resetTarget.removeAttribute('disabled')
272 } else {
273 this.resetTarget.setAttribute('disabled', 'disabled')
274 }
275 }
276
277 // Todo - Need to clear anything that's been hidden
278 columnSelect(e) {
279 const condition = this.conditionTargets.find((condition) => condition.contains(e.target))
280 const column = e.target.value
281 const type = e.target.options[e.target.selectedIndex].dataset.type
282
283 // Remove error class
284 e.target.classList.remove('error')
285
286 // Show the correct operator
287 this.operatorTargets.filter((operator) => {
288 return condition.contains(operator)
289 }).forEach((operator) => {
290 const matchingType = operator.dataset.type === type
291 operator.classList.toggle('show', matchingType)
292 })
293
294 // Show the correct operand field
295 this.operandTargets.filter((operand) => {
296 return condition.contains(operand)
297 }).forEach((operand) => {
298 const matchingColumn = operand.dataset.column === column
299 operand.classList.toggle('show', matchingColumn)
300 })
301 }
302
303 changeFilterLogic(event) {
304 this.filterLogicValue = event.target.value
305 }
306
307 operandChange(e) {
308 e.target.classList.remove('error')
309 }
310
311 operandKeyDown(e) {
312 if (e.keyCode === 13) {
313 // Enter key pressed
314 this.apply()
315 }
316 }
317 }
318