PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.6.2
Independent Analytics – WordPress Analytics Plugin v2.6.2
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 / report_controller.js
independent-analytics / javascript-source / controllers Last commit date
campaign_builder_controller.js 2 years ago chart_controller.js 2 years 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 dates_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 2 years 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 2 years 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 2 years 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
report_controller.js
409 lines
1 import {Controller} from "@hotwired/stimulus"
2 import {downloadCSV} from '../download'
3 import html2pdf from 'html2pdf.js';
4
5 class Report_Controller extends Controller {
6 /**
7 * Store the jQuery request so that it can be canceled if a new report is requested before the
8 * current one is fetched.
9 */
10 static request;
11 static targets = ['loadMore', 'exportCSV', 'exportPDF']
12 static values = {
13 name: String,
14 relativeRangeId: String,
15 exactStart: String,
16 exactEnd: String,
17 group: String,
18 chartInterval: String,
19 sortColumn: String,
20 sortDirection: String,
21 columns: Array,
22 quickStats: Array,
23 primaryChartMetricId: String,
24 secondaryChartMetricId: String,
25 filters: Array
26 }
27
28 exactStart = undefined
29 exactEnd = undefined
30 relativeRangeId = undefined
31 columns = undefined
32 quickStats = undefined
33 filters = []
34 sortColumn = undefined
35 sortDirection = undefined
36 group = undefined
37 chartInterval = undefined
38 primaryChartMetricId = undefined
39 secondaryChartMetricId = undefined
40 page = 1
41
42 connect() {
43 // If any values are empty strings, set them equal to undefined instead
44 this.exactStart = this.exactStartValue === "" ? undefined : this.exactStartValue;
45 this.exactEnd = this.exactEndValue === "" ? undefined : this.exactEndValue;
46 this.relativeRangeId = this.relativeRangeIdValue === "" ? undefined : this.relativeRangeIdValue
47 this.columns = this.columnsValue
48 this.quickStats = this.quickStatsValue
49 this.group = this.groupValue
50 this.chartInterval = this.chartIntervalValue
51 this.sortColumn = this.sortColumnValue
52 this.sortDirection = this.sortDirectionValue
53 this.primaryChartMetricId = this.primaryChartMetricIdValue
54 this.secondaryChartMetricId = this.secondaryChartMetricIdValue
55 this.filters = this.filtersValue
56 document.addEventListener('iawp:changeDates', this.datesChanged)
57 document.addEventListener('iawp:changeColumns', this.columnsChanged)
58 document.addEventListener('iawp:changeQuickStats', this.quickStatsChanged)
59 document.addEventListener('iawp:changeFilters', this.filtersChanged)
60 document.addEventListener('iawp:changeSort', this.sortChanged)
61 document.addEventListener('iawp:changeGroup', this.changeGroup)
62 document.addEventListener('iawp:changeChartInterval', this.changeChartInterval)
63 document.addEventListener('iawp:changePrimaryChartMetric', this.changePrimaryChartMetric)
64 document.addEventListener('iawp:changeSecondaryChartMetric', this.changeSecondaryChartMetric)
65 this.fetch({
66 tableOnly: this.filters.length === 0,
67 showLoadingOverlay: false
68 })
69 }
70
71 disconnect() {
72 document.removeEventListener('iawp:changeDates', this.datesChanged)
73 document.removeEventListener('iawp:changeColumns', this.columnsChanged)
74 document.removeEventListener('iawp:changeQuickStats', this.quickStatsChanged)
75 document.removeEventListener('iawp:changeFilters', this.filtersChanged)
76 document.removeEventListener('iawp:changeSort', this.sortChanged)
77 document.removeEventListener('iawp:changeGroup', this.changeGroup)
78 document.removeEventListener('iawp:changeChartInterval', this.changeChartInterval)
79 document.removeEventListener('iawp:changePrimaryChartMetric', this.changePrimaryChartMetric)
80 document.removeEventListener('iawp:changeSecondaryChartMetric', this.changeSecondaryChartMetric)
81 }
82
83 emitChangedOption(detail) {
84 document.dispatchEvent(
85 new CustomEvent('iawp:changedOption', {
86 detail
87 })
88 )
89 }
90
91 changePrimaryChartMetric = (e) => {
92 this.primaryChartMetricId = e.detail.primaryChartMetricId
93 this.emitChangedOption({
94 'primary_chart_metric_id': this.primaryChartMetricId
95 })
96 }
97
98 changeSecondaryChartMetric = (e) => {
99 this.secondaryChartMetricId = e.detail.secondaryChartMetricId
100 this.emitChangedOption({
101 'secondary_chart_metric_id': this.secondaryChartMetricId
102 })
103 }
104
105 datesChanged = (e) => {
106 this.exactStart = e.detail.exactStart
107 this.exactEnd = e.detail.exactEnd
108 this.relativeRangeId = e.detail.relativeRangeId
109 this.page = 1;
110
111 this.emitChangedOption({
112 'exact_start': this.exactStart || null,
113 'exact_end': this.exactEnd || null,
114 'relative_range_id': this.relativeRangeId || null
115 })
116 this.fetch({newDateRange: true})
117 }
118
119 columnsChanged = (e) => {
120 this.columns = e.detail.optionIds
121 this.emitChangedOption({
122 'columns': this.columns
123 })
124 }
125
126 quickStatsChanged = (e) => {
127 this.quickStats = e.detail.optionIds
128 this.emitChangedOption({
129 'quick_stats': this.quickStats
130 })
131 }
132
133 filtersChanged = (e) => {
134 this.filters = e.detail.filters
135 this.page = 1;
136
137 this.emitChangedOption({
138 'filters': this.filters
139 })
140 this.fetch({showLoadingOverlay: e.detail.showLoadingOverlay})
141 }
142
143 sortChanged = (e) => {
144 this.sortColumn = e.detail.sortColumn
145 this.sortDirection = e.detail.sortDirection
146 this.page = 1;
147
148 this.emitChangedOption({
149 'sort_column': this.sortColumn,
150 'sort_direction': this.sortDirection
151 })
152 this.fetch({tableOnly: true})
153 }
154
155 changeGroup = (e) => {
156 if (this.group === e.detail.group) {
157 return;
158 }
159
160 this.group = e.detail.group
161 this.page = 1
162 this.emitChangedOption({
163 'group_name': this.group
164 })
165 this.fetch({newGroup: true});
166 }
167
168 changeChartInterval = (e) => {
169 const chartInterval = e.detail.chartInterval
170
171 if (this.chartInterval === chartInterval) {
172 return;
173 }
174
175 this.chartInterval = chartInterval
176 this.emitChangedOption({
177 'chart_interval': this.chartInterval
178 })
179 this.fetch();
180 }
181
182 loadMore = () => {
183 this.page = this.page + 1
184
185 this.fetch({tableOnly: true})
186 }
187
188 fetch({
189 tableOnly = false,
190 showLoadingOverlay = true,
191 newGroup = false,
192 newDateRange = false
193 } = {}) {
194
195 if (showLoadingOverlay) {
196 jQuery('#iawp-parent').addClass('loading');
197 }
198
199 const data = {
200 ...iawpActions.filter,
201 'filters': this.filters,
202 'exact_start': this.exactStart,
203 'exact_end': this.exactEnd,
204 'is_new_date_range': newDateRange,
205 'relative_range_id': this.relativeRangeId,
206 'table_type': jQuery('#data-table').data('table-name'),
207 'columns': this.columns,
208 'report_quick_stats': ['visitors'], // TODO
209 'primary_chart_metric_id': this.primaryChartMetricId,
210 'secondary_chart_metric_id': this.secondaryChartMetricId,
211 'sort_column': this.sortColumn,
212 'quick_stats': this.quickStats,
213 'sort_direction': this.sortDirection,
214 'group': this.group,
215 'is_new_group': newGroup,
216 'chart_interval': this.chartInterval,
217 'page': this.page,
218 };
219
220 if (Report_Controller.request) {
221 Report_Controller.request.abort();
222 }
223
224 Report_Controller.request = jQuery.post(ajaxurl, data, (response) => {
225 response = response.data
226
227 this.columns = response.columns
228 this.filters = response.filters
229 this.chartInterval = response.chartInterval
230
231 jQuery('#iawp-columns .row-number').text(response.totalNumberOfRows.toLocaleString());
232 document.getElementById('data-table').setAttribute('data-total-number-of-rows', response.totalNumberOfRows)
233
234 if (newGroup) {
235 jQuery('#iawp-table-wrapper').replaceWith(response.table)
236 jQuery('[data-plugin-group-options-option-type-value=columns]').replaceWith(response.columnsHTML)
237
238 document.dispatchEvent(
239 new CustomEvent('iawp:changeColumns', {
240 detail: {
241 optionIds: this.columns
242 }
243 })
244 )
245 } else {
246 jQuery('#iawp-rows').replaceWith(response.rows);
247 }
248
249 if (!tableOnly) {
250 jQuery('#dates-button span:last-child').text(response.label)
251 jQuery('#myChart').closest('.chart-container').replaceWith(response.chart);
252 jQuery('#quick-stats').replaceWith(response.stats);
253 }
254
255 document.dispatchEvent(
256 new CustomEvent('iawp:updateColumnsUserInterface')
257 )
258
259 document.dispatchEvent(
260 new CustomEvent('iawp:groupChanged', {
261 detail: {
262 groupId: response.groupId
263 }
264 })
265 )
266
267 document.dispatchEvent(
268 new CustomEvent('iawp:filtersChanged', {
269 detail: {
270 filtersTemplateHTML: response.filtersTemplateHTML,
271 filtersButtonsHTML: response.filtersButtonsHTML,
272 filters: response.filters
273 }
274 })
275 )
276
277 this.exportPDFTarget.removeAttribute('disabled')
278
279 if (response.isLastPage) {
280 this.loadMoreTarget.setAttribute('disabled', 'disabled')
281 } else {
282 this.loadMoreTarget.removeAttribute('disabled')
283 }
284
285 jQuery('#iawp-parent').removeClass('loading');
286 });
287 }
288
289 exportCSV() {
290 const data = {
291 ...iawpActions.filter,
292 'filters': this.filters,
293 'exact_start': this.exactStart,
294 'exact_end': this.exactEnd,
295 'is_new_date_range': false,
296 'relative_range_id': this.relativeRangeId,
297 'table_type': jQuery('#data-table').data('table-name'),
298 'columns': this.columns,
299 'primary_chart_metric_id': this.primaryChartMetricId,
300 'secondary_chart_metric_id': this.secondaryChartMetricId,
301 'sort_column': this.sortColumn,
302 'quick_stats': this.quickStats,
303 'sort_direction': this.sortDirection,
304 'group': this.group,
305 'is_new_group': false,
306 'chart_interval': this.chartInterval,
307 'page': this.page,
308 'as_csv': true
309 };
310
311 this.exportCSVTarget.classList.add('sending')
312 this.exportCSVTarget.setAttribute('disabled', 'disabled')
313
314 if (Report_Controller.csvRequest) {
315 Report_Controller.csvRequest.abort();
316 }
317
318 Report_Controller.csvRequest = jQuery.post(ajaxurl, data, (response) => {
319 downloadCSV(this.getFileName('csv'), response)
320 this.exportCSVTarget.classList.add('sent')
321 this.exportCSVTarget.classList.remove('sending')
322 this.exportCSVTarget.removeAttribute('disabled')
323
324 setTimeout(() => {
325 this.exportCSVTarget.classList.remove('sent')
326 }, 1000)
327 })
328 }
329
330 exportPDF() {
331 this.exportPDFTarget.classList.add('sending')
332 this.exportPDFTarget.setAttribute('disabled', 'disabled')
333
334 setTimeout(() => {
335 const element = document.getElementById('wpwrap').cloneNode(true)
336 const options = {
337 filename: this.getFileName('pdf'),
338 jsPDF: {
339 unit: 'in',
340 format: 'letter',
341 orientation: 'landscape'
342 },
343 html2canvas: {
344 windowWidth: 1280
345 }
346 }
347 let base64Image = null
348
349 if (window.iawp_chart) {
350 const chartImageWidth = 1080
351 const chartImageHeight = chartImageWidth * .25
352 window.iawp_chart.resize(chartImageWidth, chartImageHeight)
353 base64Image = window.iawp_chart.toBase64Image('image/png', 1);
354 window.iawp_chart.resize()
355 }
356
357 if(window.iawp_geo_chart) {
358 base64Image = window.iawp_geo_chart.getImageURI()
359 }
360
361 if(base64Image) {
362 const imageElement = document.createElement('img')
363 imageElement.src = base64Image
364
365 element.querySelector('#myChart').replaceWith(imageElement)
366 }
367
368 // Prevent stimulus controllers from firing
369 element.querySelectorAll('[data-controller]').forEach((element) => {
370 element.removeAttribute('data-controller')
371 })
372
373 // Preserve selected values in clone by manually adding "selected" to options
374 element.querySelectorAll('select').forEach((element) => {
375 if(!element.id) {
376 return
377 }
378
379 const originalValue = document.getElementById(element.id).value
380
381 element.options.forEach((option) => {
382 option.toggleAttribute('selected', option.value === originalValue)
383 })
384 })
385
386 html2pdf().set(options).from(element).toContainer().save().then(() => {
387 this.exportPDFTarget.classList.add('sent')
388 this.exportPDFTarget.classList.remove('sending')
389 this.exportPDFTarget.removeAttribute('disabled')
390
391 setTimeout(() => {
392 this.exportPDFTarget.classList.remove('sent')
393 }, 1000)
394 })
395 }, 250) // Allow animations to finish before exporting blocks things up
396 }
397
398 getFileName(fileExtension) {
399 const reportTitleElement = document.querySelector('#report-title-bar .report-title')
400
401 if (!reportTitleElement) {
402 return 'report.' + fileExtension
403 }
404
405 return reportTitleElement.innerText.replace(/[^a-zA-Z0-9]+/g, '-').toLowerCase() + '.' + fileExtension
406 }
407 }
408
409 export default Report_Controller;