summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/react/components/about_build_modal.jsx62
-rw-r--r--web/react/components/admin_console/privacy_settings.jsx16
-rw-r--r--web/react/components/create_comment.jsx3
-rw-r--r--web/react/components/navbar_dropdown.jsx22
-rw-r--r--web/react/components/post_deleted_modal.jsx36
-rw-r--r--web/react/components/post_list.jsx8
-rw-r--r--web/react/components/rhs_thread.jsx11
-rw-r--r--web/react/components/team_signup_choose_auth.jsx2
-rw-r--r--web/react/components/team_signup_with_email.jsx20
-rw-r--r--web/react/components/team_signup_with_sso.jsx10
-rw-r--r--web/react/components/user_settings/user_settings_general.jsx69
-rw-r--r--web/react/components/user_settings/user_settings_security.jsx11
-rw-r--r--web/react/utils/markdown.jsx10
-rw-r--r--web/react/utils/text_formatting.jsx7
-rw-r--r--web/sass-files/sass/partials/_settings.scss1
-rw-r--r--web/static/images/Battlehouse-logodark.pngbin6981 -> 0 bytes
-rw-r--r--web/static/images/Mattermost-logodark.pngbin10380 -> 0 bytes
-rw-r--r--web/static/images/logo-email.png (renamed from web/static/images/Bladekick-logodark.png)bin10380 -> 10380 bytes
-rw-r--r--web/web.go26
19 files changed, 253 insertions, 61 deletions
diff --git a/web/react/components/about_build_modal.jsx b/web/react/components/about_build_modal.jsx
new file mode 100644
index 000000000..d582f6bc8
--- /dev/null
+++ b/web/react/components/about_build_modal.jsx
@@ -0,0 +1,62 @@
+// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+var Modal = ReactBootstrap.Modal;
+
+export default class AboutBuildModal extends React.Component {
+ constructor(props) {
+ super(props);
+ this.doHide = this.doHide.bind(this);
+ }
+
+ doHide() {
+ this.props.onModalDismissed();
+ }
+
+ render() {
+ const config = global.window.config;
+
+ return (
+ <Modal
+ show={this.props.show}
+ onHide={this.doHide}
+ >
+ <Modal.Header closeButton={true}>
+ <Modal.Title>{`Mattermost ${config.Version}`}</Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ <div className='row form-group'>
+ <div className='col-sm-3 info__label'>{'Build Number:'}</div>
+ <div className='col-sm-9'>{config.BuildNumber}</div>
+ </div>
+ <div className='row form-group'>
+ <div className='col-sm-3 info__label'>{'Build Date:'}</div>
+ <div className='col-sm-9'>{config.BuildDate}</div>
+ </div>
+ <div className='row'>
+ <div className='col-sm-3 info__label'>{'Build Hash:'}</div>
+ <div className='col-sm-9'>{config.BuildHash}</div>
+ </div>
+ </Modal.Body>
+ <Modal.Footer>
+ <button
+ type='button'
+ className='btn btn-default'
+ onClick={this.doHide}
+ >
+ {'Close'}
+ </button>
+ </Modal.Footer>
+ </Modal>
+ );
+ }
+}
+
+AboutBuildModal.defaultProps = {
+ show: false
+};
+
+AboutBuildModal.propTypes = {
+ show: React.PropTypes.bool.isRequired,
+ onModalDismissed: React.PropTypes.func.isRequired
+}; \ No newline at end of file
diff --git a/web/react/components/admin_console/privacy_settings.jsx b/web/react/components/admin_console/privacy_settings.jsx
index c74d321e6..3467e6a40 100644
--- a/web/react/components/admin_console/privacy_settings.jsx
+++ b/web/react/components/admin_console/privacy_settings.jsx
@@ -30,7 +30,7 @@ export default class PrivacySettings extends React.Component {
var config = this.props.config;
config.PrivacySettings.ShowEmailAddress = React.findDOMNode(this.refs.ShowEmailAddress).checked;
config.PrivacySettings.ShowFullName = React.findDOMNode(this.refs.ShowFullName).checked;
- config.PrivacySettings.EnableDiagnostic = React.findDOMNode(this.refs.EnableDiagnostic).checked;
+ config.PrivacySettings.EnableSecurityFixAlert = React.findDOMNode(this.refs.EnableSecurityFixAlert).checked;
Client.saveConfig(
config,
@@ -140,7 +140,7 @@ export default class PrivacySettings extends React.Component {
<div className='form-group'>
<label
className='control-label col-sm-4'
- htmlFor='EnableDiagnostic'
+ htmlFor='EnableSecurityFixAlert'
>
{'Send Error and Diagnostic: '}
</label>
@@ -148,10 +148,10 @@ export default class PrivacySettings extends React.Component {
<label className='radio-inline'>
<input
type='radio'
- name='EnableDiagnostic'
+ name='EnableSecurityFixAlert'
value='true'
- ref='EnableDiagnostic'
- defaultChecked={this.props.config.PrivacySettings.EnableDiagnostic}
+ ref='EnableSecurityFixAlert'
+ defaultChecked={this.props.config.PrivacySettings.EnableSecurityFixAlert}
onChange={this.handleChange}
/>
{'true'}
@@ -159,14 +159,14 @@ export default class PrivacySettings extends React.Component {
<label className='radio-inline'>
<input
type='radio'
- name='EnableDiagnostic'
+ name='EnableSecurityFixAlert'
value='false'
- defaultChecked={!this.props.config.PrivacySettings.EnableDiagnostic}
+ defaultChecked={!this.props.config.PrivacySettings.EnableSecurityFixAlert}
onChange={this.handleChange}
/>
{'false'}
</label>
- <p className='help-text'>{'When true, The server will periodically send error and diagnostic information to Mattermost.'}</p>
+ <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>
</div>
</div>
diff --git a/web/react/components/create_comment.jsx b/web/react/components/create_comment.jsx
index 9c233ea26..550f85d3d 100644
--- a/web/react/components/create_comment.jsx
+++ b/web/react/components/create_comment.jsx
@@ -106,10 +106,11 @@ export default class CreateComment extends React.Component {
let state = {};
if (err.message === 'Invalid RootId parameter') {
+ PostStore.removePendingPost(post.channel_id, post.pending_post_id);
+
if ($('#post_deleted').length > 0) {
$('#post_deleted').modal('show');
}
- PostStore.removePendingPost(post.pending_post_id);
} else {
post.state = Constants.POST_FAILED;
PostStore.updatePendingPost(post);
diff --git a/web/react/components/navbar_dropdown.jsx b/web/react/components/navbar_dropdown.jsx
index 30c4e94ae..ff7a53848 100644
--- a/web/react/components/navbar_dropdown.jsx
+++ b/web/react/components/navbar_dropdown.jsx
@@ -6,6 +6,8 @@ var client = require('../utils/client.jsx');
var UserStore = require('../stores/user_store.jsx');
var TeamStore = require('../stores/team_store.jsx');
+var AboutBuildModal = require('./about_build_modal.jsx');
+
var Constants = require('../utils/constants.jsx');
function getStateFromStores() {
@@ -18,7 +20,9 @@ export default class NavbarDropdown extends React.Component {
this.blockToggle = false;
this.handleLogoutClick = this.handleLogoutClick.bind(this);
+ this.handleAboutModal = this.handleAboutModal.bind(this);
this.onListenerChange = this.onListenerChange.bind(this);
+ this.aboutModalDismissed = this.aboutModalDismissed.bind(this);
this.state = getStateFromStores();
}
@@ -26,6 +30,12 @@ export default class NavbarDropdown extends React.Component {
e.preventDefault();
client.logout();
}
+ handleAboutModal() {
+ this.setState({showAboutModal: true});
+ }
+ aboutModalDismissed() {
+ this.setState({showAboutModal: false});
+ }
componentDidMount() {
UserStore.addTeamsChangeListener(this.onListenerChange);
TeamStore.addChangeListener(this.onListenerChange);
@@ -228,6 +238,18 @@ export default class NavbarDropdown extends React.Component {
{'Report a Problem'}
</a>
</li>
+ <li>
+ <a
+ href='#'
+ onClick={this.handleAboutModal}
+ >
+ {'About Mattermost'}
+ </a>
+ </li>
+ <AboutBuildModal
+ show={this.state.showAboutModal}
+ onModalDismissed={this.aboutModalDismissed}
+ />
</ul>
</li>
</ul>
diff --git a/web/react/components/post_deleted_modal.jsx b/web/react/components/post_deleted_modal.jsx
index d284a9d1b..3f487d20f 100644
--- a/web/react/components/post_deleted_modal.jsx
+++ b/web/react/components/post_deleted_modal.jsx
@@ -2,13 +2,41 @@
// See License.txt for license information.
var UserStore = require('../stores/user_store.jsx');
+var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
+var Constants = require('../utils/constants.jsx');
+var ActionTypes = Constants.ActionTypes;
export default class PostDeletedModal extends React.Component {
constructor(props) {
super(props);
+ this.handleClose = this.handleClose.bind(this);
+
this.state = {};
}
+ componentDidMount() {
+ $(React.findDOMNode(this.refs.modal)).on('hidden.bs.modal', () => {
+ this.handleClose();
+ });
+ }
+ handleClose() {
+ AppDispatcher.handleServerAction({
+ type: ActionTypes.RECIEVED_SEARCH,
+ results: null
+ });
+
+ AppDispatcher.handleServerAction({
+ type: ActionTypes.RECIEVED_SEARCH_TERM,
+ term: null,
+ do_search: false,
+ is_mention_search: false
+ });
+
+ AppDispatcher.handleServerAction({
+ type: ActionTypes.RECIEVED_POST_SELECTED,
+ results: null
+ });
+ }
render() {
var currentUser = UserStore.getCurrentUser();
@@ -31,17 +59,17 @@ export default class PostDeletedModal extends React.Component {
data-dismiss='modal'
aria-label='Close'
>
- <span aria-hidden='true'>&times;</span>
+ <span aria-hidden='true'>{'×'}</span>
</button>
<h4
className='modal-title'
id='myModalLabel'
>
- Comment could not be posted
+ {'Comment could not be posted'}
</h4>
</div>
<div className='modal-body'>
- <p>Someone deleted the message on which you tried to post a comment.</p>
+ <p>{'Someone deleted the message on which you tried to post a comment.'}</p>
</div>
<div className='modal-footer'>
<button
@@ -49,7 +77,7 @@ export default class PostDeletedModal extends React.Component {
className='btn btn-primary'
data-dismiss='modal'
>
- Okay
+ {'Okay'}
</button>
</div>
</div>
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx
index 6741a9bdd..d2bab4902 100644
--- a/web/react/components/post_list.jsx
+++ b/web/react/components/post_list.jsx
@@ -379,13 +379,9 @@ export default class PostList extends React.Component {
<p className='channel-intro__content'>
Welcome to {channel.display_name}!
<br/><br/>
- This is the first channel teammates see when they
- <br/>
- sign up - use it for posting updates everyone needs to know.
+ This is the first channel teammates see when they sign up - use it for posting updates everyone needs to know.
<br/><br/>
- To create a new channel or join an existing one, go to
- <br/>
- the Left Hand Sidebar under “Channels” and click “More…”.
+ To create a new channel or join an existing one, go to the Left Sidebar under “Channels” and click “More…”.
<br/>
</p>
</div>
diff --git a/web/react/components/rhs_thread.jsx b/web/react/components/rhs_thread.jsx
index 2f23d80d9..27a784701 100644
--- a/web/react/components/rhs_thread.jsx
+++ b/web/react/components/rhs_thread.jsx
@@ -23,7 +23,7 @@ export default class RhsThread extends React.Component {
}
getStateFromStores() {
var postList = PostStore.getSelectedPost();
- if (!postList || postList.order.length < 1) {
+ if (!postList || postList.order.length < 1 || !postList.posts[postList.order[0]]) {
return {postList: {}};
}
@@ -49,7 +49,10 @@ export default class RhsThread extends React.Component {
}.bind(this));
}
componentDidUpdate() {
- $('.post-right__scroll').scrollTop($('.post-right__scroll')[0].scrollHeight);
+ if ($('.post-right__scroll')[0]) {
+ $('.post-right__scroll').scrollTop($('.post-right__scroll')[0].scrollHeight);
+ }
+
$('.post-right__scroll').perfectScrollbar('update');
this.resize();
}
@@ -67,7 +70,7 @@ export default class RhsThread extends React.Component {
// if something was changed in the channel like adding a
// comment or post then lets refresh the sidebar list
var currentSelected = PostStore.getSelectedPost();
- if (!currentSelected || currentSelected.order.length === 0) {
+ if (!currentSelected || currentSelected.order.length === 0 || !currentSelected.posts[currentSelected.order[0]]) {
return;
}
@@ -103,7 +106,7 @@ export default class RhsThread extends React.Component {
render() {
var postList = this.state.postList;
- if (postList == null) {
+ if (postList == null || !postList.order) {
return (
<div></div>
);
diff --git a/web/react/components/team_signup_choose_auth.jsx b/web/react/components/team_signup_choose_auth.jsx
index b8264b887..8cdeace03 100644
--- a/web/react/components/team_signup_choose_auth.jsx
+++ b/web/react/components/team_signup_choose_auth.jsx
@@ -52,7 +52,7 @@ export default class ChooseAuthPage extends React.Component {
<div>
{buttons}
<div className='form-group margin--extra-2x'>
- <span><a href='/find_team'>{'Find my team'}</a></span>
+ <span><a href='/find_team'>{'Find my teams'}</a></span>
</div>
</div>
);
diff --git a/web/react/components/team_signup_with_email.jsx b/web/react/components/team_signup_with_email.jsx
index 4fb1c0d01..015969dce 100644
--- a/web/react/components/team_signup_with_email.jsx
+++ b/web/react/components/team_signup_with_email.jsx
@@ -14,8 +14,8 @@ export default class EmailSignUpPage extends React.Component {
}
handleSubmit(e) {
e.preventDefault();
- let team = {};
- let state = {serverError: ''};
+ var team = {};
+ var state = {serverError: ''};
team.email = React.findDOMNode(this.refs.email).value.trim().toLowerCase();
if (!team.email || !Utils.isEmail(team.email)) {
@@ -31,20 +31,25 @@ export default class EmailSignUpPage extends React.Component {
}
Client.signupTeam(team.email,
- function success(data) {
+ (data) => {
if (data.follow_link) {
window.location.href = data.follow_link;
} else {
window.location.href = `/signup_team_confirm/?email=${encodeURIComponent(team.email)}`;
}
},
- function fail(err) {
+ (err) => {
state.serverError = err.message;
this.setState(state);
- }.bind(this)
+ }
);
}
render() {
+ var serverError = null;
+ if (this.state.serverError) {
+ serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
+ }
+
return (
<form
role='form'
@@ -65,11 +70,12 @@ export default class EmailSignUpPage extends React.Component {
className='btn btn-md btn-primary'
type='submit'
>
- Sign up
+ {'Sign up'}
</button>
+ {serverError}
</div>
<div className='form-group margin--extra-2x'>
- <span><a href='/find_team'>{`Find my team`}</a></span>
+ <span><a href='/find_team'>{`Find my teams`}</a></span>
</div>
</form>
);
diff --git a/web/react/components/team_signup_with_sso.jsx b/web/react/components/team_signup_with_sso.jsx
index 14f281f7a..bc7e13738 100644
--- a/web/react/components/team_signup_with_sso.jsx
+++ b/web/react/components/team_signup_with_sso.jsx
@@ -40,17 +40,17 @@ export default class SSOSignUpPage extends React.Component {
client.createTeamWithSSO(team,
this.props.service,
- function success(data) {
+ (data) => {
if (data.follow_link) {
window.location.href = data.follow_link;
} else {
window.location.href = '/' + team.name + '/channels/town-square';
}
},
- function fail(err) {
+ (err) => {
state.serverError = err.message;
this.setState(state);
- }.bind(this)
+ }
);
}
nameChange() {
@@ -85,7 +85,7 @@ export default class SSOSignUpPage extends React.Component {
disabled={disabled}
>
<span className='icon'/>
- <span>Create team with GitLab Account</span>
+ <span>{'Create team with GitLab Account'}</span>
</a>
);
}
@@ -112,7 +112,7 @@ export default class SSOSignUpPage extends React.Component {
{serverError}
</div>
<div className='form-group margin--extra-2x'>
- <span><a href='/find_team'>{'Find my team'}</a></span>
+ <span><a href='/find_team'>{'Find my teams'}</a></span>
</div>
</form>
);
diff --git a/web/react/components/user_settings/user_settings_general.jsx b/web/react/components/user_settings/user_settings_general.jsx
index c1d4c4ab5..c6c508ad7 100644
--- a/web/react/components/user_settings/user_settings_general.jsx
+++ b/web/react/components/user_settings/user_settings_general.jsx
@@ -2,6 +2,7 @@
// See License.txt for license information.
var UserStore = require('../../stores/user_store.jsx');
+var ErrorStore = require('../../stores/error_store.jsx');
var SettingItemMin = require('../setting_item_min.jsx');
var SettingItemMax = require('../setting_item_max.jsx');
var SettingPicture = require('../setting_picture.jsx');
@@ -27,6 +28,7 @@ export default class UserSettingsGeneralTab extends React.Component {
this.updateLastName = this.updateLastName.bind(this);
this.updateNickname = this.updateNickname.bind(this);
this.updateEmail = this.updateEmail.bind(this);
+ this.updateConfirmEmail = this.updateConfirmEmail.bind(this);
this.updatePicture = this.updatePicture.bind(this);
this.updateSection = this.updateSection.bind(this);
@@ -96,6 +98,7 @@ export default class UserSettingsGeneralTab extends React.Component {
var user = UserStore.getCurrentUser();
var email = this.state.email.trim().toLowerCase();
+ var confirmEmail = this.state.confirmEmail.trim().toLowerCase();
if (user.email === email) {
return;
@@ -106,8 +109,12 @@ export default class UserSettingsGeneralTab extends React.Component {
return;
}
- user.email = email;
+ if (email !== confirmEmail) {
+ this.setState({emailError: 'The new emails you entered do not match'});
+ return;
+ }
+ user.email = email;
this.submitUser(user);
}
submitUser(user) {
@@ -115,6 +122,13 @@ export default class UserSettingsGeneralTab extends React.Component {
function updateSuccess() {
this.updateSection('');
AsyncClient.getMe();
+ const verificationEnabled = global.window.config.SendEmailNotifications === 'true' && global.window.config.RequireEmailVerification === 'true';
+
+ if (verificationEnabled) {
+ ErrorStore.storeLastError({message: 'Check your email at ' + user.email + ' to verify the address.'});
+ ErrorStore.emitChange();
+ this.setState({emailChangeInProgress: true});
+ }
}.bind(this),
function updateFailure(err) {
var state = this.setupInitialState(this.props);
@@ -177,6 +191,9 @@ export default class UserSettingsGeneralTab extends React.Component {
updateEmail(e) {
this.setState({email: e.target.value});
}
+ updateConfirmEmail(e) {
+ this.setState({confirmEmail: e.target.value});
+ }
updatePicture(e) {
if (e.target.files && e.target.files[0]) {
this.setState({picture: e.target.files[0]});
@@ -188,7 +205,8 @@ export default class UserSettingsGeneralTab extends React.Component {
}
}
updateSection(section) {
- this.setState(assign({}, this.setupInitialState(this.props), {clientError: '', serverError: '', emailError: ''}));
+ const emailChangeInProgress = this.state.emailChangeInProgress;
+ this.setState(assign({}, this.setupInitialState(this.props), {emailChangeInProgress: emailChangeInProgress, clientError: '', serverError: '', emailError: ''}));
this.submitActive = false;
this.props.updateSection(section);
}
@@ -208,9 +226,9 @@ export default class UserSettingsGeneralTab extends React.Component {
}
setupInitialState(props) {
var user = props.user;
- var emailEnabled = global.window.config.SendEmailNotifications === 'true';
+
return {username: user.username, firstName: user.first_name, lastName: user.last_name, nickname: user.nickname,
- email: user.email, picture: null, loadingPicture: false, emailEnabled: emailEnabled};
+ email: user.email, confirmEmail: '', picture: null, loadingPicture: false, emailChangeInProgress: false};
}
render() {
var user = this.props.user;
@@ -434,10 +452,19 @@ export default class UserSettingsGeneralTab extends React.Component {
}
var emailSection;
if (this.props.activeSection === 'email') {
- let helpText = <div>Email is used for notifications, and requires verification if changed.</div>;
+ const emailEnabled = global.window.config.SendEmailNotifications === 'true';
+ const emailVerificationEnabled = global.window.config.RequireEmailVerification === 'true';
+ let helpText = 'Email is used for notifications, and requires verification if changed.';
- if (!this.state.emailEnabled) {
+ if (!emailEnabled) {
helpText = <div className='setting-list__hint text-danger'>{'Email has been disabled by your system administrator. No notification emails will be sent until it is enabled.'}</div>;
+ } else if (!emailVerificationEnabled) {
+ helpText = 'Email is used for notifications.';
+ } else if (this.state.emailChangeInProgress) {
+ const newEmail = UserStore.getCurrentUser().email;
+ if (newEmail) {
+ helpText = 'A verification email was sent to ' + newEmail + '.';
+ }
}
inputs.push(
@@ -453,6 +480,22 @@ export default class UserSettingsGeneralTab extends React.Component {
/>
</div>
</div>
+ </div>
+ );
+
+ inputs.push(
+ <div key='confirmEmailSetting'>
+ <div className='form-group'>
+ <label className='col-sm-5 control-label'>{'Confirm Email'}</label>
+ <div className='col-sm-7'>
+ <input
+ className='form-control'
+ type='text'
+ onChange={this.updateConfirmEmail}
+ value={this.state.confirmEmail}
+ />
+ </div>
+ </div>
{helpText}
</div>
);
@@ -471,10 +514,22 @@ export default class UserSettingsGeneralTab extends React.Component {
/>
);
} else {
+ let describe = '';
+ if (this.state.emailChangeInProgress) {
+ const newEmail = UserStore.getCurrentUser().email;
+ if (newEmail) {
+ describe = 'New Address: ' + newEmail + '\nCheck your email to verify the above address.';
+ } else {
+ describe = 'Check your email to verify your new address';
+ }
+ } else {
+ describe = UserStore.getCurrentUser().email;
+ }
+
emailSection = (
<SettingItemMin
title='Email'
- describe={UserStore.getCurrentUser().email}
+ describe={describe}
updateSection={function updateEmailSection() {
this.updateSection('email');
}.bind(this)}
diff --git a/web/react/components/user_settings/user_settings_security.jsx b/web/react/components/user_settings/user_settings_security.jsx
index b59c08af0..4ff4775a7 100644
--- a/web/react/components/user_settings/user_settings_security.jsx
+++ b/web/react/components/user_settings/user_settings_security.jsx
@@ -251,17 +251,6 @@ export default class SecurityTab extends React.Component {
<div className='divider-dark first'/>
{passwordSection}
<div className='divider-dark'/>
- <ul
- className='section-min'
- >
- <li className='col-sm-10 section-title'>{'Version ' + global.window.config.Version}</li>
- <li className='col-sm-7 section-describe'>
- <div className='text-nowrap'>{'Build Number: ' + global.window.config.BuildNumber}</div>
- <div className='text-nowrap'>{'Build Date: ' + global.window.config.BuildDate}</div>
- <div className='text-nowrap'>{'Build Hash: ' + global.window.config.BuildHash}</div>
- </li>
- </ul>
- <div className='divider-dark'/>
<br></br>
<a
data-toggle='modal'
diff --git a/web/react/utils/markdown.jsx b/web/react/utils/markdown.jsx
index 7e88f8644..aff776d05 100644
--- a/web/react/utils/markdown.jsx
+++ b/web/react/utils/markdown.jsx
@@ -2,6 +2,7 @@
// See License.txt for license information.
const TextFormatting = require('./text_formatting.jsx');
+const Utils = require('./utils.jsx');
const marked = require('marked');
@@ -39,7 +40,14 @@ export class MattermostMarkdownRenderer extends marked.Renderer {
if (title) {
output += ' title="' + title + '"';
}
- output += ' target="_blank">' + text + '</a>';
+
+ if (outHref.lastIndexOf(Utils.getTeamURLFromAddressBar(), 0) === 0) {
+ output += '>';
+ } else {
+ output += ' target="_blank">';
+ }
+
+ output += text + '</a>';
return output;
}
diff --git a/web/react/utils/text_formatting.jsx b/web/react/utils/text_formatting.jsx
index 34e42cbae..b8ed58258 100644
--- a/web/react/utils/text_formatting.jsx
+++ b/web/react/utils/text_formatting.jsx
@@ -96,8 +96,13 @@ function autolinkUrls(text, tokens) {
const index = tokens.size;
const alias = `MM_LINK${index}`;
+ var target = 'target="_blank"';
+ if (url.lastIndexOf(Utils.getTeamURLFromAddressBar(), 0) === 0) {
+ target = '';
+ }
+
tokens.set(alias, {
- value: `<a class='theme' target='_blank' href='${url}'>${linkText}</a>`,
+ value: '<a class="theme"' + target + ' href="${url}">${linkText}</a>',
originalText: linkText
});
diff --git a/web/sass-files/sass/partials/_settings.scss b/web/sass-files/sass/partials/_settings.scss
index 9369cc097..8debb0b4e 100644
--- a/web/sass-files/sass/partials/_settings.scss
+++ b/web/sass-files/sass/partials/_settings.scss
@@ -132,6 +132,7 @@
.section-describe {
@include opacity(0.7);
+ white-space:pre;
}
.divider-dark {
diff --git a/web/static/images/Battlehouse-logodark.png b/web/static/images/Battlehouse-logodark.png
deleted file mode 100644
index 1fc5b68ca..000000000
--- a/web/static/images/Battlehouse-logodark.png
+++ /dev/null
Binary files differ
diff --git a/web/static/images/Mattermost-logodark.png b/web/static/images/Mattermost-logodark.png
deleted file mode 100644
index c16978ba8..000000000
--- a/web/static/images/Mattermost-logodark.png
+++ /dev/null
Binary files differ
diff --git a/web/static/images/Bladekick-logodark.png b/web/static/images/logo-email.png
index c16978ba8..c16978ba8 100644
--- a/web/static/images/Bladekick-logodark.png
+++ b/web/static/images/logo-email.png
Binary files differ
diff --git a/web/web.go b/web/web.go
index b87636187..8dfac4a8d 100644
--- a/web/web.go
+++ b/web/web.go
@@ -372,11 +372,22 @@ func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) {
return
}
- //api.Handle404(w, r)
- //Bad channel urls just redirect to the town-square for now
+ // We will attempt to auto-join open channels
+ if cr := <-api.Srv.Store.Channel().GetByName(c.Session.TeamId, name); cr.Err != nil {
+ http.Redirect(w, r, c.GetTeamURL()+"/channels/town-square", http.StatusFound)
+ } else {
+ channel := cr.Data.(*model.Channel)
+ if channel.Type == model.CHANNEL_OPEN {
+ api.JoinChannel(c, channel.Id, "")
+ if c.Err != nil {
+ return
+ }
- http.Redirect(w, r, c.GetTeamURL()+"/channels/town-square", http.StatusFound)
- return
+ channelId = channel.Id
+ } else {
+ http.Redirect(w, r, c.GetTeamURL()+"/channels/town-square", http.StatusFound)
+ }
+ }
}
}
@@ -414,7 +425,12 @@ func verifyEmail(c *api.Context, w http.ResponseWriter, r *http.Request) {
return
} else {
user := result.Data.(*model.User)
- api.FireAndForgetVerifyEmail(user.Id, user.Email, team.Name, team.DisplayName, c.GetSiteURL(), c.GetTeamURLFromTeam(team))
+
+ if user.LastActivityAt > 0 {
+ api.FireAndForgetEmailChangeVerifyEmail(user.Id, user.Email, team.Name, team.DisplayName, c.GetSiteURL(), c.GetTeamURLFromTeam(team))
+ } else {
+ api.FireAndForgetVerifyEmail(user.Id, user.Email, team.Name, team.DisplayName, c.GetSiteURL(), c.GetTeamURLFromTeam(team))
+ }
newAddress := strings.Replace(r.URL.String(), "&resend=true", "&resend_success=true", -1)
http.Redirect(w, r, newAddress, http.StatusFound)