You've already forked mattermost-webapp
mirror of
https://github.com/zerotier/mattermost-webapp.git
synced 2026-05-22 16:23:25 -07:00
af6a14ff9d
This adds 2 new widgets: * AdminHeader, which is a widget that makes the Admin Console page header which can take any components or values as children. * FormattedAdminHeader, which is a child widget that can be used where the AdminHeader component is to contain a single localised (markdown) string. These are not the most complicated components in existence, but they are distinctly UI widgets that can be separated from the code, and were needed for the code I was writing at the present.
385 lines
13 KiB
React
385 lines
13 KiB
React
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
|
|
import React from 'react';
|
|
import {FormattedMessage} from 'react-intl';
|
|
import PropTypes from 'prop-types';
|
|
|
|
import * as AdminActions from 'actions/admin_actions.jsx';
|
|
import Constants from 'utils/constants.jsx';
|
|
|
|
import FormattedMarkdownMessage from 'components/formatted_markdown_message.jsx';
|
|
|
|
import FormattedAdminHeader from 'components/widgets/admin_console/formatted_admin_header.jsx';
|
|
|
|
import DoughnutChart from '../doughnut_chart.jsx';
|
|
import LineChart from '../line_chart.jsx';
|
|
import StatisticCount from '../statistic_count.jsx';
|
|
|
|
import {
|
|
formatPostsPerDayData,
|
|
formatUsersWithPostsPerDayData,
|
|
formatChannelDoughtnutData,
|
|
formatPostDoughtnutData,
|
|
} from '../format.jsx';
|
|
|
|
const StatTypes = Constants.StatTypes;
|
|
|
|
export default class SystemAnalytics extends React.PureComponent {
|
|
static propTypes = {
|
|
isLicensed: PropTypes.bool.isRequired,
|
|
stats: PropTypes.object,
|
|
}
|
|
|
|
componentDidMount() {
|
|
AdminActions.getStandardAnalytics();
|
|
AdminActions.getPostsPerDayAnalytics();
|
|
AdminActions.getUsersPerDayAnalytics();
|
|
|
|
if (this.props.isLicensed) {
|
|
AdminActions.getAdvancedAnalytics();
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const stats = this.props.stats;
|
|
const isLicensed = this.props.isLicensed;
|
|
const skippedIntensiveQueries = stats[StatTypes.TOTAL_POSTS] === -1;
|
|
const postCountsDay = formatPostsPerDayData(stats[StatTypes.POST_PER_DAY]);
|
|
const userCountsWithPostsDay = formatUsersWithPostsPerDayData(stats[StatTypes.USERS_WITH_POSTS_PER_DAY]);
|
|
|
|
let banner;
|
|
let postCount;
|
|
let postTotalGraph;
|
|
let activeUserGraph;
|
|
if (skippedIntensiveQueries) {
|
|
banner = (
|
|
<div className='banner'>
|
|
<div className='banner__content'>
|
|
<FormattedMarkdownMessage
|
|
id='analytics.system.skippedIntensiveQueries'
|
|
defaultMessage='To maximize performance, some statistics are disabled. You can [re-enable them in config.json](!https://docs.mattermost.com/administration/statistics.html).'
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
} else {
|
|
postCount = (
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalPosts'
|
|
defaultMessage='Total Posts'
|
|
/>
|
|
}
|
|
icon='fa-comment'
|
|
count={stats[StatTypes.TOTAL_POSTS]}
|
|
/>
|
|
);
|
|
|
|
postTotalGraph = (
|
|
<div className='row'>
|
|
<LineChart
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalPosts'
|
|
defaultMessage='Total Posts'
|
|
/>
|
|
}
|
|
data={postCountsDay}
|
|
width={740}
|
|
height={225}
|
|
/>
|
|
</div>
|
|
);
|
|
|
|
activeUserGraph = (
|
|
<div className='row'>
|
|
<LineChart
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.activeUsers'
|
|
defaultMessage='Active Users With Posts'
|
|
/>
|
|
}
|
|
data={userCountsWithPostsDay}
|
|
width={740}
|
|
height={225}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
let advancedStats;
|
|
let advancedGraphs;
|
|
let sessionCount;
|
|
let commandCount;
|
|
let incomingCount;
|
|
let outgoingCount;
|
|
if (this.props.isLicensed) {
|
|
sessionCount = (
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalSessions'
|
|
defaultMessage='Total Sessions'
|
|
/>
|
|
}
|
|
icon='fa-signal'
|
|
count={stats[StatTypes.TOTAL_SESSIONS]}
|
|
/>
|
|
);
|
|
|
|
commandCount = (
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalCommands'
|
|
defaultMessage='Total Commands'
|
|
/>
|
|
}
|
|
icon='fa-terminal'
|
|
count={stats[StatTypes.TOTAL_COMMANDS]}
|
|
/>
|
|
);
|
|
|
|
incomingCount = (
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalIncomingWebhooks'
|
|
defaultMessage='Incoming Webhooks'
|
|
/>
|
|
}
|
|
icon='fa-arrow-down'
|
|
count={stats[StatTypes.TOTAL_IHOOKS]}
|
|
/>
|
|
);
|
|
|
|
outgoingCount = (
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalOutgoingWebhooks'
|
|
defaultMessage='Outgoing Webhooks'
|
|
/>
|
|
}
|
|
icon='fa-arrow-up'
|
|
count={stats[StatTypes.TOTAL_OHOOKS]}
|
|
/>
|
|
);
|
|
|
|
advancedStats = (
|
|
<div>
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalWebsockets'
|
|
defaultMessage='WebSocket Conns'
|
|
/>
|
|
}
|
|
icon='fa-user'
|
|
count={stats[StatTypes.TOTAL_WEBSOCKET_CONNECTIONS]}
|
|
/>
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalMasterDbConnections'
|
|
defaultMessage='Master DB Conns'
|
|
/>
|
|
}
|
|
icon='fa-terminal'
|
|
count={stats[StatTypes.TOTAL_MASTER_DB_CONNECTIONS]}
|
|
/>
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalReadDbConnections'
|
|
defaultMessage='Replica DB Conns'
|
|
/>
|
|
}
|
|
icon='fa-terminal'
|
|
count={stats[StatTypes.TOTAL_READ_DB_CONNECTIONS]}
|
|
/>
|
|
</div>
|
|
);
|
|
|
|
const channelTypeData = formatChannelDoughtnutData(stats[StatTypes.TOTAL_PUBLIC_CHANNELS], stats[StatTypes.TOTAL_PRIVATE_GROUPS]);
|
|
const postTypeData = formatPostDoughtnutData(stats[StatTypes.TOTAL_FILE_POSTS], stats[StatTypes.TOTAL_HASHTAG_POSTS], stats[StatTypes.TOTAL_POSTS]);
|
|
|
|
let postTypeGraph;
|
|
if (stats[StatTypes.TOTAL_POSTS] !== -1) {
|
|
postTypeGraph = (
|
|
<DoughnutChart
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.postTypes'
|
|
defaultMessage='Posts, Files and Hashtags'
|
|
/>
|
|
}
|
|
data={postTypeData}
|
|
width={300}
|
|
height={225}
|
|
/>
|
|
);
|
|
}
|
|
|
|
advancedGraphs = (
|
|
<div className='row'>
|
|
<DoughnutChart
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.channelTypes'
|
|
defaultMessage='Channel Types'
|
|
/>
|
|
}
|
|
data={channelTypeData}
|
|
width={300}
|
|
height={225}
|
|
/>
|
|
{postTypeGraph}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const userCount = (
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalUsers'
|
|
defaultMessage='Total Active Users'
|
|
/>
|
|
}
|
|
icon='fa-user'
|
|
count={stats[StatTypes.TOTAL_USERS]}
|
|
/>
|
|
);
|
|
|
|
const teamCount = (
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalTeams'
|
|
defaultMessage='Total Teams'
|
|
/>
|
|
}
|
|
icon='fa-users'
|
|
count={stats[StatTypes.TOTAL_TEAMS]}
|
|
/>
|
|
);
|
|
|
|
const channelCount = (
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.totalChannels'
|
|
defaultMessage='Total Channels'
|
|
/>
|
|
}
|
|
icon='fa-globe'
|
|
count={stats[StatTypes.TOTAL_PUBLIC_CHANNELS] + stats[StatTypes.TOTAL_PRIVATE_GROUPS]}
|
|
/>
|
|
);
|
|
|
|
const dailyActiveUsers = (
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.dailyActiveUsers'
|
|
defaultMessage='Daily Active Users'
|
|
/>
|
|
}
|
|
icon='fa-users'
|
|
count={stats[StatTypes.DAILY_ACTIVE_USERS]}
|
|
/>
|
|
);
|
|
|
|
const monthlyActiveUsers = (
|
|
<StatisticCount
|
|
title={
|
|
<FormattedMessage
|
|
id='analytics.system.monthlyActiveUsers'
|
|
defaultMessage='Monthly Active Users'
|
|
/>
|
|
}
|
|
icon='fa-users'
|
|
count={stats[StatTypes.MONTHLY_ACTIVE_USERS]}
|
|
/>
|
|
);
|
|
|
|
let firstRow;
|
|
let secondRow;
|
|
if (isLicensed && skippedIntensiveQueries) {
|
|
firstRow = (
|
|
<div>
|
|
{userCount}
|
|
{teamCount}
|
|
{channelCount}
|
|
{sessionCount}
|
|
</div>
|
|
);
|
|
|
|
secondRow = (
|
|
<div>
|
|
{commandCount}
|
|
{incomingCount}
|
|
{outgoingCount}
|
|
</div>
|
|
);
|
|
} else if (isLicensed && !skippedIntensiveQueries) {
|
|
firstRow = (
|
|
<div>
|
|
{userCount}
|
|
{teamCount}
|
|
{channelCount}
|
|
{postCount}
|
|
</div>
|
|
);
|
|
|
|
secondRow = (
|
|
<div>
|
|
{sessionCount}
|
|
{commandCount}
|
|
{incomingCount}
|
|
{outgoingCount}
|
|
</div>
|
|
);
|
|
} else if (!isLicensed) {
|
|
firstRow = (
|
|
<div>
|
|
{userCount}
|
|
{teamCount}
|
|
{channelCount}
|
|
{postCount}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const thirdRow = (
|
|
<div>
|
|
{dailyActiveUsers}
|
|
{monthlyActiveUsers}
|
|
</div>
|
|
);
|
|
|
|
return (
|
|
<div className='wrapper--fixed team_statistics'>
|
|
<FormattedAdminHeader
|
|
id='analytics.system.title'
|
|
defaultMessage='System Statistics'
|
|
/>
|
|
{banner}
|
|
<div className='row'>
|
|
{firstRow}
|
|
{secondRow}
|
|
{thirdRow}
|
|
{advancedStats}
|
|
</div>
|
|
{advancedGraphs}
|
|
{postTotalGraph}
|
|
{activeUserGraph}
|
|
</div>
|
|
);
|
|
}
|
|
}
|