* Create the system console setting and send to webapp

* MI-1145: Add custom status APIs

* MI-1145 Add slash commands to set and clear status

* Add validation for custom status API

* Trim custom status message

* Code refactoring

- Run gofmt

- Rename constants

* Remove sendUserUpdated webhook event

* Fix recent custom status length

* Update error conditions

* Disable /status slash command when config setting is off

* MI-1155: Create the feature flag for custom status APIs and slash commands

* Move recent custom statuses to user preferences (#7)

* Move recent custom statuses to user preferences

* Code refactoring and feedback changes

* Update slash command text and emoji regex

* Make the custom status feature flag off by default

* Update SetCustomStatus, handle recents not set better

* Update status codes

* Update slash command handling

* Add telementry settings

* Fix i18n order

* Revert "Fix i18n order"

This reverts commit 499f7eaca8180336f5bcca360cc0133365899e08.

* Update i18n strings
Этот коммит содержится в:
Chetanya Kandhari
2021-02-18 16:38:01 +05:30
коммит произвёл GitHub
родитель 22308ea21c
Коммит 7585e16d84
15 изменённых файлов: 509 добавлений и 0 удалений

Просмотреть файл

@@ -1857,6 +1857,7 @@ type TeamSettings struct {
EnableOpenServer *bool `access:"authentication"`
EnableUserDeactivation *bool `access:"experimental"`
RestrictCreationToDomains *string `access:"authentication"` // telemetry: none
EnableCustomUserStatuses *bool `access:"site"`
EnableCustomBrand *bool `access:"site"`
CustomBrandText *string `access:"site"`
CustomDescriptionText *string `access:"site"`
@@ -1910,6 +1911,10 @@ func (s *TeamSettings) SetDefaults() {
s.RestrictCreationToDomains = NewString("")
}
if s.EnableCustomUserStatuses == nil {
s.EnableCustomUserStatuses = NewBool(true)
}
if s.EnableCustomBrand == nil {
s.EnableCustomBrand = NewBool(false)
}

103
model/custom_status.go Обычный файл
Просмотреть файл

@@ -0,0 +1,103 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import (
"encoding/json"
"io"
)
const (
UserPropsKeyCustomStatus = "customStatus"
CustomStatusTextMaxRunes = 100
MaxRecentCustomStatuses = 5
)
type CustomStatus struct {
Emoji string `json:"emoji"`
Text string `json:"text"`
}
func (cs *CustomStatus) TrimMessage() {
runes := []rune(cs.Text)
if len(runes) > CustomStatusTextMaxRunes {
cs.Text = string(runes[:CustomStatusTextMaxRunes])
}
}
func (cs *CustomStatus) ToJson() string {
csCopy := *cs
b, _ := json.Marshal(csCopy)
return string(b)
}
func CustomStatusFromJson(data io.Reader) *CustomStatus {
var cs *CustomStatus
_ = json.NewDecoder(data).Decode(&cs)
return cs
}
type RecentCustomStatuses []CustomStatus
func (rcs *RecentCustomStatuses) Contains(cs *CustomStatus) bool {
var csJSON = cs.ToJson()
// status is empty
if cs == nil || csJSON == "" || (cs.Emoji == "" && cs.Text == "") {
return false
}
for _, status := range *rcs {
if status.ToJson() == csJSON {
return true
}
}
return false
}
func (rcs *RecentCustomStatuses) Add(cs *CustomStatus) *RecentCustomStatuses {
newRCS := (*rcs)[:0]
// if same `text` exists in existing recent custom statuses, modify existing status
for _, status := range *rcs {
if status.Text != cs.Text {
newRCS = append(newRCS, status)
}
}
newRCS = append(RecentCustomStatuses{*cs}, newRCS...)
if len(newRCS) > MaxRecentCustomStatuses {
newRCS = newRCS[:MaxRecentCustomStatuses]
}
return &newRCS
}
func (rcs *RecentCustomStatuses) Remove(cs *CustomStatus) *RecentCustomStatuses {
var csJSON = cs.ToJson()
if csJSON == "" || (cs.Emoji == "" && cs.Text == "") {
return rcs
}
newRCS := (*rcs)[:0]
for _, status := range *rcs {
if status.ToJson() != csJSON {
newRCS = append(newRCS, status)
}
}
return &newRCS
}
func (rcs *RecentCustomStatuses) ToJson() string {
rcsCopy := *rcs
b, _ := json.Marshal(rcsCopy)
return string(b)
}
func RecentCustomStatusesFromJson(data io.Reader) *RecentCustomStatuses {
var rcs *RecentCustomStatuses
_ = json.NewDecoder(data).Decode(&rcs)
return rcs
}

Просмотреть файл

@@ -17,6 +17,12 @@ const (
var EMOJI_PATTERN = regexp.MustCompile(`:[a-zA-Z0-9_-]+:`)
// ALL_EMOJI_PATTERN is same as the EMOJI_PATTERN except for allowing a '+' character.
// This is to allow the system emoji :+1: to be matched.
// We kept a separate variable to avoid renaming help texts for custom emoji's.
// TODO: Merge ALL_EMOJI_PATTERN with EMOJI_PATTERN after updating custom emoji help texts
var ALL_EMOJI_PATTERN = regexp.MustCompile(`:[a-zA-Z0-9_+-]+:`)
type Emoji struct {
Id string `json:"id"`
CreateAt int64 `json:"create_at"`

Просмотреть файл

@@ -18,6 +18,10 @@ type FeatureFlags struct {
// Toggle on and off support for Collapsed Threads
CollapsedThreads bool
// Toggle on and off support for Custom User Statuses
CustomUserStatuses bool
// Feature flags to control plugin versions
PluginIncidentManagement string `plugin_id:"com.mattermost.plugin-incident-management"`
}
@@ -27,6 +31,7 @@ func (f *FeatureFlags) SetDefaults() {
f.TestBoolFeature = false
f.CloudDelinquentEmailJobsEnabled = false
f.CollapsedThreads = false
f.CustomUserStatuses = false
f.PluginIncidentManagement = "1.4.0"
}

Просмотреть файл

@@ -40,6 +40,12 @@ const (
PREFERENCE_NAME_LAST_CHANNEL = "channel"
PREFERENCE_NAME_LAST_TEAM = "team"
PREFERENCE_CATEGORY_CUSTOM_STATUS = "custom_status"
PREFERENCE_NAME_RECENT_CUSTOM_STATUSES = "recent_custom_statuses"
PREFERENCE_NAME_CUSTOM_STATUS_TUTORIAL_STATE = "custom_status_tutorial_state"
PREFERENCE_CUSTOM_STATUS_MODAL_VIEWED = "custom_status_modal_viewed"
PREFERENCE_CATEGORY_NOTIFICATIONS = "notifications"
PREFERENCE_NAME_EMAIL_INTERVAL = "email_interval"

Просмотреть файл

@@ -596,6 +596,16 @@ func (u *User) AddNotifyProp(key string, value string) {
u.NotifyProps[key] = value
}
func (u *User) SetCustomStatus(cs *CustomStatus) {
u.MakeNonNil()
u.Props[UserPropsKeyCustomStatus] = cs.ToJson()
}
func (u *User) ClearCustomStatus() {
u.MakeNonNil()
u.Props[UserPropsKeyCustomStatus] = ""
}
func (u *User) GetFullName() string {
if u.FirstName != "" && u.LastName != "" {
return u.FirstName + " " + u.LastName