diff --git a/api/user.go b/api/user.go index 0a54b6a5d1..2740696e1d 100644 --- a/api/user.go +++ b/api/user.go @@ -177,9 +177,6 @@ func CreateUser(c *Context, team *model.Team, user *model.User) *model.User { } user.MakeNonNil() - if len(user.Props["theme"]) == 0 { - user.AddProp("theme", utils.Cfg.TeamSettings.DefaultThemeColor) - } if result := <-Srv.Store.User().Save(user); result.Err != nil { c.Err = result.Err diff --git a/model/user.go b/model/user.go index fdc519b990..3a2c9d56cf 100644 --- a/model/user.go +++ b/model/user.go @@ -47,6 +47,7 @@ type User struct { 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"` @@ -108,6 +109,10 @@ func (u *User) IsValid() *AppError { return NewAppError("User.IsValid", "Invalid user, password and auth data cannot both be set", "user_id="+u.Id) } + if len(u.ThemeProps) > 2000 { + return NewAppError("User.IsValid", "Invalid theme", "user_id="+u.Id) + } + return nil } diff --git a/store/sql_user_store.go b/store/sql_user_store.go index 778df367e1..3fd1c82b51 100644 --- a/store/sql_user_store.go +++ b/store/sql_user_store.go @@ -32,6 +32,7 @@ func NewSqlUserStore(sqlStore *SqlStore) UserStore { table.ColMap("Roles").SetMaxSize(64) table.ColMap("Props").SetMaxSize(4000) table.ColMap("NotifyProps").SetMaxSize(2000) + table.ColMap("ThemeProps").SetMaxSize(2000) table.SetUniqueTogether("Email", "TeamId") table.SetUniqueTogether("Username", "TeamId") } @@ -40,6 +41,7 @@ func NewSqlUserStore(sqlStore *SqlStore) UserStore { } func (us SqlUserStore) UpgradeSchemaIfNeeded() { + us.CreateColumnIfNotExists("Users", "ThemeProps", "varchar(2000)", "character varying(2000)", "{}") } func (us SqlUserStore) CreateIndexesIfNotExists() { diff --git a/web/react/components/channel_loader.jsx b/web/react/components/channel_loader.jsx index 20ea34e153..962ba26ee7 100644 --- a/web/react/components/channel_loader.jsx +++ b/web/react/components/channel_loader.jsx @@ -12,6 +12,7 @@ var PostStore = require('../stores/post_store.jsx'); var UserStore = require('../stores/user_store.jsx'); var Utils = require('../utils/utils.jsx'); +var Constants = require('../utils/constants.jsx'); export default class ChannelLoader extends React.Component { constructor(props) { @@ -68,25 +69,10 @@ export default class ChannelLoader extends React.Component { /* Update CSS classes to match user theme */ var user = UserStore.getCurrentUser(); - if (user.props && user.props.theme) { - Utils.changeCss('div.theme', 'background-color:' + user.props.theme + ';'); - Utils.changeCss('.btn.btn-primary', 'background: ' + user.props.theme + ';'); - Utils.changeCss('.modal .modal-header', 'background: ' + user.props.theme + ';'); - Utils.changeCss('.mention', 'background: ' + user.props.theme + ';'); - Utils.changeCss('.mention-link', 'color: ' + user.props.theme + ';'); - Utils.changeCss('@media(max-width: 768px){.search-bar__container', 'background: ' + user.props.theme + ';}'); - Utils.changeCss('.search-item-container:hover', 'background: ' + Utils.changeOpacity(user.props.theme, 0.05) + ';'); - } - - if (user.props.theme !== '#000000' && user.props.theme !== '#585858') { - Utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + Utils.changeColor(user.props.theme, -10) + ';'); - Utils.changeCss('a.theme', 'color:' + user.props.theme + '; fill:' + user.props.theme + '!important;'); - } else if (user.props.theme === '#000000') { - Utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + Utils.changeColor(user.props.theme, +50) + ';'); - $('.team__header').addClass('theme--black'); - } else if (user.props.theme === '#585858') { - Utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + Utils.changeColor(user.props.theme, +10) + ';'); - $('.team__header').addClass('theme--gray'); + if ($.isPlainObject(user.theme_props) && !$.isEmptyObject(user.theme_props)) { + Utils.applyTheme(user.theme_props); + } else { + Utils.applyTheme(Constants.THEMES.default); } /* Setup global mouse events */ diff --git a/web/react/components/popover_list_members.jsx b/web/react/components/popover_list_members.jsx index ec873dd00f..a2ca8b00ff 100644 --- a/web/react/components/popover_list_members.jsx +++ b/web/react/components/popover_list_members.jsx @@ -65,7 +65,7 @@ export default class PopoverListMembers extends React.Component { > {count}