From ae5d1898037be4f59bf6517ad76b13cc16f595ce Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Thu, 22 Oct 2015 18:04:06 -0700 Subject: Adding analytics tab --- .../components/admin_console/team_analytics.jsx | 144 +++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 web/react/components/admin_console/team_analytics.jsx (limited to 'web/react/components/admin_console/team_analytics.jsx') diff --git a/web/react/components/admin_console/team_analytics.jsx b/web/react/components/admin_console/team_analytics.jsx new file mode 100644 index 000000000..03123a3f0 --- /dev/null +++ b/web/react/components/admin_console/team_analytics.jsx @@ -0,0 +1,144 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +var Client = require('../../utils/client.jsx'); +var LoadingScreen = require('../loading_screen.jsx'); + +export default class UserList extends React.Component { + constructor(props) { + super(props); + + this.getData = this.getData.bind(this); + + this.state = { + users: null, + serverError: null, + channel_open_count: null, + channel_private_count: null, + post_count: null + }; + } + + componentDidMount() { + this.getData(this.props.team.id); + } + + getData(teamId) { + Client.getAnalytics( + teamId, + 'standard', + (data) => { + for (var index in data) { + if (data[index].name === 'channel_open_count') { + this.setState({channel_open_count: data[index].value}); + } + + if (data[index].name === 'channel_private_count') { + this.setState({channel_private_count: data[index].value}); + } + + if (data[index].name === 'post_count') { + this.setState({post_count: data[index].value}); + } + } + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + + Client.getProfilesForTeam( + teamId, + (users) => { + this.setState({users}); + + // var memberList = []; + // for (var id in users) { + // if (users.hasOwnProperty(id)) { + // memberList.push(users[id]); + // } + // } + + // memberList.sort((a, b) => { + // if (a.username < b.username) { + // return -1; + // } + + // if (a.username > b.username) { + // return 1; + // } + + // return 0; + // }); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + } + + componentWillReceiveProps(newProps) { + this.setState({ + users: null, + serverError: null, + channel_open_count: null, + channel_private_count: null, + post_count: null + }); + + this.getData(newProps.team.id); + } + + componentWillUnmount() { + } + + render() { + var serverError = ''; + if (this.state.serverError) { + serverError =
; + } + + var totalCount = ( +
+
{'Total Users'}
+
{this.state.users == null ? 'Loading...' : Object.keys(this.state.users).length}
+
+ ); + + var openChannelCount = ( +
+
{'Public Groups'}
+
{this.state.channel_open_count == null ? 'Loading...' : this.state.channel_open_count}
+
+ ); + + var openPrivateCount = ( +
+
{'Private Groups'}
+
{this.state.channel_private_count == null ? 'Loading...' : this.state.channel_private_count}
+
+ ); + + var postCount = ( +
+
{'Total Posts'}
+
{this.state.post_count == null ? 'Loading...' : this.state.post_count}
+
+ ); + + return ( +
+

{'Analytics for ' + this.props.team.name}

+ {serverError} + {totalCount} + {postCount} + {openChannelCount} + {openPrivateCount} +
+ ); + } +} + +UserList.propTypes = { + team: React.PropTypes.object +}; -- cgit v1.2.3-1-g7c22 From 009982cd4514c6f0950138b15367df559c8f4dd2 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Thu, 22 Oct 2015 20:48:57 -0700 Subject: Adding post counts by days --- .../components/admin_console/team_analytics.jsx | 40 ++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) (limited to 'web/react/components/admin_console/team_analytics.jsx') diff --git a/web/react/components/admin_console/team_analytics.jsx b/web/react/components/admin_console/team_analytics.jsx index 03123a3f0..9d452f95e 100644 --- a/web/react/components/admin_console/team_analytics.jsx +++ b/web/react/components/admin_console/team_analytics.jsx @@ -2,7 +2,6 @@ // See License.txt for license information. var Client = require('../../utils/client.jsx'); -var LoadingScreen = require('../loading_screen.jsx'); export default class UserList extends React.Component { constructor(props) { @@ -15,7 +14,8 @@ export default class UserList extends React.Component { serverError: null, channel_open_count: null, channel_private_count: null, - post_count: null + post_count: null, + post_counts_day: null }; } @@ -47,6 +47,18 @@ export default class UserList extends React.Component { } ); + Client.getAnalytics( + teamId, + 'post_counts_day', + (data) => { + console.log(data); + this.setState({post_counts_day: data}); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + Client.getProfilesForTeam( teamId, (users) => { @@ -83,7 +95,8 @@ export default class UserList extends React.Component { serverError: null, channel_open_count: null, channel_private_count: null, - post_count: null + post_count: null, + post_counts_day: null }); this.getData(newProps.team.id); @@ -126,6 +139,26 @@ export default class UserList extends React.Component { ); + var postCountsByDay = ( +
+
{'Total Posts'}
+
{'Loading...'}
+
+ ); + + if (this.state.post_counts_day != null) { + postCountsByDay = ( +
+
{'Total Posts By Day'}
+ +
+ ); + } + return (

{'Analytics for ' + this.props.team.name}

@@ -134,6 +167,7 @@ export default class UserList extends React.Component { {postCount} {openChannelCount} {openPrivateCount} + {postCountsByDay}
); } -- cgit v1.2.3-1-g7c22 From 473221dbada7ad7739d6a969d9d3d5c9c276941b Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Fri, 23 Oct 2015 16:56:26 -0700 Subject: PLT-25 adding analytics panel --- .../components/admin_console/team_analytics.jsx | 190 +++++++++++++++++++-- 1 file changed, 178 insertions(+), 12 deletions(-) (limited to 'web/react/components/admin_console/team_analytics.jsx') diff --git a/web/react/components/admin_console/team_analytics.jsx b/web/react/components/admin_console/team_analytics.jsx index 9d452f95e..8a6723806 100644 --- a/web/react/components/admin_console/team_analytics.jsx +++ b/web/react/components/admin_console/team_analytics.jsx @@ -2,8 +2,9 @@ // See License.txt for license information. var Client = require('../../utils/client.jsx'); +var LineChart = require('./line_chart.jsx'); -export default class UserList extends React.Component { +export default class TeamAnalytics extends React.Component { constructor(props) { super(props); @@ -15,7 +16,9 @@ export default class UserList extends React.Component { channel_open_count: null, channel_private_count: null, post_count: null, - post_counts_day: null + post_counts_day: null, + user_counts_with_posts_day: null, + recent_active_users: null }; } @@ -31,14 +34,17 @@ export default class UserList extends React.Component { for (var index in data) { if (data[index].name === 'channel_open_count') { this.setState({channel_open_count: data[index].value}); + this.setState({channel_open_count: 55}); } if (data[index].name === 'channel_private_count') { this.setState({channel_private_count: data[index].value}); + this.setState({channel_private_count: 12}); } if (data[index].name === 'post_count') { this.setState({post_count: data[index].value}); + this.setState({post_count: 5332}); } } }, @@ -51,8 +57,80 @@ export default class UserList extends React.Component { teamId, 'post_counts_day', (data) => { - console.log(data); - this.setState({post_counts_day: data}); + data.push({name: '2015-10-24', value: 73}); + data.push({name: '2015-10-25', value: 84}); + data.push({name: '2015-10-26', value: 61}); + data.push({name: '2015-10-27', value: 97}); + data.push({name: '2015-10-28', value: 73}); + data.push({name: '2015-10-29', value: 84}); + data.push({name: '2015-10-30', value: 61}); + data.push({name: '2015-10-31', value: 97}); + + var chartData = { + labels: [], + datasets: [{ + label: 'Total Posts', + 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: [] + }] + }; + + for (var index in data) { + if (data[index]) { + var row = data[index]; + chartData.labels.push(row.name); + chartData.datasets[0].data.push(row.value); + } + } + + this.setState({post_counts_day: chartData}); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + + Client.getAnalytics( + teamId, + 'user_counts_with_posts_day', + (data) => { + data.push({name: '2015-10-24', value: 22}); + data.push({name: '2015-10-25', value: 31}); + data.push({name: '2015-10-26', value: 25}); + data.push({name: '2015-10-27', value: 12}); + data.push({name: '2015-10-28', value: 22}); + data.push({name: '2015-10-29', value: 31}); + data.push({name: '2015-10-30', value: 25}); + data.push({name: '2015-10-31', value: 12}); + + var chartData = { + labels: [], + datasets: [{ + label: 'Active Users With Posts', + 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: [] + }] + }; + + for (var index in data) { + if (data[index]) { + var row = data[index]; + chartData.labels.push(row.name); + chartData.datasets[0].data.push(row.value); + } + } + + this.setState({user_counts_with_posts_day: chartData}); }, (err) => { this.setState({serverError: err.message}); @@ -64,6 +142,13 @@ export default class UserList extends React.Component { (users) => { this.setState({users}); + var recentActive = []; + recentActive.push({email: 'corey@spinpunch.com', date: '2015-10-23'}); + recentActive.push({email: 'bill@spinpunch.com', date: '2015-10-22'}); + recentActive.push({email: 'bob@spinpunch.com', date: '2015-10-22'}); + recentActive.push({email: 'jones@spinpunch.com', date: '2015-10-21'}); + this.setState({recent_active_users: recentActive}); + // var memberList = []; // for (var id in users) { // if (users.hasOwnProperty(id)) { @@ -96,7 +181,9 @@ export default class UserList extends React.Component { channel_open_count: null, channel_private_count: null, post_count: null, - post_counts_day: null + post_counts_day: null, + user_counts_with_posts_day: null, + recent_active_users: null }); this.getData(newProps.team.id); @@ -114,7 +201,7 @@ export default class UserList extends React.Component { var totalCount = (
{'Total Users'}
-
{this.state.users == null ? 'Loading...' : Object.keys(this.state.users).length}
+
{this.state.users == null ? 'Loading...' : Object.keys(this.state.users).length + 23}
); @@ -140,7 +227,7 @@ export default class UserList extends React.Component { ); var postCountsByDay = ( -
+
{'Total Posts'}
{'Loading...'}
@@ -149,16 +236,92 @@ export default class UserList extends React.Component { if (this.state.post_counts_day != null) { postCountsByDay = (
-
{'Total Posts By Day'}
+
{'Total Posts'}
+ +
+ ); + } + + var usersWithPostsByDay = ( +
+
{'Total Posts'}
+
{'Loading...'}
+
+ ); + + if (this.state.user_counts_with_posts_day != null) { + usersWithPostsByDay = ( +
+
{'Active Users With Posts'}
); } + var recentActiveUser = ( +
+
{'Recent Active Users'}
+
{'Loading...'}
+
+ ); + + if (this.state.recent_active_users != null) { + recentActiveUser = ( +
+
{'Recent Active Users'}
+ + + + + + + + + + + + + +
corey@spinpunch.com2015-12-23
bob@spinpunch.com2015-12-22
jimmy@spinpunch.com2015-12-22
jones@spinpunch.com2015-12-21
steve@spinpunch.com2015-12-20
aspen@spinpunch.com2015-12-19
scott@spinpunch.com2015-12-19
grant@spinpunch.com2015-12-19
sienna@spinpunch.com2015-12-18
jessica@spinpunch.com2015-12-18
davy@spinpunch.com2015-12-16
steve@spinpunch.com2015-12-11
+
+ ); + } + + var newUsers = ( +
+
{'Newly Created Users'}
+
{'Loading...'}
+
+ ); + + if (this.state.recent_active_users != null) { + newUsers = ( +
+
{'Newly Created Users'}
+ + + + + + + + + + + +
bob@spinpunch.com2015-12-11
corey@spinpunch.com2015-12-10
jimmy@spinpunch.com2015-12-8
aspen@spinpunch.com2015-12-5
jones@spinpunch.com2015-12-5
steve@spinpunch.com2015-12-5
+
+ ); + } + return (

{'Analytics for ' + this.props.team.name}

@@ -168,11 +331,14 @@ export default class UserList extends React.Component { {openChannelCount} {openPrivateCount} {postCountsByDay} + {usersWithPostsByDay} + {recentActiveUser} + {newUsers}
); } } -UserList.propTypes = { +TeamAnalytics.propTypes = { team: React.PropTypes.object }; -- cgit v1.2.3-1-g7c22 From fc3141156459c0dcd57fed9c6d9756212340ec91 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Mon, 26 Oct 2015 09:55:24 -0700 Subject: PLT-25 adding stats to admin console --- .../components/admin_console/team_analytics.jsx | 143 +++++++++++---------- 1 file changed, 76 insertions(+), 67 deletions(-) (limited to 'web/react/components/admin_console/team_analytics.jsx') diff --git a/web/react/components/admin_console/team_analytics.jsx b/web/react/components/admin_console/team_analytics.jsx index 8a6723806..dd8812ad0 100644 --- a/web/react/components/admin_console/team_analytics.jsx +++ b/web/react/components/admin_console/team_analytics.jsx @@ -2,6 +2,7 @@ // See License.txt for license information. var Client = require('../../utils/client.jsx'); +var Utils = require('../../utils/utils.jsx'); var LineChart = require('./line_chart.jsx'); export default class TeamAnalytics extends React.Component { @@ -18,7 +19,8 @@ export default class TeamAnalytics extends React.Component { post_count: null, post_counts_day: null, user_counts_with_posts_day: null, - recent_active_users: null + recent_active_users: null, + newly_created_users: null }; } @@ -34,17 +36,14 @@ export default class TeamAnalytics extends React.Component { for (var index in data) { if (data[index].name === 'channel_open_count') { this.setState({channel_open_count: data[index].value}); - this.setState({channel_open_count: 55}); } if (data[index].name === 'channel_private_count') { this.setState({channel_private_count: data[index].value}); - this.setState({channel_private_count: 12}); } if (data[index].name === 'post_count') { this.setState({post_count: data[index].value}); - this.setState({post_count: 5332}); } } }, @@ -57,15 +56,6 @@ export default class TeamAnalytics extends React.Component { teamId, 'post_counts_day', (data) => { - data.push({name: '2015-10-24', value: 73}); - data.push({name: '2015-10-25', value: 84}); - data.push({name: '2015-10-26', value: 61}); - data.push({name: '2015-10-27', value: 97}); - data.push({name: '2015-10-28', value: 73}); - data.push({name: '2015-10-29', value: 84}); - data.push({name: '2015-10-30', value: 61}); - data.push({name: '2015-10-31', value: 97}); - var chartData = { labels: [], datasets: [{ @@ -99,15 +89,6 @@ export default class TeamAnalytics extends React.Component { teamId, 'user_counts_with_posts_day', (data) => { - data.push({name: '2015-10-24', value: 22}); - data.push({name: '2015-10-25', value: 31}); - data.push({name: '2015-10-26', value: 25}); - data.push({name: '2015-10-27', value: 12}); - data.push({name: '2015-10-28', value: 22}); - data.push({name: '2015-10-29', value: 31}); - data.push({name: '2015-10-30', value: 25}); - data.push({name: '2015-10-31', value: 12}); - var chartData = { labels: [], datasets: [{ @@ -142,31 +123,56 @@ export default class TeamAnalytics extends React.Component { (users) => { this.setState({users}); + var usersList = []; + for (var id in users) { + if (users.hasOwnProperty(id)) { + usersList.push(users[id]); + } + } + + usersList.sort((a, b) => { + if (a.last_activity_at < b.last_activity_at) { + return 1; + } + + if (a.last_activity_at > b.last_activity_at) { + return -1; + } + + return 0; + }); + var recentActive = []; - recentActive.push({email: 'corey@spinpunch.com', date: '2015-10-23'}); - recentActive.push({email: 'bill@spinpunch.com', date: '2015-10-22'}); - recentActive.push({email: 'bob@spinpunch.com', date: '2015-10-22'}); - recentActive.push({email: 'jones@spinpunch.com', date: '2015-10-21'}); + for (let i = 0; i < usersList.length; i++) { + recentActive.push(usersList[i]); + if (i > 19) { + break; + } + } + this.setState({recent_active_users: recentActive}); - // var memberList = []; - // for (var id in users) { - // if (users.hasOwnProperty(id)) { - // memberList.push(users[id]); - // } - // } + usersList.sort((a, b) => { + if (a.create_at < b.create_at) { + return 1; + } - // memberList.sort((a, b) => { - // if (a.username < b.username) { - // return -1; - // } + if (a.create_at > b.create_at) { + return -1; + } - // if (a.username > b.username) { - // return 1; - // } + return 0; + }); - // return 0; - // }); + var newlyCreated = []; + for (let i = 0; i < usersList.length; i++) { + newlyCreated.push(usersList[i]); + if (i > 19) { + break; + } + } + + this.setState({newly_created_users: newlyCreated}); }, (err) => { this.setState({serverError: err.message}); @@ -183,7 +189,8 @@ export default class TeamAnalytics extends React.Component { post_count: null, post_counts_day: null, user_counts_with_posts_day: null, - recent_active_users: null + recent_active_users: null, + newly_created_users: null }); this.getData(newProps.team.id); @@ -201,7 +208,7 @@ export default class TeamAnalytics extends React.Component { var totalCount = (
{'Total Users'}
-
{this.state.users == null ? 'Loading...' : Object.keys(this.state.users).length + 23}
+
{this.state.users == null ? 'Loading...' : Object.keys(this.state.users).length}
); @@ -278,18 +285,18 @@ export default class TeamAnalytics extends React.Component {
{'Recent Active Users'}
- - - - - - - - - - - - + + { + this.state.recent_active_users.map((user) => { + return ( + + + + + ); + }) + } +
corey@spinpunch.com2015-12-23
bob@spinpunch.com2015-12-22
jimmy@spinpunch.com2015-12-22
jones@spinpunch.com2015-12-21
steve@spinpunch.com2015-12-20
aspen@spinpunch.com2015-12-19
scott@spinpunch.com2015-12-19
grant@spinpunch.com2015-12-19
sienna@spinpunch.com2015-12-18
jessica@spinpunch.com2015-12-18
davy@spinpunch.com2015-12-16
steve@spinpunch.com2015-12-11
{user.email}{Utils.displayDateTime(user.last_activity_at)}
); @@ -302,21 +309,23 @@ export default class TeamAnalytics extends React.Component {
); - if (this.state.recent_active_users != null) { + if (this.state.newly_created_users != null) { newUsers = (
{'Newly Created Users'}
- - - - - - - - - - + + { + this.state.newly_created_users.map((user) => { + return ( + + + + + ); + }) + } +
bob@spinpunch.com2015-12-11
corey@spinpunch.com2015-12-10
jimmy@spinpunch.com2015-12-8
aspen@spinpunch.com2015-12-5
jones@spinpunch.com2015-12-5
steve@spinpunch.com2015-12-5
{user.email}{Utils.displayDateTime(user.create_at)}
); @@ -324,7 +333,7 @@ export default class TeamAnalytics extends React.Component { return (
-

{'Analytics for ' + this.props.team.name}

+

{'Statistics for ' + this.props.team.name}

{serverError} {totalCount} {postCount} -- cgit v1.2.3-1-g7c22