summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md74
-rw-r--r--api/auto_environment.go (renamed from api/auto_enviroment.go)30
-rw-r--r--api/auto_teams.go2
-rw-r--r--api/command.go18
-rw-r--r--doc/install/Amazon-Elastic-Beanstalk.md45
-rw-r--r--doc/install/SMTP-Email-Setup.md12
-rw-r--r--doc/process/documentation-guidelines.md185
-rw-r--r--manualtesting/manual_testing.go6
-rw-r--r--manualtesting/test_autolink.go2
-rw-r--r--store/sql_audit_store.go4
-rw-r--r--store/sql_channel_store.go6
-rw-r--r--store/sql_oauth_store.go10
-rw-r--r--store/sql_post_store.go2
-rw-r--r--store/sql_preference_store.go6
-rw-r--r--store/sql_session_store.go8
-rw-r--r--store/sql_system_store.go6
-rw-r--r--store/sql_team_store.go8
-rw-r--r--store/sql_user_store.go12
-rw-r--r--web/react/components/post_info.jsx2
-rw-r--r--web/react/components/post_list.jsx5
-rw-r--r--web/react/components/search_bar.jsx1
-rw-r--r--web/react/components/team_signup_display_name_page.jsx3
-rw-r--r--web/react/components/team_signup_url_page.jsx4
-rw-r--r--web/react/utils/utils.jsx2
-rw-r--r--web/sass-files/sass/partials/_headers.scss3
-rw-r--r--web/sass-files/sass/partials/_responsive.scss2
-rw-r--r--web/sass-files/sass/partials/_search.scss5
-rw-r--r--web/static/help/about.html2
28 files changed, 371 insertions, 94 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8082b2536..46b74ccb3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,9 +7,79 @@ The "UNDER DEVELOPMENT" section of the Mattermost changelog appears in the produ
- **Release candidate anticipated:** 2015-11-10
- **Final release anticipated:** 2015-11-16
-### Changes
+### Improvements
-- IE 10 no longer supported since global share of IE 10 fell below 5%
+Onboarding
+
+- New tutorial explaining how to use Mattermost for new users
+
+Messaging and Notifications
+
+- Users can now search for teammates to add to **Direct Message** list via **More** menu
+- Users can now personalize Direct Messages list by removing users listed
+- Link previews - Adding URL with .gif file adds image below message
+
+Search
+
+- Adding search term `in:[channel_url_name]` now limits searches within a specific channel
+- Adding search term `from:[username]` now limits searches to messages from a specific user
+- Tip explaining search options when clicking into search box
+
+Integrations
+
+- [Outgoing webhooks](https://github.com/mattermost/platform/blob/master/doc/integrations/webhooks/Outgoing-Webhooks.md) now available
+- Made available [application template showing outgoing webhooks working with Mattermost and external application](https://github.com/mattermost/mattermost-integration-giphy)
+
+User Interface
+
+- Member list in Channel display now scrollable, and includes Message button to message channel members directly
+- Added ability to edit previous message by hitting UP arrow
+- Syntax highlighting added for code blocks
+ - Languages include `Diff, Apache, Makefile, HTTP, JSON, Markdown, Java, CSS, nginx, ObjectiveC, Python, XML, Perl, Bash, PHP, Coffee, C, SQL, Go, Ruby, Java, and ini`.
+ - Use by adding the name of the language on the first link of the code block, for example: ```python
+ - Syntax color theme can be defined under **Account Settings** > **Appearance Settings** > **Custom Theme**
+
+Team Settings
+
+- Added Team Settings option to include account creation URL on team login page
+- Added Team Settings option to include link to given team on root page
+- Ability to rotate invite code for invite URL
+
+System Console
+
+- New statistics page
+- Configurable option to create an account directly from team page
+
+#### Bug Fixes
+
+- Various fixes to theme colors
+
+### Compatibility
+
+- IE 11 new minimum version for IE, since IE 10 share fell below 5% on desktop
+- Safari 8 new minimum version for Safari, since Safari 7 fell below 1% on desktop
+
+#### Known Issues
+
+- Microsoft Edge does not yet support drag and drop
+- Incoming webhooks no longer disrupted when channel is deleted
+
+#### Contributors
+
+Many thanks to our external contributors. In no particular order:
+
+- [florianorben](https://github.com/florianorben)
+- [trashcan](https://github.com/trashcan)
+- [girishso](https://github.com/girishso)
+- [apaatsio](https://github.com/apaatsio)
+- [jlebleu](https://github.com/jlebleu)
+- [stasvovk](https://github.com/stasvovk)
+- [mcmillhj](https://github.com/mcmillhj)
+- [sharms](https://github.com/sharms)
+- [jvasallo](https://github.com/jvasallo)
+- [layzerar](https://github.com/layzerar)
+- [optimistiks](https://github.com/optimistiks)
+- [layzerar](https://github.com/layzerar)
## Release v1.1.1 (Bug Fix Release)
diff --git a/api/auto_enviroment.go b/api/auto_environment.go
index c6453f5da..68186ec6c 100644
--- a/api/auto_enviroment.go
+++ b/api/auto_environment.go
@@ -10,42 +10,42 @@ import (
"time"
)
-type TestEnviroment struct {
- Teams []*model.Team
- Enviroments []TeamEnviroment
+type TestEnvironment struct {
+ Teams []*model.Team
+ Environments []TeamEnvironment
}
-func CreateTestEnviromentWithTeams(client *model.Client, rangeTeams utils.Range, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TestEnviroment, bool) {
+func CreateTestEnvironmentWithTeams(client *model.Client, rangeTeams utils.Range, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TestEnvironment, bool) {
rand.Seed(time.Now().UTC().UnixNano())
teamCreator := NewAutoTeamCreator(client)
teamCreator.Fuzzy = fuzzy
teams, err := teamCreator.CreateTestTeams(rangeTeams)
if err != true {
- return TestEnviroment{}, false
+ return TestEnvironment{}, false
}
- enviroment := TestEnviroment{teams, make([]TeamEnviroment, len(teams))}
+ environment := TestEnvironment{teams, make([]TeamEnvironment, len(teams))}
for i, team := range teams {
userCreator := NewAutoUserCreator(client, team.Id)
userCreator.Fuzzy = fuzzy
randomUser, err := userCreator.createRandomUser()
if err != true {
- return TestEnviroment{}, false
+ return TestEnvironment{}, false
}
client.LoginById(randomUser.Id, USER_PASSWORD)
- teamEnviroment, err := CreateTestEnviromentInTeam(client, team.Id, rangeChannels, rangeUsers, rangePosts, fuzzy)
+ teamEnvironment, err := CreateTestEnvironmentInTeam(client, team.Id, rangeChannels, rangeUsers, rangePosts, fuzzy)
if err != true {
- return TestEnviroment{}, false
+ return TestEnvironment{}, false
}
- enviroment.Enviroments[i] = teamEnviroment
+ environment.Environments[i] = teamEnvironment
}
- return enviroment, true
+ return environment, true
}
-func CreateTestEnviromentInTeam(client *model.Client, teamID string, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TeamEnviroment, bool) {
+func CreateTestEnvironmentInTeam(client *model.Client, teamID string, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TeamEnvironment, bool) {
rand.Seed(time.Now().UTC().UnixNano())
// We need to create at least one user
@@ -57,7 +57,7 @@ func CreateTestEnviromentInTeam(client *model.Client, teamID string, rangeChanne
userCreator.Fuzzy = fuzzy
users, err := userCreator.CreateTestUsers(rangeUsers)
if err != true {
- return TeamEnviroment{}, false
+ return TeamEnvironment{}, false
}
usernames := make([]string, len(users))
for i, user := range users {
@@ -77,7 +77,7 @@ func CreateTestEnviromentInTeam(client *model.Client, teamID string, rangeChanne
}
if err != true {
- return TeamEnviroment{}, false
+ return TeamEnvironment{}, false
}
numPosts := utils.RandIntFromRange(rangePosts)
numImages := utils.RandIntFromRange(rangePosts) / 4
@@ -93,5 +93,5 @@ func CreateTestEnviromentInTeam(client *model.Client, teamID string, rangeChanne
}
}
- return TeamEnviroment{users, channels}, true
+ return TeamEnvironment{users, channels}, true
}
diff --git a/api/auto_teams.go b/api/auto_teams.go
index 6677ac9bf..082415d32 100644
--- a/api/auto_teams.go
+++ b/api/auto_teams.go
@@ -8,7 +8,7 @@ import (
"github.com/mattermost/platform/utils"
)
-type TeamEnviroment struct {
+type TeamEnvironment struct {
Users []*model.User
Channels []*model.Channel
}
diff --git a/api/command.go b/api/command.go
index 7b3fb9236..50ca41155 100644
--- a/api/command.go
+++ b/api/command.go
@@ -411,11 +411,11 @@ func loadTestSetupCommand(c *Context, command *model.Command) bool {
if doTeams {
if err := CreateBasicUser(client); err != nil {
- l4g.Error("Failed to create testing enviroment")
+ l4g.Error("Failed to create testing environment")
return true
}
client.LoginByEmail(BTEST_TEAM_NAME, BTEST_USER_EMAIL, BTEST_USER_PASSWORD)
- enviroment, err := CreateTestEnviromentWithTeams(
+ environment, err := CreateTestEnvironmentWithTeams(
client,
utils.Range{numTeams, numTeams},
utils.Range{numChannels, numChannels},
@@ -423,18 +423,18 @@ func loadTestSetupCommand(c *Context, command *model.Command) bool {
utils.Range{numPosts, numPosts},
doFuzz)
if err != true {
- l4g.Error("Failed to create testing enviroment")
+ l4g.Error("Failed to create testing environment")
return true
} else {
- l4g.Info("Testing enviroment created")
- for i := 0; i < len(enviroment.Teams); i++ {
- l4g.Info("Team Created: " + enviroment.Teams[i].Name)
- l4g.Info("\t User to login: " + enviroment.Enviroments[i].Users[0].Email + ", " + USER_PASSWORD)
+ l4g.Info("Testing environment created")
+ for i := 0; i < len(environment.Teams); i++ {
+ l4g.Info("Team Created: " + environment.Teams[i].Name)
+ l4g.Info("\t User to login: " + environment.Environments[i].Users[0].Email + ", " + USER_PASSWORD)
}
}
} else {
client.MockSession(c.Session.Token)
- CreateTestEnviromentInTeam(
+ CreateTestEnvironmentInTeam(
client,
c.Session.TeamId,
utils.Range{numChannels, numChannels},
@@ -446,7 +446,7 @@ func loadTestSetupCommand(c *Context, command *model.Command) bool {
} else if strings.Index(cmd, command.Command) == 0 {
command.AddSuggestion(&model.SuggestCommand{
Suggestion: cmd,
- Description: "Creates a testing enviroment in current team. [teams] [fuzz] <Num Channels> <Num Users> <NumPosts>"})
+ Description: "Creates a testing environment in current team. [teams] [fuzz] <Num Channels> <Num Users> <NumPosts>"})
}
return false
diff --git a/doc/install/Amazon-Elastic-Beanstalk.md b/doc/install/Amazon-Elastic-Beanstalk.md
index 0416b67ea..8738ab3ac 100644
--- a/doc/install/Amazon-Elastic-Beanstalk.md
+++ b/doc/install/Amazon-Elastic-Beanstalk.md
@@ -1,27 +1,26 @@
## AWS Elastic Beanstalk Setup (Docker)
+These instructions will guide you through the process of setting up Mattermost for product evaluation using an EBS Docker single-container application using [Dockerrun.aws.zip](https://github.com/mattermost/platform/raw/master/docker/1.1/Dockerrun.aws.zip).
-1. Create a new Elastic Beanstalk Docker application using the [Dockerrun.aws.zip](https://github.com/mattermost/platform/raw/master/docker/1.0/Dockerrun.aws.zip) file provided.
- 1. From the AWS console select Elastic Beanstalk.
- 2. Select "Create New Application" from the top right.
- 3. Name the application and press next.
- 4. Select "Create a web server" environment.
- 5. If asked, select create an IAM role and instance profile and press next.
- 6. For predefined configuration select under Generic: Docker. For environment type select single instance.
- 7. For application source, select upload your own and upload Dockerrun.aws.zip from [Dockerrun.aws.zip](https://github.com/mattermost/platform/raw/master/docker/1.0/Dockerrun.aws.zip). Everything else may be left at default.
- 8. Select an environment name, this is how you will refer to your environment. Make sure the URL is available then press next.
- 9. The options on the additional resources page may be left at default unless you wish to change them. Press Next.
- 10. On the configuration details place. Select an instance type of t2.small or larger.
- 11. You can set the configuration details as you please but they may be left at their defaults. When you are done press next.
- 12. Environment tags my be left blank. Press next.
- 13. You will be asked to review your information. Press Launch.
-
-4. Try it out!
- 14. Wait for beanstalk to update the environment.
- 15. Try it out by entering the domain of the form \*.elasticbeanstalk.com found at the top of the dashboard into your browser. You can also map your own domain if you wish.
-
-
- ### (Recommended) Enable Email
- The default single-container Docker instance for Mattermost is designed for product evaluation, and sets `ByPassEmail=true` so the product can run without enabling email, when doing so maybe difficult.
+1. From your [AWS console]( https://console.aws.amazon.com/console/home) select **Elastic Beanstalk** under the Compute section.
+2. Select **Create New Application** from the top right.
+3. Name your Elastic Beanstalk application and click **Next**,
+4. Select **Create web server** on the New Enviroment page.
+5. If asked, select **Create an IAM role and instance profile**, then click **Next**.
+6. On the Enviroment Type page,
+ 1. Set Predefined Configuration to **Docker** under the generic heading in the drop-down list.
+ 2. Set Environment Type to **Single instance** in the drop-down list.
+ 3. Click **Next**.
+7. For Application Source, select **Upload your own** and upload the [Dockerrun.aws.zip](https://github.com/mattermost/platform/raw/master/docker/1.1/Dockerrun.aws.zip) file, then click **Next**.
+8. Type an Environment Name and URL. Make sure the URL is available by clicking **Check availability**, then click **Next**.
+9. The options on the Additional Resources page may be left at default unless you wish to change them. Click **Next**.
+10. On the Configuration Details page,
+ 1. Select an Instance Type of **t2.small** or larger.
+ 2. The remaining options may be left at their default values unless you wish to change them. Click **Next**.
+11. Environment tags may be left blank. Click **Next**.
+12. You will be asked to review your information, then click **Launch**.
+14. It may take a few minutes for beanstalk to launch your environment. If the launch is successful, you will see a see a large green checkmark and the Health status should change to “Green”.
+15. Test your environment by clicking the domain link next to your application name at the top of the dashboard. Alternatively, enter the domain into your browser in the form `http://<your-ebs-application-url>.elasticbeanstalk.com`. You can also map your own domain if you wish. If everything is working correctly, the domain should navigate you to the Mattermost signup page. Enjoy exploring Mattermost!
- To see the product's full functionality, [enabling SMTP email is recommended](SMTP-Email-Setup.md).
+### (Recommended) Enable Email
+The default single-container Docker instance for Mattermost is designed for product evaluation, and sets `SendEmailNotifications=false` so the product can function without enabling email. To see the product's full functionality, [enabling SMTP email is recommended](SMTP-Email-Setup.md).
diff --git a/doc/install/SMTP-Email-Setup.md b/doc/install/SMTP-Email-Setup.md
index bb57d95ba..7d9beae89 100644
--- a/doc/install/SMTP-Email-Setup.md
+++ b/doc/install/SMTP-Email-Setup.md
@@ -52,10 +52,18 @@ To enable email, configure an SMTP email service as follows:
* Set **Connection Security** to **(empty)**
##### Gmail
-* Information needed
+* Set **SMTP Username** to **your_email@gmail.com**
+* Set **SMTP Password** to **your_password**
+* Set **SMTP Server** to **smtp.gmail.com**
+* Set **SMTP Port** to **587**
+* Set **Connection Security** to **TLS**
##### Office 365
-* Information needed
+* Set **SMTP Username** to **Office 365 username**
+* Set **SMTP Password** to **Office 365 password**
+* Set **SMTP Server** to **smtp.office365.com**
+* Set **SMTP Port** to **587**
+* Set **Connection Security** to **TLS**
##### Hotmail
* Set **SMTP Username** to **your_email@hotmail.com**
diff --git a/doc/process/documentation-guidelines.md b/doc/process/documentation-guidelines.md
new file mode 100644
index 000000000..f37f0c5fc
--- /dev/null
+++ b/doc/process/documentation-guidelines.md
@@ -0,0 +1,185 @@
+# Documentation Conventions
+
+The most important thing about documentation is getting it done and out to the community.
+
+After that, we can work on upgrading the quality of documentation. The below chart summarizes the different levels of documentation and how the quality gates are applied.
+
+_Note: Documentation Guidelines are new, and iterating. Documentation has started to balloon and this is our attempt at reducing ambiguity and increasing consistency, but the conventions here are very open to discussion._
+
+| Stars | Benchmark | Timeline |
+|:-------------|:--------------------------------|:--------------------------------|
+| 1 | Documentation is correct. | First draft checked in by developer. Okay to ship in first release of new feature. |
+| 2 | Documentation a) follows all objective formatting criteria, b) is tested by someone other than the author, c) satisfies above. | First edit under objective rules. Required before second release cycle with this feature included. |
+| 3 | Documentation a) follows all subjective style criteria, b) is reviewed and edited by someone who has previously authored 3-star documentation, and c) satisfies above. | Second edit under subjective rules. Required before third release cycle with this feature included |
+| 4 | Documentation a) has received at least 1 edit due to user feedback, b) has received at least one unprompted compliment from user community on quality, c) satisfies above. | Additional edits to refine documentation based on user feedback |
+
+## 1-Star Requirements: Correctness
+
+### List precise dependencies
+
+1. Be explicit about what specific dependencies have been tested as part of an installation procedure.
+2. Be explicit about assumptions of compatibility on systems that have not been tested.
+3. Do not claim the system works on later versions of a platform if backwards compatibility is not a priority for the dependency (It's okay to say Chrome version 43 and higher, but not Python 2.6 and higher, because Python 3.0 is explicitly incompatible with previous versions).
+
+#### Correct
+
+----
+This procedure works on an Ubuntu 14.04 server with Python 2.6 installed and should work on compatible Linux-based operating systems and compatible versions of Python.
+
+----
+#### Incorrect
+
+----
+This procedure works on Linux servers running Python.
+
+also:
+
+This procedure works on Linux servers running Python 2.6 and higher.
+
+----
+## 2-Star Requirements: Objective Formatting Checklist
+
+### Use headings
+
+Headings in markdown provide anchors that can be used to easily reference sub-sections of long pieces of documentation. This is preferrable to just numbering sections without headings.
+
+##### Correct:
+
+----
+##### Step 1: Add a heading
+This makes things easier to reference via hyperlinks
+##### Step 2: Link to headings
+So things are eariser to find
+
+----
+##### Incorrect:
+
+----
+**Step 1: Add a heading**
+This makes things easier to reference via hyperlinks
+**Step 2: Link to headings**
+So things are eariser to find
+----
+
+### Use appropriate heading case
+
+Cases in headings may vary depending on usage.
+
+#### When to use Title Case
+
+H1, H2, H3 headings should be "Title Case" and less than four words, except if a colon is used, then four words per segment separated by the colon.
+
+These large headings are typically shorter and help with navigating large documents
+
+#### When to use sentence case
+
+H3, H4, H5 headings should be "Sentence case" and can be any length.
+
+These headers are smaller and used to summarize sections. H3 can be considered either a large or small heading.
+
+These conventions are new, so there's flexibility around them, when you're not sure, consider the convention here as default.
+
+### One instruction per line
+
+It's easy to miss instructions when they're compounded. Have only one instruction per line, so documentation looks more like a checklist.
+
+A support person should be able to say "Did you complete step 7?" instead of "Did you complete the second part of step 7 after doing XXX?"
+
+##### Correct:
+
+----
+
+6. For **Predefined configuration** look under **Generic** and select **Docker**.
+ 7. For **Environment type** select **Single instance**
+
+----
+
+##### Incorrect:
+
+----
+
+6. For **Predefined configuration** look under **Generic** and select **Docker**. For **Environment type** select **Single instance**
+
+----
+
+### Lists end without periods
+
+Sentences within bullet points or numbered lists should end in normal punctuation. The sentence or fragment at the end of a bullet point should not have a period.
+
+##### Correct
+
+----
+- This is a sentence within a bullet point. This is the end of a bullet point without a period
+
+----
+##### Incorrect
+
+----
+- This is an incorrect ending of a bullet point with a period.
+
+----
+### Avoid Passive Phrases
+
+Examples of passive phrases include "have", "had", "was", "can be", "has been" and documentation is shorter and clearer without them.
+
+##### Correct
+
+----
+This software **runs** on any server that supports Python.
+
+----
+##### Incorrect
+
+----
+This software **can be run** on any server that supports Python.
+
+----
+## 3-Star Requirements: Subjective Style Guidelines
+
+### Be Concise
+
+Try to use fewer words when possible.
+
+##### Correct:
+
+----
+This integration posts [issue](http://doc.gitlab.com/ee/web_hooks/web_hooks.html#issues-events), [comment](http://doc.gitlab.com/ee/web_hooks/web_hooks.html#comment-events) and [merge request](http://doc.gitlab.com/ee/web_hooks/web_hooks.html#merge-request-events) events from a GitLab repository into specific Mattermost channels by formatting output from [GitLab's outgoing webhooks](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/web_hooks/web_hooks.md) to [Mattermost's incoming webhooks](https://github.com/mattermost/platform/blob/master/doc/integrations/webhooks/Incoming-Webhooks.md).
+
+----
+##### Incorrect:
+
+----
+This integration makes use of GitLab's outgoing webhooks and Mattermost's incoming webhooks to post GitLab events into Mattermost. You can find GitLab's outgoing webhooks described [here](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/web_hooks/web_hooks.md) and Mattermost's incoming webhooks described [here](https://github.com/mattermost/platform/blob/master/doc/integrations/webhooks/Incoming-Webhooks.md).
+
+----
+
+### Use appropriate emphasis
+
+Mention Clickable Controls in **Bold**, Sections and Setting Names in *Italics*, and Key Strokes in `pre-formatted text`.
+
+To make it clear and consistent across documentation on how we describe controls that a user is asked to manipulate, we have a number of guidelines:
+
+**Bold**
+- Please **bold** the names of controls you're asking users to click. The text that is bolded should match the label of the control in the user interface. Do not format these references with _italics_, ALL-CAPS or `pre-formatted text`.
+- Use `>` to express a series of clicks, for example clicking on **Button One** > **Button Two** > **Button Three**.
+- If a button might be difficult to find, give a hint about its location _before_ mentioning the name of the control (this helps people find the hint before they start searching, if the see the name of the button first, they might not continue reading to find the hint before starting to look).
+
+***Italics***
+- Please *italicize* setting names or section headings that identify that the user is looking in the correct area. The text that is italicized should match the name of the setting or section in the user interface.
+- It is helpful to use italics to guide the user to the correct area before mentioning a clickable action in bold.
+
+**`pre-formatted text`**
+- Please use `pre-formatted text` to identify when a user must enter key strokes or paste text into an input box.
+
+#### Correct
+
+----
+Type `mattermost-integration-giphy` in the *repo-name* field, then click **Search** and then the **Connect** button once Heroku finds your repository
+
+----
+#### Incorrect
+
+----
+Type "mattermost-integration-giphy" in the **repo-name** field, then click Search and then the *Connect* button once Heroku finds your repository
+
+----
diff --git a/manualtesting/manual_testing.go b/manualtesting/manual_testing.go
index 3c2289626..ffdb578a4 100644
--- a/manualtesting/manual_testing.go
+++ b/manualtesting/manual_testing.go
@@ -16,7 +16,7 @@ import (
"time"
)
-type TestEnviroment struct {
+type TestEnvironment struct {
Params map[string][]string
Client *model.Client
CreatedTeamId string
@@ -121,8 +121,8 @@ func manualTest(c *api.Context, w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/channels/town-square", http.StatusTemporaryRedirect)
}
- // Setup test enviroment
- env := TestEnviroment{
+ // Setup test environment
+ env := TestEnvironment{
Params: params,
Client: client,
CreatedTeamId: teamID,
diff --git a/manualtesting/test_autolink.go b/manualtesting/test_autolink.go
index e4d49659a..a13ec7a75 100644
--- a/manualtesting/test_autolink.go
+++ b/manualtesting/test_autolink.go
@@ -19,7 +19,7 @@ http://www.google.com.pk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&cad=rja&uact=8
https://medium.com/@slackhq/11-useful-tips-for-getting-the-most-of-slack-5dfb3d1af77
`
-func testAutoLink(env TestEnviroment) *model.AppError {
+func testAutoLink(env TestEnvironment) *model.AppError {
l4g.Info("Manual Auto Link Test")
channelID, err := getChannelID(model.DEFAULT_CHANNEL, env.CreatedTeamId, env.CreatedUserId)
if err != true {
diff --git a/store/sql_audit_store.go b/store/sql_audit_store.go
index 898cf8f78..b3e2daea0 100644
--- a/store/sql_audit_store.go
+++ b/store/sql_audit_store.go
@@ -46,7 +46,7 @@ func (s SqlAuditStore) Save(audit *model.Audit) StoreChannel {
if err := s.GetMaster().Insert(audit); err != nil {
result.Err = model.NewAppError("SqlAuditStore.Save",
- "We encounted an error saving the audit", "user_id="+
+ "We encountered an error saving the audit", "user_id="+
audit.UserId+" action="+audit.Action)
}
@@ -75,7 +75,7 @@ func (s SqlAuditStore) Get(user_id string, limit int) StoreChannel {
var audits model.Audits
if _, err := s.GetReplica().Select(&audits, "SELECT * FROM Audits WHERE UserId = :user_id ORDER BY CreateAt DESC LIMIT :limit",
map[string]interface{}{"user_id": user_id, "limit": limit}); err != nil {
- result.Err = model.NewAppError("SqlAuditStore.Get", "We encounted an error finding the audits", "user_id="+user_id)
+ result.Err = model.NewAppError("SqlAuditStore.Get", "We encountered an error finding the audits", "user_id="+user_id)
} else {
result.Data = audits
}
diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go
index 14896c0a0..2d62b8614 100644
--- a/store/sql_channel_store.go
+++ b/store/sql_channel_store.go
@@ -247,7 +247,7 @@ func (s SqlChannelStore) Update(channel *model.Channel) StoreChannel {
result.Err = model.NewAppError("SqlChannelStore.Update", "A channel with that handle already exists", "id="+channel.Id+", "+err.Error())
}
} else {
- result.Err = model.NewAppError("SqlChannelStore.Update", "We encounted an error updating the channel", "id="+channel.Id+", "+err.Error())
+ result.Err = model.NewAppError("SqlChannelStore.Update", "We encountered an error updating the channel", "id="+channel.Id+", "+err.Error())
}
} else if count != 1 {
result.Err = model.NewAppError("SqlChannelStore.Update", "We couldn't update the channel", "id="+channel.Id)
@@ -297,7 +297,7 @@ func (s SqlChannelStore) Get(id string) StoreChannel {
result := StoreResult{}
if obj, err := s.GetReplica().Get(model.Channel{}, id); err != nil {
- result.Err = model.NewAppError("SqlChannelStore.Get", "We encounted an error finding the channel", "id="+id+", "+err.Error())
+ result.Err = model.NewAppError("SqlChannelStore.Get", "We encountered an error finding the channel", "id="+id+", "+err.Error())
} else if obj == nil {
result.Err = model.NewAppError("SqlChannelStore.Get", "We couldn't find the existing channel", "id="+id)
} else {
@@ -537,7 +537,7 @@ func (s SqlChannelStore) UpdateMember(member *model.ChannelMember) StoreChannel
}
if _, err := s.GetMaster().Update(member); err != nil {
- result.Err = model.NewAppError("SqlChannelStore.UpdateMember", "We encounted an error updating the channel member",
+ result.Err = model.NewAppError("SqlChannelStore.UpdateMember", "We encountered an error updating the channel member",
"channel_id="+member.ChannelId+", "+"user_id="+member.UserId+", "+err.Error())
} else {
result.Data = member
diff --git a/store/sql_oauth_store.go b/store/sql_oauth_store.go
index db52e379b..751207b85 100644
--- a/store/sql_oauth_store.go
+++ b/store/sql_oauth_store.go
@@ -102,7 +102,7 @@ func (as SqlOAuthStore) UpdateApp(app *model.OAuthApp) StoreChannel {
}
if oldAppResult, err := as.GetMaster().Get(model.OAuthApp{}, app.Id); err != nil {
- result.Err = model.NewAppError("SqlOAuthStore.UpdateApp", "We encounted an error finding the app", "app_id="+app.Id+", "+err.Error())
+ result.Err = model.NewAppError("SqlOAuthStore.UpdateApp", "We encountered an error finding the app", "app_id="+app.Id+", "+err.Error())
} else if oldAppResult == nil {
result.Err = model.NewAppError("SqlOAuthStore.UpdateApp", "We couldn't find the existing app to update", "app_id="+app.Id)
} else {
@@ -112,7 +112,7 @@ func (as SqlOAuthStore) UpdateApp(app *model.OAuthApp) StoreChannel {
app.CreatorId = oldApp.CreatorId
if count, err := as.GetMaster().Update(app); err != nil {
- result.Err = model.NewAppError("SqlOAuthStore.UpdateApp", "We encounted an error updating the app", "app_id="+app.Id+", "+err.Error())
+ result.Err = model.NewAppError("SqlOAuthStore.UpdateApp", "We encountered an error updating the app", "app_id="+app.Id+", "+err.Error())
} else if count != 1 {
result.Err = model.NewAppError("SqlOAuthStore.UpdateApp", "We couldn't update the app", "app_id="+app.Id)
} else {
@@ -135,7 +135,7 @@ func (as SqlOAuthStore) GetApp(id string) StoreChannel {
result := StoreResult{}
if obj, err := as.GetReplica().Get(model.OAuthApp{}, id); err != nil {
- result.Err = model.NewAppError("SqlOAuthStore.GetApp", "We encounted an error finding the app", "app_id="+id+", "+err.Error())
+ result.Err = model.NewAppError("SqlOAuthStore.GetApp", "We encountered an error finding the app", "app_id="+id+", "+err.Error())
} else if obj == nil {
result.Err = model.NewAppError("SqlOAuthStore.GetApp", "We couldn't find the existing app", "app_id="+id)
} else {
@@ -208,7 +208,7 @@ func (as SqlOAuthStore) GetAccessData(token string) StoreChannel {
accessData := model.AccessData{}
if err := as.GetReplica().SelectOne(&accessData, "SELECT * FROM OAuthAccessData WHERE Token = :Token", map[string]interface{}{"Token": token}); err != nil {
- result.Err = model.NewAppError("SqlOAuthStore.GetAccessData", "We encounted an error finding the access token", err.Error())
+ result.Err = model.NewAppError("SqlOAuthStore.GetAccessData", "We encountered an error finding the access token", err.Error())
} else {
result.Data = &accessData
}
@@ -300,7 +300,7 @@ func (as SqlOAuthStore) GetAuthData(code string) StoreChannel {
result := StoreResult{}
if obj, err := as.GetReplica().Get(model.AuthData{}, code); err != nil {
- result.Err = model.NewAppError("SqlOAuthStore.GetAuthData", "We encounted an error finding the authorization code", err.Error())
+ result.Err = model.NewAppError("SqlOAuthStore.GetAuthData", "We encountered an error finding the authorization code", err.Error())
} else if obj == nil {
result.Err = model.NewAppError("SqlOAuthStore.GetAuthData", "We couldn't find the existing authorization code", "")
} else {
diff --git a/store/sql_post_store.go b/store/sql_post_store.go
index 7894ff488..f514d23ed 100644
--- a/store/sql_post_store.go
+++ b/store/sql_post_store.go
@@ -548,7 +548,7 @@ func (s SqlPostStore) Search(teamId string, userId string, params *model.SearchP
_, err := s.GetReplica().Select(&posts, searchQuery, queryParams)
if err != nil {
- result.Err = model.NewAppError("SqlPostStore.Search", "We encounted an error while searching for posts", "teamId="+teamId+", err="+err.Error())
+ result.Err = model.NewAppError("SqlPostStore.Search", "We encountered an error while searching for posts", "teamId="+teamId+", err="+err.Error())
}
list := &model.PostList{Order: make([]string, 0, len(posts))}
diff --git a/store/sql_preference_store.go b/store/sql_preference_store.go
index bf6e030bf..f9f38b747 100644
--- a/store/sql_preference_store.go
+++ b/store/sql_preference_store.go
@@ -173,7 +173,7 @@ func (s SqlPreferenceStore) Get(userId string, category string, name string) Sto
UserId = :UserId
AND Category = :Category
AND Name = :Name`, map[string]interface{}{"UserId": userId, "Category": category, "Name": name}); err != nil {
- result.Err = model.NewAppError("SqlPreferenceStore.Get", "We encounted an error while finding preferences", err.Error())
+ result.Err = model.NewAppError("SqlPreferenceStore.Get", "We encountered an error while finding preferences", err.Error())
} else {
result.Data = preference
}
@@ -201,7 +201,7 @@ func (s SqlPreferenceStore) GetCategory(userId string, category string) StoreCha
WHERE
UserId = :UserId
AND Category = :Category`, map[string]interface{}{"UserId": userId, "Category": category}); err != nil {
- result.Err = model.NewAppError("SqlPreferenceStore.GetCategory", "We encounted an error while finding preferences", err.Error())
+ result.Err = model.NewAppError("SqlPreferenceStore.GetCategory", "We encountered an error while finding preferences", err.Error())
} else {
result.Data = preferences
}
@@ -228,7 +228,7 @@ func (s SqlPreferenceStore) GetAll(userId string) StoreChannel {
Preferences
WHERE
UserId = :UserId`, map[string]interface{}{"UserId": userId}); err != nil {
- result.Err = model.NewAppError("SqlPreferenceStore.GetAll", "We encounted an error while finding preferences", err.Error())
+ result.Err = model.NewAppError("SqlPreferenceStore.GetAll", "We encountered an error while finding preferences", err.Error())
} else {
result.Data = preferences
}
diff --git a/store/sql_session_store.go b/store/sql_session_store.go
index 15ec6924b..27b34ee39 100644
--- a/store/sql_session_store.go
+++ b/store/sql_session_store.go
@@ -80,9 +80,9 @@ func (me SqlSessionStore) Get(sessionIdOrToken string) StoreChannel {
var sessions []*model.Session
if _, err := me.GetReplica().Select(&sessions, "SELECT * FROM Sessions WHERE Token = :Token OR Id = :Id LIMIT 1", map[string]interface{}{"Token": sessionIdOrToken, "Id": sessionIdOrToken}); err != nil {
- result.Err = model.NewAppError("SqlSessionStore.Get", "We encounted an error finding the session", "sessionIdOrToken="+sessionIdOrToken+", "+err.Error())
+ result.Err = model.NewAppError("SqlSessionStore.Get", "We encountered an error finding the session", "sessionIdOrToken="+sessionIdOrToken+", "+err.Error())
} else if sessions == nil || len(sessions) == 0 {
- result.Err = model.NewAppError("SqlSessionStore.Get", "We encounted an error finding the session", "sessionIdOrToken="+sessionIdOrToken)
+ result.Err = model.NewAppError("SqlSessionStore.Get", "We encountered an error finding the session", "sessionIdOrToken="+sessionIdOrToken)
} else {
result.Data = sessions[0]
}
@@ -109,7 +109,7 @@ func (me SqlSessionStore) GetSessions(userId string) StoreChannel {
var sessions []*model.Session
if _, err := me.GetReplica().Select(&sessions, "SELECT * FROM Sessions WHERE UserId = :UserId ORDER BY LastActivityAt DESC", map[string]interface{}{"UserId": userId}); err != nil {
- result.Err = model.NewAppError("SqlSessionStore.GetSessions", "We encounted an error while finding user sessions", err.Error())
+ result.Err = model.NewAppError("SqlSessionStore.GetSessions", "We encountered an error while finding user sessions", err.Error())
} else {
result.Data = sessions
@@ -165,7 +165,7 @@ func (me SqlSessionStore) CleanUpExpiredSessions(userId string) StoreChannel {
result := StoreResult{}
if _, err := me.GetMaster().Exec("DELETE FROM Sessions WHERE UserId = :UserId AND ExpiresAt != 0 AND :ExpiresAt > ExpiresAt", map[string]interface{}{"UserId": userId, "ExpiresAt": model.GetMillis()}); err != nil {
- result.Err = model.NewAppError("SqlSessionStore.CleanUpExpiredSessions", "We encounted an error while deleting expired user sessions", err.Error())
+ result.Err = model.NewAppError("SqlSessionStore.CleanUpExpiredSessions", "We encountered an error while deleting expired user sessions", err.Error())
} else {
result.Data = userId
}
diff --git a/store/sql_system_store.go b/store/sql_system_store.go
index a4cb52d4d..1fbdfb333 100644
--- a/store/sql_system_store.go
+++ b/store/sql_system_store.go
@@ -37,7 +37,7 @@ func (s SqlSystemStore) Save(system *model.System) StoreChannel {
result := StoreResult{}
if err := s.GetMaster().Insert(system); err != nil {
- result.Err = model.NewAppError("SqlSystemStore.Save", "We encounted an error saving the system property", "")
+ result.Err = model.NewAppError("SqlSystemStore.Save", "We encountered an error saving the system property", "")
}
storeChannel <- result
@@ -55,7 +55,7 @@ func (s SqlSystemStore) Update(system *model.System) StoreChannel {
result := StoreResult{}
if _, err := s.GetMaster().Update(system); err != nil {
- result.Err = model.NewAppError("SqlSystemStore.Save", "We encounted an error updating the system property", "")
+ result.Err = model.NewAppError("SqlSystemStore.Save", "We encountered an error updating the system property", "")
}
storeChannel <- result
@@ -75,7 +75,7 @@ func (s SqlSystemStore) Get() StoreChannel {
var systems []model.System
props := make(model.StringMap)
if _, err := s.GetReplica().Select(&systems, "SELECT * FROM Systems"); err != nil {
- result.Err = model.NewAppError("SqlSystemStore.Get", "We encounted an error finding the system properties", "")
+ result.Err = model.NewAppError("SqlSystemStore.Get", "We encountered an error finding the system properties", "")
} else {
for _, prop := range systems {
props[prop.Name] = prop.Value
diff --git a/store/sql_team_store.go b/store/sql_team_store.go
index ebf982ec4..dfc07d3d8 100644
--- a/store/sql_team_store.go
+++ b/store/sql_team_store.go
@@ -97,7 +97,7 @@ func (s SqlTeamStore) Update(team *model.Team) StoreChannel {
}
if oldResult, err := s.GetMaster().Get(model.Team{}, team.Id); err != nil {
- result.Err = model.NewAppError("SqlTeamStore.Update", "We encounted an error finding the team", "id="+team.Id+", "+err.Error())
+ result.Err = model.NewAppError("SqlTeamStore.Update", "We encountered an error finding the team", "id="+team.Id+", "+err.Error())
} else if oldResult == nil {
result.Err = model.NewAppError("SqlTeamStore.Update", "We couldn't find the existing team to update", "id="+team.Id)
} else {
@@ -107,7 +107,7 @@ func (s SqlTeamStore) Update(team *model.Team) StoreChannel {
team.Name = oldTeam.Name
if count, err := s.GetMaster().Update(team); err != nil {
- result.Err = model.NewAppError("SqlTeamStore.Update", "We encounted an error updating the team", "id="+team.Id+", "+err.Error())
+ result.Err = model.NewAppError("SqlTeamStore.Update", "We encountered an error updating the team", "id="+team.Id+", "+err.Error())
} else if count != 1 {
result.Err = model.NewAppError("SqlTeamStore.Update", "We couldn't update the team", "id="+team.Id)
} else {
@@ -149,7 +149,7 @@ func (s SqlTeamStore) Get(id string) StoreChannel {
result := StoreResult{}
if obj, err := s.GetReplica().Get(model.Team{}, id); err != nil {
- result.Err = model.NewAppError("SqlTeamStore.Get", "We encounted an error finding the team", "id="+id+", "+err.Error())
+ result.Err = model.NewAppError("SqlTeamStore.Get", "We encountered an error finding the team", "id="+id+", "+err.Error())
} else if obj == nil {
result.Err = model.NewAppError("SqlTeamStore.Get", "We couldn't find the existing team", "id="+id)
} else {
@@ -230,7 +230,7 @@ func (s SqlTeamStore) GetTeamsForEmail(email string) StoreChannel {
var data []*model.Team
if _, err := s.GetReplica().Select(&data, "SELECT Teams.* FROM Teams, Users WHERE Teams.Id = Users.TeamId AND Users.Email = :Email", map[string]interface{}{"Email": email}); err != nil {
- result.Err = model.NewAppError("SqlTeamStore.GetTeamsForEmail", "We encounted a problem when looking up teams", "email="+email+", "+err.Error())
+ result.Err = model.NewAppError("SqlTeamStore.GetTeamsForEmail", "We encountered a problem when looking up teams", "email="+email+", "+err.Error())
}
for _, team := range data {
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index d825cda57..3347df08b 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -118,7 +118,7 @@ func (us SqlUserStore) Update(user *model.User, allowActiveUpdate bool) StoreCha
}
if oldUserResult, err := us.GetMaster().Get(model.User{}, user.Id); err != nil {
- result.Err = model.NewAppError("SqlUserStore.Update", "We encounted an error finding the account", "user_id="+user.Id+", "+err.Error())
+ result.Err = model.NewAppError("SqlUserStore.Update", "We encountered an error finding the account", "user_id="+user.Id+", "+err.Error())
} else if oldUserResult == nil {
result.Err = model.NewAppError("SqlUserStore.Update", "We couldn't find the existing account to update", "user_id="+user.Id)
} else {
@@ -161,7 +161,7 @@ func (us SqlUserStore) Update(user *model.User, allowActiveUpdate bool) StoreCha
} else if IsUniqueConstraintError(err.Error(), "Username", "users_username_teamid_key") {
result.Err = model.NewAppError("SqlUserStore.Update", "This username is already taken. Please choose another.", "user_id="+user.Id+", "+err.Error())
} else {
- result.Err = model.NewAppError("SqlUserStore.Update", "We encounted an error updating the account", "user_id="+user.Id+", "+err.Error())
+ result.Err = model.NewAppError("SqlUserStore.Update", "We encountered an error updating the account", "user_id="+user.Id+", "+err.Error())
}
} else if count != 1 {
result.Err = model.NewAppError("SqlUserStore.Update", "We couldn't update the account", fmt.Sprintf("user_id=%v, count=%v", user.Id, count))
@@ -306,7 +306,7 @@ func (us SqlUserStore) Get(id string) StoreChannel {
result := StoreResult{}
if obj, err := us.GetReplica().Get(model.User{}, id); err != nil {
- result.Err = model.NewAppError("SqlUserStore.Get", "We encounted an error finding the account", "user_id="+id+", "+err.Error())
+ result.Err = model.NewAppError("SqlUserStore.Get", "We encountered an error finding the account", "user_id="+id+", "+err.Error())
} else if obj == nil {
result.Err = model.NewAppError("SqlUserStore.Get", "We couldn't find the existing account", "user_id="+id)
} else {
@@ -351,7 +351,7 @@ func (us SqlUserStore) GetProfiles(teamId string) StoreChannel {
var users []*model.User
if _, err := us.GetReplica().Select(&users, "SELECT * FROM Users WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil {
- result.Err = model.NewAppError("SqlUserStore.GetProfiles", "We encounted an error while finding user profiles", err.Error())
+ result.Err = model.NewAppError("SqlUserStore.GetProfiles", "We encountered an error while finding user profiles", err.Error())
} else {
userMap := make(map[string]*model.User)
@@ -382,7 +382,7 @@ func (us SqlUserStore) GetSystemAdminProfiles() StoreChannel {
var users []*model.User
if _, err := us.GetReplica().Select(&users, "SELECT * FROM Users WHERE Roles = :Roles", map[string]interface{}{"Roles": "system_admin"}); err != nil {
- result.Err = model.NewAppError("SqlUserStore.GetSystemAdminProfiles", "We encounted an error while finding user profiles", err.Error())
+ result.Err = model.NewAppError("SqlUserStore.GetSystemAdminProfiles", "We encountered an error while finding user profiles", err.Error())
} else {
userMap := make(map[string]*model.User)
@@ -498,7 +498,7 @@ func (us SqlUserStore) GetForExport(teamId string) StoreChannel {
var users []*model.User
if _, err := us.GetReplica().Select(&users, "SELECT * FROM Users WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil {
- result.Err = model.NewAppError("SqlUserStore.GetProfiles", "We encounted an error while finding user profiles", err.Error())
+ result.Err = model.NewAppError("SqlUserStore.GetProfiles", "We encountered an error while finding user profiles", err.Error())
} else {
for _, u := range users {
u.Password = ""
diff --git a/web/react/components/post_info.jsx b/web/react/components/post_info.jsx
index 6937ec216..ddda48e06 100644
--- a/web/react/components/post_info.jsx
+++ b/web/react/components/post_info.jsx
@@ -126,7 +126,7 @@ export default class PostInfo extends React.Component {
lastCommentClass = ' comment-icon__container__show';
}
- if (this.props.commentCount >= 1 && post.state !== Constants.POST_FAILED && post.state !== Constants.POST_LOADING) {
+ if (this.props.commentCount >= 1 && post.state !== Constants.POST_FAILED && post.state !== Constants.POST_LOADING && post.state !== Constants.POST_DELETED) {
comments = (
<a
href='#'
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx
index b9741bac4..444736db5 100644
--- a/web/react/components/post_list.jsx
+++ b/web/react/components/post_list.jsx
@@ -556,6 +556,11 @@ export default class PostList extends React.Component {
var post = posts[order[i]];
var parentPost = posts[post.parent_id];
+ // If the post is a comment whose parent has been deleted, don't add it to the list.
+ if (parentPost && parentPost.state === Constants.POST_DELETED) {
+ continue;
+ }
+
var sameUser = false;
var sameRoot = false;
var hideProfilePic = false;
diff --git a/web/react/components/search_bar.jsx b/web/react/components/search_bar.jsx
index 83c10494a..1b81a5ee0 100644
--- a/web/react/components/search_bar.jsx
+++ b/web/react/components/search_bar.jsx
@@ -185,6 +185,7 @@ export default class SearchBar extends React.Component {
className='search__form relative-div'
onSubmit={this.handleSubmit}
style={{overflow: 'visible'}}
+ autoComplete='off'
>
<span className='glyphicon glyphicon-search sidebar__search-icon' />
<input
diff --git a/web/react/components/team_signup_display_name_page.jsx b/web/react/components/team_signup_display_name_page.jsx
index 4d08274e4..2005ecc31 100644
--- a/web/react/components/team_signup_display_name_page.jsx
+++ b/web/react/components/team_signup_display_name_page.jsx
@@ -25,6 +25,9 @@ export default class TeamSignupDisplayNamePage extends React.Component {
if (!displayName) {
this.setState({nameError: 'This field is required'});
return;
+ } else if (displayName.length < 4 || displayName.length > 15) {
+ this.setState({nameError: 'Name must be 4 or more characters up to a maximum of 15'});
+ return;
}
this.props.state.wizard = 'team_url';
diff --git a/web/react/components/team_signup_url_page.jsx b/web/react/components/team_signup_url_page.jsx
index 02d5cab8e..8972fda1a 100644
--- a/web/react/components/team_signup_url_page.jsx
+++ b/web/react/components/team_signup_url_page.jsx
@@ -35,8 +35,8 @@ export default class TeamSignupUrlPage extends React.Component {
if (cleanedName !== name || !urlRegex.test(name)) {
this.setState({nameError: "Use only lower case letters, numbers and dashes. Must start with a letter and can't end in a dash."});
return;
- } else if (cleanedName.length <= 2 || cleanedName.length > 15) {
- this.setState({nameError: 'Name must be 3 or more characters up to a maximum of 15'});
+ } else if (cleanedName.length < 4 || cleanedName.length > 15) {
+ this.setState({nameError: 'Name must be 4 or more characters up to a maximum of 15'});
return;
}
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index c7c8549b9..4bd651649 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -976,7 +976,7 @@ export function isBrowserIE() {
}
export function isBrowserEdge() {
- return window.naviagtor && navigator.userAgent && navigator.userAgent.toLowerCase().indexOf('edge') > -1;
+ return window.navigator && navigator.userAgent && navigator.userAgent.toLowerCase().indexOf('edge') > -1;
}
export function getDirectChannelName(id, otherId) {
diff --git a/web/sass-files/sass/partials/_headers.scss b/web/sass-files/sass/partials/_headers.scss
index 7e776bf76..feb392234 100644
--- a/web/sass-files/sass/partials/_headers.scss
+++ b/web/sass-files/sass/partials/_headers.scss
@@ -1,3 +1,6 @@
+#channel-header {
+ padding: 3px 0;
+}
.row {
&.header {
position: relative;
diff --git a/web/sass-files/sass/partials/_responsive.scss b/web/sass-files/sass/partials/_responsive.scss
index b85fa638a..8f353c401 100644
--- a/web/sass-files/sass/partials/_responsive.scss
+++ b/web/sass-files/sass/partials/_responsive.scss
@@ -763,7 +763,7 @@
.channel__wrap & {
padding-top: 45px;
}
- .channel-header {
+ #channel-header {
display: none;
}
}
diff --git a/web/sass-files/sass/partials/_search.scss b/web/sass-files/sass/partials/_search.scss
index e50dc398a..73b69c866 100644
--- a/web/sass-files/sass/partials/_search.scss
+++ b/web/sass-files/sass/partials/_search.scss
@@ -1,5 +1,8 @@
+#channel-header .search-bar__container {
+ padding: 8px 8px 8px 0;
+}
.search-bar__container {
- padding: 8px 8px 8px 0;
+ padding: 12px 8px 12px 0;
}
.search__clear {
display: none;
diff --git a/web/static/help/about.html b/web/static/help/about.html
index 4659aa9cc..6bdbee27e 100644
--- a/web/static/help/about.html
+++ b/web/static/help/about.html
@@ -5,7 +5,7 @@
</p>
<p>We built Mattermost to help teams focus on what matters most to them. It works for us, we hope it works for you too.
-Learn more, or download the source code from <a href=http://mattermost.com>http://mattermost.com</a>.</p>
+Learn more, or download the source code from <a href=http://mattermost.org>http://mattermost.org</a>.</p>
<h1>Join the community</h1>
<p>To take part in the community building Mattermost, please consider sharing comments, feature requests, votes, and contributions. If you like the project, please Tweet about us at <a href=https://twitter.com/mattermosthq>@mattermosthq</a>.</p>