Spamworldpro Mini Shell
Spamworldpro


Server : Apache
System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64
User : corals ( 1002)
PHP Version : 7.4.33
Disable Function : exec,passthru,shell_exec,system
Directory :  /home/corals/mets.corals.io/wp-content/plugins/wp-analytify/assets/js/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/corals/mets.corals.io/wp-content/plugins/wp-analytify/assets/js/stats-core.js
'use strict';

/**
 * 
 * This file handles all the ajax requests for the core dashboard.
 * This also includes generating charts and populating the data into a view.
 * 
 */

jQuery(function ($) {

	/**
	 * Handles the ajax request for the dashboard stats.
	 *
	 * @param {string} endpoint The API endpoint.
	 * @param {object} data     The data to send in the request.
	 * 
	 * @returns {object}
	 */
	const fetch_stats = async (endpoint, data = {}) => {

		// start/end dates and date differ.
		if ($('#analytify_date_start').length) {
			data.sd = $('#analytify_date_start').val();
		}
		if ($('#analytify_date_end').length) {
			data.ed = $('#analytify_date_end').val();
		}
		if ($('#analytify_date_diff').length) {
			data.d_diff = $('#analytify_date_diff').val();
		}

		// convert data to url params.
		const params = new URLSearchParams();
		for (const key in data) {
			params.append(key, data[key]);
		}

		const URL = `${analytify_stats_core.url + endpoint + '/' + analytify_stats_core.delimiter}${params.toString()}`;

		let request = await fetch(URL, {
			method: "GET",
			headers: {
				"X-WP-Nonce": analytify_stats_core.nonce,
			},
		});
		return request.json();
	}

	/**
	 * Sets the target element to 'loading' state.
	 * Also clear the element's contents.
	 * 
	 * @param {element} target The target element.
	 */
	const prepare_section = (target) => {
		target.find('.analytify_stats_loading').show();
		target.find('.analytify_status_body .stats-wrapper').html('');
		target.find('.analytify_status_footer').remove();
		target.find('.empty-on-loading').html('');
	}

	/**
	 * Element should not be loading.
	 * 
	 * @param {element} target The target element.
	 */
	const should_not_be_loading = (target) => {
		target.find('.analytify_stats_loading').hide();
	}

	/**
	 * Sets the content for the element.
	 * Removes the 'loading' state.
	 * 
	 * @param {element} target     The target element.
	 * @param {string}  markup     The markup to be set (should be HTML).
	 * @param {string}  footer     The footer markup to be set.
	 * @param {boolean} pagination Whether to show the pagination or not.
	 */
	const set_section = (target, markup, footer = false, pagination = false) => {
		should_not_be_loading(target);
		target.find('.analytify_status_body .stats-wrapper').html(markup);

		if (footer || pagination) {
			let footer_markup = `<div class="analytify_status_footer">
				${footer ? `<span class="analytify_info_stats">${footer}</span>` : ''}
				${pagination ? `<div class="wp_analytify_pagination"></div>` : ''}
			</div>`;
			target.find('.analytify_status_body').after(footer_markup);
		}
	}

	/**
	 * Generates the empty stats message.
	 * 
	 * @param {element} target       The target element.
	 * @param {string}  message      The message to be shown.
	 * @param {object}  table_header The table header, if the message needs to be shown in a table.
	 * @param {string}  table_class  The table class.
	 */
	const stats_message = (target = false, message = false, table_header = false, table_class = '') => {
		let markup = `<div class="analytify-stats-error-msg">
			<div class="wpb-error-box">
				<span class="blk"><span class="line"></span><span class="dot"></span></span>
				<span class="information-txt">${message ? message : analytify_stats_core.no_stats_message}</span>
			</div>
		</div>`;

		if (table_header) {
			// If the error message is to be shown in a table.
			let thead = '';
			for (const td_key in table_header) {
				const td = table_header[td_key];
				if (td.label) {
					thead += `<th class="${td.th_class ? td.th_class : ``}">${td.label}</th>`;
				}
			}

			markup = `<table class="${table_class}">${'' !== thead ? `<thead><tr>${thead}</tr></thead>` : ''}<tbody><tr><td class="analytify_td_error_msg" colspan="${Object.keys(table_header).length}">${markup}</td></tr></tbody></table>`;
		}

		if (!target) {
			return markup;
		}
		set_section(target, markup, false, false);
	}

	/**
	 * Generates the red message box.
	 * 
	 * @param {element} target       The target element.
	 * @param {string}  message      The message to be shown.
	 * @param {object}  table_header The table header, if the message needs to be shown in a table.
	 * @param {string}  table_class  The table class.
	 */
	const red_stats_message = (target = false, message = false, table_header = false, table_class = '') => {
		let markup = `<div class="analytify-email-promo-contianer">
			<div class="analytify-email-premium-overlay">
				<div class="analytify-email-premium-popup">
					${message.title ? `<h3 class="analytify-promo-popup-heading" style="text-align:left;">${message.title}</h3>` : ``}
					${message.content ? message.content : ``}
				</div>
			</div>
		</div>`;

		if (table_header) {
			// If the error message is to be shown in a table.
			let thead = '';
			for (const td_key in table_header) {
				const td = table_header[td_key];
				if (td.label) {
					thead += `<th class="${td.th_class ? td.th_class : ``}">${td.label}</th>`;
				}
			}

			markup = `<table class="${table_class}">${'' !== thead ? `<thead><tr>${thead}</tr></thead>` : ''}<tbody><tr><td class="analytify_td_error_msg" colspan="${Object.keys(table_header).length}">${markup}</td></tr></tbody></table>`;
		}

		if (!target) {
			return markup;
		}
		set_section(target, markup, false, false);
	}

	/**
	 * Generates table from object.
	 * {headers} is to generate <thead> tag and content.
	 * {stats} is to generate <tbody> tag and content.
	 * 
	 * @param {object} headers       The headers.
	 * @param {object} stats         The stats to be shown.
	 * @param {string} table_classes Table classes
	 * @param {string} attr          Table attributes
	 * @returns {string}
	 */
	const generate_stats_table = (headers, stats, table_classes = false, attr = '') => {

		let markup = ``;

		markup += `<table class="${table_classes}" ${attr}>`;

		let thead = '';
		for (const td_key in headers) {
			const td = headers[td_key];
			if (td.label) {
				thead += `<th class="${td.th_class ? td.th_class : ``}">${td.label}</th>`;
			}
		}
		if ('' !== thead) {
			markup += `<thead><tr>${thead}</tr></thead>`;
		}

		markup += `<tbody>`;

		let i = 1;
		for (const row_id in stats) {
			const row = stats[row_id];
			markup += `<tr>`;
			for (const td_key in row) {

				let __label = '';

				if (row[td_key] === null && headers[td_key].type && 'counter' === headers[td_key].type) {
					__label = i;
				} else if (row[td_key].label) {
					__label = row[td_key].label;
				} else if (row[td_key].value) {
					__label = row[td_key].value;
				} else {
					__label = row[td_key];
				}

				let __class = '';
				if (row[td_key] && row[td_key].class) {
					__class = row[td_key].class;
				} else if (headers[td_key] && headers[td_key].td_class) {
					__class = headers[td_key].td_class;
				}

				markup += `<td class="${__class}">${__label}</td>`;
			}
			markup += `</tr>`;
			i++;
		}
		markup += `</tbody>`;

		markup += `</table>`;

		return markup;

	}

	/**
	* Generates the markup for the 'General Stats' section.
	* 
	* @param {object}  response The response from the API.
	* @param {element} target   The target element.
	*/
	const generate_general_stats_markup = (response, target) => {

		let markup = '';
		let box_number = 1;
		// loop over response.boxes
		for (const box_key in response.boxes) {
			const box = response.boxes[box_key];

			markup += `<div class="analytify_general_status_boxes${box_number === Object.keys(response.boxes).length ? ' pad_b_0' : ''}">`;
			markup += `<h4>${box.title}</h4>
					<div class="analytify_general_stats_value">
						${box.prepend ? box.prepend : ''}${box.number}${box.append ? box.append : ''}
					</div>
					<p>${box.description ? box.description : ''}</p>`;
			if (box.bottom) {
				markup += `<div class="analytify_general_status_footer_info">
						<span class="analytify_info_value ${box.bottom.arrow_type}">${box.bottom.main_text}</span>
						${box.bottom.sub_text}
					</div>`;
			}
			markup += `</div>`;

			box_number++;
		}

		// loop over response.charts
		for (const chart_key in response.charts) {
			const chart = response.charts[chart_key];

			const chart_stats = encodeURIComponent(JSON.stringify(chart.stats));
			const chart_colors = encodeURIComponent(JSON.stringify(chart.colors));

			markup += `<div class="analytify_general_status_boxes pad_b_0">
				<h4>${chart.title}</h4>
				<div id="analytify_chart_${chart_key}" style="height:240px;" data-chart-title="${chart.title}" data-stats="${chart_stats}" data-colors="${chart_colors}"></div>
			</div>`;
		}

		set_section(target, markup, response.footer, false);

	}

	/**
	* Builds charts for the 'General Stats' section.
	*/
	const es_chart_stats_general = () => {
		require.config({
			paths: {
				echarts: analytify_stats_core.dist_js_url
			}
		});

		require(
			[
				'echarts',
				'echarts/chart/pie',
			],
			function (ec) {

				if ($('#analytify_chart_new_vs_returning_visitors').length) {

					const setting_title = $('#analytify_chart_new_vs_returning_visitors').attr('data-chart-title');
					const setting_stats = JSON.parse(decodeURIComponent($('#analytify_chart_new_vs_returning_visitors').attr('data-stats')));
					const setting_colors = JSON.parse(decodeURIComponent($('#analytify_chart_new_vs_returning_visitors').attr('data-colors')));

					if (setting_stats.new.number > 0 && setting_stats.returning.number > 0) {

						const new_returning_graph_options = {
							tooltip: { trigger: 'item', formatter: "{b} {a} : {c} ({d}%)" },
							color: setting_colors,
							legend: { orient: 'horizontal', y: 'bottom', data: [setting_stats.new.label, setting_stats.returning.label] },
							series: [
								{
									name: setting_title,
									type: 'pie',
									smooth: true,
									roseType: 'radius',
									radius: [20, 60],
									center: ['50%', '42%'],
									data: [
										{ name: setting_stats.new.label, value: setting_stats.new.number },
										{ name: setting_stats.returning.label, value: setting_stats.returning.number }
									]
								}
							]
						};

						const new_returning_graph = ec.init(document.getElementById('analytify_chart_new_vs_returning_visitors'));
						new_returning_graph.setOption(new_returning_graph_options);

						window.onresize = function () {
							try {
								new_returning_graph.resize();
							} catch (err) {
								console.log(err);
							}
						}
					} else {
						$('#analytify_chart_new_vs_returning_visitors').html(`<div class="analytify_general_stats_value">0</div><p>${analytify_stats_core.no_stats_message}</p>`);
					}
				}

				if ($('#analytify_chart_visitor_devices').length) {

					const setting_title = $('#analytify_chart_visitor_devices').attr('data-chart-title');
					const setting_stats = JSON.parse(decodeURIComponent($('#analytify_chart_visitor_devices').attr('data-stats')));
					const setting_colors = JSON.parse(decodeURIComponent($('#analytify_chart_visitor_devices').attr('data-colors')));

					if (setting_stats.desktop.number > 0 || setting_stats.mobile.number > 0 || setting_stats.tablet.number > 0) {

						const user_device_graph_options = {
							tooltip: { trigger: 'item', formatter: "{a} <br/>{b} : {c} ({d}%)" },
							color: setting_colors,
							legend: { x: 'center', y: 'bottom', data: [setting_stats.mobile.label, setting_stats.tablet.label, setting_stats.desktop.label] },
							series: [
								{
									name: setting_title,
									type: 'pie',
									smooth: true,
									radius: [20, 60],
									center: ['55%', '42%'],
									roseType: 'radius',
									label: { normal: { show: false }, emphasis: { show: false } },
									lableLine: { normal: { show: false }, emphasis: { show: false } },
									data: [
										{ name: setting_stats.mobile.label, value: setting_stats.mobile.number },
										{ name: setting_stats.tablet.label, value: setting_stats.tablet.number },
										{ name: setting_stats.desktop.label, value: setting_stats.desktop.number },
									]
								}
							]
						};

						const user_device_graph = ec.init(document.getElementById('analytify_chart_visitor_devices'));
						user_device_graph.setOption(user_device_graph_options);

						window.onresize = function () {
							try {
								user_device_graph.resize();
							} catch (err) {
								console.log(err);
							}
						}
					} else {
						$('#analytify_chart_visitor_devices').html(`<div class="analytify_general_stats_value">0</div><p>${analytify_stats_core.no_stats_message}</p>`);
					}
				}
			}
		);
	}

	/**
	* Builds map for the 'Geographic' section.
	* 
	* @param {object} data Stats data for the map.
	*/
	const es_chart_map = (data) => {

		require.config({
			paths: {
				echarts: analytify_stats_core.dist_js_url
			}
		});

		require(
			[
				'echarts',
				'echarts/chart/map',
			],
			function (ec) {

				// Change the keys of the data to match the map.
				const map_data = [];
				for (const key in data.stats) {

					let single_country = {};

					single_country.name = data.stats[key].country;
					single_country.value = data.stats[key].sessions;

					if (single_country.name === 'United States') {
						single_country.name = 'United States of America';
					}

					map_data.push(single_country);
				}

				const geographic_stats_graph = ec.init(document.getElementById('analytify_geographic_stats_graph'));
				const geographic_stats_graph_option = {
					tooltip: {
						trigger: 'item',
						formatter: function (params) {
							let value = (params.value + '').split('.');
							if (value[0] != '-') {
								value = value[0];
							} else {
								value = 0;
							}
							return data.title + '<br />' + params.name + ' : ' + value;
						}
					},
					toolbox: { show: false, orient: 'horizontal', x: 'right', y: '10', feature: { restore: { show: true }, saveAsImage: { show: true } } },
					roamController: { show: true, mapTypeControl: { 'world': true }, x: 'right', y: 'bottom' },
					dataRange: { min: "1", max: data.highest, text: [data.label.high, data.label.low], realtime: true, calculable: true, color: data.colors },
					series: [
						{ name: data.title, type: 'map', mapType: 'world', roam: false, scaleLimit: { min: 1, max: 10 }, mapLocation: { y: 60 }, itemStyle: { emphasis: { label: { show: true } } }, data: map_data }
					]
				};

				// Load data into the ECharts instance.
				geographic_stats_graph.setOption(geographic_stats_graph_option);
				window.onresize = function () {
					try {
						geographic_stats_graph.resize();
					} catch (err) {
						console.log(err);
					}
				}
			}
		);
	}

	/**
	 * Returns the compare start and end date based on given start and end date.
	 * 
	 * @param {string} __start_date Start date.
	 * @param {string} __end_date   End date.
	 * @param {bool}   formatted    If true, returns formatted date to be used in the GA's dashboard url.
	 * @returns {object}
	 */
	const calc_compare_date = (__start_date, __end_date, formatted = true) => {

		const start_date = new Date(__start_date);
		const end_date = new Date(__end_date);

		return `%26_u.date00%3D${__start_date.replaceAll('-', '')}%26_u.date01%3D${__end_date.replaceAll('-', '')}`;
	}

	/**
	 * This function generate the complete GA report.
	 *
	 * @param {*} report_id 
	 * @param {*} report_type 
	 * @param {*} date_parameter 
	 * @returns
	 * 
	 */
	const generate_ga4_report_link = (report_id, report_type, date_parameter) => {
		if (!report_id) {
		  return;
		}
	
		const report_link = `https://analytics.google.com/analytics/web/#/${report_id}/reports/explorer/?`;
	
		let link = "";
	
		switch (report_type) {
		  case "top_pages":
			link = `${report_link}params=_u..nav%3Dmaui${date_parameter}&r=all-pages-and-screens&ruid=all-pages-and-screens,life-cycle,engagement`;
			break;
		  case "top_countries":
			link = `${report_link}params=_u..nav%3Dmaui${date_parameter}%26_r.explorerCard..selmet%3D%5B%22activeUsers%22%5D%26_r.explorerCard..seldim%3D%5B%22country%22%5D&r=user-demographics-detail&ruid=user-demographics-detail,user,demographics&collectionId=user`;
			break;
		  case "top_cities":
			link = `${report_link}params=_r.explorerCard..selmet%3D%5B%22activeUsers%22%5D%26_r.explorerCard..seldim%3D%5B%22city%22%5D%26_u..nav%3Dmaui${date_parameter}&r=user-demographics-detail&ruid=user-demographics-detail,user,demographics&collectionId=user`;
			break;
		  case "referer":
			link = `${report_link}params=_u..nav%3Dmaui${date_parameter}&r=lifecycle-traffic-acquisition-v2&ruid=lifecycle-traffic-acquisition-v2,life-cycle,acquisition&collectionId=life-cycle`;
			break;
		  case "top_products":
			link = `${report_link}params=_u..nav%3Dmaui${date_parameter}%26_r.explorerCard..selmet%3D%5B%22ecommercePurchases%22%5D%26_r.explorerCard..seldim%3D%5B%22itemInfoName%22%5D&r=ecomm-product&collectionId=life-cycle`;
			break;
		  case "source_medium":
			link = `${report_link}params=_u..nav%3Dmaui${date_parameter}&r=lifecycle-traffic-acquisition-v2&ruid=lifecycle-traffic-acquisition-v2,3078873331,acquisition`;
			break;
		  case "top_countries_sales":
			link = `${report_link}params=_u..nav%3Dmaui${date_parameter}%26_r.explorerCard..selmet%3D%5B%22activeUsers%22%5D%26_r.explorerCard..seldim%3D%5B%22country%22%5D&r=user-demographics-detail&ruid=user-demographics-detail,user,demographics&collectionId=user`;
			break;
		  default:
			break;
		}
	
		return link;
	}

	/**
	 * Builds the GA dashboard link for sections.
	 * Attaches the data parameter dynamically.
	 */
	const build_ga_dashboard_link = () => {
		const __start_date = $('#analytify_date_start').val();
		const __end_date = $('#analytify_date_end').val();

		const date_parameter = calc_compare_date(__start_date, __end_date, true);

		$('[data-ga-dashboard-link]').each(function (index, __element) {
			if (analytify_stats_core.ga_mode === "ga4") {
			const link = generate_ga4_report_link(
				analytify_stats_core.ga4_report_url,
				$(__element).attr("data-ga-dashboard-link"),
				date_parameter
			);

			$(__element).attr('href', link);
			} else {
				const link = $(__element).attr("data-ga-dashboard-link") + date_parameter;
        		$(__element).attr("href", link);
			}
		});
	}

	/**
	* Fetches the data and build the template for all endpoints.
	* 
	*/
	const build_sections = () => {

		// To trigger same-height js script.
		$(window).trigger('resize');
		try {
			$('[data-endpoint]').each(function (index, __element) {
				const element = $(__element);
				const type = element.attr('data-endpoint');
				const target_body = element.find('.stats-wrapper');

				prepare_section(element);

				fetch_stats(type).then((response) => {
					if (response.success) {

						switch (type) {
							case 'general-stats':
								generate_general_stats_markup(response, element);
								es_chart_stats_general();
								break;

							case 'geographic-stats':
								{
									const table_classes = 'analytify_data_tables analytify_border_th_tp analytify_pull_left analytify_half';

									const map_stats_length = Object.keys(response.map.stats).length;
									const country_stats_length = Object.keys(response.country.stats).length;
									const city_stats_length = Object.keys(response.city.stats).length;

									let markup = `
									${map_stats_length > 0 ? `<div class="analytify_txt_center analytify_graph_wraper"><div id="analytify_geographic_stats_graph" style="height:600px"></div></div>` : ``
										}
									<div class="analytify_clearfix">
										${country_stats_length > 0 ? generate_stats_table(response.country.headers, response.country.stats, table_classes) : stats_message(false, false, response.country.headers, table_classes)
										}
										${city_stats_length > 0 ? generate_stats_table(response.city.headers, response.city.stats, table_classes) : stats_message(false, false, response.city.headers, table_classes)
										}
									</div>`;

									set_section(element, markup, response.footer, false);

									if (map_stats_length > 0) {
										es_chart_map(response.map);
									}
								}
								break;

							case 'system-stats':
								{
									const browser_stats_length = Object.keys(response.browser.stats).length;
									const os_stats_length = Object.keys(response.os.stats).length;
									const mobile_stats_length = Object.keys(response.mobile.stats).length;

									const table_classes = 'analytify_data_tables';

									let markup = `<div class="analytify_clearfix">
										<div class="analytify_one_tree_table">
											${browser_stats_length > 0 ? generate_stats_table(response.browser.headers, response.browser.stats, table_classes) : stats_message(false, false, response.browser.headers, table_classes)
										}
										</div>
										<div class="analytify_one_tree_table">
											${os_stats_length > 0 ? generate_stats_table(response.os.headers, response.os.stats, table_classes) : stats_message(false, false, response.os.headers, table_classes)
										}
										</div>
										<div class="analytify_one_tree_table">
											${mobile_stats_length > 0 ? generate_stats_table(response.mobile.headers, response.mobile.stats, table_classes) : stats_message(false, false, response.mobile.headers, table_classes)
										}
										</div>
									</div>`;

									set_section(element, markup, response.footer, false);

								}
								break;

							case 'top-pages-stats':
							case 'keyword-stats':
							case 'social-stats':
							case 'referer-stats':
							case 'what-is-happening-stats':
								{
									let table_classes;
									let table_attr;
									switch (type) {
										case 'top-pages-stats':
											table_classes = 'analytify_data_tables';
											if (response.pagination) {
												table_classes += ' wp_analytify_paginated';
												table_attr = ' data-product-per-page="10"';
											}
											break;
										case 'keyword-stats':
											table_classes = 'analytify_data_tables analytify_page_stats_table';
											break;
										case 'social-stats':
											table_classes = 'analytify_data_tables analytify_no_header_table';
											break;
										case 'what-is-happening-stats':
											table_classes = 'analytify_data_tables analytify_page_stats_table';
											break;
										case 'referer-stats': 
										    table_classes = 'analytify_bar_tables';
											if (response.pagination) {
												table_classes += ' wp_analytify_paginated';
												table_attr = ' data-product-per-page="10"';
											}
											break;

										default:
											table_classes = 'analytify_bar_tables';
											break;
									}

									if (Object.keys(response.stats).length > 0) {
										const markup = generate_stats_table(response.headers, response.stats, table_classes, table_attr);
										set_section(element, markup, response.footer, response.pagination);
										if (element.find('.title-total-wrapper').length && response.title_stats) {
											element.find('.title-total-wrapper').html(response.title_stats);
										}
									} else {
										stats_message(element, false, response.headers, table_classes);
									}
								}
								break;

							default:
								break;
						}

						build_ga_dashboard_link();
						wp_analytify_paginated();
						$(window).trigger('resize');

					} else if (response.error_message) {
						should_not_be_loading(element);
						stats_message(element, response.error_message, response.headers);
					} else if (response.error_box) {
						should_not_be_loading(element);
						red_stats_message(element, response.error_box, response.headers);
					} else {
						should_not_be_loading(element);
						stats_message(element, analytify_stats_core.error_message, response.headers);
					}

				}).catch(function (error) {
					console.log(error);
				});

			});
		} catch (err) {
			console.log('err');
		}

		$(window).trigger('resize');
	}

	build_sections();

	// Call of submission of date form.
	$('form.analytify_form_date').on('submit', function (e) {
		if (analytify_stats_core.load_via_ajax) {
			e.preventDefault();
			let customEvent = new Event('analytify_form_date_submitted');
			document.dispatchEvent(customEvent);
			build_sections();
			build_ga_dashboard_link();
		}
	});

});

Spamworldpro Mini