PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.10.2
Independent Analytics – WordPress Analytics Plugin v2.10.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 / real_time_controller.js
independent-analytics / javascript-source / controllers Last commit date
campaign_builder_controller.js 1 year ago chart_controller.js 1 year ago chart_geo_controller.js 2 years 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 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 1 year 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
real_time_controller.js
297 lines
1 import {Controller} from "@hotwired/stimulus"
2 import {Chart, registerables} from 'chart.js'
3 import Isotope from "isotope-layout"
4 import htmlLegendPlugin from "../chart_plugins/html_legend_plugin";
5 import corsairPlugin from "../chart_plugins/corsair_plugin";
6
7 Chart.register(...registerables);
8 Chart.defaults.font.family = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"';
9
10 export default class extends Controller {
11 static targets = [
12 'minuteChart',
13 'secondChart',
14 'visitorMessage',
15 'pageMessage',
16 'referrerMessage',
17 'countryMessage',
18 'pagesList',
19 'referrersList',
20 'countriesList',
21 'campaignsList',
22 'device_typesList'
23 ]
24 static values = {
25 chartData: Object,
26 nonce: String,
27 visible: {
28 type: Boolean,
29 default: true
30 }
31 }
32
33 connect() {
34 document.addEventListener('visibilitychange', this.tabVisibilityChanged)
35 this.initializeChart({
36 element: this.minuteChartTarget,
37 views: this.chartDataValue['minute_interval_views'],
38 labelsShort: this.chartDataValue['minute_interval_labels_short'],
39 labelsFull: this.chartDataValue['minute_interval_labels_full']
40 })
41 this.initializeChart({
42 element: this.secondChartTarget,
43 views: this.chartDataValue['second_interval_views'],
44 labelsShort: this.chartDataValue['second_interval_labels_short'],
45 labelsFull: this.chartDataValue['second_interval_labels_full']
46 })
47 this.startServerPolling()
48 }
49
50 disconnect() {
51 document.removeEventListener('visibilitychange', this.tabVisibilityChanged)
52 }
53
54 tabVisibilityChanged = () => {
55 this.visibleValue = !document.hidden
56
57 if (this.visibleValue) {
58 this.refresh()
59 this.startServerPolling()
60 }
61 }
62
63 startServerPolling() {
64 clearInterval(this.interval)
65 this.interval = setInterval(() => {
66 if (this.visibleValue) {
67 this.refresh()
68 } else {
69 clearInterval(this.interval)
70 }
71 }, 10000)
72 }
73
74 refresh() {
75 const data = {
76 ...iawpActions.real_time_data
77 };
78
79 jQuery.post(ajaxurl, data, (response, a, b) => {
80 document.getElementById('real-time-dashboard').classList.remove('refreshed')
81 void document.getElementById('real-time-dashboard').offsetWidth
82 document.getElementById('real-time-dashboard').classList.add('refreshed')
83 if (response.success) {
84 this.rerender(response.data)
85 }
86 });
87 }
88
89 rerender(data) {
90 this.visitorMessageTarget.textContent = data.visitor_message
91 this.pageMessageTarget.textContent = data.page_message
92 this.referrerMessageTarget.textContent = data.referrer_message
93 this.countryMessageTarget.textContent = data.country_message
94 this.updateChart({
95 element: this.minuteChartTarget,
96 visitors: data.chart_data.minute_interval_visitors,
97 views: data.chart_data.minute_interval_views,
98 })
99 this.updateChart({
100 element: this.secondChartTarget,
101 visitors: data.chart_data.second_interval_visitors,
102 views: data.chart_data.second_interval_views
103 })
104 this.updateList({
105 element: this.pagesListTarget,
106 entries: data.lists.pages.entries
107 })
108 this.updateList({
109 element: this.referrersListTarget,
110 entries: data.lists.referrers.entries
111 })
112 this.updateList({
113 element: this.countriesListTarget,
114 entries: data.lists.countries.entries
115 })
116 this.updateList({
117 element: this.campaignsListTarget,
118 entries: data.lists.campaigns.entries
119 })
120 this.updateList({
121 element: this.device_typesListTarget,
122 entries: data.lists.device_types.entries
123 })
124 }
125
126 existingElements() {
127 return Array.from(this.element.querySelectorAll('li:not(.exiting)'))
128 }
129
130 existingIds() {
131 return this.existingElements().map((existingElement) => existingElement.dataset.id)
132 }
133
134 updateList({
135 element,
136 entries
137 }) {
138 let iso = element.iso
139
140 if (!iso) {
141 iso = element.iso = new Isotope(element, {
142 itemSelector: "li",
143 layoutMode: "vertical",
144 sortColumn: "position",
145 getSortData: {
146 position: (element) => {
147 return parseInt(element.dataset.position);
148 }
149 }
150 })
151 }
152
153 // Remove existing elements
154 this.existingElements().forEach((existingElement) => {
155 iso.remove(existingElement)
156 })
157
158 // Add new elements
159 entries.forEach((entry, index) => {
160 const entryElement = this.elementFromEntry(entry)
161 iso.insert(entryElement)
162 })
163
164 iso.arrange()
165
166 const totalElements = iso.items.length
167 const emptyMessage = element.parentNode.querySelector('.most-popular-empty-message')
168
169 if (totalElements > 0) {
170 emptyMessage.classList.add('hide')
171 } else {
172 emptyMessage.classList.remove('hide')
173 }
174 }
175
176 elementFromEntry(entry) {
177 const id = entry['id']
178 const position = entry['position']
179 const title = entry['title']
180 const subtitle = entry['subtitle']
181 const views = entry['views']
182 const flag = entry['flag'] ? entry['flag'] : ''
183 const subtitleHTML = subtitle ? `<span class="real-time-subtitle">${subtitle}</span>` : '';
184
185 const li = `
186 <li data-id="${id}" data-position="${position}">
187 <span class="real-time-position">${position}.</span>
188 ${flag}
189 <span class="real-time-resource">${title} ${subtitleHTML}</span>
190 <span class="real-time-stat">${views}</span>
191 </li>
192 `
193 const el = document.createElement('div');
194 el.innerHTML = li;
195 return el.firstElementChild;
196 }
197
198 initializeChart({
199 element,
200 views,
201 labelsShort,
202 labelsFull
203 }) {
204 const data = {
205 labels: labelsFull,
206 datasets: [{
207 id: 'views',
208 label: iawpText.views,
209 data: views,
210 backgroundColor: 'rgba(108,70,174,0.2)',
211 borderColor: 'rgba(108,70,174,1)',
212 borderWidth: {
213 bottom: 0,
214 top: 3,
215 left: 0,
216 right: 0
217 }
218 },]
219 }
220
221 const config = {
222 type: 'bar',
223 data,
224 options: {
225 interaction: {
226 intersect: false,
227 mode: 'index'
228 },
229 responsive: true,
230 scales: {
231 y: {
232 grid: {
233 borderColor: '#DEDAE6',
234 tickColor: '#DEDAE6',
235 display: true,
236 drawOnChartArea: true,
237 borderDash: [2, 4]
238 },
239 beginAtZero: true,
240 suggestedMax: 5,
241 ticks: {
242 color: document.body.classList.contains('iawp-dark-mode') ? '#ffffff' : '#6D6A73',
243 precision: 0
244 }
245 },
246 x: {
247 stacked: true,
248 grid: {
249 borderColor: '#DEDAE6',
250 tickColor: '#DEDAE6',
251 display: true,
252 drawOnChartArea: false,
253 },
254 ticks: {
255 color: document.body.classList.contains('iawp-dark-mode') ? '#ffffff' : '#6D6A73',
256 beginAtZero: true,
257 callback: function (value, index, values) {
258 return labelsShort[index];
259 }
260 }
261 }
262 },
263 plugins: {
264 mode: String, // 'light' or 'dark'
265 htmlLegend: {
266 container: element.parentNode.querySelector('.legend')
267 },
268 legend: {
269 display: false
270 },
271 corsair: {
272 dash: [2, 4],
273 color: '#777',
274 width: 1
275 },
276 },
277 },
278 plugins: [
279 corsairPlugin,
280 htmlLegendPlugin
281 ],
282 };
283
284 new Chart(element, config);
285 }
286
287 updateChart({
288 element,
289 views
290 }) {
291 const chart = Chart.getChart(element);
292 chart.data.datasets.forEach((dataset, index) => {
293 dataset.data.splice(0, dataset.data.length, ...views)
294 });
295 chart.update('none');
296 }
297 }