vendor
5 years ago
adblock.js
5 years ago
admin.debug.js
5 years ago
admin.min.js
5 years ago
front.debug.js
5 years ago
front.min.js
5 years ago
preview.debug.js
5 years ago
preview.min.js
5 years ago
shared-ui.min.js
5 years ago
wp-dashboard.debug.js
5 years ago
wp-dashboard.min.js
5 years ago
wp-dashboard.debug.js
363 lines
| 1 | /* global hustleVars, Chart */ |
| 2 | (function ($) { |
| 3 | 'use strict'; |
| 4 | |
| 5 | var dashboardWidget = { |
| 6 | $widget: $('.hustle-widget'), |
| 7 | activeModuleType: '', |
| 8 | activeDisplayType: 'total', |
| 9 | activeTrackingType: 'conversion', |
| 10 | activeDaysRange: '7', |
| 11 | trackingData: {}, |
| 12 | totalsData: {}, |
| 13 | daysLabels: [], |
| 14 | theChart: null, |
| 15 | init: function init() { |
| 16 | var _this = this; |
| 17 | |
| 18 | // Handle changing the tracking type and tracking date range. |
| 19 | this.$widget.find('#hustle-analytics-apply').on('click', function (e) { |
| 20 | return _this.trackingAndDaysUpdated(e); |
| 21 | }); // Handle selecting a module type. |
| 22 | |
| 23 | this.$widget.find('.hustle-options-chart .hustle-option').on('click', function (e) { |
| 24 | return _this.moduleTypeSelected(e); |
| 25 | }); // Handle selecting a display type. |
| 26 | |
| 27 | this.$widget.find('.hustle-options-embed .hustle-option').on('click', function (e) { |
| 28 | return _this.displayTypeSelected(e); |
| 29 | }); |
| 30 | this.setDaysLabels(); |
| 31 | this.setModuleType(this.$widget.find('.hustle-options-chart .hustle-option.hustle-active').data('module-type')); |
| 32 | this.retrieveData(); |
| 33 | }, |
| 34 | trackingAndDaysUpdated: function trackingAndDaysUpdated(e) { |
| 35 | e.preventDefault(); |
| 36 | var oldDaysRange = this.activeDaysRange; |
| 37 | this.activeTrackingType = this.$widget.find('#hustle-analytics-show').val(); |
| 38 | this.activeDaysRange = this.$widget.find('#hustle-analytics-data').val(); |
| 39 | this.setDaysLabels(); // If the days range didn't change, no need to trigger the ajax call. |
| 40 | // We already have the data for the different display types. |
| 41 | |
| 42 | if (oldDaysRange === this.activeDaysRange) { |
| 43 | this.buildChart(); |
| 44 | this.updateTotals(); |
| 45 | return; |
| 46 | } |
| 47 | |
| 48 | this.retrieveData(); |
| 49 | }, |
| 50 | setDaysLabels: function setDaysLabels() { |
| 51 | var begin = -1 * this.activeDaysRange; |
| 52 | this.daysLabels = hustleVars.days_labels.slice(begin); |
| 53 | }, |
| 54 | retrieveData: function retrieveData() { |
| 55 | var self = this, |
| 56 | nonce = this.$widget.data('nonce'), |
| 57 | $noDataMessage = this.$widget.find('.hustle-message-empty'), |
| 58 | data = { |
| 59 | _ajax_nonce: nonce, |
| 60 | action: 'hustle_get_wp_dashboard_widget_data', |
| 61 | days: this.activeDaysRange, |
| 62 | trackingType: this.activeTrackingType |
| 63 | }; |
| 64 | $.ajax({ |
| 65 | url: ajaxurl, |
| 66 | type: 'POST', |
| 67 | data: data, |
| 68 | success: function success(resp) { |
| 69 | if (resp.success && resp.data) { |
| 70 | self.trackingData = resp.data.data; |
| 71 | self.totalsData = resp.data.totals; |
| 72 | self.buildChart(); |
| 73 | self.updateTotals(); |
| 74 | } else { |
| 75 | $noDataMessage.show(); |
| 76 | } |
| 77 | }, |
| 78 | error: function error() { |
| 79 | $noDataMessage.show(); |
| 80 | } |
| 81 | }); |
| 82 | }, |
| 83 | moduleTypeSelected: function moduleTypeSelected(e) { |
| 84 | var $button = $(e.currentTarget), |
| 85 | moduleType = $button.data('moduleType'), |
| 86 | success = this.setModuleType(moduleType); |
| 87 | |
| 88 | if (success) { |
| 89 | // Mark the selected button as selected, and deselect the others. |
| 90 | this.markButtonAsSelected($button); |
| 91 | this.buildChart(); |
| 92 | } |
| 93 | }, |
| 94 | setModuleType: function setModuleType(moduleType) { |
| 95 | var $displayTypeWrapper = this.$widget.find('.hustle-options-embed'); // Handle the display types for the selected module type. |
| 96 | |
| 97 | if (['slidein', 'popup', 'overall'].includes(moduleType)) { |
| 98 | // Hide display types. |
| 99 | $displayTypeWrapper.hide(); |
| 100 | } else if ('social_sharing' === moduleType) { |
| 101 | // Show display types. |
| 102 | $displayTypeWrapper.show(); // Social Sharings have 'floating' display types. |
| 103 | |
| 104 | $displayTypeWrapper.find('[data-display-type="floating"]').show(); |
| 105 | } else if ('embedded' === moduleType) { |
| 106 | // Show display types. |
| 107 | $displayTypeWrapper.show(); // Embeds don't have 'floating' display types. |
| 108 | |
| 109 | $displayTypeWrapper.find('[data-display-type="floating"]').hide(); |
| 110 | } else { |
| 111 | // The module type is invalid. |
| 112 | return false; |
| 113 | } // Set the active module type. |
| 114 | |
| 115 | |
| 116 | this.activeModuleType = moduleType; |
| 117 | this.buildTrackingActionSelect(); |
| 118 | return true; |
| 119 | }, |
| 120 | displayTypeSelected: function displayTypeSelected(e) { |
| 121 | // Only embeds and ssharing modules have display types. Abort if they're not selected. |
| 122 | if (!['embedded', 'social_sharing'].includes(this.activeModuleType)) { |
| 123 | return; |
| 124 | } |
| 125 | |
| 126 | var $button = $(e.currentTarget), |
| 127 | displayType = $button.data('displayType'); // Only ssharing modules have the 'floating' display type. |
| 128 | |
| 129 | if ('floating' === displayType && 'social_sharing' !== this.activeModuleType) { |
| 130 | return; |
| 131 | } // Mark the selected button as selected, and deselect the others. |
| 132 | |
| 133 | |
| 134 | this.markButtonAsSelected($button); |
| 135 | this.activeDisplayType = displayType; |
| 136 | this.buildChart(); |
| 137 | }, |
| 138 | markButtonAsSelected: function markButtonAsSelected($button) { |
| 139 | $button.siblings('.hustle-option').removeClass('hustle-active').attr('aria-selected', false); |
| 140 | $button.addClass('hustle-active').attr('aria-selected', true); |
| 141 | }, |
| 142 | buildTrackingActionSelect: function buildTrackingActionSelect() { |
| 143 | var $select = this.$widget.find('#hustle-analytics-show'), |
| 144 | ssharingFriends = ['popup', 'slidein', 'embedded'], |
| 145 | isSsharingAlone = !hustleVars.active_module_types.some(function (el) { |
| 146 | return ssharingFriends.includes(el); |
| 147 | }); |
| 148 | var html = ''; |
| 149 | var availableActions = Object.assign({}, hustleVars.tracking_actions); |
| 150 | |
| 151 | if ('social_sharing' === this.activeModuleType || isSsharingAlone) { |
| 152 | delete availableActions.cta_conversion; |
| 153 | delete availableActions.optin_conversion; |
| 154 | |
| 155 | if ('cta_conversion' === this.activeTrackingType || 'optin_conversion' === this.activeTrackingType) { |
| 156 | this.activeTrackingType = 'view'; |
| 157 | } |
| 158 | } // Build the options for the select. |
| 159 | |
| 160 | |
| 161 | for (var action in availableActions) { |
| 162 | var selected = action === this.activeTrackingType ? 'selected' : ''; |
| 163 | html += "<option value=\"".concat(action, "\" ").concat(selected, ">").concat(availableActions[action], "</option>"); |
| 164 | } |
| 165 | |
| 166 | $select.html(html); |
| 167 | }, |
| 168 | updateTotals: function updateTotals() { |
| 169 | var totals = this.totalsData, |
| 170 | getArrowIcon = function getArrowIcon(direction) { |
| 171 | return "<span class=\"sui-icon-arrow-".concat(direction, " sui-sm\" aria-hidden=\"true\"></span>"); |
| 172 | }; |
| 173 | |
| 174 | for (var moduleType in totals) { |
| 175 | var $button = this.$widget.find(".hustle-options-chart .hustle-option[data-module-type=\"".concat(moduleType, "\"]")), |
| 176 | $valueHolder = $button.find('.hustle-option--value'), |
| 177 | $trendHolder = $button.find('.hustle-option--trend'), |
| 178 | moduleTypeData = totals[moduleType], |
| 179 | total = moduleTypeData[this.activeTrackingType].total, |
| 180 | trend = moduleTypeData[this.activeTrackingType].trend; |
| 181 | var trendHtml = ''; |
| 182 | $trendHolder.removeClass('hustle-up'); |
| 183 | $trendHolder.removeClass('hustle-down'); |
| 184 | |
| 185 | if (0 !== trend) { |
| 186 | if (0 < trend) { |
| 187 | $trendHolder.addClass('hustle-up'); |
| 188 | trendHtml += getArrowIcon('up'); |
| 189 | } else { |
| 190 | $trendHolder.addClass('hustle-down'); |
| 191 | trendHtml += getArrowIcon('down'); |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | $valueHolder.text(total); |
| 196 | trendHtml += trend + '%'; |
| 197 | $trendHolder.html(trendHtml); |
| 198 | } |
| 199 | }, |
| 200 | formatDataForChart: function formatDataForChart() { |
| 201 | var data = this.trackingData, |
| 202 | moduleType = this.activeModuleType, |
| 203 | displayType = this.activeDisplayType, |
| 204 | trackingType = this.activeTrackingType, |
| 205 | $noDataMessage = this.$widget.find('.hustle-message-empty'); |
| 206 | var moduleTypeData = {}, |
| 207 | dataToDisplay = {}, |
| 208 | dataKey = moduleType, |
| 209 | showNoDataMessage = false; |
| 210 | |
| 211 | try { |
| 212 | if (['popup', 'slidein', 'overall'].includes(moduleType) || 'total' === displayType) { |
| 213 | moduleTypeData = data[dataKey]; |
| 214 | } else { |
| 215 | // Social sharing modules are the only with 'floating' display type. |
| 216 | if ('floating' === displayType && 'social_sharing' !== moduleType) { |
| 217 | throw false; |
| 218 | } |
| 219 | |
| 220 | dataKey = moduleType + '_' + displayType; |
| 221 | moduleTypeData = data[dataKey]; |
| 222 | } // Data for this module type isn't defined. Display the message and abort. |
| 223 | |
| 224 | |
| 225 | if ('undefined' === typeof moduleTypeData) { |
| 226 | throw false; |
| 227 | } |
| 228 | |
| 229 | showNoDataMessage = 0 === this.totalsData.overall.view.total && 0 === this.totalsData.overall.conversion.total; // There's no data for this module type. |
| 230 | |
| 231 | if (!moduleTypeData || !Object.keys(moduleTypeData).length) { |
| 232 | throw false; |
| 233 | } // Get the data for the selected tracking type. |
| 234 | |
| 235 | |
| 236 | dataToDisplay = moduleTypeData[trackingType]; // There's no data for this type. |
| 237 | |
| 238 | if ('undefined' === typeof dataToDisplay || !Object.keys(dataToDisplay).length) { |
| 239 | throw false; |
| 240 | } |
| 241 | |
| 242 | dataToDisplay = Object.values(dataToDisplay); |
| 243 | } catch (e) { |
| 244 | showNoDataMessage = true; |
| 245 | dataToDisplay = Array(parseInt(this.activeDaysRange)).fill(0); |
| 246 | } // Display the "we haven't collected enough data yet" message if there's no data. |
| 247 | |
| 248 | |
| 249 | if (showNoDataMessage) { |
| 250 | $noDataMessage.show(); |
| 251 | } else { |
| 252 | $noDataMessage.hide(); |
| 253 | } |
| 254 | |
| 255 | return dataToDisplay; |
| 256 | }, |
| 257 | buildChart: function buildChart() { |
| 258 | var chartData = this.formatDataForChart(), |
| 259 | datasets = [{ |
| 260 | label: hustleVars.tracking_actions[this.activeTrackingType], |
| 261 | data: chartData, |
| 262 | backgroundColor: ['transparent'], |
| 263 | borderColor: ['#0085BA'], |
| 264 | borderWidth: 2, |
| 265 | pointRadius: 0, |
| 266 | pointHitRadius: 20, |
| 267 | pointHoverRadius: 4, |
| 268 | pointHoverBorderColor: '#0085BA', |
| 269 | pointHoverBackgroundColor: '#FFFFFF' |
| 270 | }]; |
| 271 | |
| 272 | if (this.theChart) { |
| 273 | this.theChart.destroy(); |
| 274 | } |
| 275 | |
| 276 | this.createNewChart(datasets); |
| 277 | }, |
| 278 | createNewChart: function createNewChart(datasets) { |
| 279 | var $chartContainer = this.$widget.find('#hustle-analytics-chart'), |
| 280 | trackingTypeName = hustleVars.tracking_actions[this.activeTrackingType], |
| 281 | chartData = { |
| 282 | labels: this.daysLabels, |
| 283 | datasets: datasets |
| 284 | }, |
| 285 | chartOptions = { |
| 286 | responsive: true, |
| 287 | maintainAspectRatio: false, |
| 288 | legend: { |
| 289 | display: false |
| 290 | }, |
| 291 | scales: { |
| 292 | yAxes: [{ |
| 293 | gridLines: { |
| 294 | display: true, |
| 295 | color: '#F8F8F8', |
| 296 | zeroLineColor: '#F8F8F8', |
| 297 | drawBorder: false // Allow zeroLineColor on xAxes. |
| 298 | |
| 299 | }, |
| 300 | ticks: { |
| 301 | fontColor: '#72777C', |
| 302 | fontSize: 11 |
| 303 | } |
| 304 | }], |
| 305 | xAxes: [{ |
| 306 | gridLines: { |
| 307 | display: false, |
| 308 | zeroLineColor: 'rgba(0,0,0,0)', |
| 309 | drawBorder: false // Allow zeroLineColor on xAxes. |
| 310 | |
| 311 | }, |
| 312 | ticks: { |
| 313 | fontColor: '#72777C', |
| 314 | fontSize: 11 |
| 315 | } |
| 316 | }] |
| 317 | }, |
| 318 | elements: { |
| 319 | line: { |
| 320 | tension: 0 |
| 321 | }, |
| 322 | point: { |
| 323 | radius: 0.5 |
| 324 | } |
| 325 | }, |
| 326 | tooltips: { |
| 327 | xPadding: 12, |
| 328 | yPadding: 8, |
| 329 | backgroundColor: '#333333', |
| 330 | titleFontColor: '#FFFFFF', |
| 331 | titleFontSize: 15, |
| 332 | titleFontFamily: 'Roboto', |
| 333 | titleFontStyle: 'normal', |
| 334 | titleAlign: 'left', |
| 335 | titleSpacing: 0, |
| 336 | titleMarginBottom: 2, |
| 337 | bodyFontColor: '#AAAAAA', |
| 338 | bodyFontSize: 11, |
| 339 | bodyFontFamily: 'Roboto', |
| 340 | bodyFontStyle: 'normal', |
| 341 | bodyAlign: 'left', |
| 342 | cornerRadius: 4, |
| 343 | displayColors: false, |
| 344 | callbacks: { |
| 345 | title: function title(tooltipItem) { |
| 346 | return tooltipItem[0].yLabel + ' ' + trackingTypeName; |
| 347 | }, |
| 348 | label: function label(tooltipItem) { |
| 349 | return tooltipItem.xLabel; |
| 350 | } |
| 351 | } |
| 352 | } |
| 353 | }; |
| 354 | this.theChart = new Chart($chartContainer[0], { |
| 355 | type: 'line', |
| 356 | fill: 'start', |
| 357 | data: chartData, |
| 358 | options: chartOptions |
| 359 | }); |
| 360 | } |
| 361 | }; |
| 362 | dashboardWidget.init(); |
| 363 | })(jQuery); |