diff options
Diffstat (limited to 'webapp/components')
55 files changed, 566 insertions, 486 deletions
diff --git a/webapp/components/about_build_modal.jsx b/webapp/components/about_build_modal.jsx index 4fd946401..22354d80e 100644 --- a/webapp/components/about_build_modal.jsx +++ b/webapp/components/about_build_modal.jsx @@ -45,6 +45,7 @@ export default class AboutBuildModal extends React.Component { /> <a target='_blank' + rel='noopener noreferrer' href='http://www.mattermost.org/' > {'mattermost.org'} @@ -76,6 +77,7 @@ export default class AboutBuildModal extends React.Component { /> <a target='_blank' + rel='noopener noreferrer' href='http://about.mattermost.com/' > {'about.mattermost.com'} @@ -133,7 +135,7 @@ export default class AboutBuildModal extends React.Component { id='about.version' defaultMessage='Version:' /> - {config.Version} ({config.BuildNumber}) + {'\u00a0' + config.Version + '\u00a0' + config.BuildNumber} </div> </div> {licensee} diff --git a/webapp/components/activity_log_modal.jsx b/webapp/components/activity_log_modal.jsx index d3e5ce66d..ab6224906 100644 --- a/webapp/components/activity_log_modal.jsx +++ b/webapp/components/activity_log_modal.jsx @@ -23,7 +23,7 @@ export default class ActivityLogModal extends React.Component { this.onHide = this.onHide.bind(this); this.onShow = this.onShow.bind(this); - let state = this.getStateFromStores(); + const state = this.getStateFromStores(); state.moreInfo = []; this.state = state; @@ -43,14 +43,14 @@ export default class ActivityLogModal extends React.Component { modalContent.removeClass('animation--highlight'); }, 1500); Client.revokeSession(altId, - function handleRevokeSuccess() { + () => { AsyncClient.getSessions(); }, - function handleRevokeError(err) { - let state = this.getStateFromStores(); + (err) => { + const state = this.getStateFromStores(); state.serverError = err; this.setState(state); - }.bind(this) + } ); } onShow() { @@ -85,7 +85,7 @@ export default class ActivityLogModal extends React.Component { } } handleMoreInfo(index) { - let newMoreInfo = this.state.moreInfo; + const newMoreInfo = this.state.moreInfo; newMoreInfo[index] = true; this.setState({moreInfo: newMoreInfo}); } diff --git a/webapp/components/admin_console/admin_sidebar.jsx b/webapp/components/admin_console/admin_sidebar.jsx index da406e647..4ffc31815 100644 --- a/webapp/components/admin_console/admin_sidebar.jsx +++ b/webapp/components/admin_console/admin_sidebar.jsx @@ -134,13 +134,13 @@ export default class AdminSidebar extends React.Component { placement='top' overlay={removeTooltip} > - <span - className='menu-icon--right menu__close' - onClick={this.removeTeam.bind(this, team.id)} - style={{cursor: 'pointer'}} - > - {'×'} - </span> + <span + className='menu-icon--right menu__close' + onClick={this.removeTeam.bind(this, team.id)} + style={{cursor: 'pointer'}} + > + {'×'} + </span> </OverlayTrigger> </a> </li> @@ -424,7 +424,7 @@ export default class AdminSidebar extends React.Component { </li> </ul> <ul className='nav nav__sub-menu'> - <li> + <li> <h4> <span className='icon fa fa-gear'></span> <span> @@ -442,14 +442,14 @@ export default class AdminSidebar extends React.Component { placement='top' overlay={addTeamTooltip} > - <a - href='#' - onClick={this.showTeamSelect} - > - <i - className='fa fa-plus' - ></i> - </a> + <a + href='#' + onClick={this.showTeamSelect} + > + <i + className='fa fa-plus' + ></i> + </a> </OverlayTrigger> </span> </h4> diff --git a/webapp/components/admin_console/compliance_reports.jsx b/webapp/components/admin_console/compliance_reports.jsx index 79b0d2210..a93f7a17c 100644 --- a/webapp/components/admin_console/compliance_reports.jsx +++ b/webapp/components/admin_console/compliance_reports.jsx @@ -273,7 +273,6 @@ export default class ComplianceReports extends React.Component { defaultMessage='Compliance Reports' /> </h3> - <div className='row'> <div className='col-sm-6 col-md-4 form-group'> <label> diff --git a/webapp/components/admin_console/email_settings.jsx b/webapp/components/admin_console/email_settings.jsx index dcdf52486..71add9983 100644 --- a/webapp/components/admin_console/email_settings.jsx +++ b/webapp/components/admin_console/email_settings.jsx @@ -285,12 +285,12 @@ class EmailSettings extends React.Component { var emailSuccess = ''; if (this.state.emailSuccess) { emailSuccess = ( - <div className='alert alert-success'> + <div className='alert alert-success'> <i className='fa fa-check'></i> - <FormattedMessage - id='admin.email.emailSuccess' - defaultMessage='No errors were reported while sending an email. Please check your inbox to make sure.' - /> + <FormattedMessage + id='admin.email.emailSuccess' + defaultMessage='No errors were reported while sending an email. Please check your inbox to make sure.' + /> </div> ); } @@ -298,15 +298,15 @@ class EmailSettings extends React.Component { var emailFail = ''; if (this.state.emailFail) { emailSuccess = ( - <div className='alert alert-warning'> + <div className='alert alert-warning'> <i className='fa fa-warning'></i> - <FormattedMessage - id='admin.email.emailFail' - defaultMessage='Connection unsuccessful: {error}' - values={{ - error: this.state.emailFail - }} - /> + <FormattedMessage + id='admin.email.emailFail' + defaultMessage='Connection unsuccessful: {error}' + values={{ + error: this.state.emailFail + }} + /> </div> ); } @@ -507,10 +507,10 @@ class EmailSettings extends React.Component { defaultChecked={this.props.config.EmailSettings.EnableSignUpWithEmail} onChange={this.handleChange.bind(this, 'allowSignUpWithEmail_true')} /> - <FormattedMessage - id='admin.email.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.email.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -520,10 +520,10 @@ class EmailSettings extends React.Component { defaultChecked={!this.props.config.EmailSettings.EnableSignUpWithEmail} onChange={this.handleChange.bind(this, 'allowSignUpWithEmail_false')} /> - <FormattedMessage - id='admin.email.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.email.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -648,10 +648,10 @@ class EmailSettings extends React.Component { defaultChecked={this.props.config.EmailSettings.SendEmailNotifications} onChange={this.handleChange.bind(this, 'sendEmailNotifications_true')} /> - <FormattedMessage - id='admin.email.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.email.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -661,10 +661,10 @@ class EmailSettings extends React.Component { defaultChecked={!this.props.config.EmailSettings.SendEmailNotifications} onChange={this.handleChange.bind(this, 'sendEmailNotifications_false')} /> - <FormattedMessage - id='admin.email.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.email.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedHTMLMessage @@ -696,10 +696,10 @@ class EmailSettings extends React.Component { onChange={this.handleChange.bind(this, 'requireEmailVerification_true')} disabled={!this.state.sendEmailNotifications} /> - <FormattedMessage - id='admin.email.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.email.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -710,10 +710,10 @@ class EmailSettings extends React.Component { onChange={this.handleChange.bind(this, 'requireEmailVerification_false')} disabled={!this.state.sendEmailNotifications} /> - <FormattedMessage - id='admin.email.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.email.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage diff --git a/webapp/components/admin_console/gitlab_settings.jsx b/webapp/components/admin_console/gitlab_settings.jsx index 747905ac6..510fd0887 100644 --- a/webapp/components/admin_console/gitlab_settings.jsx +++ b/webapp/components/admin_console/gitlab_settings.jsx @@ -122,7 +122,6 @@ class GitLabSettings extends React.Component { className='form-horizontal' role='form' > - <div className='form-group'> <label className='control-label col-sm-4' @@ -143,10 +142,10 @@ class GitLabSettings extends React.Component { defaultChecked={this.props.config.GitLabSettings.Enable} onChange={this.handleChange.bind(this, 'EnableTrue')} /> - <FormattedMessage - id='admin.gitlab.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.gitlab.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -156,10 +155,10 @@ class GitLabSettings extends React.Component { defaultChecked={!this.props.config.GitLabSettings.Enable} onChange={this.handleChange.bind(this, 'EnableFalse')} /> - <FormattedMessage - id='admin.gitlab.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.gitlab.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage diff --git a/webapp/components/admin_console/image_settings.jsx b/webapp/components/admin_console/image_settings.jsx index 023e9af3b..64a7663c6 100644 --- a/webapp/components/admin_console/image_settings.jsx +++ b/webapp/components/admin_console/image_settings.jsx @@ -592,10 +592,10 @@ class FileSettings extends React.Component { defaultChecked={this.props.config.FileSettings.EnablePublicLink} onChange={this.handleChange} /> - <FormattedMessage - id='admin.image.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.image.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -605,10 +605,10 @@ class FileSettings extends React.Component { defaultChecked={!this.props.config.FileSettings.EnablePublicLink} onChange={this.handleChange} /> - <FormattedMessage - id='admin.image.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.image.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -689,4 +689,4 @@ FileSettings.propTypes = { config: React.PropTypes.object }; -export default injectIntl(FileSettings);
\ No newline at end of file +export default injectIntl(FileSettings); diff --git a/webapp/components/admin_console/license_settings.jsx b/webapp/components/admin_console/license_settings.jsx index f2c511e44..14934a3e5 100644 --- a/webapp/components/admin_console/license_settings.jsx +++ b/webapp/components/admin_console/license_settings.jsx @@ -152,6 +152,7 @@ class LicenseSettings extends React.Component { {'Mattermost Enterprise Edition. Unlock enterprise features in this software through the purchase of a subscription from '} <a target='_blank' + rel='noopener noreferrer' href='https://mattermost.com/' > {'https://mattermost.com/'} diff --git a/webapp/components/admin_console/log_settings.jsx b/webapp/components/admin_console/log_settings.jsx index 061c2b6e3..9229c62bc 100644 --- a/webapp/components/admin_console/log_settings.jsx +++ b/webapp/components/admin_console/log_settings.jsx @@ -143,10 +143,10 @@ class LogSettings extends React.Component { defaultChecked={this.props.config.LogSettings.EnableConsole} onChange={this.handleChange.bind(this, 'console_true')} /> - <FormattedMessage - id='admin.log.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.log.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -156,10 +156,10 @@ class LogSettings extends React.Component { defaultChecked={!this.props.config.LogSettings.EnableConsole} onChange={this.handleChange.bind(this, 'console_false')} /> - <FormattedMessage - id='admin.log.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.log.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -221,10 +221,10 @@ class LogSettings extends React.Component { defaultChecked={this.props.config.LogSettings.EnableFile} onChange={this.handleChange.bind(this, 'file_true')} /> - <FormattedMessage - id='admin.log.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.log.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -234,10 +234,10 @@ class LogSettings extends React.Component { defaultChecked={!this.props.config.LogSettings.EnableFile} onChange={this.handleChange.bind(this, 'file_false')} /> - <FormattedMessage - id='admin.log.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.log.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -415,4 +415,4 @@ LogSettings.propTypes = { config: React.PropTypes.object }; -export default injectIntl(LogSettings);
\ No newline at end of file +export default injectIntl(LogSettings); diff --git a/webapp/components/admin_console/privacy_settings.jsx b/webapp/components/admin_console/privacy_settings.jsx index 5045a6d31..8759472a2 100644 --- a/webapp/components/admin_console/privacy_settings.jsx +++ b/webapp/components/admin_console/privacy_settings.jsx @@ -108,10 +108,10 @@ class PrivacySettings extends React.Component { defaultChecked={this.props.config.PrivacySettings.ShowEmailAddress} onChange={this.handleChange} /> - <FormattedMessage - id='admin.privacy.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.privacy.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -121,10 +121,10 @@ class PrivacySettings extends React.Component { defaultChecked={!this.props.config.PrivacySettings.ShowEmailAddress} onChange={this.handleChange} /> - <FormattedMessage - id='admin.privacy.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.privacy.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -155,10 +155,10 @@ class PrivacySettings extends React.Component { defaultChecked={this.props.config.PrivacySettings.ShowFullName} onChange={this.handleChange} /> - <FormattedMessage - id='admin.privacy.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.privacy.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -168,10 +168,10 @@ class PrivacySettings extends React.Component { defaultChecked={!this.props.config.PrivacySettings.ShowFullName} onChange={this.handleChange} /> - <FormattedMessage - id='admin.privacy.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.privacy.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -212,4 +212,4 @@ PrivacySettings.propTypes = { config: React.PropTypes.object }; -export default injectIntl(PrivacySettings);
\ No newline at end of file +export default injectIntl(PrivacySettings); diff --git a/webapp/components/admin_console/rate_settings.jsx b/webapp/components/admin_console/rate_settings.jsx index de7a40e6b..5eb099b8a 100644 --- a/webapp/components/admin_console/rate_settings.jsx +++ b/webapp/components/admin_console/rate_settings.jsx @@ -172,10 +172,10 @@ class RateSettings extends React.Component { defaultChecked={this.props.config.RateLimitSettings.EnableRateLimiter} onChange={this.handleChange.bind(this, 'EnableRateLimiterTrue')} /> - <FormattedMessage - id='admin.rate.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.rate.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -185,10 +185,10 @@ class RateSettings extends React.Component { defaultChecked={!this.props.config.RateLimitSettings.EnableRateLimiter} onChange={this.handleChange.bind(this, 'EnableRateLimiterFalse')} /> - <FormattedMessage - id='admin.rate.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.rate.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -280,10 +280,10 @@ class RateSettings extends React.Component { onChange={this.handleChange.bind(this, 'VaryByRemoteAddrTrue')} disabled={!this.state.EnableRateLimiter} /> - <FormattedMessage - id='admin.rate.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.rate.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -294,10 +294,10 @@ class RateSettings extends React.Component { onChange={this.handleChange.bind(this, 'VaryByRemoteAddrFalse')} disabled={!this.state.EnableRateLimiter} /> - <FormattedMessage - id='admin.rate.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.rate.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -368,4 +368,4 @@ RateSettings.propTypes = { config: React.PropTypes.object }; -export default injectIntl(RateSettings);
\ No newline at end of file +export default injectIntl(RateSettings); diff --git a/webapp/components/admin_console/service_settings.jsx b/webapp/components/admin_console/service_settings.jsx index 90b6a39b4..dfd19d057 100644 --- a/webapp/components/admin_console/service_settings.jsx +++ b/webapp/components/admin_console/service_settings.jsx @@ -379,10 +379,10 @@ class ServiceSettings extends React.Component { defaultChecked={this.props.config.ServiceSettings.EnableIncomingWebhooks} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -392,10 +392,10 @@ class ServiceSettings extends React.Component { defaultChecked={!this.props.config.ServiceSettings.EnableIncomingWebhooks} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -426,10 +426,10 @@ class ServiceSettings extends React.Component { defaultChecked={this.props.config.ServiceSettings.EnableOutgoingWebhooks} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -439,10 +439,10 @@ class ServiceSettings extends React.Component { defaultChecked={!this.props.config.ServiceSettings.EnableOutgoingWebhooks} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -473,10 +473,10 @@ class ServiceSettings extends React.Component { defaultChecked={this.props.config.ServiceSettings.EnableCommands} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -486,10 +486,10 @@ class ServiceSettings extends React.Component { defaultChecked={!this.props.config.ServiceSettings.EnableCommands} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -520,10 +520,10 @@ class ServiceSettings extends React.Component { defaultChecked={this.props.config.ServiceSettings.EnableOnlyAdminIntegrations} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -533,10 +533,10 @@ class ServiceSettings extends React.Component { defaultChecked={!this.props.config.ServiceSettings.EnableOnlyAdminIntegrations} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -567,10 +567,10 @@ class ServiceSettings extends React.Component { defaultChecked={this.props.config.ServiceSettings.EnablePostUsernameOverride} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -580,10 +580,10 @@ class ServiceSettings extends React.Component { defaultChecked={!this.props.config.ServiceSettings.EnablePostUsernameOverride} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -594,7 +594,7 @@ class ServiceSettings extends React.Component { </div> </div> - <div className='form-group'> + <div className='form-group'> <label className='control-label col-sm-4' htmlFor='EnablePostIconOverride' @@ -614,10 +614,10 @@ class ServiceSettings extends React.Component { defaultChecked={this.props.config.ServiceSettings.EnablePostIconOverride} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -627,10 +627,10 @@ class ServiceSettings extends React.Component { defaultChecked={!this.props.config.ServiceSettings.EnablePostIconOverride} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -661,10 +661,10 @@ class ServiceSettings extends React.Component { defaultChecked={this.props.config.ServiceSettings.EnableTesting} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -674,10 +674,10 @@ class ServiceSettings extends React.Component { defaultChecked={!this.props.config.ServiceSettings.EnableTesting} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -708,10 +708,10 @@ class ServiceSettings extends React.Component { defaultChecked={this.props.config.ServiceSettings.EnableDeveloper} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -721,10 +721,10 @@ class ServiceSettings extends React.Component { defaultChecked={!this.props.config.ServiceSettings.EnableDeveloper} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -755,10 +755,10 @@ class ServiceSettings extends React.Component { defaultChecked={this.props.config.ServiceSettings.EnableSecurityFixAlert} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -768,10 +768,10 @@ class ServiceSettings extends React.Component { defaultChecked={!this.props.config.ServiceSettings.EnableSecurityFixAlert} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -802,10 +802,10 @@ class ServiceSettings extends React.Component { defaultChecked={this.props.config.ServiceSettings.EnableInsecureOutgoingConnections} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -815,10 +815,10 @@ class ServiceSettings extends React.Component { defaultChecked={!this.props.config.ServiceSettings.EnableInsecureOutgoingConnections} onChange={this.handleChange} /> - <FormattedMessage - id='admin.service.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage diff --git a/webapp/components/admin_console/sql_settings.jsx b/webapp/components/admin_console/sql_settings.jsx index f2e005b83..a6e09b4a0 100644 --- a/webapp/components/admin_console/sql_settings.jsx +++ b/webapp/components/admin_console/sql_settings.jsx @@ -330,10 +330,10 @@ class SqlSettings extends React.Component { defaultChecked={this.props.config.SqlSettings.Trace} onChange={this.handleChange} /> - <FormattedMessage - id='admin.sql.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.sql.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -343,10 +343,10 @@ class SqlSettings extends React.Component { defaultChecked={!this.props.config.SqlSettings.Trace} onChange={this.handleChange} /> - <FormattedMessage - id='admin.sql.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.sql.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -387,4 +387,4 @@ SqlSettings.propTypes = { config: React.PropTypes.object }; -export default injectIntl(SqlSettings);
\ No newline at end of file +export default injectIntl(SqlSettings); diff --git a/webapp/components/admin_console/team_settings.jsx b/webapp/components/admin_console/team_settings.jsx index e7bfcd74a..e3d7914a6 100644 --- a/webapp/components/admin_console/team_settings.jsx +++ b/webapp/components/admin_console/team_settings.jsx @@ -473,10 +473,10 @@ class TeamSettings extends React.Component { defaultChecked={this.props.config.TeamSettings.EnableTeamCreation} onChange={this.handleChange} /> - <FormattedMessage - id='admin.team.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.team.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -486,10 +486,10 @@ class TeamSettings extends React.Component { defaultChecked={!this.props.config.TeamSettings.EnableTeamCreation} onChange={this.handleChange} /> - <FormattedMessage - id='admin.team.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.team.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -520,10 +520,10 @@ class TeamSettings extends React.Component { defaultChecked={this.props.config.TeamSettings.EnableUserCreation} onChange={this.handleChange} /> - <FormattedMessage - id='admin.team.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.team.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -533,10 +533,10 @@ class TeamSettings extends React.Component { defaultChecked={!this.props.config.TeamSettings.EnableUserCreation} onChange={this.handleChange} /> - <FormattedMessage - id='admin.team.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.team.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -567,10 +567,10 @@ class TeamSettings extends React.Component { defaultChecked={this.props.config.TeamSettings.EnableOpenServer} onChange={this.handleChange} /> - <FormattedMessage - id='admin.team.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.team.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -580,10 +580,10 @@ class TeamSettings extends React.Component { defaultChecked={!this.props.config.TeamSettings.EnableOpenServer} onChange={this.handleChange} /> - <FormattedMessage - id='admin.team.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.team.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage @@ -643,10 +643,10 @@ class TeamSettings extends React.Component { defaultChecked={this.props.config.TeamSettings.RestrictTeamNames} onChange={this.handleChange} /> - <FormattedMessage - id='admin.team.true' - defaultMessage='true' - /> + <FormattedMessage + id='admin.team.true' + defaultMessage='true' + /> </label> <label className='radio-inline'> <input @@ -656,10 +656,10 @@ class TeamSettings extends React.Component { defaultChecked={!this.props.config.TeamSettings.RestrictTeamNames} onChange={this.handleChange} /> - <FormattedMessage - id='admin.team.false' - defaultMessage='false' - /> + <FormattedMessage + id='admin.team.false' + defaultMessage='false' + /> </label> <p className='help-text'> <FormattedMessage diff --git a/webapp/components/admin_console/user_item.jsx b/webapp/components/admin_console/user_item.jsx index ef6bd9f45..affd4b5a4 100644 --- a/webapp/components/admin_console/user_item.jsx +++ b/webapp/components/admin_console/user_item.jsx @@ -224,8 +224,8 @@ export default class UserItem extends React.Component { let showMakeSystemAdmin = user.roles === '' || user.roles === 'admin'; let showMakeActive = false; let showMakeNotActive = user.roles !== 'system_admin'; - let mfaEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MFA === 'true' && global.window.mm_config.EnableMultifactorAuthentication === 'true'; - let showMfaReset = mfaEnabled && user.mfa_active; + const mfaEnabled = global.window.mm_license.IsLicensed === 'true' && global.window.mm_license.MFA === 'true' && global.window.mm_config.EnableMultifactorAuthentication === 'true'; + const showMfaReset = mfaEnabled && user.mfa_active; if (user.delete_at > 0) { currentRoles = ( diff --git a/webapp/components/analytics/statistic_count.jsx b/webapp/components/analytics/statistic_count.jsx index cbb8935dd..89e0cc8df 100644 --- a/webapp/components/analytics/statistic_count.jsx +++ b/webapp/components/analytics/statistic_count.jsx @@ -7,7 +7,7 @@ import React from 'react'; export default class StatisticCount extends React.Component { render() { - let loading = ( + const loading = ( <FormattedMessage id='analytics.chart.loading' defaultMessage='Loading...' diff --git a/webapp/components/backstage/add_command.jsx b/webapp/components/backstage/add_command.jsx index ba9ac4e79..f3208bc5f 100644 --- a/webapp/components/backstage/add_command.jsx +++ b/webapp/components/backstage/add_command.jsx @@ -4,13 +4,12 @@ import React from 'react'; import * as AsyncClient from 'utils/async_client.jsx'; -import {browserHistory} from 'react-router'; import * as Utils from 'utils/utils.jsx'; import BackstageHeader from './backstage_header.jsx'; import {FormattedMessage} from 'react-intl'; import FormError from 'components/form_error.jsx'; -import {Link} from 'react-router'; +import {browserHistory, Link} from 'react-router'; import SpinnerButton from 'components/spinner_button.jsx'; const REQUEST_POST = 'P'; diff --git a/webapp/components/backstage/add_incoming_webhook.jsx b/webapp/components/backstage/add_incoming_webhook.jsx index 445d370b5..3d86fe7c0 100644 --- a/webapp/components/backstage/add_incoming_webhook.jsx +++ b/webapp/components/backstage/add_incoming_webhook.jsx @@ -4,14 +4,13 @@ import React from 'react'; import * as AsyncClient from 'utils/async_client.jsx'; -import {browserHistory} from 'react-router'; import * as Utils from 'utils/utils.jsx'; import BackstageHeader from './backstage_header.jsx'; import ChannelSelect from 'components/channel_select.jsx'; import {FormattedMessage} from 'react-intl'; import FormError from 'components/form_error.jsx'; -import {Link} from 'react-router'; +import {browserHistory, Link} from 'react-router'; import SpinnerButton from 'components/spinner_button.jsx'; export default class AddIncomingWebhook extends React.Component { diff --git a/webapp/components/backstage/add_outgoing_webhook.jsx b/webapp/components/backstage/add_outgoing_webhook.jsx index 245df1604..5f07217ab 100644 --- a/webapp/components/backstage/add_outgoing_webhook.jsx +++ b/webapp/components/backstage/add_outgoing_webhook.jsx @@ -4,14 +4,13 @@ import React from 'react'; import * as AsyncClient from 'utils/async_client.jsx'; -import {browserHistory} from 'react-router'; import * as Utils from 'utils/utils.jsx'; import BackstageHeader from './backstage_header.jsx'; import ChannelSelect from 'components/channel_select.jsx'; import {FormattedMessage} from 'react-intl'; import FormError from 'components/form_error.jsx'; -import {Link} from 'react-router'; +import {browserHistory, Link} from 'react-router'; import SpinnerButton from 'components/spinner_button.jsx'; export default class AddOutgoingWebhook extends React.Component { diff --git a/webapp/components/channel_header.jsx b/webapp/components/channel_header.jsx index 992244915..922f8b21c 100644 --- a/webapp/components/channel_header.jsx +++ b/webapp/components/channel_header.jsx @@ -47,6 +47,7 @@ export default class ChannelHeader extends React.Component { this.searchMentions = this.searchMentions.bind(this); this.showRenameChannelModal = this.showRenameChannelModal.bind(this); this.hideRenameChannelModal = this.hideRenameChannelModal.bind(this); + this.openRecentMentions = this.openRecentMentions.bind(this); const state = this.getStateFromStores(); state.showEditChannelPurposeModal = false; @@ -82,6 +83,7 @@ export default class ChannelHeader extends React.Component { PreferenceStore.addChangeListener(this.onListenerChange); UserStore.addChangeListener(this.onListenerChange); $('.sidebar--left .dropdown-menu').perfectScrollbar(); + document.addEventListener('keydown', this.openRecentMentions); } componentWillUnmount() { ChannelStore.removeChangeListener(this.onListenerChange); @@ -89,6 +91,7 @@ export default class ChannelHeader extends React.Component { SearchStore.removeSearchChangeListener(this.onListenerChange); PreferenceStore.removeChangeListener(this.onListenerChange); UserStore.removeChangeListener(this.onListenerChange); + document.removeEventListener('keydown', this.openRecentMentions); } onListenerChange() { const newState = this.getStateFromStores(); @@ -139,6 +142,11 @@ export default class ChannelHeader extends React.Component { is_mention_search: true }); } + openRecentMentions(e) { + if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.keyCode === Constants.KeyCodes.M) { + this.searchMentions(e); + } + } showRenameChannelModal(e) { e.preventDefault(); @@ -409,7 +417,8 @@ export default class ChannelHeader extends React.Component { } } - if (!ChannelStore.isDefault(channel)) { + const canLeave = channel.type === Constants.PRIVATE_CHANNEL ? this.state.userCount > 1 : true; + if (!ChannelStore.isDefault(channel) && canLeave) { dropdownContents.push( <li key='leave_channel' @@ -469,11 +478,11 @@ export default class ChannelHeader extends React.Component { overlay={popoverContent} ref='headerOverlay' > - <div - onClick={TextFormatting.handleClick} - className='description' - dangerouslySetInnerHTML={{__html: TextFormatting.formatText(channel.header, {singleline: true, mentionHighlight: false})}} - /> + <div + onClick={TextFormatting.handleClick} + className='description' + dangerouslySetInnerHTML={{__html: TextFormatting.formatText(channel.header, {singleline: true, mentionHighlight: false})}} + /> </OverlayTrigger> </div> </th> diff --git a/webapp/components/channel_notifications_modal.jsx b/webapp/components/channel_notifications_modal.jsx index 112c07ad0..6d2b4c284 100644 --- a/webapp/components/channel_notifications_modal.jsx +++ b/webapp/components/channel_notifications_modal.jsx @@ -289,10 +289,10 @@ export default class ChannelNotificationsModal extends React.Component { checked={this.state.unreadLevel === 'all'} onChange={this.handleUpdateMarkUnreadLevel.bind(this, 'all')} /> - <FormattedMessage - id='channel_notifications.allUnread' - defaultMessage='For all unread messages' - /> + <FormattedMessage + id='channel_notifications.allUnread' + defaultMessage='For all unread messages' + /> </label> <br/> </div> diff --git a/webapp/components/create_comment.jsx b/webapp/components/create_comment.jsx index 30e89e500..c25be8716 100644 --- a/webapp/components/create_comment.jsx +++ b/webapp/components/create_comment.jsx @@ -72,6 +72,7 @@ class CreateComment extends React.Component { const draft = PostStore.getCommentDraft(this.props.rootId); this.state = { messageText: draft.message, + lastMessage: '', uploadsInProgress: draft.uploadsInProgress, previews: draft.previews, submitting: false, @@ -111,7 +112,7 @@ class CreateComment extends React.Component { return; } - let post = {}; + const post = {}; post.filenames = []; post.message = this.state.messageText; @@ -144,7 +145,7 @@ class CreateComment extends React.Component { AsyncClient.getPosts(this.props.channelId); const channel = ChannelStore.get(this.props.channelId); - let member = ChannelStore.getMember(this.props.channelId); + const member = ChannelStore.getMember(this.props.channelId); member.msg_count = channel.total_msg_count; member.last_viewed_at = Date.now(); ChannelStore.setChannelMember(member); @@ -172,6 +173,7 @@ class CreateComment extends React.Component { this.setState({ messageText: '', + lastMessage: this.state.messageText, submitting: false, postError: null, previews: [], @@ -190,7 +192,7 @@ class CreateComment extends React.Component { GlobalActions.emitLocalUserTypingEvent(this.props.channelId, this.props.rootId); } handleUserInput(messageText) { - let draft = PostStore.getCommentDraft(this.props.rootId); + const draft = PostStore.getCommentDraft(this.props.rootId); draft.message = messageText; PostStore.storeCommentDraft(this.props.rootId, draft); @@ -203,7 +205,7 @@ class CreateComment extends React.Component { return; } - if (e.keyCode === KeyCodes.UP && this.state.messageText === '') { + if (!e.ctrlKey && e.keyCode === KeyCodes.UP && this.state.messageText === '') { e.preventDefault(); const lastPost = PostStore.getCurrentUsersLatestPost(this.props.channelId, this.props.rootId); @@ -221,12 +223,24 @@ class CreateComment extends React.Component { comments: PostStore.getCommentCount(lastPost) }); } + + if (e.ctrlKey && e.keyCode === KeyCodes.UP) { + const lastPost = PostStore.getCurrentUsersLatestPost(this.props.channelId, this.props.rootId); + if (!lastPost) { + return; + } + let message = lastPost.message; + if (this.state.lastMessage !== '') { + message = this.state.lastMessage; + } + this.setState({messageText: message}); + } } handleUploadClick() { this.focusTextbox(); } handleUploadStart(clientIds) { - let draft = PostStore.getCommentDraft(this.props.rootId); + const draft = PostStore.getCommentDraft(this.props.rootId); draft.uploadsInProgress = draft.uploadsInProgress.concat(clientIds); PostStore.storeCommentDraft(this.props.rootId, draft); @@ -238,7 +252,7 @@ class CreateComment extends React.Component { this.focusTextbox(); } handleFileUploadComplete(filenames, clientIds) { - let draft = PostStore.getCommentDraft(this.props.rootId); + const draft = PostStore.getCommentDraft(this.props.rootId); // remove each finished file from uploads for (let i = 0; i < clientIds.length; i++) { @@ -258,7 +272,7 @@ class CreateComment extends React.Component { if (clientId === -1) { this.setState({serverError: err}); } else { - let draft = PostStore.getCommentDraft(this.props.rootId); + const draft = PostStore.getCommentDraft(this.props.rootId); const index = draft.uploadsInProgress.indexOf(clientId); if (index !== -1) { @@ -271,8 +285,8 @@ class CreateComment extends React.Component { } } removePreview(id) { - let previews = this.state.previews; - let uploadsInProgress = this.state.uploadsInProgress; + const previews = this.state.previews; + const uploadsInProgress = this.state.uploadsInProgress; // id can either be the path of an uploaded file or the client id of an in progress upload let index = previews.indexOf(id); @@ -287,7 +301,7 @@ class CreateComment extends React.Component { previews.splice(index, 1); } - let draft = PostStore.getCommentDraft(this.props.rootId); + const draft = PostStore.getCommentDraft(this.props.rootId); draft.previews = previews; draft.uploadsInProgress = uploadsInProgress; PostStore.storeCommentDraft(this.props.rootId, draft); diff --git a/webapp/components/create_post.jsx b/webapp/components/create_post.jsx index d173fe42b..863f969df 100644 --- a/webapp/components/create_post.jsx +++ b/webapp/components/create_post.jsx @@ -77,6 +77,7 @@ class CreatePost extends React.Component { this.state = { channelId: ChannelStore.getCurrentId(), messageText: draft.messageText, + lastMessage: '', uploadsInProgress: draft.uploadsInProgress, previews: draft.previews, submitting: false, @@ -126,7 +127,7 @@ class CreatePost extends React.Component { } this.setState({submitting: true, serverError: null}); - + this.setState({lastMessage: this.state.messageText}); if (post.message.indexOf('/') === 0) { Client.executeCommand( this.state.channelId, @@ -350,7 +351,7 @@ class CreatePost extends React.Component { return; } - if (e.keyCode === KeyCodes.UP && this.state.messageText === '') { + if (!e.ctrlKey && e.keyCode === KeyCodes.UP && this.state.messageText === '') { e.preventDefault(); const channelId = ChannelStore.getCurrentId(); @@ -371,6 +372,19 @@ class CreatePost extends React.Component { comments: PostStore.getCommentCount(lastPost) }); } + + if (e.ctrlKey && e.keyCode === KeyCodes.UP) { + const channelId = ChannelStore.getCurrentId(); + const lastPost = PostStore.getCurrentUsersLatestPost(channelId); + if (!lastPost) { + return; + } + let message = lastPost.message; + if (this.state.lastMessage !== '') { + message = this.state.lastMessage; + } + this.setState({messageText: message}); + } } showPostDeletedModal() { this.setState({ diff --git a/webapp/components/error_bar.jsx b/webapp/components/error_bar.jsx index d28be671d..a3ed337f1 100644 --- a/webapp/components/error_bar.jsx +++ b/webapp/components/error_bar.jsx @@ -81,7 +81,7 @@ export default class ErrorBar extends React.Component { className='error-bar__close' onClick={this.handleClose} > - × + {'×'} </a> </div> ); diff --git a/webapp/components/file_attachment.jsx b/webapp/components/file_attachment.jsx index 4a040a35b..c909b9afb 100644 --- a/webapp/components/file_attachment.jsx +++ b/webapp/components/file_attachment.jsx @@ -149,12 +149,12 @@ class FileAttachment extends React.Component { if (this.state.fileSize < 0) { Client.getFileInfo( filename, - function success(data) { + (data) => { if (this.canSetState) { this.setState({fileSize: parseInt(data.size, 10)}); } - }.bind(this), - function error() { + }, + () => { // Do nothing } ); @@ -175,7 +175,8 @@ class FileAttachment extends React.Component { className='post-image__column' key={filename} > - <a className='post-image__thumbnail' + <a + className='post-image__thumbnail' href='#' onClick={() => this.props.handleImageClick(this.props.index)} > @@ -186,9 +187,10 @@ class FileAttachment extends React.Component { href={fileUrl} download={filenameString} data-toggle='tooltip' - title={this.props.intl.formatMessage(holders.download) + ' \"' + filenameString + '\"'} + title={this.props.intl.formatMessage(holders.download) + ' "' + filenameString + '"'} className='post-image__name' target='_blank' + rel='noopener noreferrer' > {trimmedFilename} </a> @@ -198,6 +200,7 @@ class FileAttachment extends React.Component { download={filenameString} className='post-image__download' target='_blank' + rel='noopener noreferrer' > <span className='fa fa-download' diff --git a/webapp/components/file_info_preview.jsx b/webapp/components/file_info_preview.jsx index d5dcd75eb..fe4e76f91 100644 --- a/webapp/components/file_info_preview.jsx +++ b/webapp/components/file_info_preview.jsx @@ -38,6 +38,7 @@ export default function FileInfoPreview({filename, fileUrl, fileInfo, formatMess className={'file-details__preview'} to={fileUrl} target='_blank' + rel='noopener noreferrer' > <span className='file-details__preview-helper'/> <img src={Utils.getPreviewImagePath(filename)}/> diff --git a/webapp/components/file_upload.jsx b/webapp/components/file_upload.jsx index 05f1701a8..829e580b9 100644 --- a/webapp/components/file_upload.jsx +++ b/webapp/components/file_upload.jsx @@ -284,7 +284,10 @@ class FileUpload extends React.Component { keyUpload(e) { if ((e.ctrlKey || e.metaKey) && e.keyCode === Constants.KeyCodes.U) { - $(this.refs.input).focus().trigger('click'); + e.preventDefault(); + if (this.props.postType === 'post' && document.activeElement.id === 'post_textbox' || this.props.postType === 'comment' && document.activeElement.id === 'reply_textbox') { + $(this.refs.fileInput).focus().trigger('click'); + } } } diff --git a/webapp/components/header_footer_template.jsx b/webapp/components/header_footer_template.jsx index 71716c4fb..d153a5719 100644 --- a/webapp/components/header_footer_template.jsx +++ b/webapp/components/header_footer_template.jsx @@ -33,8 +33,8 @@ export default class NotLoggedIn extends React.Component { id='help_link' className='pull-right footer-link' target='_blank' + rel='noopener noreferrer' href={global.window.mm_config.HelpLink} - rel='noreferrer' > <FormattedMessage id='web.footer.help'/> </a> @@ -42,8 +42,8 @@ export default class NotLoggedIn extends React.Component { id='terms_link' className='pull-right footer-link' target='_blank' + rel='noopener noreferrer' href={global.window.mm_config.TermsOfServiceLink} - rel='noreferrer' > <FormattedMessage id='web.footer.terms'/> </a> @@ -51,8 +51,8 @@ export default class NotLoggedIn extends React.Component { id='privacy_link' className='pull-right footer-link' target='_blank' + rel='noopener noreferrer' href={global.window.mm_config.PrivacyPolicyLink} - rel='noreferrer' > <FormattedMessage id='web.footer.privacy'/> </a> @@ -60,8 +60,8 @@ export default class NotLoggedIn extends React.Component { id='about_link' className='pull-right footer-link' target='_blank' + rel='noopener noreferrer' href={global.window.mm_config.AboutLink} - rel='noreferrer' > <FormattedMessage id='web.footer.about'/> </a> diff --git a/webapp/components/invite_member_modal.jsx b/webapp/components/invite_member_modal.jsx index 4ac620f08..205988dc8 100644 --- a/webapp/components/invite_member_modal.jsx +++ b/webapp/components/invite_member_modal.jsx @@ -258,15 +258,17 @@ class InviteMemberModal extends React.Component { var removeButton = null; if (index) { - removeButton = (<div> - <button - type='button' - className='btn btn-link remove__member' - onClick={this.removeInviteFields.bind(this, index)} - > - <span className='fa fa-trash'></span> - </button> - </div>); + removeButton = ( + <div> + <button + type='button' + className='btn btn-link remove__member' + onClick={this.removeInviteFields.bind(this, index)} + > + <span className='fa fa-trash'></span> + </button> + </div> + ); } var emailClass = 'form-group invite'; if (emailError) { @@ -283,54 +285,56 @@ class InviteMemberModal extends React.Component { if (lastNameError) { lastNameClass += ' has-error'; } - nameFields = (<div className='row--invite'> - <div className='col-sm-6'> - <div className={firstNameClass}> - <input - type='text' - className='form-control' - ref={'first_name' + index} - placeholder={formatMessage(holders.firstname)} - maxLength='64' - disabled={!this.state.emailEnabled || !this.state.userCreationEnabled} - spellCheck='false' - /> - {firstNameError} - </div> - </div> - <div className='col-sm-6'> - <div className={lastNameClass}> - <input - type='text' - className='form-control' - ref={'last_name' + index} - placeholder={formatMessage(holders.lastname)} - maxLength='64' - disabled={!this.state.emailEnabled || !this.state.userCreationEnabled} - spellCheck='false' - /> - {lastNameError} - </div> - </div> - </div>); + nameFields = ( + <div className='row--invite'> + <div className='col-sm-6'> + <div className={firstNameClass}> + <input + type='text' + className='form-control' + ref={'first_name' + index} + placeholder={formatMessage(holders.firstname)} + maxLength='64' + disabled={!this.state.emailEnabled || !this.state.userCreationEnabled} + spellCheck='false' + /> + {firstNameError} + </div> + </div> + <div className='col-sm-6'> + <div className={lastNameClass}> + <input + type='text' + className='form-control' + ref={'last_name' + index} + placeholder={formatMessage(holders.lastname)} + maxLength='64' + disabled={!this.state.emailEnabled || !this.state.userCreationEnabled} + spellCheck='false' + /> + {lastNameError} + </div> + </div> + </div> + ); inviteSections[index] = ( <div key={'key' + index}> - {removeButton} - <div className={emailClass}> - <input - onKeyUp={this.displayNameKeyUp} - type='text' - ref={'email' + index} - className='form-control' - placeholder='email@domain.com' - maxLength='64' - disabled={!this.state.emailEnabled || !this.state.userCreationEnabled} - spellCheck='false' - /> - {emailError} - </div> - {nameFields} + {removeButton} + <div className={emailClass}> + <input + onKeyUp={this.displayNameKeyUp} + type='text' + ref={'email' + index} + className='form-control' + placeholder='email@domain.com' + maxLength='64' + disabled={!this.state.emailEnabled || !this.state.userCreationEnabled} + spellCheck='false' + /> + {emailError} + </div> + {nameFields} </div> ); } diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx index 21ca53649..ee199fc03 100644 --- a/webapp/components/navbar.jsx +++ b/webapp/components/navbar.jsx @@ -218,20 +218,23 @@ export default class Navbar extends React.Component { </li> ); - leaveChannelOption = ( - <li role='presentation'> - <a - role='menuitem' - href='#' - onClick={this.handleLeave} - > - <FormattedMessage - id='navbar.leave' - defaultMessage='Leave Channel' - /> - </a> - </li> - ); + const canLeave = channel.type === Constants.PRIVATE_CHANNEL ? this.state.userCount > 1 : true; + if (canLeave) { + leaveChannelOption = ( + <li role='presentation'> + <a + role='menuitem' + href='#' + onClick={this.handleLeave} + > + <FormattedMessage + id='navbar.leave' + defaultMessage='Leave Channel' + /> + </a> + </li> + ); + } } var manageMembersOption; diff --git a/webapp/components/navbar_dropdown.jsx b/webapp/components/navbar_dropdown.jsx index 7f1cfce7c..162841f32 100644 --- a/webapp/components/navbar_dropdown.jsx +++ b/webapp/components/navbar_dropdown.jsx @@ -28,6 +28,7 @@ export default class NavbarDropdown extends React.Component { this.handleAboutModal = this.handleAboutModal.bind(this); this.aboutModalDismissed = this.aboutModalDismissed.bind(this); this.onTeamChange = this.onTeamChange.bind(this); + this.openAccountSettings = this.openAccountSettings.bind(this); this.state = { showUserSettingsModal: false, @@ -53,6 +54,7 @@ export default class NavbarDropdown extends React.Component { }); TeamStore.addChangeListener(this.onTeamChange); + document.addEventListener('keydown', this.openAccountSettings); } onTeamChange() { @@ -65,8 +67,13 @@ export default class NavbarDropdown extends React.Component { componentWillUnmount() { $(ReactDOM.findDOMNode(this.refs.dropdown)).off('hide.bs.dropdown'); TeamStore.removeChangeListener(this.onTeamChange); + document.removeEventListener('keydown', this.openAccountSettings); + } + openAccountSettings(e) { + if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.keyCode === Constants.KeyCodes.A) { + this.setState({showUserSettingsModal: true}); + } } - render() { var teamLink = ''; var inviteLink = ''; @@ -228,8 +235,8 @@ export default class NavbarDropdown extends React.Component { <li> <Link target='_blank' + rel='noopener noreferrer' to={global.window.mm_config.HelpLink} - rel='noreferrer' > <FormattedMessage id='navbar_dropdown.help' @@ -246,8 +253,8 @@ export default class NavbarDropdown extends React.Component { <li> <Link target='_blank' + rel='noopener noreferrer' to={global.window.mm_config.ReportAProblemLink} - rel='noreferrer' > <FormattedMessage id='navbar_dropdown.report' diff --git a/webapp/components/post_attachment.jsx b/webapp/components/post_attachment.jsx index 1c3df6ea2..8b5ff91f2 100644 --- a/webapp/components/post_attachment.jsx +++ b/webapp/components/post_attachment.jsx @@ -59,7 +59,7 @@ class PostAttachment extends React.Component { toggleCollapseState(e) { e.preventDefault(); - let state = this.state; + const state = this.state; state.text = state.collapsed ? state.uncollapsedText : state.collapsedText; state.collapsed = !state.collapsed; this.setState(state); @@ -142,22 +142,22 @@ class PostAttachment extends React.Component { }); if (headerCols.length > 0) { // Flush last fields fieldTables.push( - <table - className='attachment___fields' - key={'attachment__table__' + nrTables} - > - <thead> - <tr> + <table + className='attachment___fields' + key={'attachment__table__' + nrTables} + > + <thead> + <tr> {headerCols} - </tr> - </thead> - <tbody> - <tr> - {bodyCols} - </tr> - </tbody> - </table> - ); + </tr> + </thead> + <tbody> + <tr> + {bodyCols} + </tr> + </tbody> + </table> + ); } return ( <div> @@ -209,6 +209,7 @@ class PostAttachment extends React.Component { <a href={data.author_link} target='_blank' + rel='noopener noreferrer' > {author} </a> @@ -226,6 +227,7 @@ class PostAttachment extends React.Component { className='attachment__title-link' href={data.title_link} target='_blank' + rel='noopener noreferrer' > {data.title} </a> diff --git a/webapp/components/post_attachment_oembed.jsx b/webapp/components/post_attachment_oembed.jsx index a4e4ce001..359c7cc35 100644 --- a/webapp/components/post_attachment_oembed.jsx +++ b/webapp/components/post_attachment_oembed.jsx @@ -72,30 +72,31 @@ export default class PostAttachmentOEmbed extends React.Component { className='attachment attachment--oembed' ref='attachment' > - <div className='attachment__content'> - <div - className={'clearfix attachment__container'} + <div className='attachment__content'> + <div + className={'clearfix attachment__container'} + > + <h1 + className='attachment__title' > - <h1 - className='attachment__title' + <a + className='attachment__title-link' + href={data.url} + target='_blank' + rel='noopener noreferrer' > - <a - className='attachment__title-link' - href={data.url} - target='_blank' - > - {data.title} - </a> - </h1> - <div > - <div - className={'attachment__body attachment__body--no_thumb'} - > - {content} - </div> + {data.title} + </a> + </h1> + <div > + <div + className={'attachment__body attachment__body--no_thumb'} + > + {content} </div> </div> </div> + </div> </div> ); } diff --git a/webapp/components/post_body_additional_content.jsx b/webapp/components/post_body_additional_content.jsx index 452597dde..cdb735b47 100644 --- a/webapp/components/post_body_additional_content.jsx +++ b/webapp/components/post_body_additional_content.jsx @@ -120,7 +120,8 @@ export default class PostBodyAdditionalContent extends React.Component { let toggle; if (Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMBED_TOGGLE)) { toggle = ( - <a className='post__embed-visibility' + <a + className='post__embed-visibility' data-expanded={this.state.embedVisible} aria-label='Toggle Embed Visibility' onClick={this.toggleEmbedVisibility} @@ -131,7 +132,8 @@ export default class PostBodyAdditionalContent extends React.Component { return ( <div> {toggle} - <div className='post__embed-container' + <div + className='post__embed-container' hidden={!this.state.embedVisible} > {generateEmbed} diff --git a/webapp/components/removed_from_channel_modal.jsx b/webapp/components/removed_from_channel_modal.jsx index d037c089d..2199dbbec 100644 --- a/webapp/components/removed_from_channel_modal.jsx +++ b/webapp/components/removed_from_channel_modal.jsx @@ -98,7 +98,11 @@ export default class RemovedFromChannelModal extends React.Component { className='close' data-dismiss='modal' aria-label='Close' - ><span aria-hidden='true'>×</span></button> + > + <span aria-hidden='true'> + {'×'} + </span> + </button> <h4 className='modal-title'> <FormattedMessage id='removed_channel.from' @@ -107,16 +111,16 @@ export default class RemovedFromChannelModal extends React.Component { <span className='name'>{channelName}</span></h4> </div> <div className='modal-body'> - <p> - <FormattedMessage - id='removed_channel.remover' - defaultMessage='{remover} removed you from {channel}' - values={{ - remover: (remover), - channel: (channelName) - }} - /> - </p> + <p> + <FormattedMessage + id='removed_channel.remover' + defaultMessage='{remover} removed you from {channel}' + values={{ + remover: (remover), + channel: (channelName) + }} + /> + </p> </div> <div className='modal-footer'> <button diff --git a/webapp/components/settings_sidebar.jsx b/webapp/components/settings_sidebar.jsx index d55eb5366..dc59409a0 100644 --- a/webapp/components/settings_sidebar.jsx +++ b/webapp/components/settings_sidebar.jsx @@ -23,7 +23,7 @@ export default class SettingsSidebar extends React.Component { } } render() { - let tabList = this.props.tabs.map(function makeTab(tab) { + let tabList = this.props.tabs.map((tab) => { let key = `${tab.name}_li`; let className = ''; if (this.props.activeTab === tab.name) { @@ -44,7 +44,7 @@ export default class SettingsSidebar extends React.Component { </a> </li> ); - }.bind(this)); + }); return ( <div> diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx index a4d85f4ff..d20fef603 100644 --- a/webapp/components/sidebar.jsx +++ b/webapp/components/sidebar.jsx @@ -640,13 +640,13 @@ export default class Sidebar extends React.Component { placement='top' overlay={createChannelTootlip} > - <a - className='add-channel-btn' - href='#' - onClick={this.showNewChannelModal.bind(this, 'O')} - > - {'+'} - </a> + <a + className='add-channel-btn' + href='#' + onClick={this.showNewChannelModal.bind(this, 'O')} + > + {'+'} + </a> </OverlayTrigger> </h4> </li> @@ -677,13 +677,13 @@ export default class Sidebar extends React.Component { placement='top' overlay={createGroupTootlip} > - <a - className='add-channel-btn' - href='#' - onClick={this.showNewChannelModal.bind(this, 'P')} - > - {'+'} - </a> + <a + className='add-channel-btn' + href='#' + onClick={this.showNewChannelModal.bind(this, 'P')} + > + {'+'} + </a> </OverlayTrigger> </h4> </li> diff --git a/webapp/components/sidebar_header.jsx b/webapp/components/sidebar_header.jsx index 143a3458a..76d9cf214 100644 --- a/webapp/components/sidebar_header.jsx +++ b/webapp/components/sidebar_header.jsx @@ -89,7 +89,7 @@ export default class SidebarHeader extends React.Component { overlay={<Tooltip id='team-name__tooltip'>{this.props.teamDisplayName}</Tooltip>} ref='descriptionOverlay' > - <div className='team__name'>{this.props.teamDisplayName}</div> + <div className='team__name'>{this.props.teamDisplayName}</div> </OverlayTrigger> </div> </a> diff --git a/webapp/components/sidebar_right_menu.jsx b/webapp/components/sidebar_right_menu.jsx index b36d84b79..218a3b164 100644 --- a/webapp/components/sidebar_right_menu.jsx +++ b/webapp/components/sidebar_right_menu.jsx @@ -174,8 +174,8 @@ export default class SidebarRightMenu extends React.Component { <li> <Link target='_blank' + rel='noopener noreferrer' to={global.window.mm_config.HelpLink} - rel='noreferrer' > <i className='fa fa-question'></i> <FormattedMessage @@ -193,8 +193,8 @@ export default class SidebarRightMenu extends React.Component { <li> <Link target='_blank' + rel='noopener noreferrer' to={global.window.mm_config.ReportAProblemLink} - rel='noreferrer' > <i className='fa fa-phone'></i> <FormattedMessage diff --git a/webapp/components/signup_user_complete.jsx b/webapp/components/signup_user_complete.jsx index 5c06cefed..b7d5e5156 100644 --- a/webapp/components/signup_user_complete.jsx +++ b/webapp/components/signup_user_complete.jsx @@ -198,6 +198,33 @@ export default class SignupUserComplete extends React.Component { ); } + handleUserCreated(user, data) { + Client.track('signup', 'signup_user_02_complete'); + Client.loginById( + data.id, + user.password, + '', + () => { + if (this.state.hash > 0) { + BrowserStore.setGlobalItem(this.state.hash, JSON.stringify({usedBefore: true})); + } + + GlobalActions.emitInitialLoad( + () => { + browserHistory.push('/select_team'); + } + ); + }, + (err) => { + if (err.id === 'api.user.login.not_verified.app_error') { + browserHistory.push('/should_verify_email?email=' + encodeURIComponent(user.email) + '&teamname=' + encodeURIComponent(this.state.teamName)); + } else { + this.setState({serverError: err.message}); + } + } + ); + } + handleSubmit(e) { e.preventDefault(); @@ -296,32 +323,7 @@ export default class SignupUserComplete extends React.Component { this.state.data, this.state.hash, this.state.inviteId, - (data) => { - Client.track('signup', 'signup_user_02_complete'); - Client.loginById( - data.id, - user.password, - '', - () => { - if (this.state.hash > 0) { - BrowserStore.setGlobalItem(this.state.hash, JSON.stringify({usedBefore: true})); - } - - GlobalActions.emitInitialLoad( - () => { - browserHistory.push('/select_team'); - } - ); - }, - (err) => { - if (err.id === 'api.user.login.not_verified.app_error') { - browserHistory.push('/should_verify_email?email=' + encodeURIComponent(user.email) + '&teamname=' + encodeURIComponent(this.state.teamName)); - } else { - this.setState({serverError: err.message}); - } - } - ); - }, + this.handleUserCreated.bind(this, user), (err) => { this.setState({serverError: err.message}); } diff --git a/webapp/components/team_general_tab.jsx b/webapp/components/team_general_tab.jsx index 1f783fe9f..9242fc03d 100644 --- a/webapp/components/team_general_tab.jsx +++ b/webapp/components/team_general_tab.jsx @@ -473,7 +473,9 @@ class GeneralTab extends React.Component { data-dismiss='modal' aria-label='Close' > - <span aria-hidden='true'>×</span> + <span aria-hidden='true'> + {'×'} + </span> </button> <h4 className='modal-title' @@ -518,4 +520,4 @@ GeneralTab.propTypes = { activeSection: React.PropTypes.string.isRequired }; -export default injectIntl(GeneralTab);
\ No newline at end of file +export default injectIntl(GeneralTab); diff --git a/webapp/components/team_import_tab.jsx b/webapp/components/team_import_tab.jsx index 782273c5a..f724a789a 100644 --- a/webapp/components/team_import_tab.jsx +++ b/webapp/components/team_import_tab.jsx @@ -123,7 +123,8 @@ class TeamImportTab extends React.Component { return ( <div> <div className='modal-header'> - <button type='button' + <button + type='button' className='close' data-dismiss='modal' aria-label='Close' diff --git a/webapp/components/team_settings_modal.jsx b/webapp/components/team_settings_modal.jsx index 657643367..fedf34ab5 100644 --- a/webapp/components/team_settings_modal.jsx +++ b/webapp/components/team_settings_modal.jsx @@ -92,7 +92,9 @@ class TeamSettingsModal extends React.Component { data-dismiss='modal' aria-label='Close' > - <span aria-hidden='true'>×</span> + <span aria-hidden='true'> + {'×'} + </span> </button> <h4 className='modal-title' @@ -133,4 +135,4 @@ TeamSettingsModal.propTypes = { intl: intlShape.isRequired }; -export default injectIntl(TeamSettingsModal);
\ No newline at end of file +export default injectIntl(TeamSettingsModal); diff --git a/webapp/components/textbox.jsx b/webapp/components/textbox.jsx index 4aa88d267..7f5ecea09 100644 --- a/webapp/components/textbox.jsx +++ b/webapp/components/textbox.jsx @@ -211,6 +211,7 @@ export default class Textbox extends React.Component { {previewLink} <a target='_blank' + rel='noopener noreferrer' href='http://docs.mattermost.com/help/getting-started/messaging-basics.html' className='textbox-help-link' > diff --git a/webapp/components/toggle_modal_button.jsx b/webapp/components/toggle_modal_button.jsx index 69bdbbda0..6082901de 100644 --- a/webapp/components/toggle_modal_button.jsx +++ b/webapp/components/toggle_modal_button.jsx @@ -25,7 +25,7 @@ export default class ModalToggleButton extends React.Component { } render() { - const {children, dialogType, dialogProps, onClick, ...props} = this.props; // eslint-disable-line no-use-before-define + const {children, dialogType, dialogProps, onClick, ...props} = this.props; // allow callers to provide an onClick which will be called before the modal is shown let clickHandler = this.show; @@ -38,7 +38,7 @@ export default class ModalToggleButton extends React.Component { } // this assumes that all modals will have a show property and an onHide event - const dialog = React.createElement(this.props.dialogType, Object.assign({}, dialogProps, { + const dialog = React.createElement(dialogType, Object.assign({}, dialogProps, { show: this.state.show, onHide: () => { this.hide(); diff --git a/webapp/components/tutorial/tutorial_intro_screens.jsx b/webapp/components/tutorial/tutorial_intro_screens.jsx index 95c26edca..a4928f9cb 100644 --- a/webapp/components/tutorial/tutorial_intro_screens.jsx +++ b/webapp/components/tutorial/tutorial_intro_screens.jsx @@ -149,6 +149,7 @@ export default class TutorialIntroScreens extends React.Component { <a href={'mailto:' + global.window.mm_config.SupportEmail} target='_blank' + rel='noopener noreferrer' > {global.window.mm_config.SupportEmail} </a> diff --git a/webapp/components/user_settings/custom_theme_chooser.jsx b/webapp/components/user_settings/custom_theme_chooser.jsx index 9fbdd1251..e77ea1d30 100644 --- a/webapp/components/user_settings/custom_theme_chooser.jsx +++ b/webapp/components/user_settings/custom_theme_chooser.jsx @@ -230,11 +230,11 @@ class CustomThemeChooser extends React.Component { overlay={popoverContent} ref='headerOverlay' > - <span className='input-group-addon'> - <img - src={codeThemeURL} - /> - </span> + <span className='input-group-addon'> + <img + src={codeThemeURL} + /> + </span> </OverlayTrigger> </div> </div> diff --git a/webapp/components/user_settings/import_theme_modal.jsx b/webapp/components/user_settings/import_theme_modal.jsx index 32da296bf..f743feee6 100644 --- a/webapp/components/user_settings/import_theme_modal.jsx +++ b/webapp/components/user_settings/import_theme_modal.jsx @@ -81,7 +81,7 @@ class ImportThemeModal extends React.Component { theme.mentionHighlightLink = '#2f81b7'; theme.codeTheme = 'github'; - let user = UserStore.getCurrentUser(); + const user = UserStore.getCurrentUser(); user.theme_props = theme; Client.updateUser(user, diff --git a/webapp/components/user_settings/premade_theme_chooser.jsx b/webapp/components/user_settings/premade_theme_chooser.jsx index 4b0faf865..9552c686d 100644 --- a/webapp/components/user_settings/premade_theme_chooser.jsx +++ b/webapp/components/user_settings/premade_theme_chooser.jsx @@ -59,6 +59,7 @@ export default class PremadeThemeChooser extends React.Component { <a href='http://docs.mattermost.com/help/settings/theme-colors.html#custom-theme-examples' target='_blank' + rel='noopener noreferrer' > <FormattedMessage id='user.settings.display.theme.otherThemes' diff --git a/webapp/components/user_settings/user_settings_notifications.jsx b/webapp/components/user_settings/user_settings_notifications.jsx index fa84ce2d6..6a3f598e2 100644 --- a/webapp/components/user_settings/user_settings_notifications.jsx +++ b/webapp/components/user_settings/user_settings_notifications.jsx @@ -150,13 +150,13 @@ class NotificationsTab extends React.Component { data.channel = this.state.channelKey.toString(); Client.updateUserNotifyProps(data, - function success() { + () => { this.props.updateSection(''); AsyncClient.getMe(); - }.bind(this), - function failure(err) { + }, + (err) => { this.setState({serverError: err.message}); - }.bind(this) + } ); } handleCancel(e) { @@ -254,7 +254,8 @@ class NotificationsTab extends React.Component { <div key='userNotificationLevelOption'> <div className='radio'> <label> - <input type='radio' + <input + type='radio' checked={notifyActive[0]} onChange={this.handleNotifyRadio.bind(this, 'all')} /> @@ -393,8 +394,8 @@ class NotificationsTab extends React.Component { /> </label> <br/> - </div> - </div> + </div> + </div> ); const extraInfo = ( diff --git a/webapp/components/user_settings/user_settings_security.jsx b/webapp/components/user_settings/user_settings_security.jsx index 700aa295a..433d08d5c 100644 --- a/webapp/components/user_settings/user_settings_security.jsx +++ b/webapp/components/user_settings/user_settings_security.jsx @@ -608,11 +608,11 @@ class SecurityTab extends React.Component { const inputs = []; inputs.push( <div key='userSignInOption'> - {emailOption} - {gitlabOption} - <br/> - {ldapOption} - {googleOption} + {emailOption} + {gitlabOption} + <br/> + {ldapOption} + {googleOption} </div> ); diff --git a/webapp/components/user_settings/user_settings_theme.jsx b/webapp/components/user_settings/user_settings_theme.jsx index f19538f71..389fde004 100644 --- a/webapp/components/user_settings/user_settings_theme.jsx +++ b/webapp/components/user_settings/user_settings_theme.jsx @@ -212,7 +212,8 @@ export default class ThemeSetting extends React.Component { key='premadeThemeColorLabel' > <label> - <input type='radio' + <input + type='radio' checked={!displayCustom} onChange={this.updateType.bind(this, 'premade')} /> @@ -233,7 +234,8 @@ export default class ThemeSetting extends React.Component { key='customThemeColorLabel' > <label> - <input type='radio' + <input + type='radio' checked={displayCustom} onChange={this.updateType.bind(this, 'custom')} /> diff --git a/webapp/components/view_image.jsx b/webapp/components/view_image.jsx index c4d7cb4aa..f70a57cb8 100644 --- a/webapp/components/view_image.jsx +++ b/webapp/components/view_image.jsx @@ -404,6 +404,7 @@ function ImagePreview({filename, fileUrl, fileInfo, maxHeight}) { <a href={fileUrl} target='_blank' + rel='noopener noreferrer' download={true} > <img diff --git a/webapp/components/view_image_popover_bar.jsx b/webapp/components/view_image_popover_bar.jsx index 5b9b2362f..3554ae3f8 100644 --- a/webapp/components/view_image_popover_bar.jsx +++ b/webapp/components/view_image_popover_bar.jsx @@ -54,6 +54,7 @@ export default class ViewImagePopoverBar extends React.Component { download={this.props.filename} className='text' target='_blank' + rel='noopener noreferrer' > <FormattedMessage id='view_image_popover.download' diff --git a/webapp/components/youtube_video.jsx b/webapp/components/youtube_video.jsx index 6083fd8a1..f96504e88 100644 --- a/webapp/components/youtube_video.jsx +++ b/webapp/components/youtube_video.jsx @@ -4,7 +4,7 @@ import $ from 'jquery'; import ChannelStore from 'stores/channel_store.jsx'; -const ytRegex = /(?:http|https):\/\/(?:www\.)?(?:(?:youtube\.com\/(?:(?:v\/)|(\/u\/\w\/)|(?:(?:watch|embed\/watch)(?:\/|.*v=))|(?:embed\/)|(?:user\/[^\/]+\/u\/[0-9]\/)))|(?:youtu\.be\/))([^#\&\?]*)/; +const ytRegex = /(?:http|https):\/\/(?:www\.)?(?:(?:youtube\.com\/(?:(?:v\/)|(\/u\/\w\/)|(?:(?:watch|embed\/watch)(?:\/|.*v=))|(?:embed\/)|(?:user\/[^\/]+\/u\/[0-9]\/)))|(?:youtu\.be\/))([^#&\?]*)/; import React from 'react'; import {Link} from 'react-router'; |