diff options
-rw-r--r-- | api/admin.go | 2 | ||||
-rw-r--r-- | api/api_test.go | 1 | ||||
-rw-r--r-- | api/context.go | 3 | ||||
-rw-r--r-- | api/post.go | 22 | ||||
-rw-r--r-- | api/templates/password_change_body.html | 2 | ||||
-rw-r--r-- | api/templates/password_change_subject.html | 2 | ||||
-rw-r--r-- | doc/developer/tests/test-links.md | 1 | ||||
-rw-r--r-- | doc/help/Markdown.md | 2 | ||||
-rw-r--r-- | i18n/en.json | 4 | ||||
-rw-r--r-- | i18n/es.json | 10 | ||||
-rw-r--r-- | model/utils.go | 40 | ||||
-rw-r--r-- | web/react/components/rhs_thread.jsx | 12 | ||||
-rw-r--r-- | web/react/utils/utils.jsx | 4 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_post.scss | 1 |
14 files changed, 87 insertions, 19 deletions
diff --git a/api/admin.go b/api/admin.go index 61741b445..72a95ba6a 100644 --- a/api/admin.go +++ b/api/admin.go @@ -41,7 +41,7 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) { file, err := os.Open(utils.GetLogFileLocation(utils.Cfg.LogSettings.FileLocation)) if err != nil { - c.Err = model.NewAppError("getLogs", c.T("api.admin.file_read_error"), err.Error()) + c.Err = model.NewLocAppError("getLogs", "api.admin.file_read_error", nil, err.Error()) } defer file.Close() diff --git a/api/api_test.go b/api/api_test.go index 2ef4e196d..4d7192e4b 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -14,6 +14,7 @@ var Client *model.Client func Setup() { if Srv == nil { utils.LoadConfig("config.json") + utils.InitTranslations() utils.Cfg.TeamSettings.MaxUsersPerTeam = 50 NewServer() StartServer() diff --git a/api/context.go b/api/context.go index b6ffb1a29..a3311a971 100644 --- a/api/context.go +++ b/api/context.go @@ -206,6 +206,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } if c.Err != nil { + c.Err.Translate(c.T) c.Err.RequestId = c.RequestId c.LogError(c.Err) c.Err.Where = r.URL.Path @@ -373,7 +374,7 @@ func (c *Context) RemoveSessionCookie(w http.ResponseWriter, r *http.Request) { } func (c *Context) SetInvalidParam(where string, name string) { - c.Err = model.NewAppError(where, "Invalid "+name+" parameter", "") + c.Err = model.NewLocAppError(where, "api.context.invalid_param", map[string]interface{}{"Name": name}, "") c.Err.StatusCode = http.StatusBadRequest } diff --git a/api/post.go b/api/post.go index 7cd45d310..42c3c304d 100644 --- a/api/post.go +++ b/api/post.go @@ -185,6 +185,28 @@ func CreateWebhookPost(c *Context, channelId, text, overrideUsername, overrideIc attachment["text"] = aText list[i] = attachment } + if _, ok := attachment["pretext"]; ok { + aText := attachment["pretext"].(string) + aText = linkWithTextRegex.ReplaceAllString(aText, "[${2}](${1})") + attachment["pretext"] = aText + list[i] = attachment + } + if fVal, ok := attachment["fields"]; ok { + if fields, ok := fVal.([]interface{}); ok { + // parse attachment field links into Markdown format + for j, fInt := range fields { + field := fInt.(map[string]interface{}) + if _, ok := field["text"]; ok { + fText := field["text"].(string) + fText = linkWithTextRegex.ReplaceAllString(fText, "[${2}](${1})") + field["text"] = fText + fields[j] = field + } + } + attachment["fields"] = fields + list[i] = attachment + } + } } post.AddProp(key, list) } diff --git a/api/templates/password_change_body.html b/api/templates/password_change_body.html index 82f4d5429..6199a3423 100644 --- a/api/templates/password_change_body.html +++ b/api/templates/password_change_body.html @@ -18,7 +18,7 @@ <tr> <td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;"> <h2 style="font-weight: normal; margin-top: 10px;">You updated your password</h2> - <p>You updated your password for {{.Props.TeamDisplayName}} on {{ .Props.TeamURL }} by {{.Props.Method}}.<br>If this change wasn't initiated by you, please contact your system administrator.</p> + <p>Your password has been updated for {{.Props.TeamDisplayName}} on {{ .Props.TeamURL }} by {{.Props.Method}}.<br>If this change wasn't initiated by you, please contact your system administrator.</p> </td> </tr> <tr> diff --git a/api/templates/password_change_subject.html b/api/templates/password_change_subject.html index e7a794090..0cbf052c1 100644 --- a/api/templates/password_change_subject.html +++ b/api/templates/password_change_subject.html @@ -1 +1 @@ -{{define "password_change_subject"}}You updated your password for {{.Props.TeamDisplayName}} on {{ .ClientCfg.SiteName }}{{end}} +{{define "password_change_subject"}}Your password has been updated for {{.Props.TeamDisplayName}} on {{ .ClientCfg.SiteName }}{{end}} diff --git a/doc/developer/tests/test-links.md b/doc/developer/tests/test-links.md index 91e3e9403..b4a04e439 100644 --- a/doc/developer/tests/test-links.md +++ b/doc/developer/tests/test-links.md @@ -40,7 +40,6 @@ http:// ./make-compiled-client.sh test.:test https://<your-mattermost-url>/signup/gitlab -https://your-mattermost-url>/signup/gitlab #### Only the links within these sentences should auto-link: diff --git a/doc/help/Markdown.md b/doc/help/Markdown.md index d185a4160..9d3cb2a90 100644 --- a/doc/help/Markdown.md +++ b/doc/help/Markdown.md @@ -88,7 +88,7 @@ and ## Emojis -Emoji provided free by [Emoji One](http://emojione.com/). Check out a full list of emojis [here](http://http://emoji.codes/). +Emoji provided free by [Emoji One](http://emojione.com/). Check out a full list of emojis [here](http://emoji.codes/). ``` :smile: :+1: :sheep: diff --git a/i18n/en.json b/i18n/en.json index 67cf9c31e..d1035e89a 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -10,5 +10,9 @@ { "id": "api.admin.file_read_error", "translation": "Error reading log file" + }, + { + "id": "api.context.invalid_param", + "translation": "Invalid {{.Name}} parameter" } ]
\ No newline at end of file diff --git a/i18n/es.json b/i18n/es.json index 67cf9c31e..efa5b857b 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -1,14 +1,18 @@ [ { "id": "utils.i18n.loaded", - "translation": "Loaded system translations for '%v' from '%v'" + "translation": "Loaded system translations for '%v' from '%v' spanish test!" }, { "id": "mattermost.current_version", - "translation": "Current version is %v (%v/%v/%v)" + "translation": "Current version is %v (%v/%v/%v) spanish test!" }, { "id": "api.admin.file_read_error", - "translation": "Error reading log file" + "translation": "Error reading log file spanish test!" + }, + { + "id": "api.context.invalid_param", + "translation": "Invalid {{.Name}} parameter spanish test!" } ]
\ No newline at end of file diff --git a/model/utils.go b/model/utils.go index 617c95efd..a18ca760e 100644 --- a/model/utils.go +++ b/model/utils.go @@ -9,13 +9,15 @@ import ( "encoding/base32" "encoding/json" "fmt" - "github.com/pborman/uuid" "io" "net/mail" "net/url" "regexp" "strings" "time" + + goi18n "github.com/nicksnyder/go-i18n/i18n" + "github.com/pborman/uuid" ) type StringInterface map[string]interface{} @@ -23,20 +25,31 @@ type StringMap map[string]string type StringArray []string type EncryptStringMap map[string]string -// AppError is returned for any http response that's not in the 200 range. type AppError struct { - Message string `json:"message"` // Message to be display to the end user without debugging information - DetailedError string `json:"detailed_error"` // Internal error string to help the developer - RequestId string `json:"request_id"` // The RequestId that's also set in the header - StatusCode int `json:"status_code"` // The http status code - Where string `json:"-"` // The function where it happened in the form of Struct.Func - IsOAuth bool `json:"is_oauth"` // Whether the error is OAuth specific + Id string `json:"id"` + Message string `json:"message"` // Message to be display to the end user without debugging information + DetailedError string `json:"detailed_error"` // Internal error string to help the developer + RequestId string `json:"request_id"` // The RequestId that's also set in the header + StatusCode int `json:"status_code"` // The http status code + Where string `json:"-"` // The function where it happened in the form of Struct.Func + IsOAuth bool `json:"is_oauth"` // Whether the error is OAuth specific + params map[string]interface{} `json:"-"` } func (er *AppError) Error() string { return er.Where + ": " + er.Message + ", " + er.DetailedError } +func (er *AppError) Translate(T goi18n.TranslateFunc) { + if len(er.Message) == 0 { + if er.params == nil { + er.Message = T(er.Id) + } else { + er.Message = T(er.Id, er.params) + } + } +} + func (er *AppError) ToJson() string { b, err := json.Marshal(er) if err != nil { @@ -68,6 +81,17 @@ func NewAppError(where string, message string, details string) *AppError { return ap } +func NewLocAppError(where string, id string, params map[string]interface{}, details string) *AppError { + ap := &AppError{} + ap.Id = id + ap.params = params + ap.Where = where + ap.DetailedError = details + ap.StatusCode = 500 + ap.IsOAuth = false + return ap +} + var encoding = base32.NewEncoding("ybndrfg8ejkmcpqxot1uwisza345h769") // NewId is a globally unique identifier. It is a [A-Z0-9] string 26 diff --git a/web/react/components/rhs_thread.jsx b/web/react/components/rhs_thread.jsx index 2edcd8b37..945b09e37 100644 --- a/web/react/components/rhs_thread.jsx +++ b/web/react/components/rhs_thread.jsx @@ -17,6 +17,8 @@ export default class RhsThread extends React.Component { constructor(props) { super(props); + this.mounted = false; + this.onChange = this.onChange.bind(this); this.onChangeAll = this.onChangeAll.bind(this); this.forceUpdateInfo = this.forceUpdateInfo.bind(this); @@ -50,8 +52,11 @@ export default class RhsThread extends React.Component { PostStore.addSelectedPostChangeListener(this.onChange); PostStore.addChangeListener(this.onChangeAll); PreferenceStore.addChangeListener(this.forceUpdateInfo); + this.resize(); window.addEventListener('resize', this.handleResize); + + this.mounted = true; } componentDidUpdate() { if ($('.post-right__scroll')[0]) { @@ -63,7 +68,10 @@ export default class RhsThread extends React.Component { PostStore.removeSelectedPostChangeListener(this.onChange); PostStore.removeChangeListener(this.onChangeAll); PreferenceStore.removeChangeListener(this.forceUpdateInfo); + window.removeEventListener('resize', this.handleResize); + + this.mounted = false; } forceUpdateInfo() { if (this.state.postList) { @@ -82,7 +90,7 @@ export default class RhsThread extends React.Component { } onChange() { var newState = this.getStateFromStores(); - if (!Utils.areObjectsEqual(newState, this.state)) { + if (this.mounted && !Utils.areObjectsEqual(newState, this.state)) { this.setState(newState); } } @@ -120,7 +128,7 @@ export default class RhsThread extends React.Component { } var newState = this.getStateFromStores(); - if (!Utils.areObjectsEqual(newState, this.state)) { + if (this.mounted && !Utils.areObjectsEqual(newState, this.state)) { this.setState(newState); } } diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 24042321f..db469952b 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -1309,6 +1309,10 @@ export function fillArray(value, length) { // Checks if a data transfer contains files not text, folders, etc.. // Slightly modified from http://stackoverflow.com/questions/6848043/how-do-i-detect-a-file-is-being-dragged-rather-than-a-draggable-element-on-my-pa export function isFileTransfer(files) { + if (isBrowserIE()) { + return files.types != null && files.types.contains('Files'); + } + return files.types != null && (files.types.indexOf ? files.types.indexOf('Files') !== -1 : files.types.contains('application/x-moz-file')); } diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss index 7b7c2d73a..c5cd10b20 100644 --- a/web/sass-files/sass/partials/_post.scss +++ b/web/sass-files/sass/partials/_post.scss @@ -183,6 +183,7 @@ body.ios { position: absolute; top: 50%; left: 50%; + pointer-events: none; } .overlay__files { |