summaryrefslogtreecommitdiffstats
path: root/web/react
diff options
context:
space:
mode:
author=Corey Hulen <corey@hulen.com>2015-10-23 16:56:26 -0700
committer=Corey Hulen <corey@hulen.com>2015-10-23 16:56:26 -0700
commit473221dbada7ad7739d6a969d9d3d5c9c276941b (patch)
tree91676813df121bc9eeba88be9eeb7d55ca9b2f08 /web/react
parent028657b43ed7d6e2b0adca322e2d47781c1b3eb4 (diff)
downloadchat-473221dbada7ad7739d6a969d9d3d5c9c276941b.tar.gz
chat-473221dbada7ad7739d6a969d9d3d5c9c276941b.tar.bz2
chat-473221dbada7ad7739d6a969d9d3d5c9c276941b.zip
PLT-25 adding analytics panel
Diffstat (limited to 'web/react')
-rw-r--r--web/react/.eslintrc3
-rw-r--r--web/react/components/admin_console/line_chart.jsx50
-rw-r--r--web/react/components/admin_console/team_analytics.jsx190
3 files changed, 230 insertions, 13 deletions
diff --git a/web/react/.eslintrc b/web/react/.eslintrc
index 6a35d3123..d78068882 100644
--- a/web/react/.eslintrc
+++ b/web/react/.eslintrc
@@ -20,7 +20,8 @@
"globals": {
"React": false,
"ReactDOM": false,
- "ReactBootstrap": false
+ "ReactBootstrap": false,
+ "Chart": false
},
"rules": {
"comma-dangle": [2, "never"],
diff --git a/web/react/components/admin_console/line_chart.jsx b/web/react/components/admin_console/line_chart.jsx
new file mode 100644
index 000000000..7e2f95c84
--- /dev/null
+++ b/web/react/components/admin_console/line_chart.jsx
@@ -0,0 +1,50 @@
+// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+export default class LineChart extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.initChart = this.initChart.bind(this);
+ this.chart = null;
+ }
+
+ componentDidMount() {
+ this.initChart(this.props);
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (this.chart) {
+ this.chart.destroy();
+ this.initChart(nextProps);
+ }
+ }
+
+ componentWillUnmount() {
+ if (this.chart) {
+ this.chart.destroy();
+ }
+ }
+
+ initChart(props) {
+ var el = ReactDOM.findDOMNode(this);
+ var ctx = el.getContext('2d');
+ this.chart = new Chart(ctx).Line(props.data, props.options || {}); //eslint-disable-line new-cap
+ }
+
+ render() {
+ return (
+ <canvas
+ width={this.props.width}
+ height={this.props.height}
+ />
+ );
+ }
+}
+
+LineChart.propTypes = {
+ width: React.PropTypes.string,
+ height: React.PropTypes.string,
+ data: React.PropTypes.object,
+ options: React.PropTypes.object
+};
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 = (
<div className='total-count text-center'>
<div>{'Total Users'}</div>
- <div>{this.state.users == null ? 'Loading...' : Object.keys(this.state.users).length}</div>
+ <div>{this.state.users == null ? 'Loading...' : Object.keys(this.state.users).length + 23}</div>
</div>
);
@@ -140,7 +227,7 @@ export default class UserList extends React.Component {
);
var postCountsByDay = (
- <div className='total-count text-center'>
+ <div className='total-count-by-day'>
<div>{'Total Posts'}</div>
<div>{'Loading...'}</div>
</div>
@@ -149,16 +236,92 @@ export default class UserList extends React.Component {
if (this.state.post_counts_day != null) {
postCountsByDay = (
<div className='total-count-by-day'>
- <div>{'Total Posts By Day'}</div>
+ <div>{'Total Posts'}</div>
+ <LineChart
+ data={this.state.post_counts_day}
+ width='740'
+ height='225'
+ />
+ </div>
+ );
+ }
+
+ var usersWithPostsByDay = (
+ <div className='total-count-by-day'>
+ <div>{'Total Posts'}</div>
+ <div>{'Loading...'}</div>
+ </div>
+ );
+
+ if (this.state.user_counts_with_posts_day != null) {
+ usersWithPostsByDay = (
+ <div className='total-count-by-day'>
+ <div>{'Active Users With Posts'}</div>
<LineChart
- data={chartData}
- width="100"
- height="250"
+ data={this.state.user_counts_with_posts_day}
+ width='740'
+ height='225'
/>
</div>
);
}
+ var recentActiveUser = (
+ <div className='recent-active-users'>
+ <div>{'Recent Active Users'}</div>
+ <div>{'Loading...'}</div>
+ </div>
+ );
+
+ if (this.state.recent_active_users != null) {
+ recentActiveUser = (
+ <div className='recent-active-users'>
+ <div>{'Recent Active Users'}</div>
+ <table width='90%'>
+ <tr><td className='recent-active-users-td'>corey@spinpunch.com</td><td className='recent-active-users-td'>2015-12-23</td></tr>
+ <tr><td className='recent-active-users-td'>bob@spinpunch.com</td><td className='recent-active-users-td'>2015-12-22</td></tr>
+ <tr><td className='recent-active-users-td'>jimmy@spinpunch.com</td><td className='recent-active-users-td'>2015-12-22</td></tr>
+ <tr><td className='recent-active-users-td'>jones@spinpunch.com</td><td className='recent-active-users-td'>2015-12-21</td></tr>
+ <tr><td className='recent-active-users-td'>steve@spinpunch.com</td><td className='recent-active-users-td'>2015-12-20</td></tr>
+ <tr><td className='recent-active-users-td'>aspen@spinpunch.com</td><td className='recent-active-users-td'>2015-12-19</td></tr>
+ <tr><td className='recent-active-users-td'>scott@spinpunch.com</td><td className='recent-active-users-td'>2015-12-19</td></tr>
+ <tr><td className='recent-active-users-td'>grant@spinpunch.com</td><td className='recent-active-users-td'>2015-12-19</td></tr>
+ <tr><td className='recent-active-users-td'>sienna@spinpunch.com</td><td className='recent-active-users-td'>2015-12-18</td></tr>
+ <tr><td className='recent-active-users-td'>jessica@spinpunch.com</td><td className='recent-active-users-td'>2015-12-18</td></tr>
+ <tr><td className='recent-active-users-td'>davy@spinpunch.com</td><td className='recent-active-users-td'>2015-12-16</td></tr>
+ <tr><td className='recent-active-users-td'>steve@spinpunch.com</td><td className='recent-active-users-td'>2015-12-11</td></tr>
+ </table>
+ </div>
+ );
+ }
+
+ var newUsers = (
+ <div className='recent-active-users'>
+ <div>{'Newly Created Users'}</div>
+ <div>{'Loading...'}</div>
+ </div>
+ );
+
+ if (this.state.recent_active_users != null) {
+ newUsers = (
+ <div className='recent-active-users'>
+ <div>{'Newly Created Users'}</div>
+ <table width='90%'>
+ <tr><td className='recent-active-users-td'>bob@spinpunch.com</td><td className='recent-active-users-td'>2015-12-11</td></tr>
+ <tr><td className='recent-active-users-td'>corey@spinpunch.com</td><td className='recent-active-users-td'>2015-12-10</td></tr>
+
+ <tr><td className='recent-active-users-td'>jimmy@spinpunch.com</td><td className='recent-active-users-td'>2015-12-8</td></tr>
+
+
+ <tr><td className='recent-active-users-td'>aspen@spinpunch.com</td><td className='recent-active-users-td'>2015-12-5</td></tr>
+
+ <tr><td className='recent-active-users-td'>jones@spinpunch.com</td><td className='recent-active-users-td'>2015-12-5</td></tr>
+ <tr><td className='recent-active-users-td'>steve@spinpunch.com</td><td className='recent-active-users-td'>2015-12-5</td></tr>
+ </table>
+ </div>
+ );
+ }
+
return (
<div className='wrapper--fixed'>
<h2>{'Analytics for ' + this.props.team.name}</h2>
@@ -168,11 +331,14 @@ export default class UserList extends React.Component {
{openChannelCount}
{openPrivateCount}
{postCountsByDay}
+ {usersWithPostsByDay}
+ {recentActiveUser}
+ {newUsers}
</div>
);
}
}
-UserList.propTypes = {
+TeamAnalytics.propTypes = {
team: React.PropTypes.object
};