summaryrefslogtreecommitdiffstats
path: root/web/react/components/admin_console
diff options
context:
space:
mode:
authorCorey Hulen <corey@hulen.com>2016-03-02 12:22:11 -0800
committerCorey Hulen <corey@hulen.com>2016-03-02 12:22:11 -0800
commitc52153bf601cee5bc21e9e79efcd1fdd5ef1dac7 (patch)
tree822f5614a031f8d65c3ddca7e3e3dfec1152e053 /web/react/components/admin_console
parentcddc9df7c4371e4240d65c6874155e1ce85adff0 (diff)
parentfbb71cab4b4c0289c1f071f9fa2e61b0b0237ece (diff)
downloadchat-c52153bf601cee5bc21e9e79efcd1fdd5ef1dac7.tar.gz
chat-c52153bf601cee5bc21e9e79efcd1fdd5ef1dac7.tar.bz2
chat-c52153bf601cee5bc21e9e79efcd1fdd5ef1dac7.zip
Merge pull request #2258 from mattermost/plt-1796
PLT-1796 Refactor and modularize analytics on the client
Diffstat (limited to 'web/react/components/admin_console')
-rw-r--r--web/react/components/admin_console/admin_controller.jsx4
-rw-r--r--web/react/components/admin_console/analytics.jsx489
-rw-r--r--web/react/components/admin_console/doughnut_chart.jsx77
-rw-r--r--web/react/components/admin_console/line_chart.jsx50
-rw-r--r--web/react/components/admin_console/statistic_count.jsx33
-rw-r--r--web/react/components/admin_console/system_analytics.jsx216
-rw-r--r--web/react/components/admin_console/team_analytics.jsx253
7 files changed, 2 insertions, 1120 deletions
diff --git a/web/react/components/admin_console/admin_controller.jsx b/web/react/components/admin_console/admin_controller.jsx
index de0b085bc..32ed70a99 100644
--- a/web/react/components/admin_console/admin_controller.jsx
+++ b/web/react/components/admin_console/admin_controller.jsx
@@ -21,10 +21,10 @@ import TeamSettingsTab from './team_settings.jsx';
import ServiceSettingsTab from './service_settings.jsx';
import LegalAndSupportSettingsTab from './legal_and_support_settings.jsx';
import TeamUsersTab from './team_users.jsx';
-import TeamAnalyticsTab from './team_analytics.jsx';
+import TeamAnalyticsTab from '../analytics/team_analytics.jsx';
import LdapSettingsTab from './ldap_settings.jsx';
import LicenseSettingsTab from './license_settings.jsx';
-import SystemAnalyticsTab from './system_analytics.jsx';
+import SystemAnalyticsTab from '../analytics/system_analytics.jsx';
export default class AdminController extends React.Component {
constructor(props) {
diff --git a/web/react/components/admin_console/analytics.jsx b/web/react/components/admin_console/analytics.jsx
deleted file mode 100644
index ec9ad4da0..000000000
--- a/web/react/components/admin_console/analytics.jsx
+++ /dev/null
@@ -1,489 +0,0 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import Constants from '../../utils/constants.jsx';
-import LineChart from './line_chart.jsx';
-import DoughnutChart from './doughnut_chart.jsx';
-import StatisticCount from './statistic_count.jsx';
-
-var Tooltip = ReactBootstrap.Tooltip;
-var OverlayTrigger = ReactBootstrap.OverlayTrigger;
-
-import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedDate} from 'mm-intl';
-
-const holders = defineMessages({
- analyticsTotalUsers: {
- id: 'admin.analytics.totalUsers',
- defaultMessage: 'Total Users'
- },
- analyticsPublicChannels: {
- id: 'admin.analytics.publicChannels',
- defaultMessage: 'Public Channels'
- },
- analyticsPrivateGroups: {
- id: 'admin.analytics.privateGroups',
- defaultMessage: 'Private Groups'
- },
- analyticsTotalPosts: {
- id: 'admin.analytics.totalPosts',
- defaultMessage: 'Total Posts'
- },
- analyticsFilePosts: {
- id: 'admin.analytics.totalFilePosts',
- defaultMessage: 'Posts with Files'
- },
- analyticsHashtagPosts: {
- id: 'admin.analytics.totalHashtagPosts',
- defaultMessage: 'Posts with Hashtags'
- },
- analyticsIncomingHooks: {
- id: 'admin.analytics.totalIncomingWebhooks',
- defaultMessage: 'Incoming Webhooks'
- },
- analyticsOutgoingHooks: {
- id: 'admin.analytics.totalOutgoingWebhooks',
- defaultMessage: 'Outgoing Webhooks'
- },
- analyticsChannelTypes: {
- id: 'admin.analytics.channelTypes',
- defaultMessage: 'Channel Types'
- },
- analyticsTextPosts: {
- id: 'admin.analytics.textPosts',
- defaultMessage: 'Posts with Text-only'
- },
- analyticsPostTypes: {
- id: 'admin.analytics.postTypes',
- defaultMessage: 'Posts, Files and Hashtags'
- }
-});
-
-export default class Analytics extends React.Component {
- constructor(props) {
- super(props);
-
- this.state = {};
- }
-
- render() { // in the future, break down these into smaller components
- const {formatMessage} = this.props.intl;
-
- var serverError = '';
- if (this.props.serverError) {
- serverError = <div className='form-group has-error'><label className='control-label'>{this.props.serverError}</label></div>;
- }
-
- let loading = (
- <h5>
- <FormattedMessage
- id='admin.analytics.loading'
- defaultMessage='Loading...'
- />
- </h5>
- );
-
- let firstRow;
- let extraGraphs;
- if (this.props.showAdvanced) {
- firstRow = (
- <div className='row'>
- <StatisticCount
- title={formatMessage(holders.analyticsTotalUsers)}
- icon='fa-users'
- count={this.props.uniqueUserCount}
- />
- <StatisticCount
- title={formatMessage(holders.analyticsTotalPosts)}
- icon='fa-comment'
- count={this.props.postCount}
- />
- <StatisticCount
- title={formatMessage(holders.analyticsIncomingHooks)}
- icon='fa-arrow-down'
- count={this.props.incomingWebhookCount}
- />
- <StatisticCount
- title={formatMessage(holders.analyticsOutgoingHooks)}
- icon='fa-arrow-up'
- count={this.props.outgoingWebhookCount}
- />
- </div>
- );
-
- const channelTypeData = [
- {
- value: this.props.channelOpenCount,
- color: '#46BFBD',
- highlight: '#5AD3D1',
- label: formatMessage(holders.analyticsPublicChannels)
- },
- {
- value: this.props.channelPrivateCount,
- color: '#FDB45C',
- highlight: '#FFC870',
- label: formatMessage(holders.analyticsPrivateGroups)
- }
- ];
-
- const postTypeData = [
- {
- value: this.props.filePostCount,
- color: '#46BFBD',
- highlight: '#5AD3D1',
- label: formatMessage(holders.analyticsFilePosts)
- },
- {
- value: this.props.filePostCount,
- color: '#F7464A',
- highlight: '#FF5A5E',
- label: formatMessage(holders.analyticsHashtagPosts)
- },
- {
- value: this.props.postCount - this.props.filePostCount - this.props.hashtagPostCount,
- color: '#FDB45C',
- highlight: '#FFC870',
- label: formatMessage(holders.analyticsTextPosts)
- }
- ];
-
- extraGraphs = (
- <div className='row'>
- <DoughnutChart
- title={formatMessage(holders.analyticsChannelTypes)}
- data={channelTypeData}
- width='300'
- height='225'
- />
- <DoughnutChart
- title={formatMessage(holders.analyticsPostTypes)}
- data={postTypeData}
- width='300'
- height='225'
- />
- </div>
- );
- } else {
- firstRow = (
- <div className='row'>
- <StatisticCount
- title={formatMessage(holders.analyticsTotalUsers)}
- icon='fa-users'
- count={this.props.uniqueUserCount}
- />
- <StatisticCount
- title={formatMessage(holders.analyticsPublicChannels)}
- icon='fa-globe'
- count={this.props.channelOpenCount}
- />
- <StatisticCount
- title={formatMessage(holders.analyticsPrivateGroups)}
- icon='fa-lock'
- count={this.props.channelPrivateCount}
- />
- <StatisticCount
- title={formatMessage(holders.analyticsTotalPosts)}
- icon='fa-comment'
- count={this.props.postCount}
- />
- </div>
- );
- }
-
- let postCountsByDay;
- if (this.props.postCountsDay == null) {
- postCountsByDay = (
- <div className='col-sm-12'>
- <div className='total-count by-day'>
- <div className='title'>
- <FormattedMessage
- id='admin.analytics.totalPosts'
- defaultMessage='Total Posts'
- />
- </div>
- <div className='content'>{loading}</div>
- </div>
- </div>
- );
- } else {
- let content;
- if (this.props.postCountsDay.labels.length === 0) {
- content = (
- <h5>
- <FormattedMessage
- id='admin.analytics.meaningful'
- defaultMessage='Not enough data for a meaningful representation.'
- />
- </h5>
- );
- } 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'>
- <FormattedMessage
- id='admin.analytics.totalPosts'
- defaultMessage='Total Posts'
- />
- </div>
- <div className='content'>
- {content}
- </div>
- </div>
- </div>
- );
- }
-
- let usersWithPostsByDay;
- if (this.props.userCountsWithPostsDay == null) {
- usersWithPostsByDay = (
- <div className='col-sm-12'>
- <div className='total-count by-day'>
- <div className='title'>
- <FormattedMessage
- id='admin.analytics.activeUsers'
- defaultMessage='Active Users With Posts'
- />
- </div>
- <div className='content'>{loading}</div>
- </div>
- </div>
- );
- } else {
- let content;
- if (this.props.userCountsWithPostsDay.labels.length === 0) {
- content = (
- <h5>
- <FormattedMessage
- id='admin.analytics.meaningful'
- defaultMessage='Not enough data for a meaningful representation.'
- />
- </h5>
- );
- } 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'>
- <FormattedMessage
- id='admin.analytics.activeUsers'
- defaultMessage='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>
- <FormattedDate
- value={user.last_activity_at}
- day='numeric'
- month='long'
- year='numeric'
- hour12={true}
- hour='2-digit'
- minute='2-digit'
- />
- </td>
- </tr>
- );
- })
- }
- </tbody>
- </table>
- );
- }
- recentActiveUser = (
- <div className='col-sm-6'>
- <div className='total-count recent-active-users'>
- <div className='title'>
- <FormattedMessage
- id='admin.analytics.recentActive'
- defaultMessage='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>
- <FormattedDate
- value={user.create_at}
- day='numeric'
- month='long'
- year='numeric'
- hour12={true}
- hour='2-digit'
- minute='2-digit'
- />
- </td>
- </tr>
- );
- })
- }
- </tbody>
- </table>
- );
- }
- newUsers = (
- <div className='col-sm-6'>
- <div className='total-count recent-active-users'>
- <div className='title'>
- <FormattedMessage
- id='admin.analytics.newlyCreated'
- defaultMessage='Newly Created Users'
- />
- </div>
- <div className='content'>
- {content}
- </div>
- </div>
- </div>
- );
- }
-
- return (
- <div className='wrapper--fixed team_statistics'>
- <h3>
- <FormattedMessage
- id='admin.analytics.title'
- defaultMessage='Statistics for {title}'
- values={{
- title: this.props.title
- }}
- />
- </h3>
- {serverError}
- {firstRow}
- {extraGraphs}
- <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 = {
- intl: intlShape.isRequired,
- title: React.PropTypes.string,
- channelOpenCount: React.PropTypes.number,
- channelPrivateCount: React.PropTypes.number,
- postCount: React.PropTypes.number,
- showAdvanced: React.PropTypes.bool,
- filePostCount: React.PropTypes.number,
- hashtagPostCount: React.PropTypes.number,
- incomingWebhookCount: React.PropTypes.number,
- outgoingWebhookCount: 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
-};
-
-export default injectIntl(Analytics);
diff --git a/web/react/components/admin_console/doughnut_chart.jsx b/web/react/components/admin_console/doughnut_chart.jsx
deleted file mode 100644
index e2dc01528..000000000
--- a/web/react/components/admin_console/doughnut_chart.jsx
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import {FormattedMessage} from 'mm-intl';
-
-export default class DoughnutChart 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.refs.canvas);
- var ctx = el.getContext('2d');
- this.chart = new Chart(ctx).Doughnut(props.data, props.options || {}); //eslint-disable-line new-cap
- }
-
- render() {
- let content;
- if (this.props.data == null) {
- content = (
- <FormattedMessage
- id='admin.analytics.loading'
- defaultMessage='Loading...'
- />
- );
- } else {
- content = (
- <canvas
- ref='canvas'
- width={this.props.width}
- height={this.props.height}
- />
- );
- }
-
- return (
- <div className='col-sm-6'>
- <div className='total-count'>
- <div className='title'>
- {this.props.title}
- </div>
- <div className='content'>
- {content}
- </div>
- </div>
- </div>
- );
- }
-}
-
-DoughnutChart.propTypes = {
- title: React.PropTypes.string,
- width: React.PropTypes.string,
- height: React.PropTypes.string,
- data: React.PropTypes.array,
- options: React.PropTypes.object
-};
diff --git a/web/react/components/admin_console/line_chart.jsx b/web/react/components/admin_console/line_chart.jsx
deleted file mode 100644
index 7e2f95c84..000000000
--- a/web/react/components/admin_console/line_chart.jsx
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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/statistic_count.jsx b/web/react/components/admin_console/statistic_count.jsx
deleted file mode 100644
index 118a0ad31..000000000
--- a/web/react/components/admin_console/statistic_count.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import {FormattedMessage} from 'mm-intl';
-
-export default class StatisticCount extends React.Component {
- render() {
- let loading = (
- <FormattedMessage
- id='admin.analytics.loading'
- defaultMessage='Loading...'
- />
- );
-
- return (
- <div className='col-sm-3'>
- <div className='total-count'>
- <div className='title'>
- {this.props.title}
- <i className={'fa ' + this.props.icon}/>
- </div>
- <div className='content'>{this.props.count == null ? loading : this.props.count}</div>
- </div>
- </div>
- );
- }
-}
-
-StatisticCount.propTypes = {
- title: React.PropTypes.string.isRequired,
- icon: React.PropTypes.string.isRequired,
- count: React.PropTypes.number
-};
diff --git a/web/react/components/admin_console/system_analytics.jsx b/web/react/components/admin_console/system_analytics.jsx
deleted file mode 100644
index f983db177..000000000
--- a/web/react/components/admin_console/system_analytics.jsx
+++ /dev/null
@@ -1,216 +0,0 @@
-// 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 {injectIntl, intlShape, defineMessages} from 'mm-intl';
-
-const labels = defineMessages({
- totalPosts: {
- id: 'admin.system_analytics.totalPosts',
- defaultMessage: 'Total Posts'
- },
- activeUsers: {
- id: 'admin.system_analytics.activeUsers',
- defaultMessage: 'Active Users With Posts'
- },
- title: {
- id: 'admin.system_analytics.title',
- defaultMessage: 'the System'
- }
-});
-
-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
- const {formatMessage} = this.props.intl;
- 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: formatMessage(labels.totalPosts),
- 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: formatMessage(labels.activeUsers),
- 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});
- }
- );
-
- if (global.window.mm_license.IsLicensed === 'true') {
- Client.getSystemAnalytics(
- 'extra_counts',
- (data) => {
- for (var index in data) {
- if (data[index].name === 'file_post_count') {
- this.setState({file_post_count: data[index].value});
- }
-
- if (data[index].name === 'hashtag_post_count') {
- this.setState({hashtag_post_count: data[index].value});
- }
-
- if (data[index].name === 'incoming_webhook_count') {
- this.setState({incoming_webhook_count: data[index].value});
- }
-
- if (data[index].name === 'outgoing_webhook_count') {
- this.setState({outgoing_webhook_count: data[index].value});
- }
- }
- },
- (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
- intl={this.props.intl}
- title={this.props.intl.formatMessage(labels.title)}
- channelOpenCount={this.state.channel_open_count}
- channelPrivateCount={this.state.channel_private_count}
- postCount={this.state.post_count}
- showAdvanced={global.window.mm_license.IsLicensed === 'true'}
- filePostCount={this.state.file_post_count}
- hashtagPostCount={this.state.hashtag_post_count}
- incomingWebhookCount={this.state.incoming_webhook_count}
- outgoingWebhookCount={this.state.outgoing_webhook_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 = {
- intl: intlShape.isRequired,
- team: React.PropTypes.object
-};
-
-export default injectIntl(SystemAnalytics);
diff --git a/web/react/components/admin_console/team_analytics.jsx b/web/react/components/admin_console/team_analytics.jsx
deleted file mode 100644
index 808d8046d..000000000
--- a/web/react/components/admin_console/team_analytics.jsx
+++ /dev/null
@@ -1,253 +0,0 @@
-// 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 {injectIntl, intlShape, defineMessages} from 'mm-intl';
-
-const labels = defineMessages({
- totalPosts: {
- id: 'admin.team_analytics.totalPosts',
- defaultMessage: 'Total Posts'
- },
- activeUsers: {
- id: 'admin.team_analytics.activeUsers',
- defaultMessage: 'Active Users With Posts'
- }
-});
-
-class TeamAnalytics 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(this.props.team.id);
- }
-
- getData(teamId) { // should be moved to an action creator eventually
- const {formatMessage} = this.props.intl;
- Client.getTeamAnalytics(
- 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});
- }
-
- if (data[index].name === 'unique_user_count') {
- this.setState({unique_user_count: data[index].value});
- }
- }
- },
- (err) => {
- this.setState({serverError: err.message});
- }
- );
-
- Client.getTeamAnalytics(
- teamId,
- 'post_counts_day',
- (data) => {
- data.reverse();
-
- var chartData = {
- labels: [],
- datasets: [{
- label: formatMessage(labels.totalPosts),
- 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.getTeamAnalytics(
- teamId,
- 'user_counts_with_posts_day',
- (data) => {
- data.reverse();
-
- var chartData = {
- labels: [],
- datasets: [{
- label: formatMessage(labels.activeUsers),
- 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});
- }
- );
-
- Client.getProfilesForTeam(
- teamId,
- (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 = [];
- for (let i = 0; i < usersList.length; i++) {
- if (usersList[i].last_activity_at == null) {
- continue;
- }
-
- recentActive.push(usersList[i]);
- if (i > 19) {
- break;
- }
- }
-
- this.setState({recent_active_users: recentActive});
-
- usersList.sort((a, b) => {
- if (a.create_at < b.create_at) {
- return 1;
- }
-
- if (a.create_at > b.create_at) {
- return -1;
- }
-
- 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});
- }
- );
- }
-
- componentWillReceiveProps(newProps) {
- this.setState({
- 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
- });
-
- this.getData(newProps.team.id);
- }
-
- render() {
- return (
- <div>
- <Analytics
- intl={this.props.intl}
- 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>
- );
- }
-}
-
-TeamAnalytics.propTypes = {
- intl: intlShape.isRequired,
- team: React.PropTypes.object
-};
-
-export default injectIntl(TeamAnalytics);