PLT-7: Refactoring frontend (chunk 2)

- System Console complete
Этот коммит содержится в:
Elias Nahum
2016-01-27 15:49:26 -03:00
родитель ceebfe20ba
Коммит c8ca70870f
20 изменённых файлов: 2485 добавлений и 437 удалений

Просмотреть файл

@@ -8,6 +8,8 @@ import LineChart from './line_chart.jsx';
var Tooltip = ReactBootstrap.Tooltip;
var OverlayTrigger = ReactBootstrap.OverlayTrigger;
import {FormattedMessage} from 'mm-intl';
export default class Analytics extends React.Component {
constructor(props) {
super(props);
@@ -21,11 +23,23 @@ export default class Analytics extends React.Component {
serverError = <div className='form-group has-error'><label className='control-label'>{this.props.serverError}</label></div>;
}
let loading = (
<FormattedMessage
id='admin.analytics.loading'
defaultMessage='Loading...'
/>
);
var totalCount = (
<div className='col-sm-3'>
<div className='total-count'>
<div className='title'>{'Total Users'}<i className='fa fa-users'/></div>
<div className='content'>{this.props.uniqueUserCount == null ? 'Loading...' : this.props.uniqueUserCount}</div>
<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>
</div>
</div>
);
@@ -33,8 +47,13 @@ export default class Analytics extends React.Component {
var openChannelCount = (
<div className='col-sm-3'>
<div className='total-count'>
<div className='title'>{'Public Channels'}<i className='fa fa-globe'/></div>
<div className='content'>{this.props.channelOpenCount == null ? 'Loading...' : this.props.channelOpenCount}</div>
<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>
);
@@ -42,8 +61,13 @@ export default class Analytics extends React.Component {
var openPrivateCount = (
<div className='col-sm-3'>
<div className='total-count'>
<div className='title'>{'Private Groups'}<i className='fa fa-lock'/></div>
<div className='content'>{this.props.channelPrivateCount == null ? 'Loading...' : this.props.channelPrivateCount}</div>
<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>
);
@@ -51,8 +75,13 @@ export default class Analytics extends React.Component {
var postCount = (
<div className='col-sm-3'>
<div className='total-count'>
<div className='title'>{'Total Posts'}<i className='fa fa-comment'/></div>
<div className='content'>{this.props.postCount == null ? 'Loading...' : this.props.postCount}</div>
<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>
</div>
</div>
);
@@ -60,8 +89,13 @@ export default class Analytics extends React.Component {
var postCountsByDay = (
<div className='col-sm-12'>
<div className='total-count by-day'>
<div className='title'>{'Total Posts'}</div>
<div className='content'>{'Loading...'}</div>
<div className='title'>
<FormattedMessage
id='admin.analytics.totalPosts'
defaultMessage='Total Posts'
/>
</div>
<div className='content'>{loading}</div>
</div>
</div>
);
@@ -69,7 +103,12 @@ export default class Analytics extends React.Component {
if (this.props.postCountsDay != null) {
let content;
if (this.props.postCountsDay.labels.length === 0) {
content = 'Not enough data for a meaningful representation.';
content = (
<FormattedMessage
id='admin.analytics.meaningful'
defaultMessage='Not enough data for a meaningful representation.'
/>
);
} else {
content = (
<LineChart
@@ -82,7 +121,12 @@ export default class Analytics extends React.Component {
postCountsByDay = (
<div className='col-sm-12'>
<div className='total-count by-day'>
<div className='title'>{'Total Posts'}</div>
<div className='title'>
<FormattedMessage
id='admin.analytics.totalPosts'
defaultMessage='Total Posts'
/>
</div>
<div className='content'>
{content}
</div>
@@ -94,8 +138,13 @@ export default class Analytics extends React.Component {
var usersWithPostsByDay = (
<div className='col-sm-12'>
<div className='total-count by-day'>
<div className='title'>{'Active Users With Posts'}</div>
<div className='content'>{'Loading...'}</div>
<div className='title'>
<FormattedMessage
id='admin.analytics.activeUsers'
defaultMessage='Active Users With Posts'
/>
</div>
<div className='content'>{loading}</div>
</div>
</div>
);
@@ -103,7 +152,12 @@ export default class Analytics extends React.Component {
if (this.props.userCountsWithPostsDay != null) {
let content;
if (this.props.userCountsWithPostsDay.labels.length === 0) {
content = 'Not enough data for a meaningful representation.';
content = (
<FormattedMessage
id='admin.analytics.meaningful'
defaultMessage='Not enough data for a meaningful representation.'
/>
);
} else {
content = (
<LineChart
@@ -116,7 +170,12 @@ export default class Analytics extends React.Component {
usersWithPostsByDay = (
<div className='col-sm-12'>
<div className='total-count by-day'>
<div className='title'>{'Active Users With Posts'}</div>
<div className='title'>
<FormattedMessage
id='admin.analytics.activeUsers'
defaultMessage='Active Users With Posts'
/>
</div>
<div className='content'>
{content}
</div>
@@ -129,7 +188,7 @@ export default class Analytics extends React.Component {
if (this.props.recentActiveUsers != null) {
let content;
if (this.props.recentActiveUsers.length === 0) {
content = 'Loading...';
content = loading;
} else {
content = (
<table>
@@ -167,7 +226,12 @@ export default class Analytics extends React.Component {
recentActiveUser = (
<div className='col-sm-6'>
<div className='total-count recent-active-users'>
<div className='title'>{'Recent Active Users'}</div>
<div className='title'>
<FormattedMessage
id='admin.analytics.recentActive'
defaultMessage='Recent Active Users'
/>
</div>
<div className='content'>
{content}
</div>
@@ -180,7 +244,7 @@ export default class Analytics extends React.Component {
if (this.props.newlyCreatedUsers != null) {
let content;
if (this.props.newlyCreatedUsers.length === 0) {
content = 'Loading...';
content = loading;
} else {
content = (
<table>
@@ -218,7 +282,12 @@ export default class Analytics extends React.Component {
newUsers = (
<div className='col-sm-6'>
<div className='total-count recent-active-users'>
<div className='title'>{'Newly Created Users'}</div>
<div className='title'>
<FormattedMessage
id='admin.analytics.newlyCreated'
defaultMessage='Newly Created Users'
/>
</div>
<div className='content'>
{content}
</div>
@@ -229,7 +298,15 @@ export default class Analytics extends React.Component {
return (
<div className='wrapper--fixed team_statistics'>
<h3>{'Statistics for ' + this.props.title}</h3>
<h3>
<FormattedMessage
id='admin.analytics.title'
defaultMessage='Statistics for {title}'
values={{
title: this.props.title
}}
/>
</h3>
{serverError}
<div className='row'>
{totalCount}

Просмотреть файл

@@ -4,7 +4,36 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
export default class GitLabSettings extends React.Component {
import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
const holders = defineMessages({
clientIdExample: {
id: 'admin.gitlab.clientIdExample',
defaultMessage: 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
},
clientSecretExample: {
id: 'admin.gitlab.clientSecretExample',
defaultMessage: 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
},
authExample: {
id: 'admin.gitlab.authExample',
defaultMessage: 'Ex ""'
},
tokenExample: {
id: 'admin.gitlab.tokenExample',
defaultMessage: 'Ex ""'
},
userExample: {
id: 'admin.gitlab.userExample',
defaultMessage: 'Ex ""'
},
saving: {
id: 'admin.gitlab.saving',
defaultMessage: 'Saving Config...'
}
});
class GitLabSettings extends React.Component {
constructor(props) {
super(props);
@@ -65,6 +94,7 @@ export default class GitLabSettings extends React.Component {
}
render() {
const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -78,7 +108,12 @@ export default class GitLabSettings extends React.Component {
return (
<div className='wrapper--fixed'>
<h3>{'GitLab Settings'}</h3>
<h3>
<FormattedMessage
id='admin.gitlab.settingsTitle'
defaultMessage='GitLab Settings'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -89,7 +124,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Enable'
>
{'Enable Sign Up With GitLab: '}
<FormattedMessage
id='admin.gitlab.enableTitle'
defaultMessage='Enable Sign Up With GitLab: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -101,7 +139,10 @@ export default class GitLabSettings extends React.Component {
defaultChecked={this.props.config.GitLabSettings.Enable}
onChange={this.handleChange.bind(this, 'EnableTrue')}
/>
{'true'}
<FormattedMessage
id='admin.gitlab.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -111,18 +152,23 @@ export default class GitLabSettings extends React.Component {
defaultChecked={!this.props.config.GitLabSettings.Enable}
onChange={this.handleChange.bind(this, 'EnableFalse')}
/>
{'false'}
<FormattedMessage
id='admin.gitlab.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>
{'When true, Mattermost allows team creation and account signup using GitLab OAuth.'} <br/>
<FormattedMessage
id='admin.gitlab.enableDescription'
defaultMessage='When true, Mattermost allows team creation and account signup using GitLab OAuth.'
/>
<br/>
</p>
<div className='help-text'>
<ol>
<li>{'Log in to your GitLab account and go to Applications -> Profile Settings.'}</li>
<li>{'Enter Redirect URIs "<your-mattermost-url>/login/gitlab/complete" (example: http://localhost:8065/login/gitlab/complete) and "<your-mattermost-url>/signup/gitlab/complete". '}</li>
<li>{'Then use "Secret" and "Id" fields from GitLab to complete the options below.'}</li>
<li>{'Complete the Endpoint URLs below. '}</li>
</ol>
<FormattedHTMLMessage
id='admin.gitlab.EnableHtmlDesc'
defaultMessage='<ol><li>Log in to your GitLab account and go to Applications -> Profile Settings.</li><li>Enter Redirect URIs "<your-mattermost-url>/login/gitlab/complete" (example: http://localhost:8065/login/gitlab/complete) and "<your-mattermost-url>/signup/gitlab/complete". </li><li>Then use "Secret" and "Id" fields from GitLab to complete the options below.</li><li>Complete the Endpoint URLs below. </li></ol>'
/>
</div>
</div>
</div>
@@ -132,7 +178,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Id'
>
{'Id:'}
<FormattedMessage
id='admin.gitlab.clientIdTitle'
defaultMessage='Id:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -140,12 +189,17 @@ export default class GitLabSettings extends React.Component {
className='form-control'
id='Id'
ref='Id'
placeholder='Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
placeholder={formatMessage(holders.clientIdExample)}
defaultValue={this.props.config.GitLabSettings.Id}
onChange={this.handleChange}
disabled={!this.state.Enable}
/>
<p className='help-text'>{'Obtain this value via the instructions above for logging into GitLab'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.gitlab.clientIdDescription'
defaultMessage='Obtain this value via the instructions above for logging into GitLab'
/>
</p>
</div>
</div>
@@ -154,7 +208,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Secret'
>
{'Secret:'}
<FormattedMessage
id='admin.gitlab.clientSecretTitle'
defaultMessage='Secret:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -162,12 +219,17 @@ export default class GitLabSettings extends React.Component {
className='form-control'
id='Secret'
ref='Secret'
placeholder='Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
placeholder={formatMessage(holders.clientSecretExample)}
defaultValue={this.props.config.GitLabSettings.Secret}
onChange={this.handleChange}
disabled={!this.state.Enable}
/>
<p className='help-text'>{'Obtain this value via the instructions above for logging into GitLab.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.gitab.clientSecretDescription'
defaultMessage='Obtain this value via the instructions above for logging into GitLab.'
/>
</p>
</div>
</div>
@@ -176,7 +238,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AuthEndpoint'
>
{'Auth Endpoint:'}
<FormattedMessage
id='admin.gitlab.authTitle'
defaultMessage='Auth Endpoint:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -184,12 +249,17 @@ export default class GitLabSettings extends React.Component {
className='form-control'
id='AuthEndpoint'
ref='AuthEndpoint'
placeholder='Ex ""'
placeholder={formatMessage(holders.authExample)}
defaultValue={this.props.config.GitLabSettings.AuthEndpoint}
onChange={this.handleChange}
disabled={!this.state.Enable}
/>
<p className='help-text'>{'Enter https://<your-gitlab-url>/oauth/authorize (example https://example.com:3000/oauth/authorize). Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.gitlab.authDescription'
defaultMessage='Enter https://<your-gitlab-url>/oauth/authorize (example https://example.com:3000/oauth/authorize). Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'
/>
</p>
</div>
</div>
@@ -198,7 +268,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='TokenEndpoint'
>
{'Token Endpoint:'}
<FormattedMessage
id='admin.gitlab.tokenTitle'
defaultMessage='Token Endpoint:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -206,12 +279,17 @@ export default class GitLabSettings extends React.Component {
className='form-control'
id='TokenEndpoint'
ref='TokenEndpoint'
placeholder='Ex ""'
placeholder={formatMessage(holders.tokenExample)}
defaultValue={this.props.config.GitLabSettings.TokenEndpoint}
onChange={this.handleChange}
disabled={!this.state.Enable}
/>
<p className='help-text'>{'Enter https://<your-gitlab-url>/oauth/token. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.gitlab.tokenDescription'
defaultMessage='Enter https://<your-gitlab-url>/oauth/token. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'
/>
</p>
</div>
</div>
@@ -220,7 +298,10 @@ export default class GitLabSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='UserApiEndpoint'
>
{'User API Endpoint:'}
<FormattedMessage
id='admin.gitlab.userTitle'
defaultMessage='User API Endpoint:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -228,12 +309,17 @@ export default class GitLabSettings extends React.Component {
className='form-control'
id='UserApiEndpoint'
ref='UserApiEndpoint'
placeholder='Ex ""'
placeholder={formatMessage(holders.userExample)}
defaultValue={this.props.config.GitLabSettings.UserApiEndpoint}
onChange={this.handleChange}
disabled={!this.state.Enable}
/>
<p className='help-text'>{'Enter https://<your-gitlab-url>/api/v3/user. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.gitlab.userDescription'
defaultMessage='Enter https://<your-gitlab-url>/api/v3/user. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.'
/>
</p>
</div>
</div>
@@ -246,9 +332,12 @@ export default class GitLabSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
{'Save'}
<FormattedMessage
id='admin.gitlab.save'
defaultMessage='Save'
/>
</button>
</div>
</div>
@@ -283,5 +372,8 @@ export default class GitLabSettings extends React.Component {
// </div>
GitLabSettings.propTypes = {
intl: intlShape.isRequired,
config: React.PropTypes.object
};
export default injectIntl(GitLabSettings);

Просмотреть файл

@@ -5,7 +5,76 @@ import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
import crypto from 'crypto';
export default class FileSettings extends React.Component {
import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
const holders = defineMessages({
storeDisabled: {
id: 'admin.image.storeDisabled',
defaultMessage: 'Disable File Storage'
},
storeLocal: {
id: 'admin.image.storeLocal',
defaultMessage: 'Local File System'
},
storeAmazonS3: {
id: 'admin.image.storeAmazonS3',
defaultMessage: 'Amazon S3'
},
localExample: {
id: 'admin.image.localExample',
defaultMessage: 'Ex "./data/"'
},
amazonS3IdExample: {
id: 'admin.image.amazonS3IdExample',
defaultMessage: 'Ex "AKIADTOVBGERKLCBV"'
},
amazonS3SecretExample: {
id: 'admin.image.amazonS3SecretExample',
defaultMessage: 'Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
},
amazonS3BucketExample: {
id: 'admin.image.amazonS3BucketExample',
defaultMessage: 'Ex "mattermost-media"'
},
amazonS3RegionExample: {
id: 'admin.image.amazonS3RegionExample',
defaultMessage: 'Ex "us-east-1"'
},
thumbWidthExample: {
id: 'admin.image.thumbWidthExample',
defaultMessage: 'Ex "120"'
},
thumbHeightExample: {
id: 'admin.image.thumbHeightExample',
defaultMessage: 'Ex "100"'
},
previewWidthExample: {
id: 'admin.image.previewWidthExample',
defaultMessage: 'Ex "1024"'
},
previewHeightExample: {
id: 'admin.image.previewHeightExample',
defaultMessage: 'Ex "0"'
},
profileWidthExample: {
id: 'admin.image.profileWidthExample',
defaultMessage: 'Ex "1024"'
},
profileHeightExample: {
id: 'admin.image.profileHeightExample',
defaultMessage: 'Ex "0"'
},
publicLinkExample: {
id: 'admin.image.publicLinkExample',
defaultMessage: 'Ex "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"'
},
saving: {
id: 'admin.image.saving',
defaultMessage: 'Saving Config...'
}
});
class FileSettings extends React.Component {
constructor(props) {
super(props);
@@ -120,6 +189,7 @@ export default class FileSettings extends React.Component {
}
render() {
const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -143,7 +213,12 @@ export default class FileSettings extends React.Component {
return (
<div className='wrapper--fixed'>
<h3>{'File Settings'}</h3>
<h3>
<FormattedMessage
id='admin.image.fileSettings'
defaultMessage='File Settings'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -154,7 +229,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='DriverName'
>
{'Store Files In:'}
<FormattedMessage
id='admin.image.storeTitle'
defaultMessage='Store Files In:'
/>
</label>
<div className='col-sm-8'>
<select
@@ -164,9 +242,9 @@ export default class FileSettings extends React.Component {
defaultValue={this.props.config.FileSettings.DriverName}
onChange={this.handleChange.bind(this, 'DriverName')}
>
<option value=''>{'Disable File Storage'}</option>
<option value='local'>{'Local File System'}</option>
<option value='amazons3'>{'Amazon S3'}</option>
<option value=''>{formatMessage(holders.storeDisabled)}</option>
<option value='local'>{formatMessage(holders.storeLocal)}</option>
<option value='amazons3'>{formatMessage(holders.storeAmazonS3)}</option>
</select>
</div>
</div>
@@ -176,7 +254,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Directory'
>
{'Local Directory Location:'}
<FormattedMessage
id='admin.image.localTitle'
defaultMessage='Local Directory Location:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -184,12 +265,17 @@ export default class FileSettings extends React.Component {
className='form-control'
id='Directory'
ref='Directory'
placeholder='Ex "./data/"'
placeholder={formatMessage(holders.localExample)}
defaultValue={this.props.config.FileSettings.Directory}
onChange={this.handleChange}
disabled={!enableFile}
/>
<p className='help-text'>{'Directory to which image files are written. If blank, will be set to ./data/.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.localDescription'
defaultMessage='Directory to which image files are written. If blank, will be set to ./data/.'
/>
</p>
</div>
</div>
@@ -198,7 +284,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AmazonS3AccessKeyId'
>
{'Amazon S3 Access Key Id:'}
<FormattedMessage
id='admin.image.amazonS3IdTitle'
defaultMessage='Amazon S3 Access Key Id:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -206,12 +295,17 @@ export default class FileSettings extends React.Component {
className='form-control'
id='AmazonS3AccessKeyId'
ref='AmazonS3AccessKeyId'
placeholder='Ex "AKIADTOVBGERKLCBV"'
placeholder={formatMessage(holders.amazonS3IdExample)}
defaultValue={this.props.config.FileSettings.AmazonS3AccessKeyId}
onChange={this.handleChange}
disabled={!enableS3}
/>
<p className='help-text'>{'Obtain this credential from your Amazon EC2 administrator.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.amazonS3IdDescription'
defaultMessage='Obtain this credential from your Amazon EC2 administrator.'
/>
</p>
</div>
</div>
@@ -220,7 +314,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AmazonS3SecretAccessKey'
>
{'Amazon S3 Secret Access Key:'}
<FormattedMessage
id='admin.image.amazonS3SecretTitle'
defaultMessage='Amazon S3 Secret Access Key:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -228,12 +325,17 @@ export default class FileSettings extends React.Component {
className='form-control'
id='AmazonS3SecretAccessKey'
ref='AmazonS3SecretAccessKey'
placeholder='Ex "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
placeholder={formatMessage(holders.amazonS3SecretExample)}
defaultValue={this.props.config.FileSettings.AmazonS3SecretAccessKey}
onChange={this.handleChange}
disabled={!enableS3}
/>
<p className='help-text'>{'Obtain this credential from your Amazon EC2 administrator.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.amazonS3SecretDescription'
defaultMessage='Obtain this credential from your Amazon EC2 administrator.'
/>
</p>
</div>
</div>
@@ -242,7 +344,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AmazonS3Bucket'
>
{'Amazon S3 Bucket:'}
<FormattedMessage
id='admin.image.amazonS3BucketTitle'
defaultMessage='Amazon S3 Bucket:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -250,12 +355,17 @@ export default class FileSettings extends React.Component {
className='form-control'
id='AmazonS3Bucket'
ref='AmazonS3Bucket'
placeholder='Ex "mattermost-media"'
placeholder={formatMessage(holders.amazonS3BucketExample)}
defaultValue={this.props.config.FileSettings.AmazonS3Bucket}
onChange={this.handleChange}
disabled={!enableS3}
/>
<p className='help-text'>{'Name you selected for your S3 bucket in AWS.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.amazonS3BucketDescription'
defaultMessage='Name you selected for your S3 bucket in AWS.'
/>
</p>
</div>
</div>
@@ -264,7 +374,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AmazonS3Region'
>
{'Amazon S3 Region:'}
<FormattedMessage
id='admin.image.amazonS3RegionTitle'
defaultMessage='Amazon S3 Region:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -272,12 +385,17 @@ export default class FileSettings extends React.Component {
className='form-control'
id='AmazonS3Region'
ref='AmazonS3Region'
placeholder='Ex "us-east-1"'
placeholder={formatMessage(holders.amazonS3RegionExample)}
defaultValue={this.props.config.FileSettings.AmazonS3Region}
onChange={this.handleChange}
disabled={!enableS3}
/>
<p className='help-text'>{'AWS region you selected for creating your S3 bucket.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.amazonS3RegionDescription'
defaultMessage='AWS region you selected for creating your S3 bucket.'
/>
</p>
</div>
</div>
@@ -286,7 +404,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ThumbnailWidth'
>
{'Thumbnail Width:'}
<FormattedMessage
id='admin.image.thumbWidthTitle'
defaultMessage='Thumbnail Width:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -294,11 +415,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='ThumbnailWidth'
ref='ThumbnailWidth'
placeholder='Ex "120"'
placeholder={formatMessage(holders.thumbWidthExample)}
defaultValue={this.props.config.FileSettings.ThumbnailWidth}
onChange={this.handleChange}
/>
<p className='help-text'>{'Width of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.thumbWidthDescription'
defaultMessage='Width of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past.'
/>
</p>
</div>
</div>
@@ -307,7 +433,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ThumbnailHeight'
>
{'Thumbnail Height:'}
<FormattedMessage
id='admin.image.thumbHeightTitle'
defaultMessage='Thumbnail Height:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -315,11 +444,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='ThumbnailHeight'
ref='ThumbnailHeight'
placeholder='Ex "100"'
placeholder={formatMessage(holders.thumbHeightExample)}
defaultValue={this.props.config.FileSettings.ThumbnailHeight}
onChange={this.handleChange}
/>
<p className='help-text'>{'Height of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.thumbHeightDescription'
defaultMessage='Height of thumbnails generated from uploaded images. Updating this value changes how thumbnail images render in future, but does not change images created in the past.'
/>
</p>
</div>
</div>
@@ -328,7 +462,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='PreviewWidth'
>
{'Preview Width:'}
<FormattedMessage
id='admin.image.previewWidthTitle'
defaultMessage='Preview Width:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -336,11 +473,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='PreviewWidth'
ref='PreviewWidth'
placeholder='Ex "1024"'
placeholder={formatMessage(holders.previewWidthExample)}
defaultValue={this.props.config.FileSettings.PreviewWidth}
onChange={this.handleChange}
/>
<p className='help-text'>{'Maximum width of preview image. Updating this value changes how preview images render in future, but does not change images created in the past.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.previewWidthDescription'
defaultMessage='Maximum width of preview image. Updating this value changes how preview images render in future, but does not change images created in the past.'
/>
</p>
</div>
</div>
@@ -349,7 +491,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='PreviewHeight'
>
{'Preview Height:'}
<FormattedMessage
id='admin.image.previewHeightTitle'
defaultMessage='Preview Height:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -357,11 +502,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='PreviewHeight'
ref='PreviewHeight'
placeholder='Ex "0"'
placeholder={formatMessage(holders.previewHeightExample)}
defaultValue={this.props.config.FileSettings.PreviewHeight}
onChange={this.handleChange}
/>
<p className='help-text'>{'Maximum height of preview image ("0": Sets to auto-size). Updating this value changes how preview images render in future, but does not change images created in the past.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.previewHeightDescription'
defaultMessage='Maximum height of preview image ("0": Sets to auto-size). Updating this value changes how preview images render in future, but does not change images created in the past.'
/>
</p>
</div>
</div>
@@ -370,7 +520,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ProfileWidth'
>
{'Profile Width:'}
<FormattedMessage
id='admin.image.profileWidthTitle'
defaultMessage='Profile Width:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -378,11 +531,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='ProfileWidth'
ref='ProfileWidth'
placeholder='Ex "1024"'
placeholder={formatMessage(holders.profileWidthExample)}
defaultValue={this.props.config.FileSettings.ProfileWidth}
onChange={this.handleChange}
/>
<p className='help-text'>{'Width of profile picture.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.profileWidthDescription'
defaultMessage='Width of profile picture.'
/>
</p>
</div>
</div>
@@ -391,7 +549,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ProfileHeight'
>
{'Profile Height:'}
<FormattedMessage
id='admin.image.profileHeightTitle'
defaultMessage='Profile Height:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -399,11 +560,16 @@ export default class FileSettings extends React.Component {
className='form-control'
id='ProfileHeight'
ref='ProfileHeight'
placeholder='Ex "0"'
placeholder={formatMessage(holders.profileHeightExample)}
defaultValue={this.props.config.FileSettings.ProfileHeight}
onChange={this.handleChange}
/>
<p className='help-text'>{'Height of profile picture.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.profileHeightDescription'
defaultMessage='Height of profile picture.'
/>
</p>
</div>
</div>
@@ -412,7 +578,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnablePublicLink'
>
{'Share Public File Link: '}
<FormattedMessage
id='admin.image.shareTitle'
defaultMessage='Share Public File Link: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -424,7 +593,10 @@ export default class FileSettings extends React.Component {
defaultChecked={this.props.config.FileSettings.EnablePublicLink}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.image.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -434,9 +606,17 @@ export default class FileSettings extends React.Component {
defaultChecked={!this.props.config.FileSettings.EnablePublicLink}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.image.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'Allow users to share public links to files and images.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.shareDescription'
defaultMessage='Allow users to share public links to files and images.'
/>
</p>
</div>
</div>
@@ -445,7 +625,10 @@ export default class FileSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='PublicLinkSalt'
>
{'Public Link Salt:'}
<FormattedMessage
id='admin.image.publicLinkTitle'
defaultMessage='Public Link Salt:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -453,17 +636,25 @@ export default class FileSettings extends React.Component {
className='form-control'
id='PublicLinkSalt'
ref='PublicLinkSalt'
placeholder='Ex "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"'
placeholder={formatMessage(holders.publicLinkExample)}
defaultValue={this.props.config.FileSettings.PublicLinkSalt}
onChange={this.handleChange}
/>
<p className='help-text'>{'32-character salt added to signing of public image links. Randomly generated on install. Click "Re-Generate" to create new salt.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.image.publicLinkDescription'
defaultMessage='32-character salt added to signing of public image links. Randomly generated on install. Click "Re-Generate" to create new salt.'
/>
</p>
<div className='help-text'>
<button
className='btn btn-default'
onClick={this.handleGenerate}
>
{'Re-Generate'}
<FormattedMessage
id='admin.image.regenerate'
defaultMessage='Re-Generate'
/>
</button>
</div>
</div>
@@ -478,9 +669,12 @@ export default class FileSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
{'Save'}
<FormattedMessage
id='admin.image.save'
defaultMessage='Save'
/>
</button>
</div>
</div>
@@ -492,5 +686,8 @@ export default class FileSettings extends React.Component {
}
FileSettings.propTypes = {
intl: intlShape.isRequired,
config: React.PropTypes.object
};
export default injectIntl(FileSettings);

Просмотреть файл

@@ -4,10 +4,55 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
const DEFAULT_LDAP_PORT = 389;
const DEFAULT_QUERY_TIMEOUT = 60;
export default class LdapSettings extends React.Component {
var holders = defineMessages({
serverEx: {
id: 'admin.ldap.serverEx',
defaultMessage: 'Ex "10.0.0.23"'
},
portEx: {
id: 'admin.ldap.portEx',
defaultMessage: 'Ex "389"'
},
baseEx: {
id: 'admin.ldap.baseEx',
defaultMessage: 'Ex "dc=mydomain,dc=com"'
},
firstnameAttrEx: {
id: 'admin.ldap.firstnameAttrEx',
defaultMessage: 'Ex "givenName"'
},
lastnameAttrEx: {
id: 'admin.ldap.lastnameAttrEx',
defaultMessage: 'Ex "sn"'
},
emailAttrEx: {
id: 'admin.ldap.emailAttrEx',
defaultMessage: 'Ex "mail"'
},
usernameAttrEx: {
id: 'admin.ldap.usernameAttrEx',
defaultMessage: 'Ex "sAMAccountName"'
},
idAttrEx: {
id: 'admin.ldap.idAttrEx',
defaultMessage: 'Ex "sAMAccountName"'
},
queryEx: {
id: 'admin.ldap.queryEx',
defaultMessage: 'Ex "60"'
},
saving: {
id: 'admin.ldap.saving',
defaultMessage: 'Saving Config...'
}
});
class LdapSettings extends React.Component {
constructor(props) {
super(props);
@@ -80,6 +125,7 @@ export default class LdapSettings extends React.Component {
);
}
render() {
const {formatMessage} = this.props.intl;
let serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -97,8 +143,18 @@ export default class LdapSettings extends React.Component {
bannerContent = (
<div className='banner'>
<div className='banner__content'>
<h4 className='banner__heading'>{'Note:'}</h4>
<p>{'If a user attribute changes on the LDAP server it will be updated the next time the user enters their credentials to log in to Mattermost. This includes if a user is made inactive or removed from an LDAP server. Synchronization with LDAP servers is planned in a future release.'}</p>
<h4 className='banner__heading'>
<FormattedMessage
id='admin.ldap.bannerHeading'
defaultMessage='Note:'
/>
</h4>
<p>
<FormattedMessage
id='admin.ldap.bannerDesc'
defaultMessage='If a user attribute changes on the LDAP server it will be updated the next time the user enters their credentials to log in to Mattermost. This includes if a user is made inactive or removed from an LDAP server. Synchronization with LDAP servers is planned in a future release.'
/>
</p>
</div>
</div>
);
@@ -106,17 +162,10 @@ export default class LdapSettings extends React.Component {
bannerContent = (
<div className='banner warning'>
<div className='banner__content'>
<h4 className='banner__heading'>{'Note:'}</h4>
<p>
{'LDAP is an enterprise feature. Your current license does not support LDAP. Click '}
<a
href='http://mattermost.com'
target='_blank'
>
{'here'}
</a>
{' for information and pricing on enterprise licenses.'}
</p>
<FormattedHTMLMessage
id='admin.ldap.noLicense'
defaultMessage='<h4 className="banner__heading">Note:</h4><p>LDAP is an enterprise feature. Your current license does not support LDAP. Click <a href="http://mattermost.com"target="_blank">here</a> for information and pricing on enterprise licenses.</p>'
/>
</div>
</div>
);
@@ -125,7 +174,12 @@ export default class LdapSettings extends React.Component {
return (
<div className='wrapper--fixed'>
{bannerContent}
<h3>{'LDAP Settings'}</h3>
<h3>
<FormattedMessage
id='admin.ldap.title'
defaultMessage='LDAP Settings'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -135,7 +189,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Enable'
>
{'Enable Login With LDAP:'}
<FormattedMessage
id='admin.ldap.enableTitle'
defaultMessage='Enable Login With LDAP:'
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -148,7 +205,10 @@ export default class LdapSettings extends React.Component {
onChange={this.handleEnable}
disabled={!licenseEnabled}
/>
{'true'}
<FormattedMessage
id='admin.ldap.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -158,9 +218,17 @@ export default class LdapSettings extends React.Component {
defaultChecked={!this.props.config.LdapSettings.Enable}
onChange={this.handleDisable}
/>
{'false'}
<FormattedMessage
id='admin.ldap.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When true, Mattermost allows login using LDAP'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.enableDesc'
defaultMessage='When true, Mattermost allows login using LDAP'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -168,7 +236,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='LdapServer'
>
{'LDAP Server:'}
<FormattedMessage
id='admin.ldap.serverTitle'
defaultMessage='LDAP Server:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -176,12 +247,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='LdapServer'
ref='LdapServer'
placeholder='Ex "10.0.0.23"'
placeholder={formatMessage(holders.serverEx)}
defaultValue={this.props.config.LdapSettings.LdapServer}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'The domain or IP address of LDAP server.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.serverDesc'
defaultMessage='The domain or IP address of LDAP server.'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -189,7 +265,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='LdapPort'
>
{'LDAP Port:'}
<FormattedMessage
id='admin.ldap.portTitle'
defaultMessage='LDAP Port:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -197,12 +276,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='LdapPort'
ref='LdapPort'
placeholder='Ex "389"'
placeholder={formatMessage(holders.portEx)}
defaultValue={this.props.config.LdapSettings.LdapPort}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'The port Mattermost will use to connect to the LDAP server. Default is 389.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.portDesc'
defaultMessage='The port Mattermost will use to connect to the LDAP server. Default is 389.'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -210,7 +294,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='BaseDN'
>
{'BaseDN:'}
<FormattedMessage
id='admin.ldap.baseTitle'
defaultMessage='BaseDN:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -218,12 +305,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='BaseDN'
ref='BaseDN'
placeholder='Ex "dc=mydomain,dc=com"'
placeholder={formatMessage(holders.baseEx)}
defaultValue={this.props.config.LdapSettings.BaseDN}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'The Base DN is the Distinguished Name of the location where Mattermost should start its search for users in the LDAP tree.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.baseDesc'
defaultMessage='The Base DN is the Distinguished Name of the location where Mattermost should start its search for users in the LDAP tree.'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -231,7 +323,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='BindUsername'
>
{'Bind Username:'}
<FormattedMessage
id='admin.ldap.bindUserTitle'
defaultMessage='Bind Username:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -244,7 +339,12 @@ export default class LdapSettings extends React.Component {
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'The username used to perform the LDAP search. This should typically be an account created specifically for use with Mattermost. It should have access limited to read the portion of the LDAP tree specified in the BaseDN field.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.bindUserDesc'
defaultMessage='The username used to perform the LDAP search. This should typically be an account created specifically for use with Mattermost. It should have access limited to read the portion of the LDAP tree specified in the BaseDN field.'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -252,7 +352,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='BindPassword'
>
{'Bind Password:'}
<FormattedMessage
id='admin.ldap.bindPwdTitle'
defaultMessage='Bind Password:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -265,7 +368,12 @@ export default class LdapSettings extends React.Component {
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'Password of the user given in "Bind Username".'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.bindPwdDesc'
defaultMessage='Password of the user given in "Bind Username".'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -273,7 +381,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='FirstNameAttribute'
>
{'First Name Attrubute'}
<FormattedMessage
id='admin.ldap.firstnameAttrTitle'
defaultMessage='First Name Attrubute'
/>
</label>
<div className='col-sm-8'>
<input
@@ -281,12 +392,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='FirstNameAttribute'
ref='FirstNameAttribute'
placeholder='Ex "givenName"'
placeholder={formatMessage(holders.firstnameAttrEx)}
defaultValue={this.props.config.LdapSettings.FirstNameAttribute}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'The attribute in the LDAP server that will be used to populate the first name of users in Mattermost.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.firstnameAttrDesc'
defaultMessage='The attribute in the LDAP server that will be used to populate the first name of users in Mattermost.'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -294,7 +410,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='LastNameAttribute'
>
{'Last Name Attribute:'}
<FormattedMessage
id='admin.ldap.lastnameAttrTitle'
defaultMessage='Last Name Attribute:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -302,12 +421,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='LastNameAttribute'
ref='LastNameAttribute'
placeholder='Ex "sn"'
placeholder={formatMessage(holders.lastnameAttrEx)}
defaultValue={this.props.config.LdapSettings.LastNameAttribute}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'The attribute in the LDAP server that will be used to populate the last name of users in Mattermost.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.lastnameAttrDesc'
defaultMessage='The attribute in the LDAP server that will be used to populate the last name of users in Mattermost.'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -315,7 +439,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EmailAttribute'
>
{'Email Attribute:'}
<FormattedMessage
id='admin.ldap.emailAttrTitle'
defaultMessage='Email Attribute:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -323,12 +450,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='EmailAttribute'
ref='EmailAttribute'
placeholder='Ex "mail"'
placeholder={formatMessage(holders.emailAttrEx)}
defaultValue={this.props.config.LdapSettings.EmailAttribute}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'The attribute in the LDAP server that will be used to populate the email addresses of users in Mattermost.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.emailAttrDesc'
defaultMessage='The attribute in the LDAP server that will be used to populate the email addresses of users in Mattermost.'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -336,7 +468,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='UsernameAttribute'
>
{'Username Attribute:'}
<FormattedMessage
id='admin.ldap.usernameAttrTitle'
defaultMessage='Username Attribute:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -344,12 +479,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='UsernameAttribute'
ref='UsernameAttribute'
placeholder='Ex "sAMAccountName"'
placeholder={formatMessage(holders.usernameAttrEx)}
defaultValue={this.props.config.LdapSettings.UsernameAttribute}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'The attribute in the LDAP server that will be used to populate the username field in Mattermost. This may be the same as the ID Attribute.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.uernameAttrDesc'
defaultMessage='The attribute in the LDAP server that will be used to populate the username field in Mattermost. This may be the same as the ID Attribute.'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -357,7 +497,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='IdAttribute'
>
{'Id Attribute: '}
<FormattedMessage
id='admin.ldap.idAttrTitle'
defaultMessage='Id Attribute: '
/>
</label>
<div className='col-sm-8'>
<input
@@ -365,12 +508,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='IdAttribute'
ref='IdAttribute'
placeholder='Ex "sAMAccountName"'
placeholder={formatMessage(holders.idAttrEx)}
defaultValue={this.props.config.LdapSettings.IdAttribute}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'The attribute in the LDAP server that will be used as a unique identifier in Mattermost. It should be an LDAP attribute with a value that does not change, such as username or uid. If a users Id Attribute changes, it will create a new Mattermost account unassociated with their old one. This is the value used to log in to Mattermost in the "LDAP Username" field on the sign in page. Normally this attribute is the same as the “Username Attribute” field above. If your team typically uses domain\\username to sign in to other services with LDAP, you may choose to put domain\\username in this field to maintain consistency between sites.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.idAttrDesc'
defaultMessage='The attribute in the LDAP server that will be used as a unique identifier in Mattermost. It should be an LDAP attribute with a value that does not change, such as username or uid. If a users Id Attribute changes, it will create a new Mattermost account unassociated with their old one. This is the value used to log in to Mattermost in the "LDAP Username" field on the sign in page. Normally this attribute is the same as the “Username Attribute” field above. If your team typically uses domain\\username to sign in to other services with LDAP, you may choose to put domain\\username in this field to maintain consistency between sites.'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -378,7 +526,10 @@ export default class LdapSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='QueryTimeout'
>
{'Query Timeout (seconds):'}
<FormattedMessage
id='admin.ldap.queryTitle'
defaultMessage='Query Timeout (seconds):'
/>
</label>
<div className='col-sm-8'>
<input
@@ -386,12 +537,17 @@ export default class LdapSettings extends React.Component {
className='form-control'
id='QueryTimeout'
ref='QueryTimeout'
placeholder='Ex "60"'
placeholder={formatMessage(holders.queryEx)}
defaultValue={this.props.config.LdapSettings.QueryTimeout}
onChange={this.handleChange}
disabled={!this.state.enable}
/>
<p className='help-text'>{'The timeout value for queries to the LDAP server. Increase if you are getting timeout errors caused by a slow LDAP server.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.ldap.queryDesc'
defaultMessage='The timeout value for queries to the LDAP server. Increase if you are getting timeout errors caused by a slow LDAP server.'
/>
</p>
</div>
</div>
<div className='form-group'>
@@ -403,9 +559,12 @@ export default class LdapSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
{'Save'}
<FormattedMessage
id='admin.ldap.save'
defaultMessage='Save'
/>
</button>
</div>
</div>
@@ -418,5 +577,8 @@ LdapSettings.defaultProps = {
};
LdapSettings.propTypes = {
intl: intlShape.isRequired,
config: React.PropTypes.object
};
export default injectIntl(LdapSettings);

Просмотреть файл

@@ -4,7 +4,16 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
export default class LegalAndSupportSettings extends React.Component {
import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
var holders = defineMessages({
saving: {
id: 'admin.support.saving',
defaultMessage: 'Saving Config...'
}
});
class LegalAndSupportSettings extends React.Component {
constructor(props) {
super(props);
@@ -69,7 +78,12 @@ export default class LegalAndSupportSettings extends React.Component {
return (
<div className='wrapper--fixed'>
<h3>{'Legal and Support Settings'}</h3>
<h3>
<FormattedMessage
id='admin.support.title'
defaultMessage='Legal and Support Settings'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -80,7 +94,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='TermsOfServiceLink'
>
{'Terms of Service link:'}
<FormattedMessage
id='admin.support.termsTitle'
defaultMessage='Terms of Service link:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -91,7 +108,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.TermsOfServiceLink}
onChange={this.handleChange}
/>
<p className='help-text'>{'Link to Terms of Service available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.support.termsDesc'
defaultMessage='Link to Terms of Service available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.'
/>
</p>
</div>
</div>
@@ -100,7 +122,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='PrivacyPolicyLink'
>
{'Privacy Policy link:'}
<FormattedMessage
id='admin.support.privacyTitle'
defaultMessage='Privacy Policy link:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -111,7 +136,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.PrivacyPolicyLink}
onChange={this.handleChange}
/>
<p className='help-text'>{'Link to Privacy Policy available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.support.privacyDesc'
defaultMessage='Link to Privacy Policy available to users on desktop and on mobile. Leaving this blank will hide the option to display a notice.'
/>
</p>
</div>
</div>
@@ -120,7 +150,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AboutLink'
>
{'About link:'}
<FormattedMessage
id='admin.support.aboutTitle'
defaultMessage='About link:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -131,7 +164,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.AboutLink}
onChange={this.handleChange}
/>
<p className='help-text'>{'Link to About page for more information on your Mattermost deployment, for example its purpose and audience within your organization. Defaults to Mattermost information page.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.support.aboutDesc'
defaultMessage='Link to About page for more information on your Mattermost deployment, for example its purpose and audience within your organization. Defaults to Mattermost information page.'
/>
</p>
</div>
</div>
@@ -140,7 +178,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='HelpLink'
>
{'Help link:'}
<FormattedMessage
id='admin.support.helpTitle'
defaultMessage='Help link:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -151,7 +192,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.HelpLink}
onChange={this.handleChange}
/>
<p className='help-text'>{'Link to help documentation from team site main menu. Typically not changed unless your organization chooses to create custom documentation.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.support.helpDesc'
defaultMessage='Link to help documentation from team site main menu. Typically not changed unless your organization chooses to create custom documentation.'
/>
</p>
</div>
</div>
@@ -160,7 +206,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ReportAProblemLink'
>
{'Report a Problem link:'}
<FormattedMessage
id='admin.support.problemTitle'
defaultMessage='Report a Problem link:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -171,7 +220,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.ReportAProblemLink}
onChange={this.handleChange}
/>
<p className='help-text'>{'Link to help documentation from team site main menu. By default this points to the peer-to-peer troubleshooting forum where users can search for, find and request help with technical issues.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.support.problemDesc'
defaultMessage='Link to help documentation from team site main menu. By default this points to the peer-to-peer troubleshooting forum where users can search for, find and request help with technical issues.'
/>
</p>
</div>
</div>
@@ -180,7 +234,10 @@ export default class LegalAndSupportSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SupportEmail'
>
{'Support email:'}
<FormattedMessage
id='admin.support.emailTitle'
defaultMessage='Support email:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -191,7 +248,12 @@ export default class LegalAndSupportSettings extends React.Component {
defaultValue={this.props.config.SupportSettings.SupportEmail}
onChange={this.handleChange}
/>
<p className='help-text'>{'Email shown during tutorial for end users to ask support questions.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.support.emailHelp'
defaultMessage='Email shown during tutorial for end users to ask support questions.'
/>
</p>
</div>
</div>
@@ -204,9 +266,12 @@ export default class LegalAndSupportSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + this.props.intl.formatMessage(holders.saving)}
>
{'Save'}
<FormattedMessage
id='admin.support.save'
defaultMessage='Save'
/>
</button>
</div>
</div>
@@ -218,5 +283,8 @@ export default class LegalAndSupportSettings extends React.Component {
}
LegalAndSupportSettings.propTypes = {
intl: intlShape.isRequired,
config: React.PropTypes.object
};
export default injectIntl(LegalAndSupportSettings);

Просмотреть файл

@@ -4,7 +4,20 @@
import * as Utils from '../../utils/utils.jsx';
import * as Client from '../../utils/client.jsx';
export default class LicenseSettings extends React.Component {
import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
const holders = defineMessages({
removing: {
id: 'admin.license.removing',
defaultMessage: 'Removing License...'
},
uploading: {
id: 'admin.license.uploading',
defaultMessage: 'Uploading License...'
}
});
class LicenseSettings extends React.Component {
constructor(props) {
super(props);
@@ -88,41 +101,26 @@ export default class LicenseSettings extends React.Component {
let licenseKey;
if (global.window.mm_license.IsLicensed === 'true') {
edition = 'Mattermost Enterprise Edition. Designed for enterprise-scale communication.';
edition = (
<FormattedMessage
id='admin.license.enterpriseEdition'
defaultMessage='Mattermost Enterprise Edition. Designed for enterprise-scale communication.'
/>
);
licenseType = (
<div>
<p>
{'This compiled release of Mattermost platform is provided under a '}
<a
href='http://mattermost.com'
target='_blank'
>
{'commercial license'}
</a>
{' from Mattermost, Inc. based on your subscription level and is subject to the '}
<a
href={global.window.mm_config.TermsOfServiceLink}
target='_blank'
>
{'Terms of Service.'}
</a>
</p>
<p>{'Your subscription details are as follows:'}</p>
{'Name: ' + global.window.mm_license.Name}
<br/>
{'Company or organization name: ' + global.window.mm_license.Company}
<br/>
{'Number of users: ' + global.window.mm_license.Users}
<br/>
{`License issued: ${Utils.displayDate(parseInt(global.window.mm_license.IssuedAt, 10))} ${Utils.displayTime(parseInt(global.window.mm_license.IssuedAt, 10), true)}`}
<br/>
{'Start date of license: ' + Utils.displayDate(parseInt(global.window.mm_license.StartsAt, 10))}
<br/>
{'Expiry date of license: ' + Utils.displayDate(parseInt(global.window.mm_license.ExpiresAt, 10))}
<br/>
{'LDAP: ' + global.window.mm_license.LDAP}
<br/>
</div>
<FormattedHTMLMessage
id='admin.license.entrepriseType'
defaultMessage='<div><p>This compiled release of Mattermost platform is provided under a <a href="http://mattermost.com" target="_blank">commercial license</a>
from Mattermost, Inc. based on your subscription level and is subject to the <a href="{terms}" target="_blank">Terms of Service.</a></p>
<p>Your subscription details are as follows:</p>
Name: {name}<br />
Company or organization name: {company}<br/>
Number of users: {users}<br/>
License issued: {issued}<br/>
Start date of license: {start}<br/>
Expiry date of license: {expires}<br/>
LDAP: {ldap}<br/></div>'
/>
);
licenseKey = (
@@ -131,32 +129,39 @@ export default class LicenseSettings extends React.Component {
className='btn btn-danger'
onClick={this.handleRemove}
id='remove-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Removing License...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + this.props.intl.formatMessage(holders.removing)}
>
{'Remove Enterprise License and Downgrade Server'}
<FormattedMessage
id='admin.license.keyRemove'
defaultMessage='Remove Enterprise License and Downgrade Server'
/>
</button>
<br/>
<br/>
<p className='help-text'>
{'If youre migrating servers you may need to remove your license key from this server in order to install it on a new server. To start, '}
<a
href='http://mattermost.com'
target='_blank'
>
{'disable all Enterprise Edition features on this server'}
</a>
{'. This will enable the ability to remove the license key and downgrade this server from Enterprise Edition to Team Edition.'}
<FormattedHTMLMessage
id='admin.licence.keyMigration'
defaultMessage='If youre migrating servers you may need to remove your license key from this server in order to install it on a new server. To start,
<a href="http://mattermost.com" target="_blank">disable all Enterprise Edition features on this server</a>.
This will enable the ability to remove the license key and downgrade this server from Enterprise Edition to Team Edition.'
/>
</p>
</div>
);
} else {
edition = 'Mattermost Team Edition. Designed for teams from 5 to 50 users.';
edition = (
<FormattedMessage
id='admin.license.teamEdition'
defaultMessage='Mattermost Team Edition. Designed for teams from 5 to 50 users.'
/>
);
licenseType = (
<span>
<p>{'This compiled release of Mattermost platform is offered under an MIT license.'}</p>
<p>{'See MIT-COMPILED-LICENSE.txt in your root install directory for details. See NOTICES.txt for information about open source software used in this system.'}</p>
</span>
<FormattedHTMLMessage
id='admin.license.teamType'
defaultMessage='<span><p>This compiled release of Mattermost platform is offered under an MIT license.</p>
<p>See MIT-COMPILED-LICENSE.txt in your root install directory for details. See NOTICES.txt for information about open source software used in this system.</p></span>'
/>
);
licenseKey = (
@@ -173,23 +178,23 @@ export default class LicenseSettings extends React.Component {
disabled={!this.state.fileSelected}
onClick={this.handleSubmit}
id='upload-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Uploading License...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + this.props.intl.formatMessage(holders.uploading)}
>
{'Upload'}
<FormattedMessage
id='admin.license.upload'
defaultMessage='Upload'
/>
</button>
<br/>
<br/>
<br/>
{serverError}
<p className='help-text'>
{'Upload a license key for Mattermost Enterprise Edition to upgrade this server. '}
<a
href='http://mattermost.com'
target='_blank'
>
{'Visit us online'}
</a>
{' to learn more about the benefits of Enterprise Edition or to purchase a key.'}
<FormattedHTMLMessage
id='admin.license.uploadDesc'
defaultMessage='Upload a license key for Mattermost Enterprise Edition to upgrade this server. <a href="http://mattermost.com" target="_blank">Visit us online</a>
to learn more about the benefits of Enterprise Edition or to purchase a key.'
/>
</p>
</div>
);
@@ -197,7 +202,12 @@ export default class LicenseSettings extends React.Component {
return (
<div className='wrapper--fixed'>
<h3>{'Edition and License'}</h3>
<h3>
<FormattedMessage
id='admin.license.title'
defaultMessage='Edition and License'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -206,7 +216,10 @@ export default class LicenseSettings extends React.Component {
<label
className='control-label col-sm-4'
>
{'Edition: '}
<FormattedMessage
id='admin.license.edition'
defaultMessage='Edition: '
/>
</label>
<div className='col-sm-8'>
{edition}
@@ -216,7 +229,10 @@ export default class LicenseSettings extends React.Component {
<label
className='control-label col-sm-4'
>
{'License: '}
<FormattedMessage
id='admin.license.type'
defaultMessage='License: '
/>
</label>
<div className='col-sm-8'>
{licenseType}
@@ -226,7 +242,10 @@ export default class LicenseSettings extends React.Component {
<label
className='control-label col-sm-4'
>
{'License Key: '}
<FormattedMessage
id='admin.license.key'
defaultMessage='License Key: '
/>
</label>
{licenseKey}
</div>
@@ -235,3 +254,9 @@ export default class LicenseSettings extends React.Component {
);
}
}
LicenseSettings.propTypes = {
intl: intlShape.isRequired
};
export default injectIntl(LicenseSettings);

Просмотреть файл

@@ -4,7 +4,24 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
export default class LogSettings extends React.Component {
import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
const holders = defineMessages({
locationPlaceholder: {
id: 'admin.log.locationPlaceholder',
defaultMessage: 'Enter your file location'
},
formatPlaceholder: {
id: 'admin.log.formatPlaceholder',
defaultMessage: 'Enter your file format'
},
saving: {
id: 'admin.log.saving',
defaultMessage: 'Saving Config...'
}
});
class LogSettings extends React.Component {
constructor(props) {
super(props);
@@ -78,6 +95,7 @@ export default class LogSettings extends React.Component {
}
render() {
const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -90,7 +108,12 @@ export default class LogSettings extends React.Component {
return (
<div className='wrapper--fixed'>
<h3>{'Log Settings'}</h3>
<h3>
<FormattedMessage
id='admin.log.logSettings'
defaultMessage='Log Settings'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -101,7 +124,10 @@ export default class LogSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='consoleEnable'
>
{'Log To The Console: '}
<FormattedMessage
id='admin.log.consoleTitle'
defaultMessage='Log To The Console: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -113,7 +139,10 @@ export default class LogSettings extends React.Component {
defaultChecked={this.props.config.LogSettings.EnableConsole}
onChange={this.handleChange.bind(this, 'console_true')}
/>
{'true'}
<FormattedMessage
id='admin.log.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -123,9 +152,17 @@ export default class LogSettings extends React.Component {
defaultChecked={!this.props.config.LogSettings.EnableConsole}
onChange={this.handleChange.bind(this, 'console_false')}
/>
{'false'}
<FormattedMessage
id='admin.log.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'Typically set to false in production. Developers may set this field to true to output log messages to console based on the console level option. If true, server writes messages to the standard output stream (stdout).'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.log.consoleDescription'
defaultMessage='Typically set to false in production. Developers may set this field to true to output log messages to console based on the console level option. If true, server writes messages to the standard output stream (stdout).'
/>
</p>
</div>
</div>
@@ -134,7 +171,10 @@ export default class LogSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='consoleLevel'
>
{'Console Log Level:'}
<FormattedMessage
id='admin.log.levelTitle'
defaultMessage='Console Log Level:'
/>
</label>
<div className='col-sm-8'>
<select
@@ -149,7 +189,12 @@ export default class LogSettings extends React.Component {
<option value='INFO'>{'INFO'}</option>
<option value='ERROR'>{'ERROR'}</option>
</select>
<p className='help-text'>{'This setting determines the level of detail at which log events are written to the console. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.log.levelDescription'
defaultMessage='This setting determines the level of detail at which log events are written to the console. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.'
/>
</p>
</div>
</div>
@@ -157,7 +202,10 @@ export default class LogSettings extends React.Component {
<label
className='control-label col-sm-4'
>
{'Log To File: '}
<FormattedMessage
id='admin.log.fileTitle'
defaultMessage='Log To File: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -169,7 +217,10 @@ export default class LogSettings extends React.Component {
defaultChecked={this.props.config.LogSettings.EnableFile}
onChange={this.handleChange.bind(this, 'file_true')}
/>
{'true'}
<FormattedMessage
id='admin.log.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -179,9 +230,17 @@ export default class LogSettings extends React.Component {
defaultChecked={!this.props.config.LogSettings.EnableFile}
onChange={this.handleChange.bind(this, 'file_false')}
/>
{'false'}
<FormattedMessage
id='admin.log.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'Typically set to true in production. When true, log files are written to the log file specified in file location field below.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.log.fileDescription'
defaultMessage='Typically set to true in production. When true, log files are written to the log file specified in file location field below.'
/>
</p>
</div>
</div>
@@ -190,7 +249,10 @@ export default class LogSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='fileLevel'
>
{'File Log Level:'}
<FormattedMessage
id='admin.log.fileLevelTitle'
defaultMessage='File Log Level:'
/>
</label>
<div className='col-sm-8'>
<select
@@ -205,7 +267,12 @@ export default class LogSettings extends React.Component {
<option value='INFO'>{'INFO'}</option>
<option value='ERROR'>{'ERROR'}</option>
</select>
<p className='help-text'>{'This setting determines the level of detail at which log events are written to the log file. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.log.fileLevelDescription'
defaultMessage='This setting determines the level of detail at which log events are written to the log file. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.'
/>
</p>
</div>
</div>
@@ -214,7 +281,10 @@ export default class LogSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='fileLocation'
>
{'File Location:'}
<FormattedMessage
id='admin.log.locationTitle'
defaultMessage='File Location:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -222,12 +292,17 @@ export default class LogSettings extends React.Component {
className='form-control'
id='fileLocation'
ref='fileLocation'
placeholder='Enter your file location'
placeholder={formatMessage(holders.locationPlaceholder)}
defaultValue={this.props.config.LogSettings.FileLocation}
onChange={this.handleChange}
disabled={!this.state.fileEnable}
/>
<p className='help-text'>{'File to which log files are written. If blank, will be set to ./logs/mattermost, which writes logs to mattermost.log. Log rotation is enabled and every 10,000 lines of log information is written to new files stored in the same directory, for example mattermost.2015-09-23.001, mattermost.2015-09-23.002, and so forth.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.log.locationDescription'
defaultMessage='File to which log files are written. If blank, will be set to ./logs/mattermost, which writes logs to mattermost.log. Log rotation is enabled and every 10,000 lines of log information is written to new files stored in the same directory, for example mattermost.2015-09-23.001, mattermost.2015-09-23.002, and so forth.'
/>
</p>
</div>
</div>
@@ -236,7 +311,10 @@ export default class LogSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='fileFormat'
>
{'File Format:'}
<FormattedMessage
id='admin.log.formatTitle'
defaultMessage='File Format:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -244,25 +322,58 @@ export default class LogSettings extends React.Component {
className='form-control'
id='fileFormat'
ref='fileFormat'
placeholder='Enter your file format'
placeholder={formatMessage(holders.formatPlaceholder)}
defaultValue={this.props.config.LogSettings.FileFormat}
onChange={this.handleChange}
disabled={!this.state.fileEnable}
/>
<div className='help-text'>
{'Format of log message output. If blank will be set to "[%D %T] [%L] %M", where:'}
<FormattedMessage
id='admin.log.formatDescription'
defaultMessage='Format of log message output. If blank will be set to "[%D %T] [%L] %M", where:'
/>
<div className='help-text'>
<table
className='table table-bordered'
cellPadding='5'
>
<tbody>
<tr><td className='help-text'>{'%T'}</td><td className='help-text'>{'Time (15:04:05 MST)'}</td></tr>
<tr><td className='help-text'>{'%D'}</td><td className='help-text'>{'Date (2006/01/02)'}</td></tr>
<tr><td className='help-text'>{'%d'}</td><td className='help-text'>{'Date (01/02/06)'}</td></tr>
<tr><td className='help-text'>{'%L'}</td><td className='help-text'>{'Level (DEBG, INFO, EROR)'}</td></tr>
<tr><td className='help-text'>{'%S'}</td><td className='help-text'>{'Source'}</td></tr>
<tr><td className='help-text'>{'%M'}</td><td className='help-text'>{'Message'}</td></tr>
<tr><td className='help-text'>{'%T'}</td><td className='help-text'>
<FormattedMessage
id='admin.log.formatTime'
defaultMessage='Time (15:04:05 MST)'
/>
</td></tr>
<tr><td className='help-text'>{'%D'}</td><td className='help-text'>
<FormattedMessage
id='admin.log.formatDateLong'
defaultMessage='Date (2006/01/02)'
/>
</td></tr>
<tr><td className='help-text'>{'%d'}</td><td className='help-text'>
<FormattedMessage
id='admin.log.formatDateShort'
defaultMessage='Date (01/02/06)'
/>
</td></tr>
<tr><td className='help-text'>{'%L'}</td><td className='help-text'>
<FormattedMessage
id='admin.log.formatLevel'
defaultMessage='Level (DEBG, INFO, EROR)'
/>
</td></tr>
<tr><td className='help-text'>{'%S'}</td><td className='help-text'>
<FormattedMessage
id='admin.log.formatSource'
defaultMessage='Source'
/>
</td></tr>
<tr><td className='help-text'>{'%M'}</td><td className='help-text'>
<FormattedMessage
id='admin.log.formatMessage'
defaultMessage='Message'
/>
</td></tr>
</tbody>
</table>
</div>
@@ -279,9 +390,12 @@ export default class LogSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
{'Save'}
<FormattedMessage
id='admin.log.save'
defaultMessage='Save'
/>
</button>
</div>
</div>
@@ -293,5 +407,8 @@ export default class LogSettings extends React.Component {
}
LogSettings.propTypes = {
intl: intlShape.isRequired,
config: React.PropTypes.object
};
export default injectIntl(LogSettings);

Просмотреть файл

@@ -5,6 +5,8 @@ import AdminStore from '../../stores/admin_store.jsx';
import LoadingScreen from '../loading_screen.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
import {FormattedMessage} from 'mm-intl';
export default class Logs extends React.Component {
constructor(props) {
super(props);
@@ -73,13 +75,21 @@ export default class Logs extends React.Component {
return (
<div className='panel'>
<h3>{'Server Logs'}</h3>
<h3>
<FormattedMessage
id='admin.logs.title'
defaultMessage='Server Logs'
/>
</h3>
<button
type='submit'
className='btn btn-primary'
onClick={this.reload}
>
{'Reload'}
<FormattedMessage
id='admin.logs.reload'
defaultMessage='Reload'
/>
</button>
<div className='log__panel'>
{content}

Просмотреть файл

@@ -4,7 +4,16 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
export default class PrivacySettings extends React.Component {
import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
const holders = defineMessages({
saving: {
id: 'admin.privacy.saving',
defaultMessage: 'Saving Config...'
}
});
class PrivacySettings extends React.Component {
constructor(props) {
super(props);
@@ -64,7 +73,12 @@ export default class PrivacySettings extends React.Component {
return (
<div className='wrapper--fixed'>
<h3>{'Privacy Settings'}</h3>
<h3>
<FormattedMessage
id='admin.privacy.title'
defaultMessage='Privacy Settings'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -75,7 +89,10 @@ export default class PrivacySettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ShowEmailAddress'
>
{'Show Email Address: '}
<FormattedMessage
id='admin.privacy.showEmailTitle'
defaultMessage='Show Email Address: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -87,7 +104,10 @@ export default class PrivacySettings extends React.Component {
defaultChecked={this.props.config.PrivacySettings.ShowEmailAddress}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.privacy.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -97,9 +117,17 @@ export default class PrivacySettings extends React.Component {
defaultChecked={!this.props.config.PrivacySettings.ShowEmailAddress}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.privacy.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When false, hides email address of users from other users in the user interface, including team owners and team administrators. Used when system is set up for managing teams where some users choose to keep their contact information private.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.privacy.showEmailDescription'
defaultMessage='When false, hides email address of users from other users in the user interface, including team owners and team administrators. Used when system is set up for managing teams where some users choose to keep their contact information private.'
/>
</p>
</div>
</div>
@@ -108,7 +136,10 @@ export default class PrivacySettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ShowFullName'
>
{'Show Full Name: '}
<FormattedMessage
id='admin.privacy.showFullNameTitle'
defaultMessage='Show Full Name: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -120,7 +151,10 @@ export default class PrivacySettings extends React.Component {
defaultChecked={this.props.config.PrivacySettings.ShowFullName}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.privacy.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -130,9 +164,17 @@ export default class PrivacySettings extends React.Component {
defaultChecked={!this.props.config.PrivacySettings.ShowFullName}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.privacy.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When false, hides full name of users from other users, including team owners and team administrators. Username is shown in place of full name.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.privacy.showFullNameDescription'
defaultMessage='When false, hides full name of users from other users, including team owners and team administrators. Username is shown in place of full name.'
/>
</p>
</div>
</div>
@@ -145,9 +187,12 @@ export default class PrivacySettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + this.props.intl.formatMessage(holders.saving)}
>
{'Save'}
<FormattedMessage
id='admin.privacy.save'
defaultMessage='Save'
/>
</button>
</div>
</div>
@@ -159,5 +204,8 @@ export default class PrivacySettings extends React.Component {
}
PrivacySettings.propTypes = {
intl: intlShape.isRequired,
config: React.PropTypes.object
};
export default injectIntl(PrivacySettings);

Просмотреть файл

@@ -4,7 +4,28 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
export default class RateSettings extends React.Component {
import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
const holders = defineMessages({
queriesExample: {
id: 'admin.rate.queriesExample',
defaultMessage: 'Ex "10"'
},
memoryExample: {
id: 'admin.rate.memoryExample',
defaultMessage: 'Ex "10000"'
},
httpHeaderExample: {
id: 'admin.rate.httpHeaderExample',
defaultMessage: 'Ex "X-Real-IP", "X-Forwarded-For"'
},
saving: {
id: 'admin.rate.saving',
defaultMessage: 'Saving Config...'
}
});
class RateSettings extends React.Component {
constructor(props) {
super(props);
@@ -85,6 +106,7 @@ export default class RateSettings extends React.Component {
}
render() {
const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -100,12 +122,27 @@ export default class RateSettings extends React.Component {
<div className='banner'>
<div className='banner__content'>
<h4 className='banner__heading'>{'Note:'}</h4>
<p>{'Changing properties in this section will require a server restart before taking effect.'}</p>
<h4 className='banner__heading'>
<FormattedMessage
id='admin.rate.noteTitle'
defaultMessage='Note:'
/>
</h4>
<p>
<FormattedMessage
id='admin.rate.noteDescription'
defaultMessage='Changing properties in this section will require a server restart before taking effect.'
/>
</p>
</div>
</div>
<h3>{'Rate Limit Settings'}</h3>
<h3>
<FormattedMessage
id='admin.rate.title'
defaultMessage='Rate Limit Settings'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -116,7 +153,10 @@ export default class RateSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableRateLimiter'
>
{'Enable Rate Limiter: '}
<FormattedMessage
id='admin.rate.enableLimiterTitle'
defaultMessage='Enable Rate Limiter: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -128,7 +168,10 @@ export default class RateSettings extends React.Component {
defaultChecked={this.props.config.RateLimitSettings.EnableRateLimiter}
onChange={this.handleChange.bind(this, 'EnableRateLimiterTrue')}
/>
{'true'}
<FormattedMessage
id='admin.rate.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -138,9 +181,17 @@ export default class RateSettings extends React.Component {
defaultChecked={!this.props.config.RateLimitSettings.EnableRateLimiter}
onChange={this.handleChange.bind(this, 'EnableRateLimiterFalse')}
/>
{'false'}
<FormattedMessage
id='admin.rate.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When true, APIs are throttled at rates specified below.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.rate.enableLimiterDescription'
defaultMessage='When true, APIs are throttled at rates specified below.'
/>
</p>
</div>
</div>
@@ -149,7 +200,10 @@ export default class RateSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='PerSec'
>
{'Number Of Queries Per Second:'}
<FormattedMessage
id='admin.rate.queriesTitle'
defaultMessage='Number Of Queries Per Second:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -157,12 +211,17 @@ export default class RateSettings extends React.Component {
className='form-control'
id='PerSec'
ref='PerSec'
placeholder='Ex "10"'
placeholder={formatMessage(holders.queriesExample)}
defaultValue={this.props.config.RateLimitSettings.PerSec}
onChange={this.handleChange}
disabled={!this.state.EnableRateLimiter}
/>
<p className='help-text'>{'Throttles API at this number of requests per second.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.rate.queriesDescription'
defaultMessage='Throttles API at this number of requests per second.'
/>
</p>
</div>
</div>
@@ -171,7 +230,10 @@ export default class RateSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='MemoryStoreSize'
>
{'Memory Store Size:'}
<FormattedMessage
id='admin.rate.memoryTitle'
defaultMessage='Memory Store Size:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -179,12 +241,17 @@ export default class RateSettings extends React.Component {
className='form-control'
id='MemoryStoreSize'
ref='MemoryStoreSize'
placeholder='Ex "10000"'
placeholder={formatMessage(holders.memoryExample)}
defaultValue={this.props.config.RateLimitSettings.MemoryStoreSize}
onChange={this.handleChange}
disabled={!this.state.EnableRateLimiter}
/>
<p className='help-text'>{'Maximum number of users sessions connected to the system as determined by "Vary By Remote Address" and "Vary By Header" settings below.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.rate.memoryDescription'
defaultMessage='Maximum number of users sessions connected to the system as determined by "Vary By Remote Address" and "Vary By Header" settings below.'
/>
</p>
</div>
</div>
@@ -193,7 +260,10 @@ export default class RateSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='VaryByRemoteAddr'
>
{'Vary By Remote Address: '}
<FormattedMessage
id='admin.rate.remoteTitle'
defaultMessage='Vary By Remote Address: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -206,7 +276,10 @@ export default class RateSettings extends React.Component {
onChange={this.handleChange.bind(this, 'VaryByRemoteAddrTrue')}
disabled={!this.state.EnableRateLimiter}
/>
{'true'}
<FormattedMessage
id='admin.rate.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -217,9 +290,17 @@ export default class RateSettings extends React.Component {
onChange={this.handleChange.bind(this, 'VaryByRemoteAddrFalse')}
disabled={!this.state.EnableRateLimiter}
/>
{'false'}
<FormattedMessage
id='admin.rate.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When true, rate limit API access by IP address.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.rate.remoteDescription'
defaultMessage='When true, rate limit API access by IP address.'
/>
</p>
</div>
</div>
@@ -228,7 +309,10 @@ export default class RateSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='VaryByHeader'
>
{'Vary By HTTP Header:'}
<FormattedMessage
id='admin.rate.httpHeaderTitle'
defaultMessage='Vary By HTTP Header:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -236,12 +320,17 @@ export default class RateSettings extends React.Component {
className='form-control'
id='VaryByHeader'
ref='VaryByHeader'
placeholder='Ex "X-Real-IP", "X-Forwarded-For"'
placeholder={formatMessage(holders.httpHeaderExample)}
defaultValue={this.props.config.RateLimitSettings.VaryByHeader}
onChange={this.handleChange}
disabled={!this.state.EnableRateLimiter || this.state.VaryByRemoteAddr}
/>
<p className='help-text'>{'When filled in, vary rate limiting by HTTP header field specified (e.g. when configuring NGINX set to "X-Real-IP", when configuring AmazonELB set to "X-Forwarded-For").'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.rate.httpHeaderDescription'
defaultMessage='When filled in, vary rate limiting by HTTP header field specified (e.g. when configuring NGINX set to "X-Real-IP", when configuring AmazonELB set to "X-Forwarded-For").'
/>
</p>
</div>
</div>
@@ -254,9 +343,12 @@ export default class RateSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
{'Save'}
<FormattedMessage
id='admin.rate.save'
defaultMessage='Save'
/>
</button>
</div>
</div>
@@ -268,5 +360,8 @@ export default class RateSettings extends React.Component {
}
RateSettings.propTypes = {
intl: intlShape.isRequired,
config: React.PropTypes.object
};
export default injectIntl(RateSettings);

Просмотреть файл

@@ -5,7 +5,16 @@ import * as Client from '../../utils/client.jsx';
import Constants from '../../utils/constants.jsx';
var Modal = ReactBootstrap.Modal;
export default class ResetPasswordModal extends React.Component {
import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
var holders = defineMessages({
submit: {
id: 'admin.reset_password.submit',
defaultMessage: 'Please enter at least {chars} characters.'
}
});
class ResetPasswordModal extends React.Component {
constructor(props) {
super(props);
@@ -22,7 +31,7 @@ export default class ResetPasswordModal extends React.Component {
var password = ReactDOM.findDOMNode(this.refs.password).value;
if (!password || password.length < Constants.MIN_PASSWORD_LENGTH) {
this.setState({serverError: 'Please enter at least ' + Constants.MIN_PASSWORD_LENGTH + ' characters.'});
this.setState({serverError: this.props.intl.formatMessage(holders.submit, {chars: Constants.MIN_PASSWORD_LENGTH})});
return;
}
@@ -67,7 +76,12 @@ export default class ResetPasswordModal extends React.Component {
onHide={this.doCancel}
>
<Modal.Header closeButton={true}>
<Modal.Title>{'Reset Password'}</Modal.Title>
<Modal.Title>
<FormattedMessage
id='admin.reset_password.title'
defaultMessage='Reset Password'
/>
</Modal.Title>
</Modal.Header>
<form
role='form'
@@ -82,7 +96,10 @@ export default class ResetPasswordModal extends React.Component {
title='New Password'
className='input-group-addon'
>
{'New Password'}
<FormattedMessage
id='admin.reset_password.newPassword'
defaultMessage='New Password'
/>
</span>
<input
type='password'
@@ -103,7 +120,10 @@ export default class ResetPasswordModal extends React.Component {
className='btn btn-default'
onClick={this.doCancel}
>
{'Close'}
<FormattedMessage
id='admin.reset_password.close'
defaultMessage='Close'
/>
</button>
<button
onClick={this.doSubmit}
@@ -111,7 +131,10 @@ export default class ResetPasswordModal extends React.Component {
className='btn btn-primary'
tabIndex='2'
>
{'Select'}
<FormattedMessage
id='admin.reset_password.select'
defaultMessage='Select'
/>
</button>
</Modal.Footer>
</form>
@@ -125,9 +148,12 @@ ResetPasswordModal.defaultProps = {
};
ResetPasswordModal.propTypes = {
intl: intlShape.isRequired,
user: React.PropTypes.object,
team: React.PropTypes.object,
show: React.PropTypes.bool.isRequired,
onModalSubmit: React.PropTypes.func,
onModalDismissed: React.PropTypes.func
};
export default injectIntl(ResetPasswordModal);

Просмотреть файл

@@ -4,11 +4,40 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
import {injectIntl, intlShape, defineMessages, FormattedMessage, FormattedHTMLMessage} from 'mm-intl';
const DefaultSessionLength = 30;
const DefaultMaximumLoginAttempts = 10;
const DefaultSessionCacheInMinutes = 10;
export default class ServiceSettings extends React.Component {
var holders = defineMessages({
listenExample: {
id: 'admin.service.listenExample',
defaultMessage: 'Ex ":8065"'
},
attemptExample: {
id: 'admin.service.attemptExample',
defaultMessage: 'Ex "10"'
},
segmentExample: {
id: 'admin.service.segmentExample',
defaultMessage: 'Ex "g3fgGOXJAQ43QV7rAh6iwQCkV4cA1Gs"'
},
googleExample: {
id: 'admin.service.googleExample',
defaultMessage: 'Ex "7rAh6iwQCkV4cA1Gsg3fgGOXJAQ43QV"'
},
sessionDaysEx: {
id: 'admin.service.sessionDaysEx',
defaultMessage: 'Ex "30"'
},
saving: {
id: 'admin.service.saving',
defaultMessage: 'Saving Config...'
}
});
class ServiceSettings extends React.Component {
constructor(props) {
super(props);
@@ -120,6 +149,7 @@ export default class ServiceSettings extends React.Component {
}
render() {
const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -133,7 +163,12 @@ export default class ServiceSettings extends React.Component {
return (
<div className='wrapper--fixed'>
<h3>{'Service Settings'}</h3>
<h3>
<FormattedMessage
id='admin.service.title'
defaultMessage='Service Settings'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -144,7 +179,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='ListenAddress'
>
{'Listen Address:'}
<FormattedMessage
id='admin.service.listenAddress'
defaultMessage='Listen Address:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -152,11 +190,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='ListenAddress'
ref='ListenAddress'
placeholder='Ex ":8065"'
placeholder={formatMessage(holders.listenExample)}
defaultValue={this.props.config.ServiceSettings.ListenAddress}
onChange={this.handleChange}
/>
<p className='help-text'>{'The address to which to bind and listen. Entering ":8065" will bind to all interfaces or you can choose one like "127.0.0.1:8065". Changing this will require a server restart before taking effect.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.listenDescription'
defaultMessage='The address to which to bind and listen. Entering ":8065" will bind to all interfaces or you can choose one like "127.0.0.1:8065". Changing this will require a server restart before taking effect.'
/>
</p>
</div>
</div>
@@ -165,7 +208,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='MaximumLoginAttempts'
>
{'Maximum Login Attempts:'}
<FormattedMessage
id='admin.service.attemptTitle'
defaultMessage='Maximum Login Attempts:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -173,11 +219,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='MaximumLoginAttempts'
ref='MaximumLoginAttempts'
placeholder='Ex "10"'
placeholder={formatMessage(holders.attemptExample)}
defaultValue={this.props.config.ServiceSettings.MaximumLoginAttempts}
onChange={this.handleChange}
/>
<p className='help-text'>{'Login attempts allowed before user is locked out and required to reset password via email.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.attemptDescription'
defaultMessage='Login attempts allowed before user is locked out and required to reset password via email.'
/>
</p>
</div>
</div>
@@ -186,7 +237,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SegmentDeveloperKey'
>
{'Segment Developer Key:'}
<FormattedMessage
id='admin.service.segmentTitle'
defaultMessage='Segment Developer Key:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -194,11 +248,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='SegmentDeveloperKey'
ref='SegmentDeveloperKey'
placeholder='Ex "g3fgGOXJAQ43QV7rAh6iwQCkV4cA1Gs"'
placeholder={formatMessage(holders.segmentExample)}
defaultValue={this.props.config.ServiceSettings.SegmentDeveloperKey}
onChange={this.handleChange}
/>
<p className='help-text'>{'For users running a SaaS services, sign up for a key at Segment.com to track metrics.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.segmentDescription'
defaultMessage='For users running a SaaS services, sign up for a key at Segment.com to track metrics.'
/>
</p>
</div>
</div>
@@ -207,7 +266,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='GoogleDeveloperKey'
>
{'Google Developer Key:'}
<FormattedMessage
id='admin.service.googleTitle'
defaultMessage='Google Developer Key:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -215,19 +277,17 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='GoogleDeveloperKey'
ref='GoogleDeveloperKey'
placeholder='Ex "7rAh6iwQCkV4cA1Gsg3fgGOXJAQ43QV"'
placeholder={formatMessage(holders.googleExample)}
defaultValue={this.props.config.ServiceSettings.GoogleDeveloperKey}
onChange={this.handleChange}
/>
<p className='help-text'>
{'Set this key to enable embedding of YouTube video previews based on hyperlinks appearing in messages or comments. Instructions to obtain a key available at '}
<a
href='https://www.youtube.com/watch?v=Im69kzhpR3I'
target='_blank'
>
{'https://www.youtube.com/watch?v=Im69kzhpR3I'}
</a>
{'. Leaving the field blank disables the automatic generation of YouTube video previews from links.'}
<FormattedHTMLMessage
id='admin.service.googleDescription'
defaultMessage='Set this key to enable embedding of YouTube video previews based on hyperlinks appearing in messages or comments. Instructions to obtain a key available at
<a href="https://www.youtube.com/watch?v=Im69kzhpR3I" target="_blank">https://www.youtube.com/watch?v=Im69kzhpR3I</a>.
Leaving the field blank disables the automatic generation of YouTube video previews from links.'
/>
</p>
</div>
</div>
@@ -237,7 +297,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableIncomingWebhooks'
>
{'Enable Incoming Webhooks: '}
<FormattedMessage
id='admin.service.webhooksTitle'
defaultMessage='Enable Incoming Webhooks: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -249,7 +312,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnableIncomingWebhooks}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.service.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -259,9 +325,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnableIncomingWebhooks}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.service.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When true, incoming webhooks will be allowed. To help combat phishing attacks, all posts from webhooks will be labelled by a BOT tag.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.webhooksDescription'
defaultMessage='When true, incoming webhooks will be allowed. To help combat phishing attacks, all posts from webhooks will be labelled by a BOT tag.'
/>
</p>
</div>
</div>
@@ -270,7 +344,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableOutgoingWebhooks'
>
{'Enable Outgoing Webhooks: '}
<FormattedMessage
id='admin.service.outWebhooksTitle'
defaultMessage='Enable Outgoing Webhooks: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -282,7 +359,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnableOutgoingWebhooks}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.service.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -292,9 +372,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnableOutgoingWebhooks}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.service.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When true, outgoing webhooks will be allowed.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.outWebhooksDesc'
defaultMessage='When true, outgoing webhooks will be allowed.'
/>
</p>
</div>
</div>
@@ -303,7 +391,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnablePostUsernameOverride'
>
{'Enable Overriding Usernames from Webhooks: '}
<FormattedMessage
id='admin.service.overrideTitle'
defaultMessage='Enable Overriding Usernames from Webhooks: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -315,7 +406,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnablePostUsernameOverride}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.service.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -325,9 +419,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnablePostUsernameOverride}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.service.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When true, webhooks will be allowed to change the username they are posting as. Note, combined with allowing icon overriding, this could open users up to phishing attacks.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.overrideDescription'
defaultMessage='When true, webhooks will be allowed to change the username they are posting as. Note, combined with allowing icon overriding, this could open users up to phishing attacks.'
/>
</p>
</div>
</div>
@@ -336,7 +438,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnablePostIconOverride'
>
{'Enable Overriding Icon from Webhooks: '}
<FormattedMessage
id='admin.service.iconTitle'
defaultMessage='Enable Overriding Icon from Webhooks: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -348,7 +453,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnablePostIconOverride}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.service.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -358,9 +466,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnablePostIconOverride}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.service.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When true, webhooks will be allowed to change the icon they post with. Note, combined with allowing username overriding, this could open users up to phishing attacks.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.iconDescription'
defaultMessage='When true, webhooks will be allowed to change the icon they post with. Note, combined with allowing username overriding, this could open users up to phishing attacks.'
/>
</p>
</div>
</div>
@@ -369,7 +485,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableTesting'
>
{'Enable Testing: '}
<FormattedMessage
id='admin.service.testingTitle'
defaultMessage='Enable Testing: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -381,7 +500,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnableTesting}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.service.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -391,9 +513,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnableTesting}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.service.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'(Developer Option) When true, /loadtest slash command is enabled to load test accounts and test data. Changing this will require a server restart before taking effect.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.testingDescription'
defaultMessage='(Developer Option) When true, /loadtest slash command is enabled to load test accounts and test data. Changing this will require a server restart before taking effect.'
/>
</p>
</div>
</div>
@@ -402,7 +532,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableDeveloper'
>
{'Enable Developer Mode: '}
<FormattedMessage
id='admin.service.developerTitle'
defaultMessage='Enable Developer Mode: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -414,7 +547,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnableDeveloper}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.service.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -424,9 +560,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnableDeveloper}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.service.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'(Developer Option) When true, extra information around errors will be displayed in the UI.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.developerDesc'
defaultMessage='(Developer Option) When true, extra information around errors will be displayed in the UI.'
/>
</p>
</div>
</div>
@@ -435,7 +579,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableSecurityFixAlert'
>
{'Enable Security Alerts: '}
<FormattedMessage
id='admin.service.securityTitle'
defaultMessage='Enable Security Alerts: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -447,7 +594,10 @@ export default class ServiceSettings extends React.Component {
defaultChecked={this.props.config.ServiceSettings.EnableSecurityFixAlert}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.service.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -457,9 +607,17 @@ export default class ServiceSettings extends React.Component {
defaultChecked={!this.props.config.ServiceSettings.EnableSecurityFixAlert}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.service.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When true, System Administrators are notified by email if a relevant security fix alert has been announced in the last 12 hours. Requires email to be enabled.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.securityDesc'
defaultMessage='When true, System Administrators are notified by email if a relevant security fix alert has been announced in the last 12 hours. Requires email to be enabled.'
/>
</p>
</div>
</div>
@@ -468,7 +626,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SessionLengthWebInDays'
>
{'Session Length for Web in Days:'}
<FormattedMessage
id='admin.service.webSessionDays'
defaultMessage='Session Length for Web in Days:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -476,11 +637,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='SessionLengthWebInDays'
ref='SessionLengthWebInDays'
placeholder='Ex "30"'
placeholder={formatMessage(holders.sessionDaysEx)}
defaultValue={this.props.config.ServiceSettings.SessionLengthWebInDays}
onChange={this.handleChange}
/>
<p className='help-text'>{'The web session will expire after the number of days specified and will require a user to login again.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.webSessionDaysDesc'
defaultMessage='The web session will expire after the number of days specified and will require a user to login again.'
/>
</p>
</div>
</div>
@@ -489,7 +655,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SessionLengthMobileInDays'
>
{'Session Length for Mobile Device in Days:'}
<FormattedMessage
id='admin.service.mobileSessionDays'
defaultMessage='Session Length for Mobile Device in Days:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -497,11 +666,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='SessionLengthMobileInDays'
ref='SessionLengthMobileInDays'
placeholder='Ex "30"'
placeholder={formatMessage(holders.sessionDaysEx)}
defaultValue={this.props.config.ServiceSettings.SessionLengthMobileInDays}
onChange={this.handleChange}
/>
<p className='help-text'>{'The native mobile session will expire after the number of days specified and will require a user to login again.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.mobileSessionDaysDesc'
defaultMessage='The native mobile session will expire after the number of days specified and will require a user to login again.'
/>
</p>
</div>
</div>
@@ -510,7 +684,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SessionLengthSSOInDays'
>
{'Session Length for SSO in Days:'}
<FormattedMessage
id='admin.service.ssoSessionDays'
defaultMessage='Session Length for SSO in Days:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -518,11 +695,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='SessionLengthSSOInDays'
ref='SessionLengthSSOInDays'
placeholder='Ex "30"'
placeholder={formatMessage(holders.sessionDaysEx)}
defaultValue={this.props.config.ServiceSettings.SessionLengthSSOInDays}
onChange={this.handleChange}
/>
<p className='help-text'>{'The SSO session will expire after the number of days specified and will require a user to login again.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.ssoSessionDaysDesc'
defaultMessage='The SSO session will expire after the number of days specified and will require a user to login again.'
/>
</p>
</div>
</div>
@@ -531,7 +713,10 @@ export default class ServiceSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SessionCacheInMinutes'
>
{'Session Cache in Minutes:'}
<FormattedMessage
id='admin.service.sessionCache'
defaultMessage='Session Cache in Minutes:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -539,11 +724,16 @@ export default class ServiceSettings extends React.Component {
className='form-control'
id='SessionCacheInMinutes'
ref='SessionCacheInMinutes'
placeholder='Ex "30"'
placeholder={formatMessage(holders.sessionDaysEx)}
defaultValue={this.props.config.ServiceSettings.SessionCacheInMinutes}
onChange={this.handleChange}
/>
<p className='help-text'>{'The number of minutes to cache a session in memory.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.service.sessionCacheDesc'
defaultMessage='The number of minutes to cache a session in memory.'
/>
</p>
</div>
</div>
@@ -556,9 +746,12 @@ export default class ServiceSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
{'Save'}
<FormattedMessage
id='admin.service.save'
defaultMessage='Save'
/>
</button>
</div>
</div>
@@ -603,5 +796,8 @@ export default class ServiceSettings extends React.Component {
// </div>
ServiceSettings.propTypes = {
intl: intlShape.isRequired,
config: React.PropTypes.object
};
export default injectIntl(ServiceSettings);

Просмотреть файл

@@ -5,7 +5,32 @@ import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
import crypto from 'crypto';
export default class SqlSettings extends React.Component {
import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
const holders = defineMessages({
warning: {
id: 'admin.sql.warning',
defaultMessage: 'Warning: re-generating this salt may cause some columns in the database to return empty results.'
},
maxConnectionsExample: {
id: 'admin.sql.maxConnectionsExample',
defaultMessage: 'Ex "10"'
},
maxOpenExample: {
id: 'admin.sql.maxOpenExample',
defaultMessage: 'Ex "10"'
},
keyExample: {
id: 'admin.sql.keyExample',
defaultMessage: 'Ex "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"'
},
saving: {
id: 'admin.sql.saving',
defaultMessage: 'Saving Config...'
}
});
class SqlSettings extends React.Component {
constructor(props) {
super(props);
@@ -74,7 +99,7 @@ export default class SqlSettings extends React.Component {
handleGenerate(e) {
e.preventDefault();
var cfm = global.window.confirm('Warning: re-generating this salt may cause some columns in the database to return empty results.');
var cfm = global.window.confirm(this.props.intl.formatMessage(holders.warning));
if (cfm === false) {
return;
}
@@ -85,6 +110,7 @@ export default class SqlSettings extends React.Component {
}
render() {
const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -111,12 +137,27 @@ export default class SqlSettings extends React.Component {
<div className='banner'>
<div className='banner__content'>
<h4 className='banner__heading'>{'Note:'}</h4>
<p>{'Changing properties in this section will require a server restart before taking effect.'}</p>
<h4 className='banner__heading'>
<FormattedMessage
id='admin.sql.noteTitle'
defaultMessage='Note:'
/>
</h4>
<p>
<FormattedMessage
id='admin.sql.noteDescription'
defaultMessage='Changing properties in this section will require a server restart before taking effect.'
/>
</p>
</div>
</div>
<h3>{'SQL Settings'}</h3>
<h3>
<FormattedMessage
id='admin.sql.title'
defaultMessage='SQL Settings'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -127,7 +168,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='DriverName'
>
{'Driver Name:'}
<FormattedMessage
id='admin.sql.driverName'
defaultMessage='Driver Name:'
/>
</label>
<div className='col-sm-8'>
<p className='help-text'>{this.props.config.SqlSettings.DriverName}</p>
@@ -139,7 +183,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='DataSource'
>
{'Data Source:'}
<FormattedMessage
id='admin.sql.dataSource'
defaultMessage='Data Source:'
/>
</label>
<div className='col-sm-8'>
<p className='help-text'>{dataSource}</p>
@@ -151,7 +198,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='DataSourceReplicas'
>
{'Data Source Replicas:'}
<FormattedMessage
id='admin.sql.replicas'
defaultMessage='Data Source Replicas:'
/>
</label>
<div className='col-sm-8'>
<p className='help-text'>{dataSourceReplicas}</p>
@@ -163,7 +213,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='MaxIdleConns'
>
{'Maximum Idle Connections:'}
<FormattedMessage
id='admin.sql.maxConnectionsTitle'
defaultMessage='Maximum Idle Connections:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -171,11 +224,16 @@ export default class SqlSettings extends React.Component {
className='form-control'
id='MaxIdleConns'
ref='MaxIdleConns'
placeholder='Ex "10"'
placeholder={formatMessage(holders.maxConnectionsExample)}
defaultValue={this.props.config.SqlSettings.MaxIdleConns}
onChange={this.handleChange}
/>
<p className='help-text'>{'Maximum number of idle connections held open to the database.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.sql.maxConnectionsDescription'
defaultMessage='Maximum number of idle connections held open to the database.'
/>
</p>
</div>
</div>
@@ -184,7 +242,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='MaxOpenConns'
>
{'Maximum Open Connections:'}
<FormattedMessage
id='admin.sql.maxOpenTitle'
defaultMessage='Maximum Open Connections:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -192,11 +253,16 @@ export default class SqlSettings extends React.Component {
className='form-control'
id='MaxOpenConns'
ref='MaxOpenConns'
placeholder='Ex "10"'
placeholder={formatMessage(holders.maxOpenExample)}
defaultValue={this.props.config.SqlSettings.MaxOpenConns}
onChange={this.handleChange}
/>
<p className='help-text'>{'Maximum number of open connections held open to the database.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.sql.maxOpenDescription'
defaultMessage='Maximum number of open connections held open to the database.'
/>
</p>
</div>
</div>
@@ -205,7 +271,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='AtRestEncryptKey'
>
{'At Rest Encrypt Key:'}
<FormattedMessage
id='admin.sql.keyTitle'
defaultMessage='At Rest Encrypt Key:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -213,17 +282,25 @@ export default class SqlSettings extends React.Component {
className='form-control'
id='AtRestEncryptKey'
ref='AtRestEncryptKey'
placeholder='Ex "gxHVDcKUyP2y1eiyW8S8na1UYQAfq6J6"'
placeholder={formatMessage(holders.keyExample)}
defaultValue={this.props.config.SqlSettings.AtRestEncryptKey}
onChange={this.handleChange}
/>
<p className='help-text'>{'32-character salt available to encrypt and decrypt sensitive fields in database.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.sql.keyDescription'
defaultMessage='32-character salt available to encrypt and decrypt sensitive fields in database.'
/>
</p>
<div className='help-text'>
<button
className='btn btn-default'
onClick={this.handleGenerate}
>
{'Re-Generate'}
<FormattedMessage
id='admin.sql.regenerate'
defaultMessage='Re-Generate'
/>
</button>
</div>
</div>
@@ -234,7 +311,10 @@ export default class SqlSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='Trace'
>
{'Trace: '}
<FormattedMessage
id='admin.sql.traceTitle'
defaultMessage='Trace: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -246,7 +326,10 @@ export default class SqlSettings extends React.Component {
defaultChecked={this.props.config.SqlSettings.Trace}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.sql.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -256,9 +339,17 @@ export default class SqlSettings extends React.Component {
defaultChecked={!this.props.config.SqlSettings.Trace}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.sql.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'(Development Mode) When true, executing SQL statements are written to the log.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.sql.traceDescription'
defaultMessage='(Development Mode) When true, executing SQL statements are written to the log.'
/>
</p>
</div>
</div>
@@ -271,9 +362,12 @@ export default class SqlSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
{'Save'}
<FormattedMessage
id='admin.sql.save'
defaultMessage='Save'
/>
</button>
</div>
</div>
@@ -285,5 +379,8 @@ export default class SqlSettings extends React.Component {
}
SqlSettings.propTypes = {
intl: intlShape.isRequired,
config: React.PropTypes.object
};
export default injectIntl(SqlSettings);

Просмотреть файл

@@ -4,7 +4,24 @@
import Analytics from './analytics.jsx';
import * as Client from '../../utils/client.jsx';
export default class SystemAnalytics extends React.Component {
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);
@@ -29,6 +46,7 @@ export default class SystemAnalytics extends React.Component {
}
getData() { // should be moved to an action creator eventually
const {formatMessage} = this.props.intl;
Client.getSystemAnalytics(
'standard',
(data) => {
@@ -63,7 +81,7 @@ export default class SystemAnalytics extends React.Component {
var chartData = {
labels: [],
datasets: [{
label: 'Total Posts',
label: formatMessage(labels.totalPosts),
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
@@ -97,7 +115,7 @@ export default class SystemAnalytics extends React.Component {
var chartData = {
labels: [],
datasets: [{
label: 'Active Users With Posts',
label: formatMessage(labels.activeUsers),
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
@@ -142,7 +160,7 @@ export default class SystemAnalytics extends React.Component {
return (
<div>
<Analytics
title={'the System'}
title={this.props.intl.formatMessage(labels.title)}
channelOpenCount={this.state.channel_open_count}
channelPrivateCount={this.state.channel_private_count}
postCount={this.state.post_count}
@@ -157,5 +175,8 @@ export default class SystemAnalytics extends React.Component {
}
SystemAnalytics.propTypes = {
intl: intlShape.isRequired,
team: React.PropTypes.object
};
export default injectIntl(SystemAnalytics);

Просмотреть файл

@@ -4,7 +4,20 @@
import Analytics from './analytics.jsx';
import * as Client from '../../utils/client.jsx';
export default class TeamAnalytics extends React.Component {
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);
@@ -29,6 +42,7 @@ export default class TeamAnalytics extends React.Component {
}
getData(teamId) { // should be moved to an action creator eventually
const {formatMessage} = this.props.intl;
Client.getTeamAnalytics(
teamId,
'standard',
@@ -65,7 +79,7 @@ export default class TeamAnalytics extends React.Component {
var chartData = {
labels: [],
datasets: [{
label: 'Total Posts',
label: formatMessage(labels.totalPosts),
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
@@ -100,7 +114,7 @@ export default class TeamAnalytics extends React.Component {
var chartData = {
labels: [],
datasets: [{
label: 'Active Users With Posts',
label: formatMessage(labels.activeUsers),
fillColor: 'rgba(151,187,205,0.2)',
strokeColor: 'rgba(151,187,205,1)',
pointColor: 'rgba(151,187,205,1)',
@@ -231,5 +245,8 @@ export default class TeamAnalytics extends React.Component {
}
TeamAnalytics.propTypes = {
intl: intlShape.isRequired,
team: React.PropTypes.object
};
export default injectIntl(TeamAnalytics);

Просмотреть файл

@@ -4,7 +4,28 @@
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
export default class TeamSettings extends React.Component {
import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl';
const holders = defineMessages({
siteNameExample: {
id: 'admin.team.siteNameExample',
defaultMessage: 'Ex "Mattermost"'
},
maxUsersExample: {
id: 'admin.team.maxUsersExample',
defaultMessage: 'Ex "25"'
},
restrictExample: {
id: 'admin.team.restrictExample',
defaultMessage: 'Ex "corp.mattermost.com, mattermost.org"'
},
saving: {
id: 'admin.team.saving',
defaultMessage: 'Saving Config...'
}
});
class TeamSettings extends React.Component {
constructor(props) {
super(props);
@@ -62,6 +83,7 @@ export default class TeamSettings extends React.Component {
}
render() {
const {formatMessage} = this.props.intl;
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
@@ -75,7 +97,12 @@ export default class TeamSettings extends React.Component {
return (
<div className='wrapper--fixed'>
<h3>{'Team Settings'}</h3>
<h3>
<FormattedMessage
id='admin.team.title'
defaultMessage='Team Settings'
/>
</h3>
<form
className='form-horizontal'
role='form'
@@ -86,7 +113,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='SiteName'
>
{'Site Name:'}
<FormattedMessage
id='admin.team.siteNameTitle'
defaultMessage='Site Name:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -94,11 +124,16 @@ export default class TeamSettings extends React.Component {
className='form-control'
id='SiteName'
ref='SiteName'
placeholder='Ex "Mattermost"'
placeholder={formatMessage(holders.siteNameExample)}
defaultValue={this.props.config.TeamSettings.SiteName}
onChange={this.handleChange}
/>
<p className='help-text'>{'Name of service shown in login screens and UI.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.team.siteNameDescription'
defaultMessage='Name of service shown in login screens and UI.'
/>
</p>
</div>
</div>
@@ -107,7 +142,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='MaxUsersPerTeam'
>
{'Max Users Per Team:'}
<FormattedMessage
id='admin.team.maxUsersTitle'
defaultMessage='Max Users Per Team:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -115,11 +153,16 @@ export default class TeamSettings extends React.Component {
className='form-control'
id='MaxUsersPerTeam'
ref='MaxUsersPerTeam'
placeholder='Ex "25"'
placeholder={formatMessage(holders.maxUsersExample)}
defaultValue={this.props.config.TeamSettings.MaxUsersPerTeam}
onChange={this.handleChange}
/>
<p className='help-text'>{'Maximum total number of users per team, including both active and inactive users.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.team.maxUsersDescription'
defaultMessage='Maximum total number of users per team, including both active and inactive users.'
/>
</p>
</div>
</div>
@@ -128,7 +171,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableTeamCreation'
>
{'Enable Team Creation: '}
<FormattedMessage
id='admin.team.teamCreationTitle'
defaultMessage='Enable Team Creation: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -140,7 +186,10 @@ export default class TeamSettings extends React.Component {
defaultChecked={this.props.config.TeamSettings.EnableTeamCreation}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.team.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -150,9 +199,17 @@ export default class TeamSettings extends React.Component {
defaultChecked={!this.props.config.TeamSettings.EnableTeamCreation}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.team.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When false, the ability to create teams is disabled. The create team button displays error when pressed.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.team.teamCreationDescription'
defaultMessage='When false, the ability to create teams is disabled. The create team button displays error when pressed.'
/>
</p>
</div>
</div>
@@ -161,7 +218,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableUserCreation'
>
{'Enable User Creation: '}
<FormattedMessage
id='admin.team.userCreationTitle'
defaultMessage='Enable User Creation: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -173,7 +233,10 @@ export default class TeamSettings extends React.Component {
defaultChecked={this.props.config.TeamSettings.EnableUserCreation}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.team.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -183,9 +246,17 @@ export default class TeamSettings extends React.Component {
defaultChecked={!this.props.config.TeamSettings.EnableUserCreation}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.team.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When false, the ability to create accounts is disabled. The create account button displays error when pressed.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.team.userCreationDescription'
defaultMessage='When false, the ability to create accounts is disabled. The create account button displays error when pressed.'
/>
</p>
</div>
</div>
@@ -194,7 +265,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='RestrictCreationToDomains'
>
{'Restrict Creation To Domains:'}
<FormattedMessage
id='admin.team.restrictTitle'
defaultMessage='Restrict Creation To Domains:'
/>
</label>
<div className='col-sm-8'>
<input
@@ -202,11 +276,16 @@ export default class TeamSettings extends React.Component {
className='form-control'
id='RestrictCreationToDomains'
ref='RestrictCreationToDomains'
placeholder='Ex "corp.mattermost.com, mattermost.org"'
placeholder={formatMessage(holders.restrictExample)}
defaultValue={this.props.config.TeamSettings.RestrictCreationToDomains}
onChange={this.handleChange}
/>
<p className='help-text'>{'Teams and user accounts can only be created from a specific domain (e.g. "mattermost.org") or list of comma-separated domains (e.g. "corp.mattermost.com, mattermost.org").'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.team.restrictDescription'
defaultMessage='Teams and user accounts can only be created from a specific domain (e.g. "mattermost.org") or list of comma-separated domains (e.g. "corp.mattermost.com, mattermost.org").'
/>
</p>
</div>
</div>
@@ -215,7 +294,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='RestrictTeamNames'
>
{'Restrict Team Names: '}
<FormattedMessage
id='admin.team.restrictNameTitle'
defaultMessage='Restrict Team Names: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -227,7 +309,10 @@ export default class TeamSettings extends React.Component {
defaultChecked={this.props.config.TeamSettings.RestrictTeamNames}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.team.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -237,9 +322,17 @@ export default class TeamSettings extends React.Component {
defaultChecked={!this.props.config.TeamSettings.RestrictTeamNames}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.team.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When true, You cannot create a team name with reserved words like www, admin, support, test, channel, etc'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.team.restrictNameDesc'
defaultMessage='When true, You cannot create a team name with reserved words like www, admin, support, test, channel, etc'
/>
</p>
</div>
</div>
@@ -248,7 +341,10 @@ export default class TeamSettings extends React.Component {
className='control-label col-sm-4'
htmlFor='EnableTeamListing'
>
{'Enable Team Directory: '}
<FormattedMessage
id='admin.team.dirTitle'
defaultMessage='Enable Team Directory: '
/>
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
@@ -260,7 +356,10 @@ export default class TeamSettings extends React.Component {
defaultChecked={this.props.config.TeamSettings.EnableTeamListing}
onChange={this.handleChange}
/>
{'true'}
<FormattedMessage
id='admin.team.true'
defaultMessage='true'
/>
</label>
<label className='radio-inline'>
<input
@@ -270,9 +369,17 @@ export default class TeamSettings extends React.Component {
defaultChecked={!this.props.config.TeamSettings.EnableTeamListing}
onChange={this.handleChange}
/>
{'false'}
<FormattedMessage
id='admin.team.false'
defaultMessage='false'
/>
</label>
<p className='help-text'>{'When true, teams that are configured to show in team directory will show on main page inplace of creating a new team.'}</p>
<p className='help-text'>
<FormattedMessage
id='admin.team.dirDesc'
defaultMessage='When true, teams that are configured to show in team directory will show on main page inplace of creating a new team.'
/>
</p>
</div>
</div>
@@ -285,9 +392,12 @@ export default class TeamSettings extends React.Component {
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> ' + formatMessage(holders.saving)}
>
{'Save'}
<FormattedMessage
id='admin.team.save'
defaultMessage='Save'
/>
</button>
</div>
</div>
@@ -299,5 +409,8 @@ export default class TeamSettings extends React.Component {
}
TeamSettings.propTypes = {
intl: intlShape.isRequired,
config: React.PropTypes.object
};
export default injectIntl(TeamSettings);

Просмотреть файл

@@ -6,6 +6,8 @@ import LoadingScreen from '../loading_screen.jsx';
import UserItem from './user_item.jsx';
import ResetPasswordModal from './reset_password_modal.jsx';
import {FormattedMessage} from 'mm-intl';
export default class UserList extends React.Component {
constructor(props) {
super(props);
@@ -122,7 +124,15 @@ export default class UserList extends React.Component {
if (this.state.users == null) {
return (
<div className='wrapper--fixed'>
<h3>{'Users for ' + this.props.team.name}</h3>
<h3>
<FormattedMessage
id='admin.userList.title'
defaultMessage='Users for {team}'
values={{
team: this.props.team.name
}}
/>
</h3>
{serverError}
<LoadingScreen />
</div>
@@ -141,7 +151,16 @@ export default class UserList extends React.Component {
return (
<div className='wrapper--fixed'>
<h3>{'Users for ' + this.props.team.name + ' (' + this.state.users.length + ')'}</h3>
<h3>
<FormattedMessage
id='admin.userList.title2'
defaultMessage='Users for {team} ({count})'
values={{
team: this.props.team.name,
count: this.state.users.length
}}
/>
</h3>
{serverError}
<form
className='form-horizontal'

Просмотреть файл

@@ -4,6 +4,8 @@
import * as Client from '../../utils/client.jsx';
import * as Utils from '../../utils/utils.jsx';
import {FormattedMessage} from 'mm-intl';
export default class UserItem extends React.Component {
constructor(props) {
super(props);
@@ -109,12 +111,27 @@ export default class UserItem extends React.Component {
}
const user = this.props.user;
let currentRoles = 'Member';
let currentRoles = (
<FormattedMessage
id='admin.user_item.member'
defaultMessage='Member'
/>
);
if (user.roles.length > 0) {
if (Utils.isSystemAdmin(user.roles)) {
currentRoles = 'System Admin';
currentRoles = (
<FormattedMessage
id='admin.user_item.sysAdmin'
defaultMessage='System Admin'
/>
);
} else if (Utils.isAdmin(user.roles)) {
currentRoles = 'Team Admin';
currentRoles = (
<FormattedMessage
id='admin.user_item.teamAdmin'
defaultMessage='Team Admin'
/>
);
} else {
currentRoles = user.roles.charAt(0).toUpperCase() + user.roles.slice(1);
}
@@ -128,7 +145,12 @@ export default class UserItem extends React.Component {
let showMakeNotActive = user.roles !== 'system_admin';
if (user.delete_at > 0) {
currentRoles = 'Inactive';
currentRoles = (
<FormattedMessage
id='admin.user_item.inactive'
defaultMessage='Inactive'
/>
);
showMakeMember = false;
showMakeAdmin = false;
showMakeSystemAdmin = false;
@@ -145,7 +167,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleMakeSystemAdmin}
>
{'Make System Admin'}
<FormattedMessage
id='admin.user_item.makeSysAdmin'
defaultMessage='Make System Admin'
/>
</a>
</li>
);
@@ -160,7 +185,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleMakeAdmin}
>
{'Make Team Admin'}
<FormattedMessage
id='admin.user_item.makeTeamAdmin'
defaultMessage='Make Team Admin'
/>
</a>
</li>
);
@@ -175,7 +203,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleMakeMember}
>
{'Make Member'}
<FormattedMessage
id='admin.user_item.makeMember'
defaultMessage='Make Member'
/>
</a>
</li>
);
@@ -190,7 +221,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleMakeActive}
>
{'Make Active'}
<FormattedMessage
id='admin.user_item.makeActive'
defaultMessage='Make Active'
/>
</a>
</li>
);
@@ -205,7 +239,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleMakeNotActive}
>
{'Make Inactive'}
<FormattedMessage
id='admin.user_item.makeInactive'
defaultMessage='Make Inactive'
/>
</a>
</li>
);
@@ -248,7 +285,10 @@ export default class UserItem extends React.Component {
href='#'
onClick={this.handleResetPassword}
>
{'Reset Password'}
<FormattedMessage
id='admin.user_item.resetPwd'
defaultMessage='Reset Password'
/>
</a>
</li>
</ul>