summaryrefslogtreecommitdiffstats
path: root/web/react/components/admin_console
diff options
context:
space:
mode:
author=Corey Hulen <corey@hulen.com>2016-02-03 10:45:58 -0800
committer=Corey Hulen <corey@hulen.com>2016-02-03 10:45:58 -0800
commitbdfa4715d65ed4b4e903a1eb4c83eba6c95455d1 (patch)
tree1626d089802a92ee208b6e7fa056378e40568a92 /web/react/components/admin_console
parent581785f5044eecdc7cf664e4c7fc59efc6babc96 (diff)
parent9bba6c79882d1f5d14b98052caf59a11fc2388d5 (diff)
downloadchat-bdfa4715d65ed4b4e903a1eb4c83eba6c95455d1.tar.gz
chat-bdfa4715d65ed4b4e903a1eb4c83eba6c95455d1.tar.bz2
chat-bdfa4715d65ed4b4e903a1eb4c83eba6c95455d1.zip
Merge branch 'master' into PLT-1429
Diffstat (limited to 'web/react/components/admin_console')
-rw-r--r--web/react/components/admin_console/admin_controller.jsx3
-rw-r--r--web/react/components/admin_console/admin_sidebar.jsx19
-rw-r--r--web/react/components/admin_console/analytics.jsx274
-rw-r--r--web/react/components/admin_console/audits.jsx94
-rw-r--r--web/react/components/admin_console/doughnut_chart.jsx77
-rw-r--r--web/react/components/admin_console/email_settings.jsx84
-rw-r--r--web/react/components/admin_console/statistic_count.jsx37
-rw-r--r--web/react/components/admin_console/system_analytics.jsx36
-rw-r--r--web/react/components/admin_console/team_analytics.jsx3
9 files changed, 542 insertions, 85 deletions
diff --git a/web/react/components/admin_console/admin_controller.jsx b/web/react/components/admin_console/admin_controller.jsx
index efd163017..360ae3ef3 100644
--- a/web/react/components/admin_console/admin_controller.jsx
+++ b/web/react/components/admin_console/admin_controller.jsx
@@ -11,6 +11,7 @@ import * as Utils from '../../utils/utils.jsx';
import EmailSettingsTab from './email_settings.jsx';
import LogSettingsTab from './log_settings.jsx';
import LogsTab from './logs.jsx';
+import AuditsTab from './audits.jsx';
import FileSettingsTab from './image_settings.jsx';
import PrivacySettingsTab from './privacy_settings.jsx';
import RateSettingsTab from './rate_settings.jsx';
@@ -138,6 +139,8 @@ export default class AdminController extends React.Component {
tab = <LogSettingsTab config={this.state.config} />;
} else if (this.state.selected === 'logs') {
tab = <LogsTab />;
+ } else if (this.state.selected === 'audits') {
+ tab = <AuditsTab />;
} else if (this.state.selected === 'image_settings') {
tab = <FileSettingsTab config={this.state.config} />;
} else if (this.state.selected === 'privacy_settings') {
diff --git a/web/react/components/admin_console/admin_sidebar.jsx b/web/react/components/admin_console/admin_sidebar.jsx
index d6bae1feb..642bfe9d7 100644
--- a/web/react/components/admin_console/admin_sidebar.jsx
+++ b/web/react/components/admin_console/admin_sidebar.jsx
@@ -214,6 +214,24 @@ export default class AdminSidebar extends React.Component {
);
}
+ let audits;
+ if (global.window.mm_license.IsLicensed === 'true') {
+ audits = (
+ <li>
+ <a
+ href='#'
+ className={this.isSelected('audits')}
+ onClick={this.handleClick.bind(this, 'audits', null)}
+ >
+ <FormattedMessage
+ id='admin.sidebar.audits'
+ defaultMessage='Audits'
+ />
+ </a>
+ </li>
+ );
+ }
+
return (
<div className='sidebar--left sidebar--collapsable'>
<div>
@@ -448,6 +466,7 @@ export default class AdminSidebar extends React.Component {
/>
</a>
</li>
+ {audits}
</ul>
</li>
</ul>
diff --git a/web/react/components/admin_console/analytics.jsx b/web/react/components/admin_console/analytics.jsx
index a22c26c34..0a159d2e3 100644
--- a/web/react/components/admin_console/analytics.jsx
+++ b/web/react/components/admin_console/analytics.jsx
@@ -4,11 +4,60 @@
import * as Utils from '../../utils/utils.jsx';
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 {FormattedMessage} from 'mm-intl';
+import {injectIntl, intlShape, defineMessages, FormattedMessage} 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) {
@@ -18,6 +67,8 @@ export default class Analytics extends React.Component {
}
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>;
@@ -30,77 +81,129 @@ export default class Analytics extends React.Component {
/>
);
- var totalCount = (
- <div className='col-sm-3'>
- <div className='total-count'>
- <div className='title'>
- <FormattedMessage
- id='admin.analytics.totalUsers'
- defaultMessage='Total Users'
- />
- <i className='fa fa-users'/></div>
- <div className='content'>{this.props.uniqueUserCount == null ? loading : this.props.uniqueUserCount}</div>
+ 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>
- </div>
- );
+ );
- var openChannelCount = (
- <div className='col-sm-3'>
- <div className='total-count'>
- <div className='title'>
- <FormattedMessage
- id='admin.analytics.publicChannels'
- defaultMessage='Public Channels'
- />
- <i className='fa fa-globe'/></div>
- <div className='content'>{this.props.channelOpenCount == null ? loading : this.props.channelOpenCount}</div>
- </div>
- </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)
+ }
+ ];
- var openPrivateCount = (
- <div className='col-sm-3'>
- <div className='total-count'>
- <div className='title'>
- <FormattedMessage
- id='admin.analytics.privateGroups'
- defaultMessage='Private Groups'
- />
- <i className='fa fa-lock'/></div>
- <div className='content'>{this.props.channelPrivateCount == null ? loading : this.props.channelPrivateCount}</div>
- </div>
- </div>
- );
+ 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)
+ }
+ ];
- var postCount = (
- <div className='col-sm-3'>
- <div className='total-count'>
- <div className='title'>
- <FormattedMessage
- id='admin.analytics.totalPosts'
- defaultMessage='Total Posts'
- />
- <i className='fa fa-comment'/></div>
- <div className='content'>{this.props.postCount == null ? loading : this.props.postCount}</div>
+ 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>
- </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>
+ );
+ }
- var postCountsByDay = (
- <div className='col-sm-12'>
- <div className='total-count by-day'>
- <div className='title'>
- <FormattedMessage
- id='admin.analytics.totalPosts'
- defaultMessage='Total Posts'
- />
+ 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 className='content'>{loading}</div>
</div>
- </div>
- );
-
- if (this.props.postCountsDay != null) {
+ );
+ } else {
let content;
if (this.props.postCountsDay.labels.length === 0) {
content = (
@@ -137,21 +240,22 @@ export default class Analytics extends React.Component {
);
}
- var 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'
- />
+ 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 className='content'>{loading}</div>
</div>
- </div>
- );
-
- if (this.props.userCountsWithPostsDay != null) {
+ );
+ } else {
let content;
if (this.props.userCountsWithPostsDay.labels.length === 0) {
content = (
@@ -312,12 +416,8 @@ export default class Analytics extends React.Component {
/>
</h3>
{serverError}
- <div className='row'>
- {totalCount}
- {postCount}
- {openChannelCount}
- {openPrivateCount}
- </div>
+ {firstRow}
+ {extraGraphs}
<div className='row'>
{postCountsByDay}
</div>
@@ -347,10 +447,16 @@ Analytics.defaultProps = {
};
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,
@@ -358,3 +464,5 @@ Analytics.propTypes = {
uniqueUserCount: React.PropTypes.number,
serverError: React.PropTypes.string
};
+
+export default injectIntl(Analytics);
diff --git a/web/react/components/admin_console/audits.jsx b/web/react/components/admin_console/audits.jsx
new file mode 100644
index 000000000..866539b3d
--- /dev/null
+++ b/web/react/components/admin_console/audits.jsx
@@ -0,0 +1,94 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import LoadingScreen from '../loading_screen.jsx';
+import AuditTable from '../audit_table.jsx';
+
+import AdminStore from '../../stores/admin_store.jsx';
+
+import * as AsyncClient from '../../utils/async_client.jsx';
+
+import {FormattedMessage} from 'mm-intl';
+
+export default class Audits extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.onAuditListenerChange = this.onAuditListenerChange.bind(this);
+ this.reload = this.reload.bind(this);
+
+ this.state = {
+ audits: AdminStore.getAudits()
+ };
+ }
+
+ componentDidMount() {
+ AdminStore.addAuditChangeListener(this.onAuditListenerChange);
+ AsyncClient.getServerAudits();
+ }
+
+ componentWillUnmount() {
+ AdminStore.removeAuditChangeListener(this.onAuditListenerChange);
+ }
+
+ onAuditListenerChange() {
+ this.setState({
+ audits: AdminStore.getAudits()
+ });
+ }
+
+ reload() {
+ AdminStore.saveAudits(null);
+ this.setState({
+ audits: null
+ });
+
+ AsyncClient.getServerAudits();
+ }
+
+ render() {
+ var content = null;
+
+ if (global.window.mm_license.IsLicensed !== 'true') {
+ return <div/>;
+ }
+
+ if (this.state.audits === null) {
+ content = <LoadingScreen />;
+ } else {
+ content = (
+ <div style={{margin: '10px'}}>
+ <AuditTable
+ audits={this.state.audits}
+ oneLine={true}
+ showUserId={true}
+ />
+ </div>
+ );
+ }
+
+ return (
+ <div className='panel'>
+ <h3>
+ <FormattedMessage
+ id='admin.audits.title'
+ defaultMessage='Server Audits'
+ />
+ </h3>
+ <button
+ type='submit'
+ className='btn btn-primary'
+ onClick={this.reload}
+ >
+ <FormattedMessage
+ id='admin.audits.reload'
+ defaultMessage='Reload'
+ />
+ </button>
+ <div className='log__panel'>
+ {content}
+ </div>
+ </div>
+ );
+ }
+}
diff --git a/web/react/components/admin_console/doughnut_chart.jsx b/web/react/components/admin_console/doughnut_chart.jsx
new file mode 100644
index 000000000..e2dc01528
--- /dev/null
+++ b/web/react/components/admin_console/doughnut_chart.jsx
@@ -0,0 +1,77 @@
+// 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/email_settings.jsx b/web/react/components/admin_console/email_settings.jsx
index ce3c8cd12..17f25a04c 100644
--- a/web/react/components/admin_console/email_settings.jsx
+++ b/web/react/components/admin_console/email_settings.jsx
@@ -112,6 +112,8 @@ class EmailSettings extends React.Component {
buildConfig() {
var config = this.props.config;
config.EmailSettings.EnableSignUpWithEmail = ReactDOM.findDOMNode(this.refs.allowSignUpWithEmail).checked;
+ config.EmailSettings.EnableSignInWithEmail = ReactDOM.findDOMNode(this.refs.allowSignInWithEmail).checked;
+ config.EmailSettings.EnableSignInWithUsername = ReactDOM.findDOMNode(this.refs.allowSignInWithUsername).checked;
config.EmailSettings.SendEmailNotifications = ReactDOM.findDOMNode(this.refs.sendEmailNotifications).checked;
config.EmailSettings.SendPushNotifications = ReactDOM.findDOMNode(this.refs.sendPushNotifications).checked;
config.EmailSettings.RequireEmailVerification = ReactDOM.findDOMNode(this.refs.requireEmailVerification).checked;
@@ -320,6 +322,88 @@ class EmailSettings extends React.Component {
<div className='form-group'>
<label
className='control-label col-sm-4'
+ htmlFor='allowSignInWithEmail'
+ >
+ <FormattedMessage
+ id='admin.email.allowEmailSignInTitle'
+ defaultMessage='Allow Sign In With Email: '
+ />
+ </label>
+ <div className='col-sm-8'>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='allowSignInWithEmail'
+ value='true'
+ ref='allowSignInWithEmail'
+ defaultChecked={this.props.config.EmailSettings.EnableSignInWithEmail}
+ onChange={this.handleChange.bind(this, 'allowSignInWithEmail_true')}
+ />
+ {'true'}
+ </label>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='allowSignInWithEmail'
+ value='false'
+ defaultChecked={!this.props.config.EmailSettings.EnableSignInWithEmail}
+ onChange={this.handleChange.bind(this, 'allowSignInWithEmail_false')}
+ />
+ {'false'}
+ </label>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.email.allowEmailSignInDescription'
+ defaultMessage='When true, Mattermost allows users to sign in using their email and password.'
+ />
+ </p>
+ </div>
+ </div>
+
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='allowSignInWithUsername'
+ >
+ <FormattedMessage
+ id='admin.email.allowUsernameSignInTitle'
+ defaultMessage='Allow Sign In With Username: '
+ />
+ </label>
+ <div className='col-sm-8'>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='allowSignInWithUsername'
+ value='true'
+ ref='allowSignInWithUsername'
+ defaultChecked={this.props.config.EmailSettings.EnableSignInWithUsername}
+ onChange={this.handleChange.bind(this, 'allowSignInWithUsername_true')}
+ />
+ {'true'}
+ </label>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='allowSignInWithUsername'
+ value='false'
+ defaultChecked={!this.props.config.EmailSettings.EnableSignInWithUsername}
+ onChange={this.handleChange.bind(this, 'allowSignInWithUsername_false')}
+ />
+ {'false'}
+ </label>
+ <p className='help-text'>
+ <FormattedMessage
+ id='admin.email.allowUsernameSignInDescription'
+ defaultMessage='When true, Mattermost allows users to sign in using their username and password. This setting is typically only used when email verification is disabled.'
+ />
+ </p>
+ </div>
+ </div>
+
+ <div className='form-group'>
+ <label
+ className='control-label col-sm-4'
htmlFor='sendEmailNotifications'
>
<FormattedMessage
diff --git a/web/react/components/admin_console/statistic_count.jsx b/web/react/components/admin_console/statistic_count.jsx
new file mode 100644
index 000000000..57af0ed1b
--- /dev/null
+++ b/web/react/components/admin_console/statistic_count.jsx
@@ -0,0 +1,37 @@
+// 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 {
+ constructor(props) {
+ super(props);
+ }
+
+ 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
index 2dd833fb2..f983db177 100644
--- a/web/react/components/admin_console/system_analytics.jsx
+++ b/web/react/components/admin_console/system_analytics.jsx
@@ -140,6 +140,34 @@ class SystemAnalytics extends React.Component {
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() {
@@ -160,10 +188,16 @@ class SystemAnalytics extends React.Component {
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}
@@ -179,4 +213,4 @@ SystemAnalytics.propTypes = {
team: React.PropTypes.object
};
-export default injectIntl(SystemAnalytics); \ No newline at end of file
+export default injectIntl(SystemAnalytics);
diff --git a/web/react/components/admin_console/team_analytics.jsx b/web/react/components/admin_console/team_analytics.jsx
index ee59b0e66..808d8046d 100644
--- a/web/react/components/admin_console/team_analytics.jsx
+++ b/web/react/components/admin_console/team_analytics.jsx
@@ -227,6 +227,7 @@ class TeamAnalytics extends React.Component {
return (
<div>
<Analytics
+ intl={this.props.intl}
title={this.props.team.name}
users={this.state.users}
channelOpenCount={this.state.channel_open_count}
@@ -249,4 +250,4 @@ TeamAnalytics.propTypes = {
team: React.PropTypes.object
};
-export default injectIntl(TeamAnalytics); \ No newline at end of file
+export default injectIntl(TeamAnalytics);