PLT-6213 Move team store and actions over to use redux (#6222)
* Move team store and actions over to user redux * Fix JS error when inviting by email
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
1fef5bf5fe
Коммит
7307156c49
24
webapp/components/analytics/team_analytics/index.js
Обычный файл
24
webapp/components/analytics/team_analytics/index.js
Обычный файл
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {getTeams} from 'mattermost-redux/actions/teams';
|
||||
|
||||
import TeamAnalytics from './team_analytics.jsx';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
...ownProps
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
getTeams
|
||||
}, dispatch)
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TeamAnalytics);
|
||||
366
webapp/components/analytics/team_analytics/team_analytics.jsx
Обычный файл
366
webapp/components/analytics/team_analytics/team_analytics.jsx
Обычный файл
@@ -0,0 +1,366 @@
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {FormattedDate, FormattedMessage, FormattedHTMLMessage} from 'react-intl';
|
||||
|
||||
import Banner from 'components/admin_console/banner.jsx';
|
||||
import LoadingScreen from 'components/loading_screen.jsx';
|
||||
|
||||
import AdminStore from 'stores/admin_store.jsx';
|
||||
import AnalyticsStore from 'stores/analytics_store.jsx';
|
||||
import BrowserStore from 'stores/browser_store.jsx';
|
||||
|
||||
import * as AsyncClient from 'utils/async_client.jsx';
|
||||
import {StatTypes} from 'utils/constants.jsx';
|
||||
import {convertTeamMapToList} from 'utils/team_utils.jsx';
|
||||
|
||||
import LineChart from 'components/analytics/line_chart.jsx';
|
||||
import StatisticCount from 'components/analytics/statistic_count.jsx';
|
||||
import TableChart from 'components/analytics/table_chart.jsx';
|
||||
import {formatPostsPerDayData, formatUsersWithPostsPerDayData} from 'components/analytics/system_analytics.jsx';
|
||||
|
||||
const LAST_ANALYTICS_TEAM = 'last_analytics_team';
|
||||
|
||||
export default class TeamAnalytics extends React.Component {
|
||||
static propTypes = {
|
||||
actions: React.PropTypes.shape({
|
||||
getTeams: React.PropTypes.func.isRequired
|
||||
}).isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.onAllTeamsChange = this.onAllTeamsChange.bind(this);
|
||||
this.handleTeamChange = this.handleTeamChange.bind(this);
|
||||
|
||||
const teams = convertTeamMapToList(AdminStore.getAllTeams());
|
||||
const teamId = BrowserStore.getGlobalItem(LAST_ANALYTICS_TEAM, teams.length > 0 ? teams[0].id : '');
|
||||
|
||||
this.state = {
|
||||
teams,
|
||||
teamId,
|
||||
team: AdminStore.getTeam(teamId),
|
||||
stats: AnalyticsStore.getAllTeam(teamId)
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
AnalyticsStore.addChangeListener(this.onChange);
|
||||
AdminStore.addAllTeamsChangeListener(this.onAllTeamsChange);
|
||||
|
||||
if (this.state.teamId !== '') {
|
||||
this.getData(this.state.teamId);
|
||||
}
|
||||
|
||||
if (this.state.teams.length === 0) {
|
||||
this.props.actions.getTeams(0, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps, nextState) {
|
||||
if (nextState.teamId !== this.state.teamId) {
|
||||
this.getData(nextState.teamId);
|
||||
}
|
||||
}
|
||||
|
||||
getData(id) {
|
||||
AsyncClient.getStandardAnalytics(id);
|
||||
AsyncClient.getPostsPerDayAnalytics(id);
|
||||
AsyncClient.getUsersPerDayAnalytics(id);
|
||||
AsyncClient.getRecentAndNewUsersAnalytics(id);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
AnalyticsStore.removeChangeListener(this.onChange);
|
||||
AdminStore.removeAllTeamsChangeListener(this.onAllTeamsChange);
|
||||
}
|
||||
|
||||
onChange() {
|
||||
this.setState({
|
||||
stats: AnalyticsStore.getAllTeam(this.state.teamId)
|
||||
});
|
||||
}
|
||||
|
||||
onAllTeamsChange() {
|
||||
const teams = convertTeamMapToList(AdminStore.getAllTeams());
|
||||
|
||||
if (teams.length > 0) {
|
||||
if (this.state.teamId) {
|
||||
this.setState({
|
||||
team: AdminStore.getTeam(this.state.teamId)
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
teamId: teams[0].id,
|
||||
team: teams[0]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
teams
|
||||
});
|
||||
}
|
||||
|
||||
handleTeamChange(e) {
|
||||
const teamId = e.target.value;
|
||||
|
||||
this.setState({
|
||||
teamId,
|
||||
team: AdminStore.getTeam(teamId)
|
||||
});
|
||||
|
||||
BrowserStore.setGlobalItem(LAST_ANALYTICS_TEAM, teamId);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.teams.length === 0 || !this.state.team || !this.state.stats) {
|
||||
return <LoadingScreen/>;
|
||||
}
|
||||
|
||||
if (this.state.teamId === '') {
|
||||
return (
|
||||
<Banner
|
||||
description={
|
||||
<FormattedMessage
|
||||
id='analytics.team.noTeams'
|
||||
defaultMessage='There are no teams on this server for which to view statistics.'
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const stats = this.state.stats;
|
||||
const postCountsDay = formatPostsPerDayData(stats[StatTypes.POST_PER_DAY]);
|
||||
const userCountsWithPostsDay = formatUsersWithPostsPerDayData(stats[StatTypes.USERS_WITH_POSTS_PER_DAY]);
|
||||
|
||||
let banner;
|
||||
let totalPostsCount;
|
||||
let postTotalGraph;
|
||||
let userActiveGraph;
|
||||
if (stats[StatTypes.TOTAL_POSTS] === -1) {
|
||||
banner = (
|
||||
<Banner
|
||||
description={
|
||||
<FormattedHTMLMessage
|
||||
id='analytics.system.skippedIntensiveQueries'
|
||||
defaultMessage="Some statistics have been omitted because they put too much load on the system to calculate. See <a href='https://docs.mattermost.com/administration/statistics.html' target='_blank'>https://docs.mattermost.com/administration/statistics.html</a> for more details."
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
totalPostsCount = (
|
||||
<StatisticCount
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='analytics.team.totalPosts'
|
||||
defaultMessage='Total Posts'
|
||||
/>
|
||||
}
|
||||
icon='fa-comment'
|
||||
count={stats[StatTypes.TOTAL_POSTS]}
|
||||
/>
|
||||
);
|
||||
|
||||
postTotalGraph = (
|
||||
<div className='row'>
|
||||
<LineChart
|
||||
key={this.state.team.id}
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='analytics.team.totalPosts'
|
||||
defaultMessage='Total Posts'
|
||||
/>
|
||||
}
|
||||
data={postCountsDay}
|
||||
options={{
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}}
|
||||
width='740'
|
||||
height='225'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
userActiveGraph = (
|
||||
<div className='row'>
|
||||
<LineChart
|
||||
key={this.state.team.id}
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='analytics.team.activeUsers'
|
||||
defaultMessage='Active Users With Posts'
|
||||
/>
|
||||
}
|
||||
data={userCountsWithPostsDay}
|
||||
options={{
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}}
|
||||
width='740'
|
||||
height='225'
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const recentActiveUsers = formatRecentUsersData(stats[StatTypes.RECENTLY_ACTIVE_USERS]);
|
||||
const newlyCreatedUsers = formatNewUsersData(stats[StatTypes.NEWLY_CREATED_USERS]);
|
||||
|
||||
const teams = this.state.teams.map((team) => {
|
||||
return (
|
||||
<option
|
||||
key={team.id}
|
||||
value={team.id}
|
||||
>
|
||||
{team.display_name}
|
||||
</option>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className='wrapper--fixed team_statistics'>
|
||||
<div className='admin-console-header team-statistics__header-row'>
|
||||
<div className='team-statistics__header'>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id='analytics.team.title'
|
||||
defaultMessage='Team Statistics for {team}'
|
||||
values={{
|
||||
team: this.state.team.display_name
|
||||
}}
|
||||
/>
|
||||
</h3>
|
||||
</div>
|
||||
<div className='team-statistics__team-filter'>
|
||||
<select
|
||||
className='form-control team-statistics__team-filter__dropdown'
|
||||
onChange={this.handleTeamChange}
|
||||
value={this.state.teamId}
|
||||
>
|
||||
{teams}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{banner}
|
||||
<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 Channels'
|
||||
/>
|
||||
}
|
||||
icon='fa-globe'
|
||||
count={stats[StatTypes.TOTAL_PRIVATE_GROUPS]}
|
||||
/>
|
||||
{totalPostsCount}
|
||||
</div>
|
||||
{postTotalGraph}
|
||||
{userActiveGraph}
|
||||
<div className='row'>
|
||||
<TableChart
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='analytics.team.recentUsers'
|
||||
defaultMessage='Recent Active Users'
|
||||
/>
|
||||
}
|
||||
data={recentActiveUsers}
|
||||
/>
|
||||
<TableChart
|
||||
title={
|
||||
<FormattedMessage
|
||||
id='analytics.team.newlyCreated'
|
||||
defaultMessage='Newly Created Users'
|
||||
/>
|
||||
}
|
||||
data={newlyCreatedUsers}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
Ссылка в новой задаче
Block a user