summaryrefslogtreecommitdiffstats
path: root/web/react/components/admin_console
diff options
context:
space:
mode:
authorCorey Hulen <corey@hulen.com>2016-01-22 17:00:09 -0600
committerCorey Hulen <corey@hulen.com>2016-01-22 17:00:09 -0600
commit1a0b12313bd0af1724df2fc6260ef284acfc5f93 (patch)
treeaf8cd83e5beba2426251532e42ba059c59af59b9 /web/react/components/admin_console
parentd352c5b64dddfb8e46b18edbd7352c41495078a1 (diff)
parent60a73ebabba6798d2b45fa8c8ac0f2bfa6144689 (diff)
downloadchat-1a0b12313bd0af1724df2fc6260ef284acfc5f93.tar.gz
chat-1a0b12313bd0af1724df2fc6260ef284acfc5f93.tar.bz2
chat-1a0b12313bd0af1724df2fc6260ef284acfc5f93.zip
Merge pull request #1956 from mattermost/plt-1779
PLT-1779 Add system-wide statistics page
Diffstat (limited to 'web/react/components/admin_console')
-rw-r--r--web/react/components/admin_console/admin_controller.jsx7
-rw-r--r--web/react/components/admin_console/admin_sidebar.jsx19
-rw-r--r--web/react/components/admin_console/analytics.jsx279
-rw-r--r--web/react/components/admin_console/system_analytics.jsx161
-rw-r--r--web/react/components/admin_console/team_analytics.jsx260
5 files changed, 497 insertions, 229 deletions
diff --git a/web/react/components/admin_console/admin_controller.jsx b/web/react/components/admin_console/admin_controller.jsx
index 0f85c238d..efd163017 100644
--- a/web/react/components/admin_console/admin_controller.jsx
+++ b/web/react/components/admin_console/admin_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AdminSidebar from './admin_sidebar.jsx';
@@ -23,6 +23,7 @@ import TeamUsersTab from './team_users.jsx';
import TeamAnalyticsTab from './team_analytics.jsx';
import LdapSettingsTab from './ldap_settings.jsx';
import LicenseSettingsTab from './license_settings.jsx';
+import SystemAnalyticsTab from './system_analytics.jsx';
export default class AdminController extends React.Component {
constructor(props) {
@@ -45,7 +46,7 @@ export default class AdminController extends React.Component {
config: AdminStore.getConfig(),
teams: AdminStore.getAllTeams(),
selectedTeams,
- selected: props.tab || 'service_settings',
+ selected: props.tab || 'system_analytics',
selectedTeam: props.teamId || null
};
@@ -165,6 +166,8 @@ export default class AdminController extends React.Component {
if (this.state.teams) {
tab = <TeamAnalyticsTab team={this.state.teams[this.state.selectedTeam]} />;
}
+ } else if (this.state.selected === 'system_analytics') {
+ tab = <SystemAnalyticsTab />;
}
}
diff --git a/web/react/components/admin_console/admin_sidebar.jsx b/web/react/components/admin_console/admin_sidebar.jsx
index 5a5eaa055..66f82c55b 100644
--- a/web/react/components/admin_console/admin_sidebar.jsx
+++ b/web/react/components/admin_console/admin_sidebar.jsx
@@ -196,6 +196,25 @@ export default class AdminSidebar extends React.Component {
<li>
<h4>
<span className='icon fa fa-gear'></span>
+ <span>{'SITE REPORTS'}</span>
+ </h4>
+ </li>
+ </ul>
+ <ul className='nav nav__sub-menu padded'>
+ <li>
+ <a
+ href='#'
+ className={this.isSelected('system_analytics')}
+ onClick={this.handleClick.bind(this, 'system_analytics', null)}
+ >
+ {'View Statistics'}
+ </a>
+ </li>
+ </ul>
+ <ul className='nav nav__sub-menu'>
+ <li>
+ <h4>
+ <span className='icon fa fa-gear'></span>
<span>{'SETTINGS'}</span>
</h4>
</li>
diff --git a/web/react/components/admin_console/analytics.jsx b/web/react/components/admin_console/analytics.jsx
new file mode 100644
index 000000000..70ef1ecab
--- /dev/null
+++ b/web/react/components/admin_console/analytics.jsx
@@ -0,0 +1,279 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import * as Utils from '../../utils/utils.jsx';
+import Constants from '../../utils/constants.jsx';
+import LineChart from './line_chart.jsx';
+
+var Tooltip = ReactBootstrap.Tooltip;
+var OverlayTrigger = ReactBootstrap.OverlayTrigger;
+
+export default class Analytics extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {};
+ }
+
+ render() { // in the future, break down these into smaller components
+ var serverError = '';
+ if (this.props.serverError) {
+ serverError = <div className='form-group has-error'><label className='control-label'>{this.props.serverError}</label></div>;
+ }
+
+ var totalCount = (
+ <div className='col-sm-3'>
+ <div className='total-count'>
+ <div className='title'>{'Total Users'}<i className='fa fa-users'/></div>
+ <div className='content'>{this.props.uniqueUserCount == null ? 'Loading...' : this.props.uniqueUserCount}</div>
+ </div>
+ </div>
+ );
+
+ var openChannelCount = (
+ <div className='col-sm-3'>
+ <div className='total-count'>
+ <div className='title'>{'Public Channels'}<i className='fa fa-globe'/></div>
+ <div className='content'>{this.props.channelOpenCount == null ? 'Loading...' : this.props.channelOpenCount}</div>
+ </div>
+ </div>
+ );
+
+ var openPrivateCount = (
+ <div className='col-sm-3'>
+ <div className='total-count'>
+ <div className='title'>{'Private Groups'}<i className='fa fa-lock'/></div>
+ <div className='content'>{this.props.channelPrivateCount == null ? 'Loading...' : this.props.channelPrivateCount}</div>
+ </div>
+ </div>
+ );
+
+ var postCount = (
+ <div className='col-sm-3'>
+ <div className='total-count'>
+ <div className='title'>{'Total Posts'}<i className='fa fa-comment'/></div>
+ <div className='content'>{this.props.postCount == null ? 'Loading...' : this.props.postCount}</div>
+ </div>
+ </div>
+ );
+
+ var postCountsByDay = (
+ <div className='col-sm-12'>
+ <div className='total-count by-day'>
+ <div className='title'>{'Total Posts'}</div>
+ <div className='content'>{'Loading...'}</div>
+ </div>
+ </div>
+ );
+
+ if (this.props.postCountsDay != null) {
+ let content;
+ if (this.props.postCountsDay.labels.length === 0) {
+ content = 'Not enough data for a meaningful representation.';
+ } else {
+ content = (
+ <LineChart
+ data={this.props.postCountsDay}
+ width='740'
+ height='225'
+ />
+ );
+ }
+ postCountsByDay = (
+ <div className='col-sm-12'>
+ <div className='total-count by-day'>
+ <div className='title'>{'Total Posts'}</div>
+ <div className='content'>
+ {content}
+ </div>
+ </div>
+ </div>
+ );
+ }
+
+ var usersWithPostsByDay = (
+ <div className='col-sm-12'>
+ <div className='total-count by-day'>
+ <div className='title'>{'Active Users With Posts'}</div>
+ <div className='content'>{'Loading...'}</div>
+ </div>
+ </div>
+ );
+
+ if (this.props.userCountsWithPostsDay != null) {
+ let content;
+ if (this.props.userCountsWithPostsDay.labels.length === 0) {
+ content = 'Not enough data for a meaningful representation.';
+ } else {
+ content = (
+ <LineChart
+ data={this.props.userCountsWithPostsDay}
+ width='740'
+ height='225'
+ />
+ );
+ }
+ usersWithPostsByDay = (
+ <div className='col-sm-12'>
+ <div className='total-count by-day'>
+ <div className='title'>{'Active Users With Posts'}</div>
+ <div className='content'>
+ {content}
+ </div>
+ </div>
+ </div>
+ );
+ }
+
+ let recentActiveUser;
+ if (this.props.recentActiveUsers != null) {
+ let content;
+ if (this.props.recentActiveUsers.length === 0) {
+ content = 'Loading...';
+ } else {
+ content = (
+ <table>
+ <tbody>
+ {
+ this.props.recentActiveUsers.map((user) => {
+ const tooltip = (
+ <Tooltip id={'recent-user-email-tooltip-' + user.id}>
+ {user.email}
+ </Tooltip>
+ );
+
+ return (
+ <tr key={'recent-user-table-entry-' + user.id}>
+ <td>
+ <OverlayTrigger
+ delayShow={Constants.OVERLAY_TIME_DELAY}
+ placement='top'
+ overlay={tooltip}
+ >
+ <time>
+ {user.username}
+ </time>
+ </OverlayTrigger>
+ </td>
+ <td>{Utils.displayDateTime(user.last_activity_at)}</td>
+ </tr>
+ );
+ })
+ }
+ </tbody>
+ </table>
+ );
+ }
+ recentActiveUser = (
+ <div className='col-sm-6'>
+ <div className='total-count recent-active-users'>
+ <div className='title'>{'Recent Active Users'}</div>
+ <div className='content'>
+ {content}
+ </div>
+ </div>
+ </div>
+ );
+ }
+
+ let newUsers;
+ if (this.props.newlyCreatedUsers != null) {
+ let content;
+ if (this.props.newlyCreatedUsers.length === 0) {
+ content = 'Loading...';
+ } else {
+ content = (
+ <table>
+ <tbody>
+ {
+ this.props.newlyCreatedUsers.map((user) => {
+ const tooltip = (
+ <Tooltip id={'new-user-email-tooltip-' + user.id}>
+ {user.email}
+ </Tooltip>
+ );
+
+ return (
+ <tr key={'new-user-table-entry-' + user.id}>
+ <td>
+ <OverlayTrigger
+ delayShow={Constants.OVERLAY_TIME_DELAY}
+ placement='top'
+ overlay={tooltip}
+ >
+ <time>
+ {user.username}
+ </time>
+ </OverlayTrigger>
+ </td>
+ <td>{Utils.displayDateTime(user.create_at)}</td>
+ </tr>
+ );
+ })
+ }
+ </tbody>
+ </table>
+ );
+ }
+ newUsers = (
+ <div className='col-sm-6'>
+ <div className='total-count recent-active-users'>
+ <div className='title'>{'Newly Created Users'}</div>
+ <div className='content'>
+ {content}
+ </div>
+ </div>
+ </div>
+ );
+ }
+
+ return (
+ <div className='wrapper--fixed team_statistics'>
+ <h3>{'Statistics for ' + this.props.title}</h3>
+ {serverError}
+ <div className='row'>
+ {totalCount}
+ {postCount}
+ {openChannelCount}
+ {openPrivateCount}
+ </div>
+ <div className='row'>
+ {postCountsByDay}
+ </div>
+ <div className='row'>
+ {usersWithPostsByDay}
+ </div>
+ <div className='row'>
+ {recentActiveUser}
+ {newUsers}
+ </div>
+ </div>
+ );
+ }
+}
+
+Analytics.defaultProps = {
+ title: null,
+ channelOpenCount: null,
+ channelPrivateCount: null,
+ postCount: null,
+ postCountsDay: null,
+ userCountsWithPostsDay: null,
+ recentActiveUsers: null,
+ newlyCreatedUsers: null,
+ uniqueUserCount: null,
+ serverError: null
+};
+
+Analytics.propTypes = {
+ title: React.PropTypes.string,
+ channelOpenCount: React.PropTypes.number,
+ channelPrivateCount: React.PropTypes.number,
+ postCount: React.PropTypes.number,
+ postCountsDay: React.PropTypes.object,
+ userCountsWithPostsDay: React.PropTypes.object,
+ recentActiveUsers: React.PropTypes.array,
+ newlyCreatedUsers: React.PropTypes.array,
+ uniqueUserCount: React.PropTypes.number,
+ serverError: React.PropTypes.string
+};
diff --git a/web/react/components/admin_console/system_analytics.jsx b/web/react/components/admin_console/system_analytics.jsx
new file mode 100644
index 000000000..f54813a94
--- /dev/null
+++ b/web/react/components/admin_console/system_analytics.jsx
@@ -0,0 +1,161 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import Analytics from './analytics.jsx';
+import * as Client from '../../utils/client.jsx';
+
+export default class SystemAnalytics extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.getData = this.getData.bind(this);
+
+ this.state = { // most of this state should be from a store in the future
+ users: null,
+ serverError: null,
+ channel_open_count: null,
+ channel_private_count: null,
+ post_count: null,
+ post_counts_day: null,
+ user_counts_with_posts_day: null,
+ recent_active_users: null,
+ newly_created_users: null,
+ unique_user_count: null
+ };
+ }
+
+ componentDidMount() {
+ this.getData();
+ }
+
+ getData() { // should be moved to an action creator eventually
+ Client.getSystemAnalytics(
+ '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});
+ }
+
+ if (data[index].name === 'unique_user_count') {
+ this.setState({unique_user_count: data[index].value});
+ }
+ }
+ },
+ (err) => {
+ this.setState({serverError: err.message});
+ }
+ );
+
+ Client.getSystemAnalytics(
+ 'post_counts_day',
+ (data) => {
+ data.reverse();
+
+ 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.getSystemAnalytics(
+ 'user_counts_with_posts_day',
+ (data) => {
+ data.reverse();
+
+ 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});
+ }
+ );
+ }
+
+ componentWillReceiveProps() {
+ this.setState({
+ serverError: null,
+ channel_open_count: null,
+ channel_private_count: null,
+ post_count: null,
+ post_counts_day: null,
+ user_counts_with_posts_day: null,
+ unique_user_count: null
+ });
+
+ this.getData();
+ }
+
+ render() {
+ return (
+ <div>
+ <Analytics
+ title={'the System'}
+ channelOpenCount={this.state.channel_open_count}
+ channelPrivateCount={this.state.channel_private_count}
+ postCount={this.state.post_count}
+ postCountsDay={this.state.post_counts_day}
+ userCountsWithPostsDay={this.state.user_counts_with_posts_day}
+ uniqueUserCount={this.state.unique_user_count}
+ serverError={this.state.serverError}
+ />
+ </div>
+ );
+ }
+}
+
+SystemAnalytics.propTypes = {
+ team: React.PropTypes.object
+};
diff --git a/web/react/components/admin_console/team_analytics.jsx b/web/react/components/admin_console/team_analytics.jsx
index fe7230946..c164dd98c 100644
--- a/web/react/components/admin_console/team_analytics.jsx
+++ b/web/react/components/admin_console/team_analytics.jsx
@@ -1,13 +1,8 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import Analytics from './analytics.jsx';
import * as Client from '../../utils/client.jsx';
-import * as Utils from '../../utils/utils.jsx';
-import Constants from '../../utils/constants.jsx';
-import LineChart from './line_chart.jsx';
-
-var Tooltip = ReactBootstrap.Tooltip;
-var OverlayTrigger = ReactBootstrap.OverlayTrigger;
export default class TeamAnalytics extends React.Component {
constructor(props) {
@@ -15,7 +10,7 @@ export default class TeamAnalytics extends React.Component {
this.getData = this.getData.bind(this);
- this.state = {
+ this.state = { // most of this state should be from a store in the future
users: null,
serverError: null,
channel_open_count: null,
@@ -24,7 +19,8 @@ export default class TeamAnalytics extends React.Component {
post_counts_day: null,
user_counts_with_posts_day: null,
recent_active_users: null,
- newly_created_users: null
+ newly_created_users: null,
+ unique_user_count: null
};
}
@@ -32,8 +28,8 @@ export default class TeamAnalytics extends React.Component {
this.getData(this.props.team.id);
}
- getData(teamId) {
- Client.getAnalytics(
+ getData(teamId) { // should be moved to an action creator eventually
+ Client.getTeamAnalytics(
teamId,
'standard',
(data) => {
@@ -49,6 +45,10 @@ export default class TeamAnalytics extends React.Component {
if (data[index].name === 'post_count') {
this.setState({post_count: data[index].value});
}
+
+ if (data[index].name === 'unique_user_count') {
+ this.setState({unique_user_count: data[index].value});
+ }
}
},
(err) => {
@@ -56,7 +56,7 @@ export default class TeamAnalytics extends React.Component {
}
);
- Client.getAnalytics(
+ Client.getTeamAnalytics(
teamId,
'post_counts_day',
(data) => {
@@ -91,7 +91,7 @@ export default class TeamAnalytics extends React.Component {
}
);
- Client.getAnalytics(
+ Client.getTeamAnalytics(
teamId,
'user_counts_with_posts_day',
(data) => {
@@ -152,6 +152,10 @@ export default class TeamAnalytics extends React.Component {
var recentActive = [];
for (let i = 0; i < usersList.length; i++) {
+ if (usersList[i].last_activity_at == null) {
+ continue;
+ }
+
recentActive.push(usersList[i]);
if (i > 19) {
break;
@@ -198,227 +202,29 @@ export default class TeamAnalytics extends React.Component {
post_counts_day: null,
user_counts_with_posts_day: null,
recent_active_users: null,
- newly_created_users: null
+ newly_created_users: null,
+ unique_user_count: null
});
this.getData(newProps.team.id);
}
- componentWillUnmount() {
- }
-
render() {
- var serverError = '';
- if (this.state.serverError) {
- serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
- }
-
- var totalCount = (
- <div className='col-sm-3'>
- <div className='total-count'>
- <div className='title'>{'Total Users'}<i className='fa fa-users'/></div>
- <div className='content'>{this.state.users == null ? 'Loading...' : Object.keys(this.state.users).length}</div>
- </div>
- </div>
- );
-
- var openChannelCount = (
- <div className='col-sm-3'>
- <div className='total-count'>
- <div className='title'>{'Public Channels'}<i className='fa fa-globe'/></div>
- <div className='content'>{this.state.channel_open_count == null ? 'Loading...' : this.state.channel_open_count}</div>
- </div>
- </div>
- );
-
- var openPrivateCount = (
- <div className='col-sm-3'>
- <div className='total-count'>
- <div className='title'>{'Private Groups'}<i className='fa fa-lock'/></div>
- <div className='content'>{this.state.channel_private_count == null ? 'Loading...' : this.state.channel_private_count}</div>
- </div>
- </div>
- );
-
- var postCount = (
- <div className='col-sm-3'>
- <div className='total-count'>
- <div className='title'>{'Total Posts'}<i className='fa fa-comment'/></div>
- <div className='content'>{this.state.post_count == null ? 'Loading...' : this.state.post_count}</div>
- </div>
- </div>
- );
-
- var postCountsByDay = (
- <div className='col-sm-12'>
- <div className='total-count by-day'>
- <div className='title'>{'Total Posts'}</div>
- <div className='content'>{'Loading...'}</div>
- </div>
- </div>
- );
-
- if (this.state.post_counts_day != null) {
- postCountsByDay = (
- <div className='col-sm-12'>
- <div className='total-count by-day'>
- <div className='title'>{'Total Posts'}</div>
- <div className='content'>
- <LineChart
- data={this.state.post_counts_day}
- width='740'
- height='225'
- />
- </div>
- </div>
- </div>
- );
- }
-
- var usersWithPostsByDay = (
- <div className='col-sm-12'>
- <div className='total-count by-day'>
- <div className='title'>{'Total Posts'}</div>
- <div>{'Loading...'}</div>
- </div>
- </div>
- );
-
- if (this.state.user_counts_with_posts_day != null) {
- usersWithPostsByDay = (
- <div className='col-sm-12'>
- <div className='total-count by-day'>
- <div className='title'>{'Active Users With Posts'}</div>
- <div className='content'>
- <LineChart
- data={this.state.user_counts_with_posts_day}
- width='740'
- height='225'
- />
- </div>
- </div>
- </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='col-sm-6'>
- <div className='total-count recent-active-users'>
- <div className='title'>{'Recent Active Users'}</div>
- <div className='content'>
- <table>
- <tbody>
- {
- this.state.recent_active_users.map((user) => {
- const tooltip = (
- <Tooltip id={'recent-user-email-tooltip-' + user.id}>
- {user.email}
- </Tooltip>
- );
-
- return (
- <tr key={'recent-user-table-entry-' + user.id}>
- <td>
- <OverlayTrigger
- delayShow={Constants.OVERLAY_TIME_DELAY}
- placement='top'
- overlay={tooltip}
- >
- <time>
- {user.username}
- </time>
- </OverlayTrigger>
- </td>
- <td>{Utils.displayDateTime(user.last_activity_at)}</td>
- </tr>
- );
- })
- }
- </tbody>
- </table>
- </div>
- </div>
- </div>
- );
- }
-
- var newUsers = (
- <div className='recent-active-users'>
- <div>{'Newly Created Users'}</div>
- <div>{'Loading...'}</div>
- </div>
- );
-
- if (this.state.newly_created_users != null) {
- newUsers = (
- <div className='col-sm-6'>
- <div className='total-count recent-active-users'>
- <div className='title'>{'Newly Created Users'}</div>
- <div className='content'>
- <table>
- <tbody>
- {
- this.state.newly_created_users.map((user) => {
- const tooltip = (
- <Tooltip id={'new-user-email-tooltip-' + user.id}>
- {user.email}
- </Tooltip>
- );
-
- return (
- <tr key={'new-user-table-entry-' + user.id}>
- <td>
- <OverlayTrigger
- delayShow={Constants.OVERLAY_TIME_DELAY}
- placement='top'
- overlay={tooltip}
- >
- <time>
- {user.username}
- </time>
- </OverlayTrigger>
- </td>
- <td>{Utils.displayDateTime(user.create_at)}</td>
- </tr>
- );
- })
- }
- </tbody>
- </table>
- </div>
- </div>
- </div>
- );
- }
-
return (
- <div className='wrapper--fixed team_statistics'>
- <h3>{'Statistics for ' + this.props.team.name}</h3>
- {serverError}
- <div className='row'>
- {totalCount}
- {postCount}
- {openChannelCount}
- {openPrivateCount}
- </div>
- <div className='row'>
- {postCountsByDay}
- </div>
- <div className='row'>
- {usersWithPostsByDay}
- </div>
- <div className='row'>
- {recentActiveUser}
- {newUsers}
- </div>
+ <div>
+ <Analytics
+ title={this.props.team.name}
+ users={this.state.users}
+ channelOpenCount={this.state.channel_open_count}
+ channelPrivateCount={this.state.channel_private_count}
+ postCount={this.state.post_count}
+ postCountsDay={this.state.post_counts_day}
+ userCountsWithPostsDay={this.state.user_counts_with_posts_day}
+ recentActiveUsers={this.state.recent_active_users}
+ newlyCreatedUsers={this.state.newly_created_users}
+ uniqueUserCount={this.state.unique_user_count}
+ serverError={this.state.serverError}
+ />
</div>
);
}