Этот коммит содержится в:
=Corey Hulen
2015-09-21 15:11:56 -07:00
родитель ee5a77ec56
Коммит ed9a2da83b
23 изменённых файлов: 563 добавлений и 353 удалений

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

@@ -1,15 +1,148 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
var Client = require('../../utils/client.jsx');
var AsyncClient = require('../../utils/async_client.jsx');
export default class EmailSettings extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleTestConnection = this.handleTestConnection.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.buildConfig = this.buildConfig.bind(this);
this.state = {
sendEmailNotifications: this.props.config.EmailSettings.SendEmailNotifications,
saveNeeded: false,
serverError: null,
emailSuccess: null,
emailFail: null
};
}
handleChange(action) {
var s = {saveNeeded: true, serverError: this.state.serverError};
if (action === 'sendEmailNotifications_true') {
s.sendEmailNotifications = true;
}
if (action === 'sendEmailNotifications_false') {
s.sendEmailNotifications = false;
}
this.setState(s);
}
buildConfig() {
var config = this.props.config;
config.EmailSettings.AllowSignUpWithEmail = React.findDOMNode(this.refs.allowSignUpWithEmail).checked;
config.EmailSettings.SendEmailNotifications = React.findDOMNode(this.refs.sendEmailNotifications).checked;
config.EmailSettings.RequireEmailVerification = React.findDOMNode(this.refs.requireEmailVerification).checked;
config.EmailSettings.SendEmailNotifications = React.findDOMNode(this.refs.sendEmailNotifications).checked;
config.EmailSettings.FeedbackName = React.findDOMNode(this.refs.feedbackName).value.trim();
config.EmailSettings.FeedbackEmail = React.findDOMNode(this.refs.feedbackEmail).value.trim();
config.EmailSettings.SMTPServer = React.findDOMNode(this.refs.SMTPServer).value.trim();
config.EmailSettings.SMTPPort = React.findDOMNode(this.refs.SMTPPort).value.trim();
config.EmailSettings.SMTPUsername = React.findDOMNode(this.refs.SMTPUsername).value.trim();
config.EmailSettings.SMTPPassword = React.findDOMNode(this.refs.SMTPPassword).value.trim();
config.EmailSettings.ConnectionSecurity = React.findDOMNode(this.refs.ConnectionSecurity).value.trim();
return config;
}
handleTestConnection(e) {
e.preventDefault();
$('#connection-button').button('loading');
var config = this.buildConfig();
Client.testEmail(
config,
() => {
this.setState({
sendEmailNotifications: config.EmailSettings.SendEmailNotifications,
serverError: null,
saveNeeded: true,
emailSuccess: true,
emailFail: null
});
},
(err) => {
this.setState({
sendEmailNotifications: config.EmailSettings.SendEmailNotifications,
serverError: null,
saveNeeded: true,
emailSuccess: null,
emailFail: err.message + ' - ' + err.detailed_error
});
$('#connection-button').button('reset');
}
);
}
handleSubmit(e) {
e.preventDefault();
$('#save-button').button('loading');
var config = this.buildConfig();
Client.saveConfig(
config,
() => {
AsyncClient.getConfig();
this.setState({
sendEmailNotifications: config.EmailSettings.SendEmailNotifications,
serverError: null,
saveNeeded: false,
emailSuccess: null,
emailFail: null
});
$('#save-button').button('reset');
},
(err) => {
this.setState({
sendEmailNotifications: config.EmailSettings.SendEmailNotifications,
serverError: err.message,
saveNeeded: true,
emailSuccess: null,
emailFail: null
});
$('#save-button').button('reset');
}
);
}
render() {
var serverError = '';
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
}
var saveClass = 'btn';
if (this.state.saveNeeded) {
saveClass = 'btn btn-primary';
}
var emailSuccess = '';
if (this.state.emailSuccess) {
emailSuccess = (
<div className='alert alert-success'>
<i className='fa fa-check'></i>{'No errors were reported while sending an email. Please check your inbox to make sure.'}
</div>
);
}
var emailFail = '';
if (this.state.emailFail) {
emailSuccess = (
<div className='alert alert-warning'>
<i className='fa fa-warning'></i>{'Connection unsuccessful: ' + this.state.emailFail}
</div>
);
}
return (
<div className='wrapper--fixed'>
<h3>{'Email Settings'}</h3>
@@ -17,149 +150,130 @@ export default class EmailSettings extends React.Component {
className='form-horizontal'
role='form'
>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='email'
htmlFor='allowSignUpWithEmail'
>
{'Bypass Email: '}
<a
href='#'
data-trigger='hover click'
data-toggle='popover'
data-position='bottom'
data-content={'Here\'s some more help text inside a popover for the Bypass Email field just to show how popovers look.'}
>
{'(?)'}
</a>
{'Allow Sign Up With Email: '}
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
<input
type='radio'
name='byPassEmail'
value='option1'
name='allowSignUpWithEmail'
value='true'
ref='allowSignUpWithEmail'
defaultChecked={this.props.config.EmailSettings.AllowSignUpWithEmail}
onChange={this.handleChange.bind(this, 'allowSignUpWithEmail_true')}
/>
{'True'}
{'true'}
</label>
<label className='radio-inline'>
<input
type='radio'
name='byPassEmail'
value='option2'
name='allowSignUpWithEmail'
value='false'
defaultChecked={!this.props.config.EmailSettings.AllowSignUpWithEmail}
onChange={this.handleChange.bind(this, 'allowSignUpWithEmail_false')}
/>
{'False'}
{'false'}
</label>
<p className='help-text'>{'This is some sample help text for the Bypass Email field'}</p>
<p className='help-text'>{'Typically set to true in production. When true Mattermost will allow team creation and account signup utilizing email and password. You would set this to false if you only wanted to allow signup from a service like OAuth or LDAP.'}</p>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='smtpUsername'
htmlFor='sendEmailNotifications'
>
{'SMTP Username:'}
{'Send Email Notifications: '}
</label>
<div className='col-sm-8'>
<input
type='email'
className='form-control'
id='smtpUsername'
placeholder='Enter your SMTP username'
value=''
/>
<div className='help-text'>
<div className='alert alert-warning'><i className='fa fa-warning'></i>{' This is some error text for the Bypass Email field'}</div>
</div>
<p className='help-text'>{'This is some sample help text for the SMTP username field'}</p>
<label className='radio-inline'>
<input
type='radio'
name='sendEmailNotifications'
value='true'
ref='sendEmailNotifications'
defaultChecked={this.props.config.EmailSettings.SendEmailNotifications}
onChange={this.handleChange.bind(this, 'sendEmailNotifications_true')}
/>
{'true'}
</label>
<label className='radio-inline'>
<input
type='radio'
name='sendEmailNotifications'
value='false'
defaultChecked={!this.props.config.EmailSettings.SendEmailNotifications}
onChange={this.handleChange.bind(this, 'sendEmailNotifications_false')}
/>
{'false'}
</label>
<p className='help-text'>{'Typically set to true in production. When true Mattermost will attempt to send email notifications. Developers may set this field to false skipping sending emails for faster development.'}</p>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='smtpPassword'
htmlFor='requireEmailVerification'
>
{'SMTP Password:'}
{'Require Email Verification: '}
</label>
<div className='col-sm-8'>
<input
type='password'
className='form-control'
id='smtpPassword'
placeholder='Enter your SMTP password'
value=''
/>
<label className='radio-inline'>
<input
type='radio'
name='requireEmailVerification'
value='true'
ref='requireEmailVerification'
defaultChecked={this.props.config.EmailSettings.RequireEmailVerification}
onChange={this.handleChange.bind(this, 'requireEmailVerification_true')}
disabled={!this.state.sendEmailNotifications}
/>
{'true'}
</label>
<label className='radio-inline'>
<input
type='radio'
name='requireEmailVerification'
value='false'
defaultChecked={!this.props.config.EmailSettings.RequireEmailVerification}
onChange={this.handleChange.bind(this, 'requireEmailVerification_false')}
disabled={!this.state.sendEmailNotifications}
/>
{'false'}
</label>
<p className='help-text'>{'Typically set to true in production. When true Mattermost will not allow a user to login without first having recieved an email with a verification link. Developers may set this field to false so skip sending verification emails for faster development.'}</p>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='smtpServer'
htmlFor='feedbackName'
>
{'SMTP Server:'}
{'Feedback Name:'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
id='smtpServer'
placeholder='Enter your SMTP server'
value=''
id='feedbackName'
ref='feedbackName'
placeholder='Ex: "Mattermost", "System", "John Smith"'
defaultValue={this.props.config.EmailSettings.FeedbackName}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
/>
<div className='help-text'>
<a
href='#'
className='help-link'
>
{'Test Connection'}
</a>
<div className='alert alert-success'><i className='fa fa-check'></i>{' Connection successful'}</div>
<div className='alert alert-warning hide'><i className='fa fa-warning'></i>{' Connection unsuccessful'}</div>
</div>
</div>
</div>
<div className='form-group'>
<label className='control-label col-sm-4'>{'Use TLS:'}</label>
<div className='col-sm-8'>
<label className='radio-inline'>
<input
type='radio'
name='tls'
value='option1'
/>
{'True'}
</label>
<label className='radio-inline'>
<input
type='radio'
name='tls'
value='option2'
/>
{'False'}
</label>
</div>
</div>
<div className='form-group'>
<label className='control-label col-sm-4'>{'Use Start TLS:'}</label>
<div className='col-sm-8'>
<label className='radio-inline'>
<input
type='radio'
name='starttls'
value='option1'
/>
{'True'}
</label>
<label className='radio-inline'>
<input
type='radio'
name='starttls'
value='option2'
/>
{'False'}
</label>
<p className='help-text'>{'Name displayed on email account used when sending notification emails from Mattermost.'}</p>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
@@ -169,143 +283,175 @@ export default class EmailSettings extends React.Component {
</label>
<div className='col-sm-8'>
<input
type='text'
type='email'
className='form-control'
id='feedbackEmail'
placeholder='Enter your feedback email'
value=''
ref='feedbackEmail'
placeholder='Ex: "mattermost@yourcompany.com", "admin@yourcompany.com"'
defaultValue={this.props.config.EmailSettings.FeedbackEmail}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
/>
<p className='help-text'>{'Email displayed on email account used when sending notification emails from Mattermost.'}</p>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='feedbackUsername'
htmlFor='SMTPUsername'
>
{'Feedback Username:'}
{'SMTP Username:'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
id='feedbackUsername'
placeholder='Enter your feedback username'
value=''
id='SMTPUsername'
ref='SMTPUsername'
placeholder='Ex: "admin@yourcompany.com", "AKIADTOVBGERKLCBV"'
defaultValue={this.props.config.EmailSettings.SMTPUsername}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
/>
</div>
</div>
<div className='form-group'>
<div className='col-sm-offset-4 col-sm-8'>
<div className='checkbox'>
<label><input type='checkbox' />{'Remember me'}</label>
</div>
<p className='help-text'>{' Obtain this credential from administrator setting up your email server.'}</p>
</div>
</div>
<div
className='panel-group'
id='accordion'
role='tablist'
aria-multiselectable='true'
>
<div className='panel panel-default'>
<div
className='panel-heading'
role='tab'
id='headingOne'
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='SMTPPassword'
>
{'SMTP Password:'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
id='SMTPPassword'
ref='SMTPPassword'
placeholder='Ex: "yourpassword", "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
defaultValue={this.props.config.EmailSettings.SMTPPassword}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
/>
<p className='help-text'>{' Obtain this credential from administrator setting up your email server.'}</p>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='SMTPServer'
>
{'SMTP Server:'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
id='SMTPServer'
ref='SMTPServer'
placeholder='Ex: "smtp.yourcompany.com", "email-smtp.us-east-1.amazonaws.com"'
defaultValue={this.props.config.EmailSettings.SMTPServer}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
/>
<p className='help-text'>{'Location of SMTP email server.'}</p>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='SMTPPort'
>
{'SMTP Port:'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
id='SMTPPort'
ref='SMTPPort'
placeholder='Ex: "25", "465"'
defaultValue={this.props.config.EmailSettings.SMTPPort}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
/>
<p className='help-text'>{'Port of SMTP email server.'}</p>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='ConnectionSecurity'
>
{'Connection Security:'}
</label>
<div className='col-sm-8'>
<select
className='form-control'
id='ConnectionSecurity'
ref='ConnectionSecurity'
defaultValue={this.props.config.EmailSettings.ConnectionSecurity}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
>
<h3 className='panel-title'>
<a
className='collapsed'
role='button'
data-toggle='collapse'
data-parent='#accordion'
href='#collapseOne'
aria-expanded='true'
aria-controls='collapseOne'
>
{'Advanced Settings '}
<i className='fa fa-plus'></i>
<i className='fa fa-minus'></i>
</a>
</h3>
<option value=''>{'None'}</option>
<option value='TLS'>{'TLS (Recommended)'}</option>
<option value='STARTTLS'>{'STARTTLS'}</option>
</select>
<div className='help-text'>
<table
className='table-bordered'
cellPadding='5'
>
<tr><td className='help-text'>{'None'}</td><td className='help-text'>{'Mattermost will send email over an unsecure connection.'}</td></tr>
<tr><td className='help-text'>{'TLS'}</td><td className='help-text'>{'Encrypts the communication between Mattermost and your email server.'}</td></tr>
<tr><td className='help-text'>{'STARTTLS'}</td><td className='help-text'>{'Takes an existing insecure connection and attempts to upgrade it to a secure connection using TLS.'}</td></tr>
</table>
</div>
<div
id='collapseOne'
className='panel-collapse collapse'
role='tabpanel'
aria-labelledby='headingOne'
>
<div className='panel-body'>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='feedbackUsername'
>
{'Apple push server:'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
id='feedbackUsername'
placeholder='Enter your Apple push server'
value=''
/>
<p className='help-text'>{'This is some sample help text for the Apple push server field'}</p>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='feedbackUsername'
>
{'Apple push certificate public:'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
id='feedbackUsername'
placeholder='Enter your public apple push certificate'
value=''
/>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='feedbackUsername'
>
{'Apple push certificate private:'}
</label>
<div className='col-sm-8'>
<input
type='text'
className='form-control'
id='feedbackUsername'
placeholder='Enter your private apple push certificate'
value=''
/>
</div>
</div>
</div>
<div className='help-text'>
<button
className='help-link'
onClick={this.handleTestConnection}
disabled={!this.state.sendEmailNotifications}
id='connection-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Testing...'}
>
{'Test Connection'}
</button>
{emailSuccess}
{emailFail}
</div>
</div>
</div>
<div className='form-group'>
<div className='col-sm-12'>
{serverError}
<button
disabled={!this.state.saveNeeded}
type='submit'
className='btn btn-primary'
className={saveClass}
onClick={this.handleSubmit}
id='save-button'
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
>
{'Save'}
</button>
</div>
</div>
</form>
</div>
);
}
}
}
EmailSettings.propTypes = {
config: React.PropTypes.object
};

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

@@ -12,13 +12,33 @@ export default class LogSettings extends React.Component {
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {
consoleEnable: this.props.config.LogSettings.ConsoleEnable,
fileEnable: this.props.config.LogSettings.FileEnable,
saveNeeded: false,
serverError: null
};
}
handleChange() {
this.setState({saveNeeded: true, serverError: this.state.serverError});
handleChange(action) {
var s = {saveNeeded: true, serverError: this.state.serverError};
if (action === 'console_true') {
s.consoleEnable = true;
}
if (action === 'console_false') {
s.consoleEnable = false;
}
if (action === 'file_true') {
s.fileEnable = true;
}
if (action === 'file_false') {
s.fileEnable = false;
}
this.setState(s);
}
handleSubmit(e) {
@@ -37,11 +57,21 @@ export default class LogSettings extends React.Component {
config,
() => {
AsyncClient.getConfig();
this.setState({serverError: null, saveNeeded: false});
this.setState({
consoleEnable: config.LogSettings.ConsoleEnable,
fileEnable: config.LogSettings.FileEnable,
serverError: null,
saveNeeded: false
});
$('#save-button').button('reset');
},
(err) => {
this.setState({serverError: err.message, saveNeeded: true});
this.setState({
consoleEnable: config.LogSettings.ConsoleEnable,
fileEnable: config.LogSettings.FileEnable,
serverError: err.message,
saveNeeded: true
});
$('#save-button').button('reset');
}
);
@@ -81,7 +111,7 @@ export default class LogSettings extends React.Component {
value='true'
ref='consoleEnable'
defaultChecked={this.props.config.LogSettings.ConsoleEnable}
onChange={this.handleChange}
onChange={this.handleChange.bind(this, 'console_true')}
/>
{'true'}
</label>
@@ -91,7 +121,7 @@ export default class LogSettings extends React.Component {
name='consoleEnable'
value='false'
defaultChecked={!this.props.config.LogSettings.ConsoleEnable}
onChange={this.handleChange}
onChange={this.handleChange.bind(this, 'console_false')}
/>
{'false'}
</label>
@@ -113,6 +143,7 @@ export default class LogSettings extends React.Component {
ref='consoleLevel'
defaultValue={this.props.config.LogSettings.consoleLevel}
onChange={this.handleChange}
disabled={!this.state.consoleEnable}
>
<option value='DEBUG'>{'DEBUG'}</option>
<option value='INFO'>{'INFO'}</option>
@@ -136,7 +167,7 @@ export default class LogSettings extends React.Component {
ref='fileEnable'
value='true'
defaultChecked={this.props.config.LogSettings.FileEnable}
onChange={this.handleChange}
onChange={this.handleChange.bind(this, 'file_true')}
/>
{'true'}
</label>
@@ -146,7 +177,7 @@ export default class LogSettings extends React.Component {
name='fileEnable'
value='false'
defaultChecked={!this.props.config.LogSettings.FileEnable}
onChange={this.handleChange}
onChange={this.handleChange.bind(this, 'file_false')}
/>
{'false'}
</label>
@@ -168,6 +199,7 @@ export default class LogSettings extends React.Component {
ref='fileLevel'
defaultValue={this.props.config.LogSettings.FileLevel}
onChange={this.handleChange}
disabled={!this.state.fileEnable}
>
<option value='DEBUG'>{'DEBUG'}</option>
<option value='INFO'>{'INFO'}</option>
@@ -193,6 +225,7 @@ export default class LogSettings extends React.Component {
placeholder='Enter your file location'
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.log. Log rotation is enabled and new files may be created in the same directory.'}</p>
</div>
@@ -214,6 +247,7 @@ export default class LogSettings extends React.Component {
placeholder='Enter your file format'
defaultValue={this.props.config.LogSettings.FileFormat}
onChange={this.handleChange}
disabled={!this.state.fileEnable}
/>
<p className='help-text'>
{'Format of log message output. If blank will be set to "[%D %T] [%L] %M", where:'}