summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--api/user.go1
-rw-r--r--doc/install/Production-Ubuntu.md10
-rw-r--r--doc/process/documentation-guidelines.md4
-rw-r--r--docker/1.0/Dockerrun.aws.zipbin711 -> 0 bytes
-rw-r--r--docker/1.2/Dockerfile (renamed from docker/1.0/Dockerfile)2
-rw-r--r--docker/1.2/Dockerrun.aws.zipbin0 -> 867 bytes
-rw-r--r--docker/1.2/Dockerrun.aws/.ebextensions/01_files.config (renamed from docker/1.0/Dockerrun.aws/.ebextensions/01_files.config)0
-rwxr-xr-xdocker/1.2/Dockerrun.aws/Dockerrun.aws.json (renamed from docker/1.0/Dockerrun.aws/Dockerrun.aws.json)2
-rw-r--r--docker/1.2/README.md23
-rw-r--r--docker/1.2/config_docker.json (renamed from docker/1.0/config_docker.json)14
-rwxr-xr-xdocker/1.2/docker-entry.sh (renamed from docker/1.0/docker-entry.sh)0
-rw-r--r--model/post.go1
-rw-r--r--model/user.go54
-rw-r--r--model/version.go1
-rw-r--r--store/sql_channel_store.go50
-rw-r--r--store/sql_post_store.go18
-rw-r--r--store/sql_team_store.go5
-rw-r--r--store/sql_user_store.go2
-rw-r--r--web/react/components/admin_console/email_settings.jsx16
-rw-r--r--web/react/components/login.jsx2
-rw-r--r--web/react/components/new_channel_modal.jsx2
-rw-r--r--web/react/components/posts_view.jsx13
-rw-r--r--web/react/components/posts_view_container.jsx2
-rw-r--r--web/react/components/tutorial/tutorial_intro_screens.jsx12
-rw-r--r--web/react/components/tutorial/tutorial_tip.jsx7
-rw-r--r--web/react/components/user_settings/manage_incoming_hooks.jsx2
-rw-r--r--web/react/components/user_settings/manage_outgoing_hooks.jsx2
-rw-r--r--web/sass-files/sass/partials/_tutorial.scss15
-rw-r--r--web/static/images/tutorialTip.gifbin18421 -> 22502 bytes
-rw-r--r--web/static/images/tutorialTipWhite.gifbin0 -> 6704 bytes
31 files changed, 140 insertions, 122 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 142e15d91..a21f118b9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -108,7 +108,7 @@ The following is for informational purposes only, no action needed. Mattermost a
- Editing a post so that it's text is blank (which should delete it) throws a 404
- No scroll bar in centre channel
- Theme color import from Slack fails to import the “Active Channel” selection color
-- Pasting images into text box fails to upload on [BROWSERS]
+- Pasting images into text box fails to upload on Firefox and Safari
- Users cannot claim accounts imported from Slack via password reset
- Slack import @mentions break
diff --git a/api/user.go b/api/user.go
index 4a52cf88b..0f868a678 100644
--- a/api/user.go
+++ b/api/user.go
@@ -669,6 +669,7 @@ func getProfiles(c *Context, w http.ResponseWriter, r *http.Request) {
}
p.Sanitize(options)
+ p.ClearNonProfileFields()
profiles[k] = p
}
diff --git a/doc/install/Production-Ubuntu.md b/doc/install/Production-Ubuntu.md
index e792a551c..098707ada 100644
--- a/doc/install/Production-Ubuntu.md
+++ b/doc/install/Production-Ubuntu.md
@@ -24,6 +24,16 @@
* ```postgre=# \q```
1. You can exit the postgres account by typing:
* ``` exit```
+1. Allow Postgres to listen on all assigned IP Addresses
+ * ```sudo vi /etc/postgresql/9.3/main/postgresql.conf```
+ * Uncomment 'listen_addresses' and change 'localhost' to '*'
+1. Alter pg_hba.conf to allow the mattermost server to talk to the postgres database
+ * ```sudo vi /etc/postgresql/9.3/main/pg_hba.conf```
+ * Add the following line to the 'IPv4 local connections'
+ * host all all 10.10.10.2/32 md5
+1. Reload Postgres database
+ * ```sudo /etc/init.d/postgresql reload```
+
## Set up Mattermost Server
1. For the purposes of this guide we will assume this server has an IP address of 10.10.10.2
diff --git a/doc/process/documentation-guidelines.md b/doc/process/documentation-guidelines.md
index f37f0c5fc..59ed0a445 100644
--- a/doc/process/documentation-guidelines.md
+++ b/doc/process/documentation-guidelines.md
@@ -49,7 +49,7 @@ Headings in markdown provide anchors that can be used to easily reference sub-se
##### Step 1: Add a heading
This makes things easier to reference via hyperlinks
##### Step 2: Link to headings
-So things are eariser to find
+So things are easier to find
----
##### Incorrect:
@@ -58,7 +58,7 @@ So things are eariser to find
**Step 1: Add a heading**
This makes things easier to reference via hyperlinks
**Step 2: Link to headings**
-So things are eariser to find
+So things are easier to find
----
### Use appropriate heading case
diff --git a/docker/1.0/Dockerrun.aws.zip b/docker/1.0/Dockerrun.aws.zip
deleted file mode 100644
index 8c2c16e10..000000000
--- a/docker/1.0/Dockerrun.aws.zip
+++ /dev/null
Binary files differ
diff --git a/docker/1.0/Dockerfile b/docker/1.2/Dockerfile
index a41c73514..6a8d69196 100644
--- a/docker/1.0/Dockerfile
+++ b/docker/1.2/Dockerfile
@@ -34,7 +34,7 @@ VOLUME /var/lib/mysql
WORKDIR /mattermost
# Copy over files
-ADD https://github.com/mattermost/platform/releases/download/v1.0.0/mattermost.tar.gz /
+ADD https://github.com/mattermost/platform/releases/download/v1.2.0-rc1/mattermost.tar.gz /
RUN tar -zxvf /mattermost.tar.gz --strip-components=1 && rm /mattermost.tar.gz
ADD config_docker.json /
ADD docker-entry.sh /
diff --git a/docker/1.2/Dockerrun.aws.zip b/docker/1.2/Dockerrun.aws.zip
new file mode 100644
index 000000000..4de6ec362
--- /dev/null
+++ b/docker/1.2/Dockerrun.aws.zip
Binary files differ
diff --git a/docker/1.0/Dockerrun.aws/.ebextensions/01_files.config b/docker/1.2/Dockerrun.aws/.ebextensions/01_files.config
index 7f40a8b34..7f40a8b34 100644
--- a/docker/1.0/Dockerrun.aws/.ebextensions/01_files.config
+++ b/docker/1.2/Dockerrun.aws/.ebextensions/01_files.config
diff --git a/docker/1.0/Dockerrun.aws/Dockerrun.aws.json b/docker/1.2/Dockerrun.aws/Dockerrun.aws.json
index 9fdded15e..c32a998e4 100755
--- a/docker/1.0/Dockerrun.aws/Dockerrun.aws.json
+++ b/docker/1.2/Dockerrun.aws/Dockerrun.aws.json
@@ -1,7 +1,7 @@
{
"AWSEBDockerrunVersion": "1",
"Image": {
- "Name": "mattermost/platform:1.0",
+ "Name": "mattermost/platform:1.2",
"Update": "true"
},
"Ports": [
diff --git a/docker/1.2/README.md b/docker/1.2/README.md
new file mode 100644
index 000000000..f737a1554
--- /dev/null
+++ b/docker/1.2/README.md
@@ -0,0 +1,23 @@
+Mattermost
+==========
+
+http:/mattermost.org
+
+Mattermost is an open-source team communication service. It brings team messaging and file sharing into one place, accessible across PCs and phones, with archiving and search.
+
+Installing Mattermost
+=====================
+
+To run an instance of the latest version of mattermost on your local machine you can run:
+
+`docker run --name mattermost-dev -d --publish 8065:80 mattermost/platform`
+
+To update this image to the latest version you can run:
+
+`docker pull mattermost/platform`
+
+To run an instance of the latest code from the master branch on GitHub you can run:
+
+`docker run --name mattermost-dev -d --publish 8065:80 mattermost/platform:dev`
+
+Any questions, please visit http://forum.mattermost.org
diff --git a/docker/1.0/config_docker.json b/docker/1.2/config_docker.json
index 806071376..80e6ab14e 100644
--- a/docker/1.0/config_docker.json
+++ b/docker/1.2/config_docker.json
@@ -5,15 +5,21 @@
"SegmentDeveloperKey": "",
"GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false,
- "EnableIncomingWebhooks": false,
- "EnableTesting": false
+ "EnableIncomingWebhooks": true,
+ "EnableOutgoingWebhooks": true,
+ "EnablePostUsernameOverride": false,
+ "EnablePostIconOverride": false,
+ "EnableTesting": false,
+ "EnableSecurityFixAlert": true
},
"TeamSettings": {
"SiteName": "Mattermost",
"MaxUsersPerTeam": 50,
"EnableTeamCreation": true,
"EnableUserCreation": true,
- "RestrictCreationToDomains": ""
+ "RestrictCreationToDomains": "",
+ "RestrictTeamNames": true,
+ "EnableTeamListing": false
},
"SqlSettings": {
"DriverName": "mysql",
@@ -86,4 +92,4 @@
"TokenEndpoint": "",
"UserApiEndpoint": ""
}
-} \ No newline at end of file
+}
diff --git a/docker/1.0/docker-entry.sh b/docker/1.2/docker-entry.sh
index 6bd2a1263..6bd2a1263 100755
--- a/docker/1.0/docker-entry.sh
+++ b/docker/1.2/docker-entry.sh
diff --git a/model/post.go b/model/post.go
index 248d40321..5578514b5 100644
--- a/model/post.go
+++ b/model/post.go
@@ -26,7 +26,6 @@ type Post struct {
ParentId string `json:"parent_id"`
OriginalId string `json:"original_id"`
Message string `json:"message"`
- ImgCount int64 `json:"img_count"`
Type string `json:"type"`
Props StringInterface `json:"props"`
Hashtags string `json:"hashtags"`
diff --git a/model/user.go b/model/user.go
index 4365f47d2..0ce8e1733 100644
--- a/model/user.go
+++ b/model/user.go
@@ -28,29 +28,29 @@ const (
type User struct {
Id string `json:"id"`
- CreateAt int64 `json:"create_at"`
- UpdateAt int64 `json:"update_at"`
+ CreateAt int64 `json:"create_at,omitempty"`
+ UpdateAt int64 `json:"update_at,omitempty"`
DeleteAt int64 `json:"delete_at"`
TeamId string `json:"team_id"`
Username string `json:"username"`
- Password string `json:"password"`
- AuthData string `json:"auth_data"`
- AuthService string `json:"auth_service"`
+ Password string `json:"password,omitempty"`
+ AuthData string `json:"auth_data,omitempty"`
+ AuthService string `json:"auth_service,omitempty"`
Email string `json:"email"`
- EmailVerified bool `json:"email_verified"`
+ EmailVerified bool `json:"email_verified,omitempty"`
Nickname string `json:"nickname"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Roles string `json:"roles"`
- LastActivityAt int64 `json:"last_activity_at"`
- LastPingAt int64 `json:"last_ping_at"`
- AllowMarketing bool `json:"allow_marketing"`
- Props StringMap `json:"props"`
- NotifyProps StringMap `json:"notify_props"`
- ThemeProps StringMap `json:"theme_props"`
- LastPasswordUpdate int64 `json:"last_password_update"`
- LastPictureUpdate int64 `json:"last_picture_update"`
- FailedAttempts int `json:"failed_attempts"`
+ LastActivityAt int64 `json:"last_activity_at,omitempty"`
+ LastPingAt int64 `json:"last_ping_at,omitempty"`
+ AllowMarketing bool `json:"allow_marketing,omitempty"`
+ Props StringMap `json:"props,omitempty"`
+ NotifyProps StringMap `json:"notify_props,omitempty"`
+ ThemeProps StringMap `json:"theme_props,omitempty"`
+ LastPasswordUpdate int64 `json:"last_password_update,omitempty"`
+ LastPictureUpdate int64 `json:"last_picture_update,omitempty"`
+ FailedAttempts int `json:"failed_attempts,omitempty"`
}
// IsValid validates the user and returns an error if it isn't configured
@@ -221,17 +221,29 @@ func (u *User) Sanitize(options map[string]bool) {
u.FirstName = ""
u.LastName = ""
}
- if len(options) != 0 && !options["skypeid"] {
- // TODO - fill in when SkypeId is added to user model
- }
- if len(options) != 0 && !options["phonenumber"] {
- // TODO - fill in when PhoneNumber is added to user model
- }
if len(options) != 0 && !options["passwordupdate"] {
u.LastPasswordUpdate = 0
}
}
+func (u *User) ClearNonProfileFields() {
+ u.CreateAt = 0
+ u.UpdateAt = 0
+ u.Password = ""
+ u.AuthData = ""
+ u.AuthService = ""
+ u.EmailVerified = false
+ u.LastActivityAt = 0
+ u.LastPingAt = 0
+ u.AllowMarketing = false
+ u.Props = StringMap{}
+ u.NotifyProps = StringMap{}
+ u.ThemeProps = StringMap{}
+ u.LastPasswordUpdate = 0
+ u.LastPictureUpdate = 0
+ u.FailedAttempts = 0
+}
+
func (u *User) MakeNonNil() {
if u.Props == nil {
u.Props = make(map[string]string)
diff --git a/model/version.go b/model/version.go
index a61004fde..6eae436bc 100644
--- a/model/version.go
+++ b/model/version.go
@@ -12,6 +12,7 @@ import (
// It should be maitained in chronological order with most current
// release at the front of the list.
var versions = []string{
+ "1.2.0",
"1.1.0",
"1.0.0",
"0.7.1",
diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go
index 2d62b8614..fc4e19442 100644
--- a/store/sql_channel_store.go
+++ b/store/sql_channel_store.go
@@ -4,7 +4,6 @@
package store
import (
- l4g "code.google.com/p/log4go"
"github.com/go-gorp/gorp"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
@@ -40,55 +39,6 @@ func NewSqlChannelStore(sqlStore *SqlStore) ChannelStore {
}
func (s SqlChannelStore) UpgradeSchemaIfNeeded() {
-
- // REMOVE AFTER 1.2 SHIP see PLT-828
- if s.CreateColumnIfNotExists("ChannelMembers", "NotifyProps", "varchar(2000)", "varchar(2000)", "{}") {
- // populate NotifyProps from existing NotifyLevel field
-
- // set default values
- _, err := s.GetMaster().Exec(
- `UPDATE
- ChannelMembers
- SET
- NotifyProps = CONCAT('{"desktop":"', CONCAT(NotifyLevel, '","mark_unread":"` + model.CHANNEL_MARK_UNREAD_ALL + `"}'))`)
- if err != nil {
- l4g.Error("Unable to set default values for ChannelMembers.NotifyProps")
- l4g.Error(err.Error())
- }
-
- // assume channels with all notifications enabled are just using the default settings
- _, err = s.GetMaster().Exec(
- `UPDATE
- ChannelMembers
- SET
- NotifyProps = '{"desktop":"` + model.CHANNEL_NOTIFY_DEFAULT + `","mark_unread":"` + model.CHANNEL_MARK_UNREAD_ALL + `"}'
- WHERE
- NotifyLevel = '` + model.CHANNEL_NOTIFY_ALL + `'`)
- if err != nil {
- l4g.Error("Unable to set values for ChannelMembers.NotifyProps when members previously had notifyLevel=all")
- l4g.Error(err.Error())
- }
-
- // set quiet mode channels to have no notifications and only mark the channel unread on mentions
- _, err = s.GetMaster().Exec(
- `UPDATE
- ChannelMembers
- SET
- NotifyProps = '{"desktop":"` + model.CHANNEL_NOTIFY_NONE + `","mark_unread":"` + model.CHANNEL_MARK_UNREAD_MENTION + `"}'
- WHERE
- NotifyLevel = 'quiet'`)
- if err != nil {
- l4g.Error("Unable to set values for ChannelMembers.NotifyProps when members previously had notifyLevel=quiet")
- l4g.Error(err.Error())
- }
-
- s.RemoveColumnIfExists("ChannelMembers", "NotifyLevel")
- }
-
- // BEGIN REMOVE AFTER 1.2.0
- s.RenameColumnIfExists("Channels", "Description", "Header", "varchar(1024)")
- s.CreateColumnIfNotExists("Channels", "Purpose", "varchar(1024)", "varchar(1024)", "")
- // END REMOVE AFTER 1.2.0
}
func (s SqlChannelStore) CreateIndexesIfNotExists() {
diff --git a/store/sql_post_store.go b/store/sql_post_store.go
index 3460fca92..f800367cb 100644
--- a/store/sql_post_store.go
+++ b/store/sql_post_store.go
@@ -9,10 +9,8 @@ import (
"strconv"
"strings"
- l4g "code.google.com/p/log4go"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
- "time"
)
type SqlPostStore struct {
@@ -40,21 +38,7 @@ func NewSqlPostStore(sqlStore *SqlStore) PostStore {
}
func (s SqlPostStore) UpgradeSchemaIfNeeded() {
- colType := s.GetColumnDataType("Posts", "Props")
- if colType != "text" {
-
- query := "ALTER TABLE Posts MODIFY COLUMN Props TEXT"
- if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
- query = "ALTER TABLE Posts ALTER COLUMN Props TYPE text"
- }
-
- _, err := s.GetMaster().Exec(query)
- if err != nil {
- l4g.Critical("Failed to alter column Posts.Props to TEXT: " + err.Error())
- time.Sleep(time.Second)
- panic("Failed to alter column Posts.Props to TEXT: " + err.Error())
- }
- }
+ s.RemoveColumnIfExists("Posts", "ImgCount") // remove after 1.3 release
}
func (s SqlPostStore) CreateIndexesIfNotExists() {
diff --git a/store/sql_team_store.go b/store/sql_team_store.go
index e0f95fa7e..1a0aeabde 100644
--- a/store/sql_team_store.go
+++ b/store/sql_team_store.go
@@ -30,11 +30,6 @@ func NewSqlTeamStore(sqlStore *SqlStore) TeamStore {
}
func (s SqlTeamStore) UpgradeSchemaIfNeeded() {
- // REMOVE AFTER 1.2 SHIP see PLT-828
- s.RemoveColumnIfExists("Teams", "AllowValet")
- s.CreateColumnIfNotExists("Teams", "InviteId", "varchar(32)", "varchar(32)", "")
- s.CreateColumnIfNotExists("Teams", "AllowOpenInvite", "tinyint(1)", "boolean", "0")
- s.CreateColumnIfNotExists("Teams", "AllowTeamListing", "tinyint(1)", "boolean", "0")
}
func (s SqlTeamStore) CreateIndexesIfNotExists() {
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index 686949a4d..d38b5c214 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -41,8 +41,6 @@ func NewSqlUserStore(sqlStore *SqlStore) UserStore {
}
func (us SqlUserStore) UpgradeSchemaIfNeeded() {
- // REMOVE AFTER 1.2 SHIP see PLT-828
- us.CreateColumnIfNotExists("Users", "ThemeProps", "varchar(2000)", "character varying(2000)", "{}")
}
func (us SqlUserStore) CreateIndexesIfNotExists() {
diff --git a/web/react/components/admin_console/email_settings.jsx b/web/react/components/admin_console/email_settings.jsx
index 40e00ff04..0cabf7f70 100644
--- a/web/react/components/admin_console/email_settings.jsx
+++ b/web/react/components/admin_console/email_settings.jsx
@@ -296,7 +296,7 @@ export default class EmailSettings extends React.Component {
className='form-control'
id='feedbackName'
ref='feedbackName'
- placeholder='Ex: "Mattermost Notification", "System", "No-Reply"'
+ placeholder='E.g.: "Mattermost Notification", "System", "No-Reply"'
defaultValue={this.props.config.EmailSettings.FeedbackName}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
@@ -318,7 +318,7 @@ export default class EmailSettings extends React.Component {
className='form-control'
id='feedbackEmail'
ref='feedbackEmail'
- placeholder='Ex: "mattermost@yourcompany.com", "admin@yourcompany.com"'
+ placeholder='E.g.: "mattermost@yourcompany.com", "admin@yourcompany.com"'
defaultValue={this.props.config.EmailSettings.FeedbackEmail}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
@@ -340,7 +340,7 @@ export default class EmailSettings extends React.Component {
className='form-control'
id='SMTPUsername'
ref='SMTPUsername'
- placeholder='Ex: "admin@yourcompany.com", "AKIADTOVBGERKLCBV"'
+ placeholder='E.g.: "admin@yourcompany.com", "AKIADTOVBGERKLCBV"'
defaultValue={this.props.config.EmailSettings.SMTPUsername}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
@@ -362,7 +362,7 @@ export default class EmailSettings extends React.Component {
className='form-control'
id='SMTPPassword'
ref='SMTPPassword'
- placeholder='Ex: "yourpassword", "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
+ placeholder='E.g.: "yourpassword", "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'
defaultValue={this.props.config.EmailSettings.SMTPPassword}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
@@ -384,7 +384,7 @@ export default class EmailSettings extends React.Component {
className='form-control'
id='SMTPServer'
ref='SMTPServer'
- placeholder='Ex: "smtp.yourcompany.com", "email-smtp.us-east-1.amazonaws.com"'
+ placeholder='E.g.: "smtp.yourcompany.com", "email-smtp.us-east-1.amazonaws.com"'
defaultValue={this.props.config.EmailSettings.SMTPServer}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
@@ -406,7 +406,7 @@ export default class EmailSettings extends React.Component {
className='form-control'
id='SMTPPort'
ref='SMTPPort'
- placeholder='Ex: "25", "465"'
+ placeholder='E.g.: "25", "465"'
defaultValue={this.props.config.EmailSettings.SMTPPort}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
@@ -476,7 +476,7 @@ export default class EmailSettings extends React.Component {
className='form-control'
id='InviteSalt'
ref='InviteSalt'
- placeholder='Ex "bjlSR4QqkXFBr7TP4oDzlfZmcNuH9Yo"'
+ placeholder='E.g.: "bjlSR4QqkXFBr7TP4oDzlfZmcNuH9Yo"'
defaultValue={this.props.config.EmailSettings.InviteSalt}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
@@ -507,7 +507,7 @@ export default class EmailSettings extends React.Component {
className='form-control'
id='PasswordResetSalt'
ref='PasswordResetSalt'
- placeholder='Ex "bjlSR4QqkXFBr7TP4oDzlfZmcNuH9Yo"'
+ placeholder='E.g.: "bjlSR4QqkXFBr7TP4oDzlfZmcNuH9Yo"'
defaultValue={this.props.config.EmailSettings.PasswordResetSalt}
onChange={this.handleChange}
disabled={!this.state.sendEmailNotifications}
diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx
index 2b9ce67ca..f7f5bd23d 100644
--- a/web/react/components/login.jsx
+++ b/web/react/components/login.jsx
@@ -215,11 +215,11 @@ export default class Login extends React.Component {
return (
<div className='signup-team__container'>
+ {verifiedBox}
<h5 className='margin--less'>{'Sign in to:'}</h5>
<h2 className='signup-team__name'>{teamDisplayName}</h2>
<h2 className='signup-team__subdomain'>{'on '}{global.window.mm_config.SiteName}</h2>
<form onSubmit={this.handleSubmit}>
- {verifiedBox}
<div className={'form-group' + errorClass}>
{serverError}
</div>
diff --git a/web/react/components/new_channel_modal.jsx b/web/react/components/new_channel_modal.jsx
index c0cea496f..2c044cd5d 100644
--- a/web/react/components/new_channel_modal.jsx
+++ b/web/react/components/new_channel_modal.jsx
@@ -115,7 +115,7 @@ export default class NewChannelModal extends React.Component {
type='text'
ref='display_name'
className='form-control'
- placeholder='Ex: "Bugs", "Marketing", "办公室恋情"'
+ placeholder='E.g.: "Bugs", "Marketing", "办公室恋情"'
maxLength='22'
value={this.props.channelData.displayName}
autoFocus={true}
diff --git a/web/react/components/posts_view.jsx b/web/react/components/posts_view.jsx
index 2b81d1d79..b782268fa 100644
--- a/web/react/components/posts_view.jsx
+++ b/web/react/components/posts_view.jsx
@@ -30,6 +30,9 @@ export default class PostsView extends React.Component {
static get SIDEBAR_OPEN() {
return 3;
}
+ static get SCROLL_TYPE_NEW_MESSAGE() {
+ return 4;
+ }
isAtBottom() {
return ((this.refs.postlist.scrollHeight - this.refs.postlist.scrollTop) === this.refs.postlist.clientHeight);
}
@@ -145,6 +148,7 @@ export default class PostsView extends React.Component {
<div
id={newSeparatorId}
key='unviewed'
+ ref='newMessageSeparator'
className='new-separator'
>
<hr
@@ -165,6 +169,15 @@ export default class PostsView extends React.Component {
window.requestAnimationFrame(() => {
this.refs.postlist.scrollTop = this.refs.postlist.scrollHeight;
});
+ } else if (this.props.scrollType === PostsView.SCROLL_TYPE_NEW_MESSAGE) {
+ window.requestAnimationFrame(() => {
+ // If separator exists scroll to it. Otherwise scroll to bottom.
+ if (this.refs.newMessageSeparator) {
+ this.refs.newMessageSeparator.scrollIntoView();
+ } else {
+ this.refs.postlist.scrollTop = this.refs.postlist.scrollHeight;
+ }
+ });
} else if (this.props.scrollType === PostsView.SCROLL_TYPE_POST && this.props.scrollPost) {
window.requestAnimationFrame(() => {
const postNode = ReactDOM.findDOMNode(this.refs[this.props.scrollPost]);
diff --git a/web/react/components/posts_view_container.jsx b/web/react/components/posts_view_container.jsx
index 5059747bd..5037a86cd 100644
--- a/web/react/components/posts_view_container.jsx
+++ b/web/react/components/posts_view_container.jsx
@@ -109,7 +109,7 @@ export default class PostsViewContainer extends React.Component {
this.setState({
currentChannelIndex: newIndex,
currentLastViewed: lastViewed,
- scrollType: PostsView.SCROLL_TYPE_BOTTOM,
+ scrollType: PostsView.SCROLL_TYPE_NEW_MESSAGE,
channels,
postLists});
}
diff --git a/web/react/components/tutorial/tutorial_intro_screens.jsx b/web/react/components/tutorial/tutorial_intro_screens.jsx
index 66ca556c6..3afc5145d 100644
--- a/web/react/components/tutorial/tutorial_intro_screens.jsx
+++ b/web/react/components/tutorial/tutorial_intro_screens.jsx
@@ -41,6 +41,11 @@ export default class TutorialIntroScreens extends React.Component {
componentDidMount() {
$('.tutorials__scroll').perfectScrollbar();
}
+ skipTutorial(e) {
+ e.preventDefault();
+ const preference = PreferenceStore.setPreference(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), '999');
+ AsyncClient.savePreferences([preference]);
+ }
createScreen() {
switch (this.state.currentScreen) {
case 0:
@@ -176,6 +181,13 @@ export default class TutorialIntroScreens extends React.Component {
>
{'Next'}
</button>
+ <a
+ className='tutorial-skip'
+ href='#'
+ onClick={this.skipTutorial}
+ >
+ {'Skip tutorial'}
+ </a>
</div>
</div>
</div>
diff --git a/web/react/components/tutorial/tutorial_tip.jsx b/web/react/components/tutorial/tutorial_tip.jsx
index 3094b2f4c..75d73e920 100644
--- a/web/react/components/tutorial/tutorial_tip.jsx
+++ b/web/react/components/tutorial/tutorial_tip.jsx
@@ -69,11 +69,16 @@ export default class TutorialTip extends React.Component {
}
}
+ var tipColor = '';
+ if (this.props.overlayClass === 'tip-overlay--header') {
+ tipColor = 'White';
+ }
+
return (
<div className={'tip-div ' + this.props.overlayClass}>
<img
className='tip-button'
- src='/static/images/tutorialTip.gif'
+ src={'/static/images/tutorialTip' + tipColor + '.gif'}
width='35'
onClick={this.toggle}
ref='target'
diff --git a/web/react/components/user_settings/manage_incoming_hooks.jsx b/web/react/components/user_settings/manage_incoming_hooks.jsx
index 6b8c09718..128c011ea 100644
--- a/web/react/components/user_settings/manage_incoming_hooks.jsx
+++ b/web/react/components/user_settings/manage_incoming_hooks.jsx
@@ -163,7 +163,7 @@ export default class ManageIncomingHooks extends React.Component {
return (
<div key='addIncomingHook'>
{'Create webhook URLs for use in external integrations. Please see '}<a href='http://mattermost.org/webhooks'>{'http://mattermost.org/webhooks'}</a> {' to learn more.'}
- <label className='control-label padding-top x2'>{'Add a new incoming webhook'}</label>
+ <div><label className='control-label padding-top x2'>{'Add a new incoming webhook'}</label></div>
<div className='row padding-top'>
<div className='col-sm-10 padding-bottom'>
<select
diff --git a/web/react/components/user_settings/manage_outgoing_hooks.jsx b/web/react/components/user_settings/manage_outgoing_hooks.jsx
index 93be988d1..7b7cf7401 100644
--- a/web/react/components/user_settings/manage_outgoing_hooks.jsx
+++ b/web/react/components/user_settings/manage_outgoing_hooks.jsx
@@ -241,7 +241,7 @@ export default class ManageOutgoingHooks extends React.Component {
return (
<div key='addOutgoingHook'>
{'Create webhooks to send new message events to an external integration. Please see '}<a href='http://mattermost.org/webhooks'>{'http://mattermost.org/webhooks'}</a> {' to learn more.'}
- <label className='control-label'>{'Add a new outgoing webhook'}</label>
+ <div><label className='control-label padding-top x2'>{'Add a new outgoing webhook'}</label></div>
<div className='padding-top divider-light'></div>
<div className='padding-top'>
<div>
diff --git a/web/sass-files/sass/partials/_tutorial.scss b/web/sass-files/sass/partials/_tutorial.scss
index 08d491fd9..cfbc3454a 100644
--- a/web/sass-files/sass/partials/_tutorial.scss
+++ b/web/sass-files/sass/partials/_tutorial.scss
@@ -127,7 +127,11 @@
right:0px;
&.tip-overlay--header {
- top: 20px;
+ top: 21px;
+ right: 2px;
+ .tip-button {
+ @include opacity(0.8);
+ }
}
&.tip-overlay--sidebar {
@@ -154,11 +158,11 @@
margin-bottom: 50px;
text-align: left;
display: inline-block;
- padding-bottom: 30px;
+ padding-bottom: 30px;
}
.btn-primary {
position: absolute;
- bottom: 0;
+ bottom: 0px;
}
}
h1 {
@@ -175,6 +179,11 @@
position: absolute;
bottom: 40px;
}
+ .tutorial-skip {
+ position: absolute;
+ bottom: 7px;
+ left: 80px;
+ }
}
.tutorial__circles {
diff --git a/web/static/images/tutorialTip.gif b/web/static/images/tutorialTip.gif
index f185ff4b9..c925f0222 100644
--- a/web/static/images/tutorialTip.gif
+++ b/web/static/images/tutorialTip.gif
Binary files differ
diff --git a/web/static/images/tutorialTipWhite.gif b/web/static/images/tutorialTipWhite.gif
new file mode 100644
index 000000000..ecf8e97be
--- /dev/null
+++ b/web/static/images/tutorialTipWhite.gif
Binary files differ