summaryrefslogtreecommitdiffstats
path: root/web/react/components/analytics
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2016-03-14 08:50:46 -0400
committerChristopher Speller <crspeller@gmail.com>2016-03-16 18:02:55 -0400
commit12896bd23eeba79884245c1c29fdc568cf21a7fa (patch)
tree4e7f83d3e2564b9b89d669e9f7905ff11768b11a /web/react/components/analytics
parent29fe6a3d13c9c7aa490fffebbe5d1b5fdf1e3090 (diff)
downloadchat-12896bd23eeba79884245c1c29fdc568cf21a7fa.tar.gz
chat-12896bd23eeba79884245c1c29fdc568cf21a7fa.tar.bz2
chat-12896bd23eeba79884245c1c29fdc568cf21a7fa.zip
Converting to Webpack. Stage 1.
Diffstat (limited to 'web/react/components/analytics')
-rw-r--r--web/react/components/analytics/doughnut_chart.jsx77
-rw-r--r--web/react/components/analytics/line_chart.jsx90
-rw-r--r--web/react/components/analytics/statistic_count.jsx33
-rw-r--r--web/react/components/analytics/system_analytics.jsx346
-rw-r--r--web/react/components/analytics/table_chart.jsx60
-rw-r--r--web/react/components/analytics/team_analytics.jsx235
6 files changed, 0 insertions, 841 deletions
diff --git a/web/react/components/analytics/doughnut_chart.jsx b/web/react/components/analytics/doughnut_chart.jsx
deleted file mode 100644
index 00bb66f0a..000000000
--- a/web/react/components/analytics/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='analytics.chart.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.node,
- width: React.PropTypes.string,
- height: React.PropTypes.string,
- data: React.PropTypes.array,
- options: React.PropTypes.object
-};
diff --git a/web/react/components/analytics/line_chart.jsx b/web/react/components/analytics/line_chart.jsx
deleted file mode 100644
index d1bb6b9cb..000000000
--- a/web/react/components/analytics/line_chart.jsx
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import {FormattedMessage} from 'mm-intl';
-
-export default class LineChart extends React.Component {
- constructor(props) {
- super(props);
-
- this.initChart = this.initChart.bind(this);
- this.chart = null;
- }
-
- componentDidMount() {
- this.initChart();
- }
-
- componentDidUpdate() {
- if (this.chart) {
- this.chart.destroy();
- }
- this.initChart();
- }
-
- componentWillUnmount() {
- if (this.chart) {
- this.chart.destroy();
- }
- }
-
- initChart() {
- if (!this.refs.canvas) {
- return;
- }
- var el = ReactDOM.findDOMNode(this.refs.canvas);
- var ctx = el.getContext('2d');
- this.chart = new Chart(ctx).Line(this.props.data, this.props.options || {}); //eslint-disable-line new-cap
- }
-
- render() {
- let content;
- if (this.props.data == null) {
- content = (
- <FormattedMessage
- id='analytics.chart.loading'
- defaultMessage='Loading...'
- />
- );
- } else if (this.props.data.labels.length === 0) {
- content = (
- <h5>
- <FormattedMessage
- id='analytics.chart.meaningful'
- defaultMessage='Not enough data for a meaningful representation.'
- />
- </h5>
- );
- } else {
- content = (
- <canvas
- ref='canvas'
- width={this.props.width}
- height={this.props.height}
- />
- );
- }
-
- return (
- <div className='col-sm-12'>
- <div className='total-count by-day'>
- <div className='title'>
- {this.props.title}
- </div>
- <div className='content'>
- {content}
- </div>
- </div>
- </div>
- );
- }
-}
-
-LineChart.propTypes = {
- title: React.PropTypes.node.isRequired,
- width: React.PropTypes.string.isRequired,
- height: React.PropTypes.string.isRequired,
- data: React.PropTypes.object,
- options: React.PropTypes.object
-};
-
diff --git a/web/react/components/analytics/statistic_count.jsx b/web/react/components/analytics/statistic_count.jsx
deleted file mode 100644
index cf457310f..000000000
--- a/web/react/components/analytics/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='analytics.chart.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.node.isRequired,
- icon: React.PropTypes.string.isRequired,
- count: React.PropTypes.number
-};
diff --git a/web/react/components/analytics/system_analytics.jsx b/web/react/components/analytics/system_analytics.jsx
deleted file mode 100644
index a2b783a79..000000000
--- a/web/react/components/analytics/system_analytics.jsx
+++ /dev/null
@@ -1,346 +0,0 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import LineChart from './line_chart.jsx';
-import DoughnutChart from './doughnut_chart.jsx';
-import StatisticCount from './statistic_count.jsx';
-
-import AnalyticsStore from '../../stores/analytics_store.jsx';
-
-import * as Utils from '../../utils/utils.jsx';
-import * as AsyncClient from '../../utils/async_client.jsx';
-import Constants from '../../utils/constants.jsx';
-const StatTypes = Constants.StatTypes;
-
-import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
-
-const holders = defineMessages({
- analyticsPublicChannels: {
- id: 'analytics.system.publicChannels',
- defaultMessage: 'Public Channels'
- },
- analyticsPrivateGroups: {
- id: 'analytics.system.privateGroups',
- defaultMessage: 'Private Groups'
- },
- analyticsFilePosts: {
- id: 'analytics.system.totalFilePosts',
- defaultMessage: 'Posts with Files'
- },
- analyticsHashtagPosts: {
- id: 'analytics.system.totalHashtagPosts',
- defaultMessage: 'Posts with Hashtags'
- },
- analyticsTextPosts: {
- id: 'analytics.system.textPosts',
- defaultMessage: 'Posts with Text-only'
- }
-});
-
-class SystemAnalytics extends React.Component {
- constructor(props) {
- super(props);
-
- this.onChange = this.onChange.bind(this);
-
- this.state = {stats: AnalyticsStore.getAllSystem()};
- }
-
- componentDidMount() {
- AnalyticsStore.addChangeListener(this.onChange);
-
- AsyncClient.getStandardAnalytics();
- AsyncClient.getPostsPerDayAnalytics();
- AsyncClient.getUsersPerDayAnalytics();
-
- if (global.window.mm_license.IsLicensed === 'true') {
- AsyncClient.getAdvancedAnalytics();
- }
- }
-
- componentWillUnmount() {
- AnalyticsStore.removeChangeListener(this.onChange);
- }
-
- shouldComponentUpdate(nextProps, nextState) {
- if (!Utils.areObjectsEqual(nextState.stats, this.state.stats)) {
- return true;
- }
-
- return false;
- }
-
- onChange() {
- this.setState({stats: AnalyticsStore.getAllSystem()});
- }
-
- render() {
- const stats = this.state.stats;
-
- let advancedCounts;
- let advancedGraphs;
- if (global.window.mm_license.IsLicensed === 'true') {
- advancedCounts = (
- <div className='row'>
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.system.totalSessions'
- defaultMessage='Total Sessions'
- />
- }
- icon='fa-signal'
- count={stats[StatTypes.TOTAL_SESSIONS]}
- />
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.system.totalCommands'
- defaultMessage='Total Commands'
- />
- }
- icon='fa-terminal'
- count={stats[StatTypes.TOTAL_COMMANDS]}
- />
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.system.totalIncomingWebhooks'
- defaultMessage='Incoming Webhooks'
- />
- }
- icon='fa-arrow-down'
- count={stats[StatTypes.TOTAL_IHOOKS]}
- />
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.system.totalOutgoingWebhooks'
- defaultMessage='Outgoing Webhooks'
- />
- }
- icon='fa-arrow-up'
- count={stats[StatTypes.TOTAL_OHOOKS]}
- />
- </div>
- );
-
- const channelTypeData = formatChannelDoughtnutData(stats[StatTypes.TOTAL_PUBLIC_CHANNELS], stats[StatTypes.TOTAL_PRIVATE_GROUPS], this.props.intl);
- const postTypeData = formatPostDoughtnutData(stats[StatTypes.TOTAL_FILE_POSTS], stats[StatTypes.TOTAL_HASHTAG_POSTS], stats[StatTypes.TOTAL_POSTS], this.props.intl);
-
- advancedGraphs = (
- <div className='row'>
- <DoughnutChart
- title={
- <FormattedMessage
- id='analytics.system.channelTypes'
- defaultMessage='Channel Types'
- />
- }
- data={channelTypeData}
- width='300'
- height='225'
- />
- <DoughnutChart
- title={
- <FormattedMessage
- id='analytics.system.postTypes'
- defaultMessage='Posts, Files and Hashtags'
- />
- }
- data={postTypeData}
- width='300'
- height='225'
- />
- </div>
- );
- }
-
- const postCountsDay = formatPostsPerDayData(stats[StatTypes.POST_PER_DAY]);
- const userCountsWithPostsDay = formatUsersWithPostsPerDayData(stats[StatTypes.USERS_WITH_POSTS_PER_DAY]);
-
- return (
- <div className='wrapper--fixed team_statistics'>
- <h3>
- <FormattedMessage
- id='analytics.system.title'
- defaultMessage='System Statistics'
- />
- </h3>
- <div className='row'>
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.system.totalUsers'
- defaultMessage='Total Users'
- />
- }
- icon='fa-user'
- count={stats[StatTypes.TOTAL_USERS]}
- />
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.system.totalTeams'
- defaultMessage='Total Teams'
- />
- }
- icon='fa-users'
- count={stats[StatTypes.TOTAL_TEAMS]}
- />
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.system.totalPosts'
- defaultMessage='Total Posts'
- />
- }
- icon='fa-comment'
- count={stats[StatTypes.TOTAL_POSTS]}
- />
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.system.totalChannels'
- defaultMessage='Total Channels'
- />
- }
- icon='fa-globe'
- count={stats[StatTypes.TOTAL_PUBLIC_CHANNELS] + stats[StatTypes.TOTAL_PRIVATE_GROUPS]}
- />
- </div>
- {advancedCounts}
- {advancedGraphs}
- <div className='row'>
- <LineChart
- title={
- <FormattedMessage
- id='analytics.system.totalPosts'
- defaultMessage='Total Posts'
- />
- }
- data={postCountsDay}
- width='740'
- height='225'
- />
- </div>
- <div className='row'>
- <LineChart
- title={
- <FormattedMessage
- id='analytics.system.activeUsers'
- defaultMessage='Active Users With Posts'
- />
- }
- data={userCountsWithPostsDay}
- width='740'
- height='225'
- />
- </div>
- </div>
- );
- }
-}
-
-SystemAnalytics.propTypes = {
- intl: intlShape.isRequired,
- team: React.PropTypes.object
-};
-
-export default injectIntl(SystemAnalytics);
-
-export function formatChannelDoughtnutData(totalPublic, totalPrivate, intl) {
- const {formatMessage} = intl;
- const channelTypeData = [
- {
- value: totalPublic,
- color: '#46BFBD',
- highlight: '#5AD3D1',
- label: formatMessage(holders.analyticsPublicChannels)
- },
- {
- value: totalPrivate,
- color: '#FDB45C',
- highlight: '#FFC870',
- label: formatMessage(holders.analyticsPrivateGroups)
- }
- ];
-
- return channelTypeData;
-}
-
-export function formatPostDoughtnutData(filePosts, hashtagPosts, totalPosts, intl) {
- const {formatMessage} = intl;
- const postTypeData = [
- {
- value: filePosts,
- color: '#46BFBD',
- highlight: '#5AD3D1',
- label: formatMessage(holders.analyticsFilePosts)
- },
- {
- value: hashtagPosts,
- color: '#F7464A',
- highlight: '#FF5A5E',
- label: formatMessage(holders.analyticsHashtagPosts)
- },
- {
- value: totalPosts - filePosts - hashtagPosts,
- color: '#FDB45C',
- highlight: '#FFC870',
- label: formatMessage(holders.analyticsTextPosts)
- }
- ];
-
- return postTypeData;
-}
-
-export function formatPostsPerDayData(data) {
- var chartData = {
- labels: [],
- datasets: [{
- 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);
- }
- }
-
- return chartData;
-}
-
-export function formatUsersWithPostsPerDayData(data) {
- var chartData = {
- labels: [],
- datasets: [{
- 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);
- }
- }
-
- return chartData;
-}
diff --git a/web/react/components/analytics/table_chart.jsx b/web/react/components/analytics/table_chart.jsx
deleted file mode 100644
index c94fa300b..000000000
--- a/web/react/components/analytics/table_chart.jsx
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import Constants from '../../utils/constants.jsx';
-
-const Tooltip = ReactBootstrap.Tooltip;
-const OverlayTrigger = ReactBootstrap.OverlayTrigger;
-
-export default class TableChart extends React.Component {
- render() {
- return (
- <div className='col-sm-6'>
- <div className='total-count recent-active-users'>
- <div className='title'>
- {this.props.title}
- </div>
- <div className='content'>
- <table>
- <tbody>
- {
- this.props.data.map((item) => {
- const tooltip = (
- <Tooltip id={'tip-table-entry-' + item.name}>
- {item.tip}
- </Tooltip>
- );
-
- return (
- <tr key={'table-entry-' + item.name}>
- <td>
- <OverlayTrigger
- delayShow={Constants.OVERLAY_TIME_DELAY}
- placement='top'
- overlay={tooltip}
- >
- <time>
- {item.name}
- </time>
- </OverlayTrigger>
- </td>
- <td>
- {item.value}
- </td>
- </tr>
- );
- })
- }
- </tbody>
- </table>
- </div>
- </div>
- </div>
- );
- }
-}
-
-TableChart.propTypes = {
- title: React.PropTypes.node,
- data: React.PropTypes.array
-};
diff --git a/web/react/components/analytics/team_analytics.jsx b/web/react/components/analytics/team_analytics.jsx
deleted file mode 100644
index 1236c070b..000000000
--- a/web/react/components/analytics/team_analytics.jsx
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import LineChart from './line_chart.jsx';
-import StatisticCount from './statistic_count.jsx';
-import TableChart from './table_chart.jsx';
-
-import AnalyticsStore from '../../stores/analytics_store.jsx';
-
-import * as Utils from '../../utils/utils.jsx';
-import * as AsyncClient from '../../utils/async_client.jsx';
-import Constants from '../../utils/constants.jsx';
-const StatTypes = Constants.StatTypes;
-
-import {formatPostsPerDayData, formatUsersWithPostsPerDayData} from './system_analytics.jsx';
-import {injectIntl, intlShape, FormattedMessage, FormattedDate} from 'mm-intl';
-
-class TeamAnalytics extends React.Component {
- constructor(props) {
- super(props);
-
- this.onChange = this.onChange.bind(this);
-
- this.state = {stats: AnalyticsStore.getAllTeam(this.props.team.id)};
- }
-
- componentDidMount() {
- AnalyticsStore.addChangeListener(this.onChange);
-
- this.getData(this.props.team.id);
- }
-
- getData(id) {
- AsyncClient.getStandardAnalytics(id);
- AsyncClient.getPostsPerDayAnalytics(id);
- AsyncClient.getUsersPerDayAnalytics(id);
- AsyncClient.getRecentAndNewUsersAnalytics(id);
- }
-
- componentWillUnmount() {
- AnalyticsStore.removeChangeListener(this.onChange);
- }
-
- componentWillReceiveProps(nextProps) {
- this.getData(nextProps.team.id);
- this.setState({stats: AnalyticsStore.getAllTeam(nextProps.team.id)});
- }
-
- shouldComponentUpdate(nextProps, nextState) {
- if (!Utils.areObjectsEqual(nextState.stats, this.state.stats)) {
- return true;
- }
-
- if (!Utils.areObjectsEqual(nextProps.team, this.props.team)) {
- return true;
- }
-
- return false;
- }
-
- onChange() {
- this.setState({stats: AnalyticsStore.getAllTeam(this.props.team.id)});
- }
-
- render() {
- const stats = this.state.stats;
- const postCountsDay = formatPostsPerDayData(stats[StatTypes.POST_PER_DAY]);
- const userCountsWithPostsDay = formatUsersWithPostsPerDayData(stats[StatTypes.USERS_WITH_POSTS_PER_DAY]);
- const recentActiveUsers = formatRecentUsersData(stats[StatTypes.RECENTLY_ACTIVE_USERS]);
- const newlyCreatedUsers = formatNewUsersData(stats[StatTypes.NEWLY_CREATED_USERS]);
-
- return (
- <div className='wrapper--fixed team_statistics'>
- <h3>
- <FormattedMessage
- id='analytics.team.title'
- defaultMessage='Team Statistics for {team}'
- values={{
- team: this.props.team.name
- }}
- />
- </h3>
- <div className='row'>
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.team.totalUsers'
- defaultMessage='Total Users'
- />
- }
- icon='fa-user'
- count={stats[StatTypes.TOTAL_USERS]}
- />
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.team.publicChannels'
- defaultMessage='Public Channels'
- />
- }
- icon='fa-users'
- count={stats[StatTypes.TOTAL_PUBLIC_CHANNELS]}
- />
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.team.privateGroups'
- defaultMessage='Private Groups'
- />
- }
- icon='fa-globe'
- count={stats[StatTypes.TOTAL_PRIVATE_GROUPS]}
- />
- <StatisticCount
- title={
- <FormattedMessage
- id='analytics.team.totalPosts'
- defaultMessage='Total Posts'
- />
- }
- icon='fa-comment'
- count={stats[StatTypes.TOTAL_POSTS]}
- />
- </div>
- <div className='row'>
- <LineChart
- title={
- <FormattedMessage
- id='analytics.team.totalPosts'
- defaultMessage='Total Posts'
- />
- }
- data={postCountsDay}
- width='740'
- height='225'
- />
- </div>
- <div className='row'>
- <LineChart
- title={
- <FormattedMessage
- id='analytics.team.activeUsers'
- defaultMessage='Active Users With Posts'
- />
- }
- data={userCountsWithPostsDay}
- width='740'
- height='225'
- />
- </div>
- <div className='row'>
- <TableChart
- title={
- <FormattedMessage
- id='analytics.team.activeUsers'
- defaultMessage='Recent Active Users'
- />
- }
- data={recentActiveUsers}
- />
- <TableChart
- title={
- <FormattedMessage
- id='analytics.team.newlyCreated'
- defaultMessage='Newly Created Users'
- />
- }
- data={newlyCreatedUsers}
- />
- </div>
- </div>
- );
- }
-}
-
-TeamAnalytics.propTypes = {
- intl: intlShape.isRequired,
- team: React.PropTypes.object.isRequired
-};
-
-export default injectIntl(TeamAnalytics);
-
-export function formatRecentUsersData(data) {
- if (data == null) {
- return [];
- }
-
- const formattedData = data.map((user) => {
- const item = {};
- item.name = user.username;
- item.value = (
- <FormattedDate
- value={user.last_activity_at}
- day='numeric'
- month='long'
- year='numeric'
- hour12={true}
- hour='2-digit'
- minute='2-digit'
- />
- );
- item.tip = user.email;
-
- return item;
- });
-
- return formattedData;
-}
-
-export function formatNewUsersData(data) {
- if (data == null) {
- return [];
- }
-
- const formattedData = data.map((user) => {
- const item = {};
- item.name = user.username;
- item.value = (
- <FormattedDate
- value={user.create_at}
- day='numeric'
- month='long'
- year='numeric'
- hour12={true}
- hour='2-digit'
- minute='2-digit'
- />
- );
- item.tip = user.email;
-
- return item;
- });
-
- return formattedData;
-}