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