diff --git a/api/preference_test.go b/api/preference_test.go
index 9d3db9e2fc..eaa92fe471 100644
--- a/api/preference_test.go
+++ b/api/preference_test.go
@@ -60,9 +60,10 @@ func TestGetAllPreferences(t *testing.T) {
Client.LoginByEmail(team.Name, user2.Email, "pwd")
+ // note that user2 will automatically have a preference set for them to show user1 for direct messages
if result, err := Client.GetAllPreferences(); err != nil {
t.Fatal(err)
- } else if data := result.Data.(model.Preferences); len(data) != 0 {
+ } else if data := result.Data.(model.Preferences); len(data) != 1 {
t.Fatal("received the wrong number of preferences")
}
}
diff --git a/doc/install/Docker-Single-Container.md b/doc/install/Docker-Single-Container.md
index 4b952cd710..7c0784ad0c 100644
--- a/doc/install/Docker-Single-Container.md
+++ b/doc/install/Docker-Single-Container.md
@@ -2,6 +2,13 @@
The following install instructions are for single-container installs of Mattermost using Docker for exploring product functionality and upgrading to newer versions.
+### One-line Docker Install ###
+
+If you have Docker set up, Mattermost installs in one-line:
+`docker run --name mattermost-dev -d --publish 8065:80 mattermost/platform`
+
+Otherwise, see step-by-step available:
+
### Mac OSX ###
1. Install Docker Toolbox using instructions at: http://docs.docker.com/installation/mac/
diff --git a/model/webhook.go b/model/webhook.go
index 3bf034908a..9b9969b968 100644
--- a/model/webhook.go
+++ b/model/webhook.go
@@ -8,6 +8,11 @@ import (
"io"
)
+const (
+ DEFAULT_WEBHOOK_USERNAME = "webhook"
+ DEFAULT_WEBHOOK_ICON = "/static/images/webhook_icon.jpg"
+)
+
type IncomingWebhook struct {
Id string `json:"id"`
CreateAt int64 `json:"create_at"`
diff --git a/web/react/components/admin_console/email_settings.jsx b/web/react/components/admin_console/email_settings.jsx
index 01759b2220..40e00ff047 100644
--- a/web/react/components/admin_console/email_settings.jsx
+++ b/web/react/components/admin_console/email_settings.jsx
@@ -440,9 +440,11 @@ export default class EmailSettings extends React.Component {
className='table table-bordered'
cellPadding='5'
>
-
| {'None'} | {'Mattermost will send email over an unsecure connection.'} |
- | {'TLS'} | {'Encrypts the communication between Mattermost and your email server.'} |
- | {'STARTTLS'} | {'Takes an existing insecure connection and attempts to upgrade it to a secure connection using TLS.'} |
+
+ | {'None'} | {'Mattermost will send email over an unsecure connection.'} |
+ | {'TLS'} | {'Encrypts the communication between Mattermost and your email server.'} |
+ | {'STARTTLS'} | {'Takes an existing insecure connection and attempts to upgrade it to a secure connection using TLS.'} |
+
diff --git a/web/react/components/admin_console/log_settings.jsx b/web/react/components/admin_console/log_settings.jsx
index 931818bb82..7e9eda89b1 100644
--- a/web/react/components/admin_console/log_settings.jsx
+++ b/web/react/components/admin_console/log_settings.jsx
@@ -249,22 +249,24 @@ export default class LogSettings extends React.Component {
onChange={this.handleChange}
disabled={!this.state.fileEnable}
/>
-
+
{'Format of log message output. If blank will be set to "[%D %T] [%L] %M", where:'}
- | {'%T'} | {'Time (15:04:05 MST)'} |
- | {'%D'} | {'Date (2006/01/02)'} |
- | {'%d'} | {'Date (01/02/06)'} |
- | {'%L'} | {'Level (DEBG, INFO, EROR)'} |
- | {'%S'} | {'Source'} |
- | {'%M'} | {'Message'} |
+
+ | {'%T'} | {'Time (15:04:05 MST)'} |
+ | {'%D'} | {'Date (2006/01/02)'} |
+ | {'%d'} | {'Date (01/02/06)'} |
+ | {'%L'} | {'Level (DEBG, INFO, EROR)'} |
+ | {'%S'} | {'Source'} |
+ | {'%M'} | {'Message'} |
+
-
+
diff --git a/web/react/components/edit_post_modal.jsx b/web/react/components/edit_post_modal.jsx
index 90d9696e7d..b259b3c18a 100644
--- a/web/react/components/edit_post_modal.jsx
+++ b/web/react/components/edit_post_modal.jsx
@@ -70,7 +70,7 @@ export default class EditPostModal extends React.Component {
refocusId: options.refocusId || ''
});
- $(React.findDOMNode(this.refs.modal)).modal('show');
+ $(ReactDOM.findDOMNode(this.refs.modal)).modal('show');
}
componentDidMount() {
var self = this;
@@ -92,7 +92,7 @@ export default class EditPostModal extends React.Component {
$('#edit_textbox').get(0).focus();
});
- $(React.findDOMNode(this.refs.modal)).on('hide.bs.modal', function onShown() {
+ $(ReactDOM.findDOMNode(this.refs.modal)).on('hide.bs.modal', function onShown() {
if (self.state.refocusId !== '') {
setTimeout(() => {
$(self.state.refocusId).get(0).focus();
diff --git a/web/react/components/popover_list_members.jsx b/web/react/components/popover_list_members.jsx
index 5ea452830e..155e886001 100644
--- a/web/react/components/popover_list_members.jsx
+++ b/web/react/components/popover_list_members.jsx
@@ -35,13 +35,20 @@ export default class PopoverListMembers extends React.Component {
const teamMembers = UserStore.getProfilesUsernameMap();
if (members && teamMembers) {
- members.sort(function compareByLocal(a, b) {
+ members.sort((a, b) => {
return a.username.localeCompare(b.username);
});
- members.forEach(function addMemberElement(m) {
+ members.forEach((m, i) => {
if (teamMembers[m.username] && teamMembers[m.username].delete_at <= 0) {
- popoverHtml.push({m.username}
);
+ popoverHtml.push(
+
+ {m.username}
+
+ );
count++;
}
});
@@ -58,7 +65,14 @@ export default class PopoverListMembers extends React.Component {
trigger='click'
placement='bottom'
rootClose={true}
- overlay={{popoverHtml}}
+ overlay={
+
+ {popoverHtml}
+
+ }
>
diff --git a/web/react/components/rhs_comment.jsx b/web/react/components/rhs_comment.jsx
index 402e640800..d3a4cfaeb9 100644
--- a/web/react/components/rhs_comment.jsx
+++ b/web/react/components/rhs_comment.jsx
@@ -29,7 +29,7 @@ export default class RhsComment extends React.Component {
var post = this.props.post;
Client.createPost(post, post.channel_id,
- function success(data) {
+ (data) => {
AsyncClient.getPosts(post.channel_id);
var channel = ChannelStore.get(post.channel_id);
@@ -43,11 +43,11 @@ export default class RhsComment extends React.Component {
post: data
});
},
- function fail() {
+ () => {
post.state = Constants.POST_FAILED;
PostStore.updatePendingPost(post);
this.forceUpdate();
- }.bind(this)
+ }
);
post.state = Constants.POST_LOADING;
@@ -84,7 +84,10 @@ export default class RhsComment extends React.Component {
if (isOwner) {
dropdownContents.push(
-
+
- Edit
+ {'Edit'}
);
@@ -103,7 +106,10 @@ export default class RhsComment extends React.Component {
if (isOwner || isAdmin) {
dropdownContents.push(
-
+
- Delete
+ {'Delete'}
);
@@ -162,7 +168,7 @@ export default class RhsComment extends React.Component {
href='#'
onClick={this.retryComment}
>
- Retry
+ {'Retry'}
);
} else if (post.state === Constants.POST_LOADING) {
@@ -213,14 +219,14 @@ export default class RhsComment extends React.Component {
diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx
index 4594555e9b..889bc0fbdb 100644
--- a/web/react/components/sidebar.jsx
+++ b/web/react/components/sidebar.jsx
@@ -46,7 +46,7 @@ export default class Sidebar extends React.Component {
const state = this.getStateFromStores();
state.newChannelModalType = '';
- state.showMoreDirectChannelsModal = false;
+ state.showDirectChannelsModal = false;
state.loadingDMChannel = -1;
this.state = state;
@@ -471,7 +471,9 @@ export default class Sidebar extends React.Component {
}
let closeButton = null;
- const removeTooltip =
{'Remove from list'};
+ const removeTooltip = (
+
{'Remove from list'}
+ );
if (handleClose && !badge) {
closeButton = (
{'Create new channel'};
- const createGroupTootlip = {'Create new group'};
+ const createChannelTootlip = (
+ {'Create new channel'}
+ );
+ const createGroupTootlip = (
+ {'Create new group'}
+ );
return (
diff --git a/web/react/components/user_profile.jsx b/web/react/components/user_profile.jsx
index 47d8363216..da0c1aaf99 100644
--- a/web/react/components/user_profile.jsx
+++ b/web/react/components/user_profile.jsx
@@ -65,19 +65,29 @@ export default class UserProfile extends React.Component {
var dataContent = [];
dataContent.push(
-

);
if (!global.window.config.ShowEmailAddress === 'true') {
- dataContent.push(
{'Email not shared'}
);
+ dataContent.push(
+
+ {'Email not shared'}
+
+ );
} else {
dataContent.push(
@@ -164,9 +163,8 @@ export default class UserSettingsAppearance extends React.Component {
- {'Custom Theme'}
-
+ />
+ {'Custom Theme'}
diff --git a/web/react/components/user_settings/user_settings_display.jsx b/web/react/components/user_settings/user_settings_display.jsx
index ec209c2187..22a62273c8 100644
--- a/web/react/components/user_settings/user_settings_display.jsx
+++ b/web/react/components/user_settings/user_settings_display.jsx
@@ -1,7 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import { savePreferences } from '../../utils/client.jsx';
+import {savePreferences} from '../../utils/client.jsx';
import SettingItemMin from '../setting_item_min.jsx';
import SettingItemMax from '../setting_item_max.jsx';
import Constants from '../../utils/constants.jsx';
@@ -38,7 +38,7 @@ export default class UserSettingsDisplay extends React.Component {
);
}
handleClockRadio(militaryTime) {
- this.setState({militaryTime: militaryTime});
+ this.setState({militaryTime});
}
updateSection(section) {
this.setState(getDisplayStateFromStores());
@@ -57,7 +57,7 @@ export default class UserSettingsDisplay extends React.Component {
const serverError = this.state.serverError || null;
let clockSection;
if (this.props.activeSection === 'clock') {
- let clockFormat = [false, false];
+ const clockFormat = [false, false];
if (this.state.militaryTime === 'true') {
clockFormat[1] = true;
} else {
@@ -77,9 +77,8 @@ export default class UserSettingsDisplay extends React.Component {
type='radio'
checked={clockFormat[0]}
onChange={this.handleClockRadio.bind(this, 'false')}
- >
- 12-hour clock (example: 4:00 PM)
-
+ />
+ {'12-hour clock (example: 4:00 PM)'}
@@ -89,9 +88,8 @@ export default class UserSettingsDisplay extends React.Component {
type='radio'
checked={clockFormat[1]}
onChange={this.handleClockRadio.bind(this, 'true')}
- >
- 24-hour clock (example: 16:00)
-
+ />
+ {'24-hour clock (example: 16:00)'}
@@ -99,7 +97,6 @@ export default class UserSettingsDisplay extends React.Component {
];
-
clockSection = (
+ >
{'×'}
+ >
{'Display Settings'}
diff --git a/web/react/components/user_settings/user_settings_notifications.jsx b/web/react/components/user_settings/user_settings_notifications.jsx
index 4dbb9b96fd..8693af494f 100644
--- a/web/react/components/user_settings/user_settings_notifications.jsx
+++ b/web/react/components/user_settings/user_settings_notifications.jsx
@@ -228,9 +228,8 @@ export default class NotificationsTab extends React.Component {
- For all activity
-
+ />
+ {'For all activity'}
@@ -240,9 +239,8 @@ export default class NotificationsTab extends React.Component {
type='radio'
checked={notifyActive[1]}
onChange={this.handleNotifyRadio.bind(this, 'mention')}
- >
- Only for mentions and direct messages
-
+ />
+ {'Only for mentions and direct messages'}
@@ -252,9 +250,8 @@ export default class NotificationsTab extends React.Component {
type='radio'
checked={notifyActive[2]}
onChange={this.handleNotifyRadio.bind(this, 'none')}
- >
- Never
-
+ />
+ {'Never'}
@@ -320,9 +317,8 @@ export default class NotificationsTab extends React.Component {
type='radio'
checked={soundActive[0]}
onChange={this.handleSoundRadio.bind(this, 'true')}
- >
- On
-
+ />
+ {'On'}
@@ -332,9 +328,8 @@ export default class NotificationsTab extends React.Component {
type='radio'
checked={soundActive[1]}
onChange={this.handleSoundRadio.bind(this, 'false')}
- >
- Off
-
+ />
+ {'Off'}
@@ -402,9 +397,8 @@ export default class NotificationsTab extends React.Component {
type='radio'
checked={emailActive[0]}
onChange={this.handleEmailRadio.bind(this, 'true')}
- >
- On
-
+ />
+ {'On'}
@@ -414,9 +408,8 @@ export default class NotificationsTab extends React.Component {
type='radio'
checked={emailActive[1]}
onChange={this.handleEmailRadio.bind(this, 'false')}
- >
- Off
-
+ />
+ {'Off'}
@@ -482,9 +475,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox'
checked={this.state.firstNameKey}
onChange={handleUpdateFirstNameKey}
- >
- {'Your case sensitive first name "' + user.first_name + '"'}
-
+ />
+ {'Your case sensitive first name "' + user.first_name + '"'}
@@ -502,9 +494,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox'
checked={this.state.usernameKey}
onChange={handleUpdateUsernameKey}
- >
- {'Your non-case sensitive username "' + user.username + '"'}
-
+ />
+ {'Your non-case sensitive username "' + user.username + '"'}
@@ -521,9 +512,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox'
checked={this.state.mentionKey}
onChange={handleUpdateMentionKey}
- >
- {'Your username mentioned "@' + user.username + '"'}
-
+ />
+ {'Your username mentioned "@' + user.username + '"'}
@@ -540,9 +530,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox'
checked={this.state.allKey}
onChange={handleUpdateAllKey}
- >
- {'Team-wide mentions "@all"'}
-
+ />
+ {'Team-wide mentions "@all"'}
@@ -559,9 +548,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox'
checked={this.state.channelKey}
onChange={handleUpdateChannelKey}
- >
- {'Channel-wide mentions "@channel"'}
-
+ />
+ {'Channel-wide mentions "@channel"'}
@@ -576,9 +564,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox'
checked={this.state.customKeysChecked}
onChange={this.updateCustomMentionKeys}
- >
- {'Other non-case sensitive words, separated by commas:'}
-
+ />
+ {'Other non-case sensitive words, separated by commas:'}