mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 19:15:58 +01:00 
			
		
		
		
	fixes #4463
This commit is contained in:
		
							
								
								
									
										109
									
								
								public/src/admin/manage/category-analytics.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								public/src/admin/manage/category-analytics.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| "use strict"; | ||||
| /*global config, define, app, socket, ajaxify, bootbox, templates, Chart, utils */ | ||||
|  | ||||
| define('admin/manage/category-analytics', [], function() { | ||||
| 	var CategoryAnalytics = {}; | ||||
|  | ||||
| 	CategoryAnalytics.init = function() { | ||||
| 		var hourlyCanvas = document.getElementById('pageviews:hourly'), | ||||
| 			dailyCanvas = document.getElementById('pageviews:daily'), | ||||
| 			topicsCanvas = document.getElementById('topics:daily'), | ||||
| 			postsCanvas = document.getElementById('posts:daily'), | ||||
| 			hourlyLabels = utils.getHoursArray().map(function(text, idx) { | ||||
| 				return idx % 3 ? '' : text; | ||||
| 			}), | ||||
| 			dailyLabels = utils.getDaysArray().map(function(text, idx) { | ||||
| 				return idx % 3 ? '' : text; | ||||
| 			}); | ||||
|  | ||||
| 		if (utils.isMobile()) { | ||||
| 			Chart.defaults.global.showTooltips = false; | ||||
| 		} | ||||
|  | ||||
| 		var data = { | ||||
| 			'pageviews:hourly': { | ||||
| 				labels: hourlyLabels, | ||||
| 				datasets: [ | ||||
| 					{ | ||||
| 						label: "", | ||||
| 						fillColor: "rgba(186,139,175,0.2)", | ||||
| 						strokeColor: "rgba(186,139,175,1)", | ||||
| 						pointColor: "rgba(186,139,175,1)", | ||||
| 						pointStrokeColor: "#fff", | ||||
| 						pointHighlightFill: "#fff", | ||||
| 						pointHighlightStroke: "rgba(186,139,175,1)", | ||||
| 						data: ajaxify.data.analytics['pageviews:hourly'] | ||||
| 					} | ||||
| 				] | ||||
| 			}, | ||||
| 			'pageviews:daily': { | ||||
| 				labels: dailyLabels, | ||||
| 				datasets: [ | ||||
| 					{ | ||||
| 						label: "", | ||||
| 						fillColor: "rgba(151,187,205,0.2)", | ||||
| 						strokeColor: "rgba(151,187,205,1)", | ||||
| 						pointColor: "rgba(151,187,205,1)", | ||||
| 						pointStrokeColor: "#fff", | ||||
| 						pointHighlightFill: "#fff", | ||||
| 						pointHighlightStroke: "rgba(151,187,205,1)", | ||||
| 						data: ajaxify.data.analytics['pageviews:daily'] | ||||
| 					} | ||||
| 				] | ||||
| 			}, | ||||
| 			'topics:daily': { | ||||
| 				labels: dailyLabels.slice(-7), | ||||
| 				datasets: [ | ||||
| 					{ | ||||
| 						label: "", | ||||
| 						fillColor: "rgba(171,70,66,0.2)", | ||||
| 						strokeColor: "rgba(171,70,66,1)", | ||||
| 						pointColor: "rgba(171,70,66,1)", | ||||
| 						pointStrokeColor: "#fff", | ||||
| 						pointHighlightFill: "#fff", | ||||
| 						pointHighlightStroke: "rgba(171,70,66,1)", | ||||
| 						data: ajaxify.data.analytics['topics:daily'] | ||||
| 					} | ||||
| 				] | ||||
| 			}, | ||||
| 			'posts:daily': { | ||||
| 				labels: dailyLabels.slice(-7), | ||||
| 				datasets: [ | ||||
| 					{ | ||||
| 						label: "", | ||||
| 						fillColor: "rgba(161,181,108,0.2)", | ||||
| 						strokeColor: "rgba(161,181,108,1)", | ||||
| 						pointColor: "rgba(161,181,108,1)", | ||||
| 						pointStrokeColor: "#fff", | ||||
| 						pointHighlightFill: "#fff", | ||||
| 						pointHighlightStroke: "rgba(161,181,108,1)", | ||||
| 						data: ajaxify.data.analytics['posts:daily'] | ||||
| 					} | ||||
| 				] | ||||
| 			}, | ||||
| 		}; | ||||
|  | ||||
| 		hourlyCanvas.width = $(hourlyCanvas).parent().width(); | ||||
| 		dailyCanvas.width = $(dailyCanvas).parent().width(); | ||||
| 		topicsCanvas.width = $(topicsCanvas).parent().width(); | ||||
| 		postsCanvas.width = $(postsCanvas).parent().width(); | ||||
| 		new Chart(hourlyCanvas.getContext('2d')).Line(data['pageviews:hourly'], { | ||||
| 			responsive: true, | ||||
| 			animation: false | ||||
| 		}); | ||||
| 		new Chart(dailyCanvas.getContext('2d')).Line(data['pageviews:daily'], { | ||||
| 			responsive: true, | ||||
| 			animation: false | ||||
| 		}); | ||||
| 		new Chart(topicsCanvas.getContext('2d')).Line(data['topics:daily'], { | ||||
| 			responsive: true, | ||||
| 			animation: false | ||||
| 		}); | ||||
| 		new Chart(postsCanvas.getContext('2d')).Line(data['posts:daily'], { | ||||
| 			responsive: true, | ||||
| 			animation: false | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	return CategoryAnalytics; | ||||
| }); | ||||
| @@ -154,12 +154,6 @@ define('admin/manage/category', [ | ||||
| 		}); | ||||
|  | ||||
| 		Category.setupPrivilegeTable(); | ||||
|  | ||||
| 		if (window.location.hash === '#analytics') { | ||||
| 			Category.setupGraphs(); | ||||
| 		} else { | ||||
| 			$('a[href="#analytics"]').on('shown.bs.tab', Category.setupGraphs); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	Category.setupPrivilegeTable = function() { | ||||
| @@ -360,106 +354,5 @@ define('admin/manage/category', [ | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	Category.setupGraphs = function() { | ||||
| 		var hourlyCanvas = document.getElementById('pageviews:hourly'), | ||||
| 			dailyCanvas = document.getElementById('pageviews:daily'), | ||||
| 			topicsCanvas = document.getElementById('topics:daily'), | ||||
| 			postsCanvas = document.getElementById('posts:daily'), | ||||
| 			hourlyLabels = utils.getHoursArray().map(function(text, idx) { | ||||
| 				return idx % 3 ? '' : text; | ||||
| 			}), | ||||
| 			dailyLabels = utils.getDaysArray().map(function(text, idx) { | ||||
| 				return idx % 3 ? '' : text; | ||||
| 			}); | ||||
|  | ||||
| 		if (utils.isMobile()) { | ||||
| 			Chart.defaults.global.showTooltips = false; | ||||
| 		} | ||||
|  | ||||
| 		var data = { | ||||
| 			'pageviews:hourly': { | ||||
| 				labels: hourlyLabels, | ||||
| 				datasets: [ | ||||
| 					{ | ||||
| 						label: "", | ||||
| 						fillColor: "rgba(186,139,175,0.2)", | ||||
| 						strokeColor: "rgba(186,139,175,1)", | ||||
| 						pointColor: "rgba(186,139,175,1)", | ||||
| 						pointStrokeColor: "#fff", | ||||
| 						pointHighlightFill: "#fff", | ||||
| 						pointHighlightStroke: "rgba(186,139,175,1)", | ||||
| 						data: ajaxify.data.analytics['pageviews:hourly'] | ||||
| 					} | ||||
| 				] | ||||
| 			}, | ||||
| 			'pageviews:daily': { | ||||
| 				labels: dailyLabels, | ||||
| 				datasets: [ | ||||
| 					{ | ||||
| 						label: "", | ||||
| 						fillColor: "rgba(151,187,205,0.2)", | ||||
| 						strokeColor: "rgba(151,187,205,1)", | ||||
| 						pointColor: "rgba(151,187,205,1)", | ||||
| 						pointStrokeColor: "#fff", | ||||
| 						pointHighlightFill: "#fff", | ||||
| 						pointHighlightStroke: "rgba(151,187,205,1)", | ||||
| 						data: ajaxify.data.analytics['pageviews:daily'] | ||||
| 					} | ||||
| 				] | ||||
| 			}, | ||||
| 			'topics:daily': { | ||||
| 				labels: dailyLabels.slice(-7), | ||||
| 				datasets: [ | ||||
| 					{ | ||||
| 						label: "", | ||||
| 						fillColor: "rgba(171,70,66,0.2)", | ||||
| 						strokeColor: "rgba(171,70,66,1)", | ||||
| 						pointColor: "rgba(171,70,66,1)", | ||||
| 						pointStrokeColor: "#fff", | ||||
| 						pointHighlightFill: "#fff", | ||||
| 						pointHighlightStroke: "rgba(171,70,66,1)", | ||||
| 						data: ajaxify.data.analytics['topics:daily'] | ||||
| 					} | ||||
| 				] | ||||
| 			}, | ||||
| 			'posts:daily': { | ||||
| 				labels: dailyLabels.slice(-7), | ||||
| 				datasets: [ | ||||
| 					{ | ||||
| 						label: "", | ||||
| 						fillColor: "rgba(161,181,108,0.2)", | ||||
| 						strokeColor: "rgba(161,181,108,1)", | ||||
| 						pointColor: "rgba(161,181,108,1)", | ||||
| 						pointStrokeColor: "#fff", | ||||
| 						pointHighlightFill: "#fff", | ||||
| 						pointHighlightStroke: "rgba(161,181,108,1)", | ||||
| 						data: ajaxify.data.analytics['posts:daily'] | ||||
| 					} | ||||
| 				] | ||||
| 			}, | ||||
| 		}; | ||||
|  | ||||
| 		hourlyCanvas.width = $(hourlyCanvas).parent().width(); | ||||
| 		dailyCanvas.width = $(dailyCanvas).parent().width(); | ||||
| 		topicsCanvas.width = $(topicsCanvas).parent().width(); | ||||
| 		postsCanvas.width = $(postsCanvas).parent().width(); | ||||
| 		new Chart(hourlyCanvas.getContext('2d')).Line(data['pageviews:hourly'], { | ||||
| 			responsive: true, | ||||
| 			animation: false | ||||
| 		}); | ||||
| 		new Chart(dailyCanvas.getContext('2d')).Line(data['pageviews:daily'], { | ||||
| 			responsive: true, | ||||
| 			animation: false | ||||
| 		}); | ||||
| 		new Chart(topicsCanvas.getContext('2d')).Line(data['topics:daily'], { | ||||
| 			responsive: true, | ||||
| 			animation: false | ||||
| 		}); | ||||
| 		new Chart(postsCanvas.getContext('2d')).Line(data['posts:daily'], { | ||||
| 			responsive: true, | ||||
| 			animation: false | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	return Category; | ||||
| }); | ||||
| @@ -14,22 +14,20 @@ var categoriesController = {}; | ||||
| categoriesController.get = function(req, res, next) { | ||||
| 	async.parallel({ | ||||
| 		category: async.apply(categories.getCategories, [req.params.category_id], req.user.uid), | ||||
| 		privileges: async.apply(privileges.categories.list, req.params.category_id), | ||||
| 		analytics: async.apply(analytics.getCategoryAnalytics, req.params.category_id) | ||||
| 		privileges: async.apply(privileges.categories.list, req.params.category_id) | ||||
| 	}, function(err, data) { | ||||
| 		if (err) { | ||||
| 			return next(err); | ||||
| 		} | ||||
|  | ||||
| 		plugins.fireHook('filter:admin.category.get', { req: req, res: res, category: data.category[0], privileges: data.privileges, analytics: data.analytics }, function(err, data) { | ||||
| 		plugins.fireHook('filter:admin.category.get', { req: req, res: res, category: data.category[0], privileges: data.privileges }, function(err, data) { | ||||
| 			if (err) { | ||||
| 				return next(err); | ||||
| 			} | ||||
| 			data.category.name = translator.escape(data.category.name); | ||||
| 			res.render('admin/manage/category', { | ||||
| 				category: data.category, | ||||
| 				privileges: data.privileges, | ||||
| 				analytics: data.analytics | ||||
| 				privileges: data.privileges | ||||
| 			}); | ||||
| 		}); | ||||
| 	}); | ||||
| @@ -40,5 +38,14 @@ categoriesController.getAll = function(req, res, next) { | ||||
| 	res.render('admin/manage/categories', {}); | ||||
| }; | ||||
|  | ||||
| categoriesController.getAnalytics = function(req, res, next) { | ||||
| 	async.parallel({ | ||||
| 		name: async.apply(categories.getCategoryField, req.params.category_id, 'name'), | ||||
| 		analytics: async.apply(analytics.getCategoryAnalytics, req.params.category_id) | ||||
| 	}, function(err, data) { | ||||
| 		res.render('admin/manage/category-analytics', data); | ||||
| 	}); | ||||
| }; | ||||
|  | ||||
|  | ||||
| module.exports = categoriesController; | ||||
|   | ||||
| @@ -52,6 +52,7 @@ function addRoutes(router, middleware, controllers) { | ||||
|  | ||||
| 	router.get('/manage/categories', middlewares, controllers.admin.categories.getAll); | ||||
| 	router.get('/manage/categories/:category_id', middlewares, controllers.admin.categories.get); | ||||
| 	router.get('/manage/categories/:category_id/analytics', middlewares, controllers.admin.categories.getAnalytics); | ||||
|  | ||||
| 	router.get('/manage/tags', middlewares, controllers.admin.tags.get); | ||||
| 	router.get('/manage/flags', middlewares, controllers.admin.flags.get); | ||||
|   | ||||
							
								
								
									
										53
									
								
								src/views/admin/manage/category-analytics.tpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/views/admin/manage/category-analytics.tpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| <a class="btn btn-primary" href="{config.relative_path}/admin/manage/categories"><i class="fa fa-fw fa-chevron-left"></i> Back to Categories List</a> | ||||
|  | ||||
| <h3>Analytics for "{name}" category</h3> | ||||
| <hr /> | ||||
|  | ||||
| <div class="row"> | ||||
| 	<div class="col-sm-6 text-center"> | ||||
| 		<div class="panel panel-default"> | ||||
| 			<div class="panel-body"> | ||||
| 				<div><canvas id="pageviews:hourly" height="250"></canvas></div> | ||||
| 				<p> | ||||
| 					 | ||||
| 				</p> | ||||
| 			</div> | ||||
| 			<div class="panel-footer"><small><strong>Figure 1</strong> – Hourly page views for this category</small></div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<div class="col-sm-6 text-center"> | ||||
| 		<div class="panel panel-default"> | ||||
| 			<div class="panel-body"> | ||||
| 				<div><canvas id="pageviews:daily" height="250"></canvas></div> | ||||
| 				<p> | ||||
| 					 | ||||
| 				</p> | ||||
| 			</div> | ||||
| 			<div class="panel-footer"><small><strong>Figure 2</strong> – Daily page views for this category</small></div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| <div class="row"> | ||||
| 	<div class="col-sm-6 text-center"> | ||||
| 		<div class="panel panel-default"> | ||||
| 			<div class="panel-body"> | ||||
| 				<div><canvas id="topics:daily" height="250"></canvas></div> | ||||
| 				<p> | ||||
| 					 | ||||
| 				</p> | ||||
| 			</div> | ||||
| 			<div class="panel-footer"><small><strong>Figure 3</strong> – Daily topics created in this category</small></div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<div class="col-sm-6 text-center"> | ||||
| 		<div class="panel panel-default"> | ||||
| 			<div class="panel-body"> | ||||
| 				<div><canvas id="posts:daily" height="250"></canvas></div> | ||||
| 				<p> | ||||
| 					 | ||||
| 				</p> | ||||
| 			</div> | ||||
| 			<div class="panel-footer"><small><strong>Figure 4</strong> – Daily posts made in this category</small></div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| @@ -3,7 +3,6 @@ | ||||
| 		<ul class="nav nav-pills"> | ||||
| 			<li class="active"><a href="#category-settings" data-toggle="tab">Category Settings</a></li> | ||||
| 			<li><a href="#privileges" data-toggle="tab">Privileges</a></li> | ||||
| 			<li><a href="#analytics" data-toggle="tab">Analytics</a></li> | ||||
| 		</ul> | ||||
| 		<br /> | ||||
| 		<div class="tab-content"> | ||||
| @@ -128,37 +127,6 @@ | ||||
| 					<!-- IMPORT admin/partials/categories/privileges.tpl --> | ||||
| 				</div> | ||||
| 			</div> | ||||
|  | ||||
| 			<div class="tab-pane fade col-xs-12" id="analytics"> | ||||
| 				<div class="row"> | ||||
| 					<div class="col-sm-6 text-center"> | ||||
| 						<div><canvas id="pageviews:hourly" height="250"></canvas></div> | ||||
| 						<p> | ||||
| 							<small><strong>Figure 1</strong> – Hourly page views for this category</small> | ||||
| 						</p> | ||||
| 					</div> | ||||
| 					<div class="col-sm-6 text-center"> | ||||
| 						<div><canvas id="pageviews:daily" height="250"></canvas></div> | ||||
| 						<p> | ||||
| 							<small><strong>Figure 2</strong> – Daily page views for this category</small> | ||||
| 						</p> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<div class="row"> | ||||
| 					<div class="col-sm-6 text-center"> | ||||
| 						<div><canvas id="topics:daily" height="250"></canvas></div> | ||||
| 						<p> | ||||
| 							<small><strong>Figure 3</strong> – Daily topics created in this category</small> | ||||
| 						</p> | ||||
| 					</div> | ||||
| 					<div class="col-sm-6 text-center"> | ||||
| 						<div><canvas id="posts:daily" height="250"></canvas></div> | ||||
| 						<p> | ||||
| 							<small><strong>Figure 4</strong> – Daily posts made in this category</small> | ||||
| 						</p> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</form> | ||||
| </div> | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
|                         <button data-cid="{categories.cid}" data-action="toggle" data-disabled="{categories.disabled}" class="btn <!-- IF categories.disabled -->btn-primary<!-- ELSE -->btn-danger<!-- ENDIF categories.disabled -->"> | ||||
|                             <!-- IF categories.disabled -->Enable<!-- ELSE -->Disable<!-- ENDIF categories.disabled --> | ||||
|                         </button> | ||||
|                         <a href="./categories/{categories.cid}/analytics" class="btn btn-default"><i class="fa fa-line-chart"></i></a> | ||||
|                         <a href="./categories/{categories.cid}" class="btn btn-default">Edit</a> | ||||
|                     </div> | ||||
|                 </div> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user