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 {
    -

    +

    {loading}
    -

    +
    {fileAttachment}
    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(
    {dataContent}} + overlay={ + + {dataContent} + + } > -
    - {name} -
    +
    + {name} +
    ); } diff --git a/web/react/components/user_settings/user_settings_appearance.jsx b/web/react/components/user_settings/user_settings_appearance.jsx index 7f363e92e9..8c62a189dd 100644 --- a/web/react/components/user_settings/user_settings_appearance.jsx +++ b/web/react/components/user_settings/user_settings_appearance.jsx @@ -152,9 +152,8 @@ export default class UserSettingsAppearance extends React.Component { - {'Theme Colors'} - + /> + {'Theme Colors'}
    @@ -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:'}