From c84baf230ccb6f95fcf43798a3eb837c625639db Mon Sep 17 00:00:00 2001 From: nickago Date: Thu, 9 Jul 2015 08:34:36 -0700 Subject: Updated database schema for full utf8 compatibility --- store/sql_post_store.go | 5 +++++ store/sql_store.go | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/store/sql_post_store.go b/store/sql_post_store.go index 7ada515d7..5b9ebfdf2 100644 --- a/store/sql_post_store.go +++ b/store/sql_post_store.go @@ -35,6 +35,11 @@ func NewSqlPostStore(sqlStore *SqlStore) PostStore { } func (s SqlPostStore) UpgradeSchemaIfNeeded() { + + // These execs are for upgrading currently created databases to full utf8mb4 compliance + // Will be removed as seen fit for upgrading + s.GetMaster().Exec("ALTER TABLE Posts charset=utf8mb4") + s.GetMaster().Exec("ALTER TABLE Posts MODIFY COLUMN Message varchar(4000) CHARACTER SET utf8mb4") } func (s SqlPostStore) CreateIndexesIfNotExists() { diff --git a/store/sql_store.go b/store/sql_store.go index a0a1a9f23..7a2d059b9 100644 --- a/store/sql_store.go +++ b/store/sql_store.go @@ -24,6 +24,7 @@ import ( sqltrace "log" "math/rand" "os" + "strings" "time" ) @@ -81,7 +82,14 @@ func NewSqlStore() Store { func setupConnection(con_type string, driver string, dataSource string, maxIdle int, maxOpen int, trace bool) *gorp.DbMap { - db, err := dbsql.Open(driver, dataSource) + charset := "" + if strings.Index(dataSource, "?") > -1 { + charset = "&charset=utf8mb4,utf8" + } else { + charset = "?charset=utf8mb4,utf8" + } + + db, err := dbsql.Open(driver, dataSource+charset) if err != nil { l4g.Critical("Failed to open sql connection to '%v' err:%v", dataSource, err) time.Sleep(time.Second) @@ -104,7 +112,7 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle if driver == "sqlite3" { dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.SqliteDialect{}} } else if driver == "mysql" { - dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8"}} + dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8MB4"}} } else { l4g.Critical("Failed to create dialect specific driver") time.Sleep(time.Second) -- cgit v1.2.3-1-g7c22 From 6a559febc292c272da24df440d80ae3b26a31d7f Mon Sep 17 00:00:00 2001 From: ralder Date: Thu, 9 Jul 2015 03:32:03 -0700 Subject: fix BrowserStore bug in actionOnItemsWithPrefix and refactor BrowserStore --- web/react/components/delete_post_modal.jsx | 4 +- web/react/components/edit_post_modal.jsx | 7 +- web/react/components/signup_team_complete.jsx | 11 +- web/react/components/signup_user_complete.jsx | 13 +-- web/react/stores/browser_store.jsx | 153 +++++++++++++++----------- web/react/stores/channel_store.jsx | 64 ++--------- web/react/stores/error_store.jsx | 11 +- web/react/stores/post_store.jsx | 59 +++------- web/react/stores/socket_store.jsx | 2 - web/react/stores/team_store.jsx | 16 +-- web/react/stores/user_store.jsx | 120 ++++---------------- 11 files changed, 150 insertions(+), 310 deletions(-) diff --git a/web/react/components/delete_post_modal.jsx b/web/react/components/delete_post_modal.jsx index fefac12d7..11970bc2b 100644 --- a/web/react/components/delete_post_modal.jsx +++ b/web/react/components/delete_post_modal.jsx @@ -56,13 +56,13 @@ module.exports = React.createClass({ $(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) { var newState = {}; if(BrowserStore.getItem('edit_state_transfer')) { - newState = JSON.parse(BrowserStore.getItem('edit_state_transfer')); + newState = BrowserStore.getItem('edit_state_transfer'); BrowserStore.removeItem('edit_state_transfer'); } else { var button = e.relatedTarget; newState = { title: $(button).attr('data-title'), channel_id: $(button).attr('data-channelid'), post_id: $(button).attr('data-postid'), comments: $(button).attr('data-comments') }; } - self.setState(newState) + self.setState(newState); }); PostStore.addSelectedPostChangeListener(this._onChange); }, diff --git a/web/react/components/edit_post_modal.jsx b/web/react/components/edit_post_modal.jsx index d741e189b..21b75bb6e 100644 --- a/web/react/components/edit_post_modal.jsx +++ b/web/react/components/edit_post_modal.jsx @@ -4,6 +4,7 @@ var Client = require('../utils/client.jsx'); var AsyncClient = require('../utils/async_client.jsx'); var Textbox = require('./textbox.jsx'); +var BrowserStore = require('../stores/browser_store.jsx'); module.exports = React.createClass({ handleEdit: function(e) { @@ -13,14 +14,14 @@ module.exports = React.createClass({ if (updatedPost.message.length === 0) { var tempState = this.state; delete tempState.editText; - BrowserStore.setItem('edit_state_transfer', JSON.stringify(tempState)); + BrowserStore.setItem('edit_state_transfer', tempState); $("#edit_post").modal('hide'); $("#delete_post").modal('show'); return; } - updatedPost.id = this.state.post_id - updatedPost.channel_id = this.state.channel_id + updatedPost.id = this.state.post_id; + updatedPost.channel_id = this.state.channel_id; Client.updatePost(updatedPost, function(data) { diff --git a/web/react/components/signup_team_complete.jsx b/web/react/components/signup_team_complete.jsx index 500ee231e..9e2a13955 100644 --- a/web/react/components/signup_team_complete.jsx +++ b/web/react/components/signup_team_complete.jsx @@ -596,19 +596,14 @@ PasswordPage = React.createClass({ module.exports = React.createClass({ updateParent: function(state, skipSet) { - BrowserStore.setGlobalItem(this.props.hash, JSON.stringify(state)); + BrowserStore.setGlobalItem(this.props.hash, state); if (!skipSet) { this.setState(state); } }, getInitialState: function() { - var props = null; - try { - props = JSON.parse(BrowserStore.getGlobalItem(this.props.hash)); - } - catch(parse_error) { - } + var props = BrowserStore.getGlobalItem(this.props.hash); if (!props) { props = {}; @@ -628,7 +623,7 @@ module.exports = React.createClass({ props.data = this.props.data; } - return props ; + return props; }, render: function() { if (this.state.wizard == "welcome") { diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx index fb96cc99f..fa0c26017 100644 --- a/web/react/components/signup_user_complete.jsx +++ b/web/react/components/signup_user_complete.jsx @@ -17,7 +17,7 @@ module.exports = React.createClass({ return; } - var username_error = utils.isValidUsername(this.state.user.username) + var username_error = utils.isValidUsername(this.state.user.username); if (username_error === "Cannot use a reserved word as a username.") { this.setState({name_error: "This username is reserved, please choose a new one.", email_error: "", password_error: "", server_error: ""}); return; @@ -53,7 +53,7 @@ module.exports = React.createClass({ UserStore.setLastEmail(this.state.user.email); UserStore.setCurrentUser(data); if (this.props.hash > 0) - BrowserStore.setGlobalItem(this.props.hash, JSON.stringify({wizard: "finished"})); + BrowserStore.setGlobalItem(this.props.hash, {wizard: "finished"}); window.location.href = '/channels/town-square'; }.bind(this), function(err) { @@ -73,12 +73,7 @@ module.exports = React.createClass({ ); }, getInitialState: function() { - var props = null; - try { - props = JSON.parse(BrowserStore.getGlobalItem(this.props.hash)); - } - catch(parse_error) { - } + var props = BrowserStore.getGlobalItem(this.props.hash); if (!props) { props = {}; @@ -91,7 +86,7 @@ module.exports = React.createClass({ props.original_email = this.props.email; } - return props ; + return props; }, render: function() { diff --git a/web/react/stores/browser_store.jsx b/web/react/stores/browser_store.jsx index 82cf9a942..4d6eb0b8d 100644 --- a/web/react/stores/browser_store.jsx +++ b/web/react/stores/browser_store.jsx @@ -1,85 +1,104 @@ // Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. -var UserStore = require('../stores/user_store.jsx'); -// Also change model/utils.go ETAG_ROOT_VERSION -var BROWSER_STORE_VERSION = '.1'; - -var _initialized = false; - -function _initialize() { - var currentVersion = localStorage.getItem("local_storage_version"); - if (currentVersion !== BROWSER_STORE_VERSION) { - localStorage.clear(); - sessionStorage.clear(); - localStorage.setItem("local_storage_version", BROWSER_STORE_VERSION); - } - _initialized = true; +var UserStore; +function getPrefix() { + if (!UserStore) UserStore = require('./user_store.jsx'); + return UserStore.getCurrentId() + '_'; } -module.exports.setItem = function(name, value) { - if (!_initialized) _initialize(); - var user_id = UserStore.getCurrentId(); - localStorage.setItem(user_id + "_" + name, value); -}; +// Also change model/utils.go ETAG_ROOT_VERSION +var BROWSER_STORE_VERSION = '.3'; -module.exports.getItem = function(name) { - if (!_initialized) _initialize(); - var user_id = UserStore.getCurrentId(); - return localStorage.getItem(user_id + "_" + name); -}; +module.exports = { + _initialized: false, -module.exports.removeItem = function(name) { - if (!_initialized) _initialize(); - var user_id = UserStore.getCurrentId(); - localStorage.removeItem(user_id + "_" + name); -}; + _initialize: function() { + var currentVersion = localStorage.getItem("local_storage_version"); + if (currentVersion !== BROWSER_STORE_VERSION) { + this.clear(); + localStorage.setItem("local_storage_version", BROWSER_STORE_VERSION); + } + this._initialized = true; + }, -module.exports.setGlobalItem = function(name, value) { - if (!_initialized) _initialize(); - localStorage.setItem(name, value); -}; + getItem: function(name, defaultValue) { + return this.getGlobalItem(getPrefix() + name, defaultValue); + }, -module.exports.getGlobalItem = function(name) { - if (!_initialized) _initialize(); - return localStorage.getItem(name); -}; + setItem: function(name, value) { + this.setGlobalItem(getPrefix() + name, value); + }, -module.exports.removeGlobalItem = function(name) { - if (!_initialized) _initialize(); - localStorage.removeItem(name); -}; + removeItem: function(name) { + if (!this._initialized) this._initialize(); -module.exports.clear = function() { - localStorage.clear(); - sessionStorage.clear(); -}; + localStorage.removeItem(getPrefix() + name); + }, + + setGlobalItem: function(name, value) { + if (!this._initialized) this._initialize(); + + localStorage.setItem(name, JSON.stringify(value)); + }, + + getGlobalItem: function(name, defaultValue) { + if (!this._initialized) this._initialize(); -// Preforms the given action on each item that has the given prefix -// Signiture for action is action(key, value) -module.exports.actionOnItemsWithPrefix = function (prefix, action) { - var user_id = UserStore.getCurrentId(); - var id_len = user_id.length; - var prefix_len = prefix.length; - for (var key in localStorage) { - if (key.substring(id_len, id_len + prefix_len) === prefix) { - var userkey = key.substring(id_len); - action(userkey, BrowserStore.getItem(key)); + var result = null; + try { + result = JSON.parse(localStorage.getItem(name)); + } catch (err) {} + + if (result === null && typeof defaultValue !== 'undefined') { + result = defaultValue; } - } -}; -module.exports.isLocalStorageSupported = function() { - try { - sessionStorage.setItem("testSession", '1'); - sessionStorage.removeItem("testSession"); + return result; + }, - localStorage.setItem("testLocal", '1'); - localStorage.removeItem("testLocal", '1'); + removeGlobalItem: function(name) { + if (!this._initialized) this._initialize(); - return true; - } - catch (e) { - return false; + localStorage.removeItem(name); + }, + + clear: function() { + localStorage.clear(); + sessionStorage.clear(); + }, + + /** + * Preforms the given action on each item that has the given prefix + * Signiture for action is action(key, value) + */ + actionOnItemsWithPrefix: function (prefix, action) { + if (!this._initialized) this._initialize(); + + var globalPrefix = getPrefix(); + var globalPrefixiLen = globalPrefix.length; + for (var key in localStorage) { + if (key.lastIndexOf(globalPrefix + prefix, 0) === 0) { + var userkey = key.substring(globalPrefixiLen); + action(userkey, this.getGlobalItem(key)); + } + } + }, + + isLocalStorageSupported: function() { + try { + sessionStorage.setItem("testSession", '1'); + sessionStorage.removeItem("testSession"); + + localStorage.setItem("testLocal", '1'); + if (localStorage.getItem("testLocal") != '1') { + return false; + } + localStorage.removeItem("testLocal", '1'); + + return true; + } catch (e) { + return false; + } } }; diff --git a/web/react/stores/channel_store.jsx b/web/react/stores/channel_store.jsx index 4429a5312..4a27e5f17 100644 --- a/web/react/stores/channel_store.jsx +++ b/web/react/stores/channel_store.jsx @@ -16,6 +16,7 @@ var MORE_CHANGE_EVENT = 'change'; var EXTRA_INFO_EVENT = 'extra_info'; var ChannelStore = assign({}, EventEmitter.prototype, { + _current_id: null, emitChange: function() { this.emit(CHANGE_EVENT); }, @@ -88,10 +89,7 @@ var ChannelStore = assign({}, EventEmitter.prototype, { return this._getMoreChannels(); }, setCurrentId: function(id) { - if (id == null) - BrowserStore.removeItem("current_channel_id"); - else - BrowserStore.setItem("current_channel_id", id); + this._current_id = id; }, setLastVisitedName: function(name) { if (name == null) @@ -117,10 +115,10 @@ var ChannelStore = assign({}, EventEmitter.prototype, { this._storeChannelMembers(cm); }, getCurrentId: function() { - return BrowserStore.getItem("current_channel_id"); + return this._current_id; }, getCurrent: function() { - var currentId = ChannelStore.getCurrentId(); + var currentId = this.getCurrentId(); if (currentId != null) return this.get(currentId); @@ -165,49 +163,22 @@ var ChannelStore = assign({}, EventEmitter.prototype, { return extra; }, _storeChannels: function(channels) { - BrowserStore.setItem("channels", JSON.stringify(channels)); + BrowserStore.setItem("channels", channels); }, _getChannels: function() { - var channels = []; - try { - channels = JSON.parse(BrowserStore.getItem("channels")); - } - catch (err) { - } - - if (channels == null) { - channels = []; - } - - return channels; + return BrowserStore.getItem("channels", []); }, _storeChannelMembers: function(channelMembers) { - BrowserStore.setItem("channel_members", JSON.stringify(channelMembers)); + BrowserStore.setItem("channel_members", channelMembers); }, _getChannelMembers: function() { - var members = {}; - try { - members = JSON.parse(BrowserStore.getItem("channel_members")); - } - catch (err) { - } - - if (members == null) { - members = {}; - } - - return members; + return BrowserStore.getItem("channel_members", {}); }, _storeMoreChannels: function(channels) { - BrowserStore.setItem("more_channels", JSON.stringify(channels)); + BrowserStore.setItem("more_channels", channels); }, _getMoreChannels: function() { - var channels = null; - try { - channels = JSON.parse(BrowserStore.getItem("more_channels")); - } - catch (err) { - } + var channels = BrowserStore.getItem("more_channels"); if (channels == null) { channels = {}; @@ -217,21 +188,10 @@ var ChannelStore = assign({}, EventEmitter.prototype, { return channels; }, _storeExtraInfos: function(extraInfos) { - BrowserStore.setItem("extra_infos", JSON.stringify(extraInfos)); + BrowserStore.setItem("extra_infos", extraInfos); }, _getExtraInfos: function() { - var members = {}; - try { - members = JSON.parse(BrowserStore.getItem("extra_infos")); - } - catch (err) { - } - - if (members == null) { - members = {}; - } - - return members; + return BrowserStore.getItem("extra_infos", {}); } }); diff --git a/web/react/stores/error_store.jsx b/web/react/stores/error_store.jsx index 3aed6aef2..203b692ec 100644 --- a/web/react/stores/error_store.jsx +++ b/web/react/stores/error_store.jsx @@ -29,18 +29,11 @@ var ErrorStore = assign({}, EventEmitter.prototype, { BrowserStore.removeItem("last_error"); }, getLastError: function() { - var error = null; - try { - error = JSON.parse(BrowserStore.getItem("last_error")); - } - catch (err) { - } - - return error; + return BrowserStore.getItem('last_error'); }, _storeLastError: function(error) { - BrowserStore.setItem("last_error", JSON.stringify(error)); + BrowserStore.setItem("last_error", error); }, }); diff --git a/web/react/stores/post_store.jsx b/web/react/stores/post_store.jsx index 8bf3fdcb2..e773bb688 100644 --- a/web/react/stores/post_store.jsx +++ b/web/react/stores/post_store.jsx @@ -106,55 +106,27 @@ var PostStore = assign({}, EventEmitter.prototype, { this.emitChange(); }, _storePosts: function(channelId, posts) { - BrowserStore.setItem("posts_" + channelId, JSON.stringify(posts)); + BrowserStore.setItem("posts_" + channelId, posts); }, getPosts: function(channelId) { - var posts = null; - try { - posts = JSON.parse(BrowserStore.getItem("posts_" + channelId)); - } - catch (err) { - } - - return posts; + return BrowserStore.getItem("posts_" + channelId); }, storeSearchResults: function(results, is_mention_search) { - BrowserStore.setItem("search_results", JSON.stringify(results)); + BrowserStore.setItem("search_results", results); is_mention_search = is_mention_search ? true : false; // force to bool - BrowserStore.setItem("is_mention_search", JSON.stringify(is_mention_search)); + BrowserStore.setItem("is_mention_search", is_mention_search); }, getSearchResults: function() { - var results = null; - try { - results = JSON.parse(BrowserStore.getItem("search_results")); - } - catch (err) { - } - - return results; + return BrowserStore.getItem("search_results"); }, getIsMentionSearch: function() { - var result = false; - try { - result = JSON.parse(BrowserStore.getItem("is_mention_search")); - } - catch (err) { - } - - return result; + return BrowserStore.getItem("is_mention_search"); }, storeSelectedPost: function(post_list) { - BrowserStore.setItem("select_post", JSON.stringify(post_list)); + BrowserStore.setItem("select_post", post_list); }, getSelectedPost: function() { - var post_list = null; - try { - post_list = JSON.parse(BrowserStore.getItem("select_post")); - } - catch (err) { - } - - return post_list; + return BrowserStore.getItem("select_post"); }, storeSearchTerm: function(term) { BrowserStore.setItem("search_term", term); @@ -165,25 +137,24 @@ var PostStore = assign({}, EventEmitter.prototype, { storeCurrentDraft: function(draft) { var channel_id = ChannelStore.getCurrentId(); var user_id = UserStore.getCurrentId(); - BrowserStore.setItem("draft_" + channel_id + "_" + user_id, JSON.stringify(draft)); + BrowserStore.setItem("draft_" + channel_id + "_" + user_id, draft); }, getCurrentDraft: function() { var channel_id = ChannelStore.getCurrentId(); var user_id = UserStore.getCurrentId(); - return JSON.parse(BrowserStore.getItem("draft_" + channel_id + "_" + user_id)); + return BrowserStore.getItem("draft_" + channel_id + "_" + user_id); }, storeDraft: function(channel_id, user_id, draft) { - BrowserStore.setItem("draft_" + channel_id + "_" + user_id, JSON.stringify(draft)); + BrowserStore.setItem("draft_" + channel_id + "_" + user_id, draft); }, getDraft: function(channel_id, user_id) { - return JSON.parse(BrowserStore.getItem("draft_" + channel_id + "_" + user_id)); + return BrowserStore.getItem("draft_" + channel_id + "_" + user_id); }, clearDraftUploads: function() { BrowserStore.actionOnItemsWithPrefix("draft_", function (key, value) { - var d = JSON.parse(value); - if (d) { - d['uploadsInProgress'] = 0; - BrowserStore.setItem(key, JSON.stringify(d)); + if (value) { + value.uploadsInProgress = 0; + BrowserStore.setItem(key, value); } }); } diff --git a/web/react/stores/socket_store.jsx b/web/react/stores/socket_store.jsx index 39800ead5..8ebb854c9 100644 --- a/web/react/stores/socket_store.jsx +++ b/web/react/stores/socket_store.jsx @@ -10,8 +10,6 @@ var client = require('../utils/client.jsx'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; -var BrowserStore = require('../stores/browser_store.jsx'); - var CHANGE_EVENT = 'change'; var conn; diff --git a/web/react/stores/team_store.jsx b/web/react/stores/team_store.jsx index c494cb5b5..b7199a4a8 100644 --- a/web/react/stores/team_store.jsx +++ b/web/react/stores/team_store.jsx @@ -63,22 +63,10 @@ var TeamStore = assign({}, EventEmitter.prototype, { this._storeTeams(teams); }, _storeTeams: function(teams) { - BrowserStore.setItem("user_teams", JSON.stringify(teams)); + BrowserStore.setItem("user_teams", teams); }, _getTeams: function() { - var teams = {}; - - try { - teams = JSON.parse(BrowserStore.getItem("user_teams")); - } - catch (err) { - } - - if (teams == null) { - teams = {}; - } - - return teams; + return BrowserStore.getItem("user_teams", {}); } }); diff --git a/web/react/stores/user_store.jsx b/web/react/stores/user_store.jsx index e832b34c7..93ddfec70 100644 --- a/web/react/stores/user_store.jsx +++ b/web/react/stores/user_store.jsx @@ -8,7 +8,7 @@ var client = require('../utils/client.jsx'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; -var BrowserStore = require('../stores/browser_store.jsx'); +var BrowserStore = require('./browser_store.jsx'); var CHANGE_EVENT = 'change'; var CHANGE_EVENT_SESSIONS = 'change_sessions'; @@ -18,6 +18,8 @@ var CHANGE_EVENT_STATUSES = 'change_statuses'; var UserStore = assign({}, EventEmitter.prototype, { + _current_id: null, + emitChange: function(userId) { this.emit(CHANGE_EVENT, userId); }, @@ -64,13 +66,10 @@ var UserStore = assign({}, EventEmitter.prototype, { this.removeListener(CHANGE_EVENT_STATUSES, callback); }, setCurrentId: function(id) { - if (id == null) - BrowserStore.removeGlobalItem("current_user_id"); - else - BrowserStore.setGlobalItem("current_user_id", id); + this._current_id = id; }, getCurrentId: function(skipFetch) { - var current_id = BrowserStore.getGlobalItem("current_user_id"); + var current_id = this._current_id; // this is a speical case to force fetch the // current user if it's missing @@ -97,21 +96,13 @@ var UserStore = assign({}, EventEmitter.prototype, { this.setCurrentId(user.id); }, getLastDomain: function() { - var last_domain = BrowserStore.getItem("last_domain"); - if (last_domain == null) { - last_domain = ""; - } - return last_domain; + return BrowserStore.getItem("last_domain", ''); }, setLastDomain: function(domain) { BrowserStore.setItem("last_domain", domain); }, getLastEmail: function() { - var last_email = BrowserStore.getItem("last_email"); - if (last_email == null) { - last_email = ""; - } - return last_email; + return BrowserStore.getItem("last_email", ''); }, setLastEmail: function(email) { BrowserStore.setItem("last_email", email); @@ -153,91 +144,36 @@ var UserStore = assign({}, EventEmitter.prototype, { this._storeProfiles(ps); }, _storeProfiles: function(profiles) { - BrowserStore.setGlobalItem("profiles", JSON.stringify(profiles)); + BrowserStore.setGlobalItem("profiles", profiles); var profileUsernameMap = {}; for (var id in profiles) { profileUsernameMap[profiles[id].username] = profiles[id]; } - BrowserStore.setGlobalItem("profileUsernameMap", JSON.stringify(profileUsernameMap)); + BrowserStore.setGlobalItem("profileUsernameMap", profileUsernameMap); }, _getProfiles: function() { - var profiles = {}; - try { - profiles = JSON.parse(BrowserStore.getGlobalItem("profiles")); - } - catch (err) { - } - - if (profiles == null) { - profiles = {}; - } - - return profiles; + return BrowserStore.getGlobalItem("profiles", {}); }, _getProfilesUsernameMap: function() { - var profileUsernameMap = {}; - try { - profileUsernameMap = JSON.parse(BrowserStore.getGlobalItem("profileUsernameMap")); - } - catch (err) { - } - - if (profileUsernameMap == null) { - profileUsernameMap = {}; - } - - return profileUsernameMap; + return BrowserStore.getGlobalItem("profileUsernameMap", {}); }, setSessions: function(sessions) { - BrowserStore.setItem("sessions", JSON.stringify(sessions)); + BrowserStore.setItem("sessions", sessions); }, getSessions: function() { - var sessions = []; - try { - sessions = JSON.parse(BrowserStore.getItem("sessions")); - } - catch (err) { - } - if (sessions == null) { - sessions = []; - } - - return sessions; + return BrowserStore.getItem("sessions", []); }, setAudits: function(audits) { - BrowserStore.setItem("audits", JSON.stringify(audits)); + BrowserStore.setItem("audits", audits); }, getAudits: function() { - var audits = []; - try { - audits = JSON.parse(BrowserStore.getItem("audits")); - } - catch (err) { - } - - if (audits == null) { - audits = []; - } - - return audits; + return BrowserStore.getItem("audits", []); }, setTeams: function(teams) { - BrowserStore.setItem("teams", JSON.stringify(teams)); + BrowserStore.setItem("teams", teams); }, getTeams: function() { - var teams = []; - try { - teams = JSON.parse(BrowserStore.getItem("teams")); - - } - catch (err) { - } - - if (teams == null) { - teams = []; - } - - return teams; + return BrowserStore.getItem("teams", []); }, getCurrentMentionKeys: function() { var user = this.getCurrentUser(); @@ -258,11 +194,7 @@ var UserStore = assign({}, EventEmitter.prototype, { } }, getLastVersion: function() { - var last_version = BrowserStore.getItem("last_version"); - if (last_version == null) { - last_version = ""; - } - return last_version; + return BrowserStore.getItem("last_version", ''); }, setLastVersion: function(version) { BrowserStore.setItem("last_version", version); @@ -272,7 +204,7 @@ var UserStore = assign({}, EventEmitter.prototype, { this.emitStatusesChange(); }, _setStatuses: function(statuses) { - BrowserStore.setItem("statuses", JSON.stringify(statuses)); + BrowserStore.setItem("statuses", statuses); }, setStatus: function(user_id, status) { var statuses = this.getStatuses(); @@ -281,18 +213,7 @@ var UserStore = assign({}, EventEmitter.prototype, { this.emitStatusesChange(); }, getStatuses: function() { - var statuses = {}; - try { - statuses = JSON.parse(BrowserStore.getItem("statuses")); - } - catch (err) { - } - - if (statuses == null) { - statuses = {}; - } - - return statuses; + return BrowserStore.getItem("statuses", {}); }, getStatus: function(id) { return this.getStatuses()[id]; @@ -341,4 +262,3 @@ UserStore.setMaxListeners(0); global.window.UserStore = UserStore; module.exports = UserStore; - -- cgit v1.2.3-1-g7c22 From e79ade46b2c43c0a6ee1ecffac91ba348aac790d Mon Sep 17 00:00:00 2001 From: ralder Date: Fri, 10 Jul 2015 12:20:00 -0700 Subject: [webui] fix incorrect height for mentions list for reply textbox --- web/react/components/mention_list.jsx | 29 ++++++++++++++++++----------- web/sass-files/sass/partials/_mentions.scss | 9 +++++---- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index ba2c53612..103ff29bb 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -9,7 +9,12 @@ var Mention = require('./mention.jsx'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; +var MAX_HEIGHT_LIST = 292; +var MAX_ITEMS_IN_LIST = 25; +var ITEM_HEIGHT = 36; + module.exports = React.createClass({ + displayName: "MentionList", componentDidMount: function() { PostStore.addMentionDataChangeListener(this._onChange); @@ -72,7 +77,7 @@ module.exports = React.createClass({ }, render: function() { var mentionText = this.state.mentionText; - if (mentionText === '-1') return (
); + if (mentionText === '-1') return null; var profiles = UserStore.getActiveOnlyProfiles(); var users = []; @@ -100,8 +105,7 @@ module.exports = React.createClass({ var mentions = {}; var index = 0; - for (var i = 0; i < users.length; i++) { - if (Object.keys(mentions).length >= 25) break; + for (var i = 0; i < users.length && index < MAX_ITEMS_IN_LIST; i++) { if (this.alreadyMentioned(users[i].username)) continue; var firstName = "", lastName = ""; @@ -127,17 +131,20 @@ module.exports = React.createClass({ } var numMentions = Object.keys(mentions).length; - if (numMentions < 1) return (
); + if (numMentions < 1) return null; - var height = (numMentions*36) + 4; - var width = $('#'+this.props.id).parent().width(); - var bottom = $(window).height() - $('#'+this.props.id).offset().top; - var left = $('#'+this.props.id).offset().left; - var max_height = $('#'+this.props.id).offset().top - 10; + var $mention_tab = $('#'+this.props.id); + var maxHeight = Math.min(MAX_HEIGHT_LIST, $mention_tab.offset().top - 10); + var style = { + height: Math.min(maxHeight, (numMentions*ITEM_HEIGHT) + 4), + width: $mention_tab.parent().width(), + bottom: $(window).height() - $mention_tab.offset().top, + left: $mention_tab.offset().left + }; return ( -
-
+
+
{ mentions }
diff --git a/web/sass-files/sass/partials/_mentions.scss b/web/sass-files/sass/partials/_mentions.scss index da46866c8..7e8c1869a 100644 --- a/web/sass-files/sass/partials/_mentions.scss +++ b/web/sass-files/sass/partials/_mentions.scss @@ -11,13 +11,14 @@ position: absolute; z-index: 1060; .mentions-box { - max-height: 303px; - position:absolute; - background-color:#fff; + width: 100%; + height: 100%; + position: absolute; + background-color: #fff; border: $border-gray; overflow-x: hidden; overflow-y: scroll; - bottom:0; + bottom: 0; } } -- cgit v1.2.3-1-g7c22 From 46d3515fad57f3c777b44d96077fec5a0ab944c1 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Fri, 10 Jul 2015 17:07:01 -0700 Subject: Changes to notifcation carriage return parsing --- web/react/components/sidebar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index 2095978e8..4a57ec263 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -249,7 +249,7 @@ var SidebarLoggedIn = React.createClass({ var repRegex = new RegExp("
", "g"); var post = JSON.parse(msg.props.post); - var msg = post.message.replace(repRegex, "\n").split("\n")[0].replace("", "").replace("", ""); + var msg = post.message.replace(repRegex, "\n").replace("\n", "").replace("", "").replace("", ""); if (msg.length > 50) { msg = msg.substring(0,49) + "..."; } -- cgit v1.2.3-1-g7c22 From dcea1de00661a9fba9129a35b4c6451234a18d9a Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Fri, 10 Jul 2015 17:32:13 -0700 Subject: Changed parser for desktop notifications to replace returns with a single space. --- web/react/components/sidebar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index 4a57ec263..934a4d22a 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -249,7 +249,7 @@ var SidebarLoggedIn = React.createClass({ var repRegex = new RegExp("
", "g"); var post = JSON.parse(msg.props.post); - var msg = post.message.replace(repRegex, "\n").replace("\n", "").replace("", "").replace("", ""); + var msg = post.message.replace(repRegex, "\n").replace(/\n+/g, " ").replace("", "").replace("", ""); if (msg.length > 50) { msg = msg.substring(0,49) + "..."; } -- cgit v1.2.3-1-g7c22 From 4cc9bfce5c8bf09f743f00421f47349b6519a25f Mon Sep 17 00:00:00 2001 From: ralder Date: Sat, 11 Jul 2015 08:32:02 -0700 Subject: [webui] fix loading animation for ie --- web/react/components/loading_screen.jsx | 24 +++++++ web/react/components/more_channels.jsx | 15 ++--- web/react/components/post.jsx | 13 ++-- web/react/components/post_body.jsx | 2 +- web/react/components/post_list.jsx | 103 +++++++++-------------------- web/react/utils/utils.jsx | 39 +++++++++-- web/sass-files/sass/partials/_loading.scss | 50 +++----------- web/sass-files/sass/partials/_post.scss | 1 + 8 files changed, 108 insertions(+), 139 deletions(-) create mode 100644 web/react/components/loading_screen.jsx diff --git a/web/react/components/loading_screen.jsx b/web/react/components/loading_screen.jsx new file mode 100644 index 000000000..5905e519b --- /dev/null +++ b/web/react/components/loading_screen.jsx @@ -0,0 +1,24 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +module.exports = React.createClass({ + displayName: "LoadingScreen", + propTypes: { + position: React.PropTypes.oneOf(['absolute', 'fixed', 'relative', 'static', 'inherit']) + }, + getDefaultProps: function() { + return { position: 'relative' }; + }, + render: function() { + return ( +
+
+

Loading

+
+
+
+
+
+ ); + } +}); diff --git a/web/react/components/more_channels.jsx b/web/react/components/more_channels.jsx index c3ddc76f3..007476f9b 100644 --- a/web/react/components/more_channels.jsx +++ b/web/react/components/more_channels.jsx @@ -7,6 +7,7 @@ var client = require('../utils/client.jsx'); var asyncClient = require('../utils/async_client.jsx'); var UserStore = require('../stores/user_store.jsx'); var ChannelStore = require('../stores/channel_store.jsx'); +var LoadingScreen = require('./loading_screen.jsx'); function getStateFromStores() { return { @@ -16,6 +17,8 @@ function getStateFromStores() { } module.exports = React.createClass({ + displayName: "MoreChannelsModal", + componentDidMount: function() { ChannelStore.addMoreChangeListener(this._onChange); $(this.refs.modal.getDOMNode()).on('shown.bs.modal', function (e) { @@ -90,7 +93,7 @@ module.exports = React.createClass({

{channel.display_name}

{channel.description}

- + ) })} @@ -100,15 +103,7 @@ module.exports = React.createClass({

No more channels to join

Click 'Create New Channel' to make a new one

) - :
-
-

Loading

-
-
-
-
-
- } + : } { server_error }
diff --git a/web/react/components/post.jsx b/web/react/components/post.jsx index 04b5ba082..32e1759dd 100644 --- a/web/react/components/post.jsx +++ b/web/react/components/post.jsx @@ -10,6 +10,7 @@ var UserStore = require('../stores/user_store.jsx'); var ActionTypes = Constants.ActionTypes; module.exports = React.createClass({ + displayName: "Post", componentDidMount: function() { $('.modal').on('show.bs.modal', function () { $('.modal-body').css('overflow-y', 'auto'); @@ -19,7 +20,7 @@ module.exports = React.createClass({ handleCommentClick: function(e) { e.preventDefault(); - data = {}; + var data = {}; data.order = [this.props.post.id]; data.posts = this.props.posts; @@ -48,7 +49,6 @@ module.exports = React.createClass({ var commentCount = 0; var commentRootId = parentPost ? post.root_id : post.id; - var rootUser = ""; for (var postId in posts) { if (posts[postId].root_id == commentRootId) { commentCount += 1; @@ -57,12 +57,7 @@ module.exports = React.createClass({ var error = this.state.error ?
: null; - if (this.props.sameRoot){ - rootUser = "same--root"; - } - else { - rootUser = "other--root"; - } + var rootUser = this.props.sameRoot ? "same--root" : "other--root"; var postType = ""; if (type != "Post"){ @@ -81,7 +76,7 @@ module.exports = React.createClass({
- : "" } + : null }
diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx index 7d5ef4d33..cf542a98f 100644 --- a/web/react/components/post_body.jsx +++ b/web/react/components/post_body.jsx @@ -120,7 +120,7 @@ module.exports = React.createClass({ return (
{ comment } -

{inner}

+

{inner}

{ filenames && filenames.length > 0 ?
{ postFiles } diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index d6dc9ce30..9e1679717 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -8,6 +8,7 @@ var UserProfile = require( './user_profile.jsx' ); var AsyncClient = require('../utils/async_client.jsx'); var CreatePost = require('./create_post.jsx'); var Post = require('./post.jsx'); +var LoadingScreen = require('./loading_screen.jsx'); var SocketStore = require('../stores/socket_store.jsx'); var utils = require('../utils/utils.jsx'); var Client = require('../utils/client.jsx'); @@ -26,37 +27,8 @@ function getStateFromStores() { }; } -function changeColor(col, amt) { - - var usePound = false; - - if (col[0] == "#") { - col = col.slice(1); - usePound = true; - } - - var num = parseInt(col,16); - - var r = (num >> 16) + amt; - - if (r > 255) r = 255; - else if (r < 0) r = 0; - - var b = ((num >> 8) & 0x00FF) + amt; - - if (b > 255) b = 255; - else if (b < 0) b = 0; - - var g = (num & 0x0000FF) + amt; - - if (g > 255) g = 255; - else if (g < 0) g = 0; - - return (usePound?"#":"") + String("000000" + (g | (b << 8) | (r << 16)).toString(16)).slice(-6); - -} - module.exports = React.createClass({ + displayName: "PostList", scrollPosition: 0, preventScrollTrigger: false, gotMorePosts: false, @@ -69,7 +41,7 @@ module.exports = React.createClass({ utils.changeCss('a.theme', 'color:'+user.props.theme+'; fill:'+user.props.theme+'!important;'); utils.changeCss('div.theme', 'background-color:'+user.props.theme+';'); utils.changeCss('.btn.btn-primary', 'background: ' + user.props.theme+';'); - utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + changeColor(user.props.theme, -10) +';'); + utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + utils.changeColor(user.props.theme, -10) +';'); utils.changeCss('.modal .modal-header', 'background: ' + user.props.theme+';'); utils.changeCss('.mention', 'background: ' + user.props.theme+';'); utils.changeCss('.mention-link', 'color: ' + user.props.theme+';'); @@ -161,24 +133,20 @@ module.exports = React.createClass({ $('body').off('click.userpopover'); }, resize: function() { + var post_holder = $(".post-list-holder-by-time")[0]; + this.preventScrollTrigger = true; if (this.gotMorePosts) { this.gotMorePosts = false; - var post_holder = $(".post-list-holder-by-time")[0]; - this.preventScrollTrigger = true; $(post_holder).scrollTop($(post_holder).scrollTop() + (post_holder.scrollHeight-this.oldScrollHeight) ); - $(post_holder).perfectScrollbar('update'); } else { - var post_holder = $(".post-list-holder-by-time")[0]; - this.preventScrollTrigger = true; if ($("#new_message")[0] && !this.scrolledToNew) { $(post_holder).scrollTop($(post_holder).scrollTop() + $("#new_message").offset().top - 63); - $(post_holder).perfectScrollbar('update'); this.scrolledToNew = true; } else { $(post_holder).scrollTop(post_holder.scrollHeight); - $(post_holder).perfectScrollbar('update'); } } + $(post_holder).perfectScrollbar('update'); }, _onChange: function() { var newState = getStateFromStores(); @@ -347,7 +315,10 @@ module.exports = React.createClass({
-

{"This is the start of your private message history with " + teammate_name + "." }
{"Private messages and files shared here are not shown to people outside this area."}

+

+ {"This is the start of your private message history with " + teammate_name + "." }
+ {"Private messages and files shared here are not shown to people outside this area."} +

); } else { @@ -410,7 +381,7 @@ module.exports = React.createClass({ { channel.type === 'P' ? " Only invited members can see this private group." : " Any member can join and read this channel." }
Set a description - Invite others to this {ui_type} + Invite others to this {ui_type}

); @@ -420,37 +391,35 @@ module.exports = React.createClass({ var postCtls = []; - if (posts != undefined) { + if (posts) { var previousPostDay = posts[order[order.length-1]] ? utils.getDateForUnixTicks(posts[order[order.length-1]].create_at): new Date(); - var currentPostDay = new Date(); + var currentPostDay; for (var i = order.length-1; i >= 0; i--) { var post = posts[order[i]]; - var parentPost; + var parentPost = post.parent_id ? posts[post.parent_id] : null; - if (post.parent_id) { - parentPost = posts[post.parent_id]; - } else { - parentPost = null; - } + var sameUser = ''; + var sameRoot = false; + var hideProfilePic = false; + var prevPost = (i < order.length - 1) ? posts[order[i + 1]] : null; - var sameUser = i < order.length-1 && posts[order[i+1]].user_id === post.user_id && post.create_at - posts[order[i+1]].create_at <= 1000*60*5 ? "same--user" : ""; - var sameRoot = i < order.length-1 && post.root_id != "" && (posts[order[i+1]].id === post.root_id || posts[order[i+1]].root_id === post.root_id) ? true : false; + if (prevPost) { + sameUser = (prevPost.user_id === post.user_id) && (post.create_at - prevPost.create_at <= 1000*60*5) ? "same--user" : ""; + sameRoot = utils.isComment(post) && (prevPost.id === post.root_id || prevPost.root_id === post.root_id); - // we only hide the profile pic if the previous post is not a comment, the current post is not a comment, and the previous post was made by the same user as the current post - var hideProfilePic = i < order.length-1 && posts[order[i+1]].user_id === post.user_id && posts[order[i+1]].root_id === '' && post.root_id === ''; + // we only hide the profile pic if the previous post is not a comment, the current post is not a comment, and the previous post was made by the same user as the current post + hideProfilePic = (prevPost.user_id === post.user_id) && !utils.isComment(prevPost) && !utils.isComment(post); + } // check if it's the last comment in a consecutive string of comments on the same post - var isLastComment = false; - if (utils.isComment(post)) { - // it is the last comment if it is last post in the channel or the next post has a different root post - isLastComment = (i === 0 || posts[order[i-1]].root_id != post.root_id); - } + // it is the last comment if it is last post in the channel or the next post has a different root post + var isLastComment = utils.isComment(post) && (i === 0 || posts[order[i-1]].root_id != post.root_id); var postCtl = ; currentPostDay = utils.getDateForUnixTicks(post.create_at); - if(currentPostDay.getDate() !== previousPostDay.getDate() || currentPostDay.getMonth() !== previousPostDay.getMonth() || currentPostDay.getFullYear() !== previousPostDay.getFullYear()) { + if (currentPostDay.toDateString() != previousPostDay.toDateString()) { postCtls.push(

@@ -469,20 +438,10 @@ module.exports = React.createClass({ ); } postCtls.push(postCtl); - previousPostDay = utils.getDateForUnixTicks(post.create_at); + previousPostDay = currentPostDay; } - } - else { - postCtls.push( -
-
-

Loading

-
-
-
-
-
- ); + } else { + postCtls.push(); } return ( @@ -497,5 +456,3 @@ module.exports = React.createClass({ ); } }); - - diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 5ded0e76f..19c074606 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -225,7 +225,7 @@ module.exports.extractLinks = function(text) { } return { "links": links, "text": text }; -} +} module.exports.escapeRegExp = function(string) { return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); @@ -671,13 +671,13 @@ module.exports.isValidUsername = function (name) { error = "First character must be a letter."; } - else + else { var lowerName = name.toLowerCase().trim(); - for (var i = 0; i < Constants.RESERVED_USERNAMES.length; i++) + for (var i = 0; i < Constants.RESERVED_USERNAMES.length; i++) { - if (lowerName === Constants.RESERVED_USERNAMES[i]) + if (lowerName === Constants.RESERVED_USERNAMES[i]) { error = "Cannot use a reserved word as a username."; break; @@ -782,3 +782,34 @@ module.exports.getHomeLink = function() { parts[0] = "www"; return window.location.protocol + "//" + parts.join("."); } + + +module.exports.changeColor =function(col, amt) { + + var usePound = false; + + if (col[0] == "#") { + col = col.slice(1); + usePound = true; + } + + var num = parseInt(col,16); + + var r = (num >> 16) + amt; + + if (r > 255) r = 255; + else if (r < 0) r = 0; + + var b = ((num >> 8) & 0x00FF) + amt; + + if (b > 255) b = 255; + else if (b < 0) b = 0; + + var g = (num & 0x0000FF) + amt; + + if (g > 255) g = 255; + else if (g < 0) g = 0; + + return (usePound?"#":"") + String("000000" + (g | (b << 8) | (r << 16)).toString(16)).slice(-6); + +}; diff --git a/web/sass-files/sass/partials/_loading.scss b/web/sass-files/sass/partials/_loading.scss index bc819e8f5..d71055722 100644 --- a/web/sass-files/sass/partials/_loading.scss +++ b/web/sass-files/sass/partials/_loading.scss @@ -2,13 +2,8 @@ display: table; width: 100%; height: 100%; - position: absolute; - @include box-sizing(border-box); + padding: 60px; text-align: center; - &.loading-screen--channel { - position: relative; - padding: 4em 0 3.5em; - } .loading__content { display: table-cell; vertical-align: middle; @@ -19,11 +14,7 @@ margin: 0 0.2em 0; display: inline-block; } - } -} -.loading-screen { - .loading__content { .round { background-color: #444; width: 4px; @@ -32,43 +23,18 @@ margin: 0 2px; opacity: 0.1; @include border-radius(10px); - -moz-animation: move 0.75s infinite linear; - -webkit-animation: move 0.75s infinite linear; - } - - #round_1 { - -moz-animation-delay: .2s; - -webkit-animation-delay: .2s; + @include animation(move 0.75s infinite linear); } - #round_2 { - -moz-animation-delay: .4s; - -webkit-animation-delay: .4s; - } - - #round_3 { - -moz-animation-delay: .6s; - -webkit-animation-delay: .6s; - } - - @-moz-keyframes move { - 0% { - opacity: 1; + @for $i from 1 through 3 { + .round-#{$i} { + @include animation-delay(.2s*$i); } - - 100% { - opacity: 0.1; - }; } - @-webkit-keyframes move { - 0% { - opacity: 1; - } - - 100% { - opacity: 0.1; - }; + @include keyframes(move) { + from { opacity: 1; } + to { opacity: 0.1; } } } } diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss index d0c536363..40ed40b49 100644 --- a/web/sass-files/sass/partials/_post.scss +++ b/web/sass-files/sass/partials/_post.scss @@ -119,6 +119,7 @@ body.ios { table-layout: fixed; width: 100%; min-height: 100%; + height: 100%; .post-list__content { display: table-cell; vertical-align: bottom; -- cgit v1.2.3-1-g7c22 From b26bc73c7880e691e77e9ca4169e9ed7735e3bc9 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Mon, 13 Jul 2015 08:32:25 -0400 Subject: should fix scrolling on forceupdate --- web/react/components/post.jsx | 2 +- web/react/components/post_list.jsx | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/web/react/components/post.jsx b/web/react/components/post.jsx index 04b5ba082..2d25e31e0 100644 --- a/web/react/components/post.jsx +++ b/web/react/components/post.jsx @@ -85,7 +85,7 @@ module.exports = React.createClass({
- +
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index 177e4a1db..3409bad28 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -63,6 +63,8 @@ module.exports = React.createClass({ oldScrollHeight: 0, oldZoom: 0, scrolledToNew: false, + p: 0, + wasForced: false, componentDidMount: function() { var user = UserStore.getCurrentUser(); if (user.props && user.props.theme) { @@ -108,6 +110,12 @@ module.exports = React.createClass({ }); $(post_holder).scroll(function(e){ + if (self.wasForced) { + console.log('hit'); + $(post_holder).scrollTop(self.p); + $(post_holder).perfectScrollbar('update'); + self.wasForced = false; + } if (!self.preventScrollTrigger) { self.scrollPosition = $(post_holder).scrollTop() + $(post_holder).innerHeight(); } @@ -197,7 +205,10 @@ module.exports = React.createClass({ this.setState(newState); } else { // Updates the timestamp on each post + this.wasForced = true; + this.p = $(".post-list-holder-by-time").scrollTop(); this.forceUpdate() + //this.refs.post0.refs.info.forceUpdate(); } }, _onSocketChange: function(msg) { @@ -452,7 +463,7 @@ module.exports = React.createClass({ isLastComment = (i === 0 || posts[order[i-1]].root_id != post.root_id); } - var postCtl = ; + var postCtl = ; currentPostDay = utils.getDateForUnixTicks(post.create_at); if(currentPostDay.getDate() !== previousPostDay.getDate() || currentPostDay.getMonth() !== previousPostDay.getMonth() || currentPostDay.getFullYear() !== previousPostDay.getFullYear()) { -- cgit v1.2.3-1-g7c22 From 614992dcb7b4a4cdcedefe3ca813a03b758a97f0 Mon Sep 17 00:00:00 2001 From: nickago Date: Mon, 13 Jul 2015 08:34:34 -0700 Subject: Added timestamp updates to right side and cleaned code --- web/react/components/post.jsx | 2 +- web/react/components/post_list.jsx | 22 +++++++++++----------- web/react/components/post_right.jsx | 18 ++++++++++++++++-- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/web/react/components/post.jsx b/web/react/components/post.jsx index 2d25e31e0..04b5ba082 100644 --- a/web/react/components/post.jsx +++ b/web/react/components/post.jsx @@ -85,7 +85,7 @@ module.exports = React.createClass({
- +
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index 59f33fb4d..e186fb706 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -63,7 +63,7 @@ module.exports = React.createClass({ oldScrollHeight: 0, oldZoom: 0, scrolledToNew: false, - p: 0, + preForcePosision: 0, wasForced: false, componentDidMount: function() { var user = UserStore.getCurrentUser(); @@ -80,6 +80,7 @@ module.exports = React.createClass({ PostStore.addChangeListener(this._onChange); ChannelStore.addChangeListener(this._onChange); + UserStore.addStatusesChangeListener(this._onTimeChange); SocketStore.addChangeListener(this._onSocketChange); $(".post-list-holder-by-time").perfectScrollbar(); @@ -110,8 +111,7 @@ module.exports = React.createClass({ $(post_holder).scroll(function(e){ if (self.wasForced) { - console.log('hit'); - $(post_holder).scrollTop(self.p); + $(post_holder).scrollTop(self.preForcePosision); $(post_holder).perfectScrollbar('update'); self.wasForced = false; } @@ -165,6 +165,7 @@ module.exports = React.createClass({ componentWillUnmount: function() { PostStore.removeChangeListener(this._onChange); ChannelStore.removeChangeListener(this._onChange); + UserStore.removeStatusesChangeListener(this._onTimeChange); SocketStore.removeChangeListener(this._onSocketChange); $('body').off('click.userpopover'); }, @@ -201,13 +202,7 @@ module.exports = React.createClass({ this.scrolledToNew = false; } this.setState(newState); - } else { - // Updates the timestamp on each post - this.wasForced = true; - this.p = $(".post-list-holder-by-time").scrollTop(); - this.forceUpdate() - //this.refs.post0.refs.info.forceUpdate(); - } + } }, _onSocketChange: function(msg) { if (msg.action == "posted") { @@ -271,6 +266,11 @@ module.exports = React.createClass({ AsyncClient.getProfiles(); } }, + _onTimeChange: function() { + this.wasForced = true; + this.preForcePosision = $(".post-list-holder-by-time").scrollTop(); + this.forceUpdate() + }, getMorePosts: function(e) { e.preventDefault(); @@ -461,7 +461,7 @@ module.exports = React.createClass({ isLastComment = (i === 0 || posts[order[i-1]].root_id != post.root_id); } - var postCtl = ; + var postCtl = ; currentPostDay = utils.getDateForUnixTicks(post.create_at); if(currentPostDay.getDate() !== previousPostDay.getDate() || currentPostDay.getMonth() !== previousPostDay.getMonth() || currentPostDay.getFullYear() !== previousPostDay.getFullYear()) { diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx index 115ee87d4..89a616d27 100644 --- a/web/react/components/post_right.jsx +++ b/web/react/components/post_right.jsx @@ -279,9 +279,11 @@ function getStateFromStores() { } module.exports = React.createClass({ + wasForced: false, componentDidMount: function() { PostStore.addSelectedPostChangeListener(this._onChange); PostStore.addChangeListener(this._onChangeAll); + UserStore.addStatusesChangeListener(this._onTimeChange); this.resize(); var self = this; $(window).resize(function(){ @@ -289,11 +291,15 @@ module.exports = React.createClass({ }); }, componentDidUpdate: function() { - this.resize(); + if(!this.wasForced){ + this.resize(); + wasForced = false + } }, componentWillUnmount: function() { PostStore.removeSelectedPostChangeListener(this._onChange); PostStore.removeChangeListener(this._onChangeAll); + UserStore.removeStatusesChangeListener(this._onTimeChange) }, _onChange: function() { if (this.isMounted()) { @@ -333,6 +339,14 @@ module.exports = React.createClass({ this.setState(getStateFromStores()); } }, + _onTimeChange: function() { + this.wasForced = true; + for (var key in this.refs) { + if(this.refs[key].forceUpdate != undefined) { + this.refs[key].forceUpdate(); + } + } + }, getInitialState: function() { return getStateFromStores(); }, @@ -392,7 +406,7 @@ module.exports = React.createClass({
{ posts_array.map(function(cpost) { - return + return })}
-- cgit v1.2.3-1-g7c22 From c3aed620316241eba48ecd2fd1f36a309bcfdff9 Mon Sep 17 00:00:00 2001 From: nickago Date: Thu, 9 Jul 2015 16:37:03 -0700 Subject: Added timestamps to pictures to stop caching --- store/sql_user_store.go | 19 +++++++++++++++++++ store/store.go | 1 + web/react/components/post.jsx | 4 +++- web/react/components/post_list.jsx | 2 +- web/react/components/post_right.jsx | 3 ++- web/react/components/user_profile.jsx | 2 +- 6 files changed, 27 insertions(+), 4 deletions(-) diff --git a/store/sql_user_store.go b/store/sql_user_store.go index fc3d125c4..77470946c 100644 --- a/store/sql_user_store.go +++ b/store/sql_user_store.go @@ -150,6 +150,25 @@ func (us SqlUserStore) Update(user *model.User, allowActiveUpdate bool) StoreCha return storeChannel } +func (us SqlUserStore) UpdateUpdateAt(userId string) StoreChannel { + storeChannel := make(StoreChannel) + + go func() { + result := StoreResult{} + + if _, err := us.GetMaster().Exec("UPDATE Users SET UpdateAt = ? WHERE Id = ?", model.GetMillis(), userId); err != nil { + result.Err = model.NewAppError("SqlUserStore.UpdateUpdateAt", "We couldn't update the update_at", "user_id="+userId) + } else { + result.Data = userId + } + + storeChannel <- result + close(storeChannel) + }() + + return storeChannel +} + func (us SqlUserStore) UpdateLastPingAt(userId string, time int64) StoreChannel { storeChannel := make(StoreChannel) diff --git a/store/store.go b/store/store.go index 070ee0562..0ed045788 100644 --- a/store/store.go +++ b/store/store.go @@ -77,6 +77,7 @@ type PostStore interface { type UserStore interface { Save(user *model.User) StoreChannel Update(user *model.User, allowRoleUpdate bool) StoreChannel + UpdateUpdateAt(userId string) StoreChannel UpdateLastPingAt(userId string, time int64) StoreChannel UpdateLastActivityAt(userId string, time int64) StoreChannel UpdateUserAndSessionActivity(userId string, sessionId string, time int64) StoreChannel diff --git a/web/react/components/post.jsx b/web/react/components/post.jsx index 04b5ba082..726fb1b02 100644 --- a/web/react/components/post.jsx +++ b/web/react/components/post.jsx @@ -74,12 +74,14 @@ module.exports = React.createClass({ currentUserCss = "current--user"; } + var timestamp = UserStore.getCurrentUser().update_at; + return (
{ !this.props.hideProfilePic ?
- +
: "" }
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index d6dc9ce30..e6e028209 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -342,7 +342,7 @@ module.exports = React.createClass({ more_messages = (
- +
diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx index 115ee87d4..d48b0f0ef 100644 --- a/web/react/components/post_right.jsx +++ b/web/react/components/post_right.jsx @@ -67,6 +67,7 @@ RootPost = React.createClass({ var message = utils.textToJsx(this.props.post.message); var filenames = this.props.post.filenames; var isOwner = UserStore.getCurrentId() == this.props.post.user_id; + var timestamp = UserStore.getProfile(this.props.post.user_id).update_at; var type = "Post"; if (this.props.post.root_id.length > 0) { @@ -118,7 +119,7 @@ RootPost = React.createClass({ return (
- +
    diff --git a/web/react/components/user_profile.jsx b/web/react/components/user_profile.jsx index 648960471..89d0a80ff 100644 --- a/web/react/components/user_profile.jsx +++ b/web/react/components/user_profile.jsx @@ -53,7 +53,7 @@ module.exports = React.createClass({ var name = this.props.overwriteName ? this.props.overwriteName : this.state.profile.username; - var data_content = ""; + var data_content = ""; if (!config.ShowEmail) { data_content += "
    Email not shared
    "; } else { -- cgit v1.2.3-1-g7c22 From 7d6d9c297f21fa8cf0848c071bcdd13691fb3d9b Mon Sep 17 00:00:00 2001 From: nickago Date: Fri, 10 Jul 2015 09:56:41 -0700 Subject: Added User update function --- api/user.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/user.go b/api/user.go index 483ae67b5..bdd26e097 100644 --- a/api/user.go +++ b/api/user.go @@ -135,6 +135,8 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) { user.EmailVerified = true } + user.EmailVerified = true + ruser := CreateUser(c, team, user) if c.Err != nil { return @@ -729,6 +731,8 @@ func uploadProfileImage(c *Context, w http.ResponseWriter, r *http.Request) { return } + Srv.Store.User().UpdateUpdateAt(c.Session.UserId) + c.LogAudit("") } -- cgit v1.2.3-1-g7c22 From f5d188e1caa4b27eb4878de41e479199ca0cafda Mon Sep 17 00:00:00 2001 From: nickago Date: Fri, 10 Jul 2015 09:57:17 -0700 Subject: Added async get to channel swap --- web/react/utils/utils.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 5ded0e76f..a5ed08d67 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -707,6 +707,7 @@ module.exports.switchChannel = function(channel, teammate_name) { AsyncClient.getChannels(true, true, true); AsyncClient.getChannelExtraInfo(true); AsyncClient.getPosts(true, channel.id); + AsyncClient.getProfiles(); $('.inner__wrap').removeClass('move--right'); $('.sidebar--left').removeClass('move--right'); -- cgit v1.2.3-1-g7c22 From c485dad84f9a94c3d1261f7e2207baf071c2d3ca Mon Sep 17 00:00:00 2001 From: nickago Date: Mon, 13 Jul 2015 09:22:42 -0700 Subject: Added update function to image update and fixed corner cases --- web/react/components/member_list_item.jsx | 3 ++- web/react/components/member_list_team.jsx | 5 +++-- web/react/components/mention.jsx | 4 +++- web/react/components/post_right.jsx | 3 ++- web/react/components/search_results.jsx | 3 ++- web/react/utils/utils.jsx | 1 - 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/web/react/components/member_list_item.jsx b/web/react/components/member_list_item.jsx index 357fd49a8..cf8c71d7e 100644 --- a/web/react/components/member_list_item.jsx +++ b/web/react/components/member_list_item.jsx @@ -23,6 +23,7 @@ module.exports = React.createClass({ var member = this.props.member; var isAdmin = this.props.isAdmin; var isMemberAdmin = member.roles.indexOf("admin") > -1; + var timestamp = UserStore.getCurrentUser().update_at; var invite; if (member.invited && this.props.handleInvite) { @@ -53,7 +54,7 @@ module.exports = React.createClass({ return (
    - + {member.username} {member.email} { invite } diff --git a/web/react/components/member_list_team.jsx b/web/react/components/member_list_team.jsx index cfb473e5e..aa53c5db6 100644 --- a/web/react/components/member_list_team.jsx +++ b/web/react/components/member_list_team.jsx @@ -61,7 +61,8 @@ var MemberListTeamItem = React.createClass({ render: function() { var server_error = this.state.server_error ?
    : null; var user = this.props.user; - var currentRoles = "Member" + var currentRoles = "Member"; + var timestamp = UserStore.getCurrentUser().update_at; if (user.roles.length > 0) { currentRoles = user.roles.charAt(0).toUpperCase() + user.roles.slice(1); @@ -83,7 +84,7 @@ var MemberListTeamItem = React.createClass({ return (
    - + {user.full_name.trim() ? user.full_name : user.username} {user.full_name.trim() ? user.username : email}
    diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx index 3c33ddf49..520b81cbb 100644 --- a/web/react/components/mention.jsx +++ b/web/react/components/mention.jsx @@ -1,5 +1,6 @@ // Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. +var UserStore = require("../stores/user_store.jsx"); module.exports = React.createClass({ handleClick: function() { @@ -7,8 +8,9 @@ module.exports = React.createClass({ }, render: function() { var icon; + var timestamp = UserStore.getCurrentUser().update_at; if (this.props.id != null) { - icon = ; + icon = ; } diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx index d48b0f0ef..408fbf83a 100644 --- a/web/react/components/post_right.jsx +++ b/web/react/components/post_right.jsx @@ -228,11 +228,12 @@ CommentPost = React.createClass({ } var message = utils.textToJsx(this.props.post.message); + var timestamp = UserStore.getCurrentUser().update_at; return (
    - +
      diff --git a/web/react/components/search_results.jsx b/web/react/components/search_results.jsx index 003a38b7e..156cf0120 100644 --- a/web/react/components/search_results.jsx +++ b/web/react/components/search_results.jsx @@ -76,6 +76,7 @@ SearchItem = React.createClass({ var message = utils.textToJsx(this.props.post.message, {searchTerm: this.props.term, noMentionHighlight: !this.props.isMentionSearch}); var channelName = ""; var channel = ChannelStore.get(this.props.post.channel_id) + var timestamp = UserStore.getCurrentUser().update_at; if (channel) { if (channel.type === 'D') { @@ -89,7 +90,7 @@ SearchItem = React.createClass({
      { channelName }
      - +
        diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index a5ed08d67..5ded0e76f 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -707,7 +707,6 @@ module.exports.switchChannel = function(channel, teammate_name) { AsyncClient.getChannels(true, true, true); AsyncClient.getChannelExtraInfo(true); AsyncClient.getPosts(true, channel.id); - AsyncClient.getProfiles(); $('.inner__wrap').removeClass('move--right'); $('.sidebar--left').removeClass('move--right'); -- cgit v1.2.3-1-g7c22 From aff43f43f8185ae6d5555ca9f99bfcc4bd3eb99e Mon Sep 17 00:00:00 2001 From: nickago Date: Mon, 13 Jul 2015 09:27:30 -0700 Subject: removed testing state --- api/user.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/user.go b/api/user.go index bdd26e097..5b052e826 100644 --- a/api/user.go +++ b/api/user.go @@ -135,8 +135,6 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) { user.EmailVerified = true } - user.EmailVerified = true - ruser := CreateUser(c, team, user) if c.Err != nil { return -- cgit v1.2.3-1-g7c22 From 8595b915afae9c494f09bd45692102ae86306ffe Mon Sep 17 00:00:00 2001 From: nickago Date: Mon, 13 Jul 2015 11:24:39 -0700 Subject: Fixed 'this' typo and added semicolon --- web/react/components/post_right.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx index 89a616d27..0c3754529 100644 --- a/web/react/components/post_right.jsx +++ b/web/react/components/post_right.jsx @@ -293,7 +293,7 @@ module.exports = React.createClass({ componentDidUpdate: function() { if(!this.wasForced){ this.resize(); - wasForced = false + this.wasForced = false; } }, componentWillUnmount: function() { -- cgit v1.2.3-1-g7c22 From f406beca8b501dad508d1ffb900bf994c4192086 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Fri, 10 Jul 2015 18:41:42 -0700 Subject: If a message has no text but has an attached image or file the desktop notification now says uploaded an image or uploaded a file respectively (if both, defaults to image) --- api/post.go | 14 ++++++++++++++ web/react/components/sidebar.jsx | 18 +++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/api/post.go b/api/post.go index 650f47062..02f997166 100644 --- a/api/post.go +++ b/api/post.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" "time" + "path/filepath" ) func InitPost(r *mux.Router) { @@ -437,6 +438,19 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) { message := model.NewMessage(teamId, post.ChannelId, post.UserId, model.ACTION_POSTED) message.Add("post", post.ToJson()) + + if len(post.Filenames) != 0 { + message.Add("otherFile", "true") + + for _, filename := range post.Filenames { + ext := filepath.Ext(filename) + if model.IsFileExtImage(ext) { + message.Add("image", "true") + break + } + } + } + if len(mentionedUsers) != 0 { message.Add("mentions", model.ArrayToJson(mentionedUsers)) } diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index 934a4d22a..cae9425d3 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -249,11 +249,27 @@ var SidebarLoggedIn = React.createClass({ var repRegex = new RegExp("
        ", "g"); var post = JSON.parse(msg.props.post); + var msgProps = msg.props; var msg = post.message.replace(repRegex, "\n").replace(/\n+/g, " ").replace("", "").replace("", ""); + if (msg.length > 50) { msg = msg.substring(0,49) + "..."; } - utils.notifyMe(title, username + " wrote: " + msg, channel); + + if (msg.length === 0) { + if (msgProps.image) { + utils.notifyMe(title, username + " uploaded an image", channel); + } + else if (msgProps.otherFile) { + utils.notifyMe(title, username + " uploaded a file", channel); + } + else { + utils.notifyMe(title, username + " did something new", channel); + } + } + else { + utils.notifyMe(title, username + " wrote: " + msg, channel); + } if (!user.notify_props || user.notify_props.desktop_sound === "true") { utils.ding(); } -- cgit v1.2.3-1-g7c22 From 0a166572c12e3e13fefee02e79ab9eca6f4d2229 Mon Sep 17 00:00:00 2001 From: Asaad Mahmood Date: Tue, 14 Jul 2015 02:30:55 +0500 Subject: Merge branch 'MM-1302' of https://github.com/nickago/platform into mm-1302 # Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit. --- web/react/components/sidebar_header.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 0b59d2036..7f8fe3d52 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -121,9 +121,12 @@ module.exports = React.createClass({ }, render: function() { var teamName = this.props.teamName ? this.props.teamName : config.SiteName; + var me = UserStore.getCurrentUser() return (
        + {me.username} { teamName }
        -- cgit v1.2.3-1-g7c22 From 3d56d9b2411fdf6db6228dee5dab3fad377a31c4 Mon Sep 17 00:00:00 2001 From: nickago Date: Mon, 13 Jul 2015 14:56:54 -0700 Subject: Add processing for messageless image posts w/ pluralization --- web/react/components/post_body.jsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx index 7d5ef4d33..2febcfa04 100644 --- a/web/react/components/post_body.jsx +++ b/web/react/components/post_body.jsx @@ -71,11 +71,22 @@ module.exports = React.createClass({ name = {profile.username}; } - var message = parentPost.message; + var message = "" + if(parentPost.message) { + message = utils.replaceHtmlEntities(parentPost.message) + } else if (parentPost.filenames.length) { + message = 2) { + message += " plus " + (parentPost.filenames.length - 1) + " other files"; + } + } comment = (

        - Commented on {name}{apostrophe} message: {utils.replaceHtmlEntities(message)} + Commented on {name}{apostrophe} message: {message}

        ); -- cgit v1.2.3-1-g7c22 From d1cb7d35fb178916c9aecef8ecc703f2a364197b Mon Sep 17 00:00:00 2001 From: Asaad Mahmood Date: Tue, 14 Jul 2015 03:26:04 +0500 Subject: mm-1302 - Adding profile pick in LHS Header --- web/react/components/sidebar_header.jsx | 10 ++++++---- web/sass-files/sass/partials/_headers.scss | 27 ++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 7f8fe3d52..54858a04d 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -77,7 +77,7 @@ var NavbarDropdown = React.createClass({ for (var i = 0; i < this.state.teams.length; i++) { var domain = this.state.teams[i]; - if (domain == utils.getSubDomain()) + if (domain == utils.getSubDomain()) continue; if (teams.length == 0) @@ -125,9 +125,11 @@ module.exports = React.createClass({ return (
        - {me.username} - { teamName } + +
        @{me.username}
        + { teamName } +
      ); diff --git a/web/sass-files/sass/partials/_headers.scss b/web/sass-files/sass/partials/_headers.scss index 1ec1109a5..7b0f24abf 100644 --- a/web/sass-files/sass/partials/_headers.scss +++ b/web/sass-files/sass/partials/_headers.scss @@ -75,14 +75,16 @@ // Team Header in Sidebar .sidebar--left, .sidebar--menu { .team__header { - padding: 0 15px 0 15px; + padding: 15px; @include legacy-pie-clearfix; a { color: #fff; } .navbar-right { font-size: 0.85em; - margin: 16px -5px 0; + position: absolute; + top: 24px; + right: 25px; .dropdown-toggle { padding: 0 10px; } @@ -100,17 +102,32 @@ display: inline-block; } } - .team__name { + .user__picture { + width: 36px; + height: 36px; float: left; - line-height: 50px; + @include border-radius(36px); + } + .header__info { + padding-left: 42px; + color: #fff; + } + .team__name, .user__name { + display: block; + line-height: 18px; font-weight: 600; - font-size: 1.2em; + font-size: 16px; max-width: 80%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-decoration: none; } + .user__name { + font-size: 14px; + font-weight: 400; + color: #eee; + } > .nav { > li { > a { -- cgit v1.2.3-1-g7c22 From b31327f072aa575d5ff97cc5e0786e50510ab456 Mon Sep 17 00:00:00 2001 From: it33 Date: Mon, 13 Jul 2015 23:40:40 -0700 Subject: Updating README_DEV.md with corrected forum links --- scripts/README_DEV.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/README_DEV.md b/scripts/README_DEV.md index 6a2dfc54d..be24daad9 100644 --- a/scripts/README_DEV.md +++ b/scripts/README_DEV.md @@ -10,7 +10,7 @@ DOCKER SETUP 3. Add a line to your /etc/hosts that goes ` dockerhost` 4. Run `boot2docker shellinit` and copy the export statements to your ~/.bash_profile -Any issues? Please let us know on our forums at: http://bit.ly/1MY1kul +Any issues? Please let us know on our forums at: http://forum.mattermost.org GO SETUP @@ -39,4 +39,4 @@ MATTERMOST SETUP 6. Then do `cd platform` and `make test`. Provided the test runs fine, you now have a complete build environment. 7. Use `make run` to run your code -Any issues? Please let us know on our forums at: http://bit.ly/1MY1kul \ No newline at end of file +Any issues? Please let us know on our forums at: http://forum.mattermost.org -- cgit v1.2.3-1-g7c22 From d9afa47ef803f3069427192acf839d21bb5a8d93 Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Tue, 14 Jul 2015 08:07:01 -0400 Subject: Revert "MM-831 Time change ping riding on the status interupt for timestamp update" --- web/react/components/post_list.jsx | 16 +--------------- web/react/components/post_right.jsx | 18 ++---------------- 2 files changed, 3 insertions(+), 31 deletions(-) diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index e73bc10cc..9349d0240 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -35,8 +35,6 @@ module.exports = React.createClass({ oldScrollHeight: 0, oldZoom: 0, scrolledToNew: false, - preForcePosision: 0, - wasForced: false, componentDidMount: function() { var user = UserStore.getCurrentUser(); if (user.props && user.props.theme) { @@ -52,7 +50,6 @@ module.exports = React.createClass({ PostStore.addChangeListener(this._onChange); ChannelStore.addChangeListener(this._onChange); - UserStore.addStatusesChangeListener(this._onTimeChange); SocketStore.addChangeListener(this._onSocketChange); $(".post-list-holder-by-time").perfectScrollbar(); @@ -82,11 +79,6 @@ module.exports = React.createClass({ }); $(post_holder).scroll(function(e){ - if (self.wasForced) { - $(post_holder).scrollTop(self.preForcePosision); - $(post_holder).perfectScrollbar('update'); - self.wasForced = false; - } if (!self.preventScrollTrigger) { self.scrollPosition = $(post_holder).scrollTop() + $(post_holder).innerHeight(); } @@ -137,7 +129,6 @@ module.exports = React.createClass({ componentWillUnmount: function() { PostStore.removeChangeListener(this._onChange); ChannelStore.removeChangeListener(this._onChange); - UserStore.removeStatusesChangeListener(this._onTimeChange); SocketStore.removeChangeListener(this._onSocketChange); $('body').off('click.userpopover'); }, @@ -170,7 +161,7 @@ module.exports = React.createClass({ this.scrolledToNew = false; } this.setState(newState); - } + } }, _onSocketChange: function(msg) { if (msg.action == "posted") { @@ -234,11 +225,6 @@ module.exports = React.createClass({ AsyncClient.getProfiles(); } }, - _onTimeChange: function() { - this.wasForced = true; - this.preForcePosision = $(".post-list-holder-by-time").scrollTop(); - this.forceUpdate(); - }, getMorePosts: function(e) { e.preventDefault(); diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx index 27195dfba..408fbf83a 100644 --- a/web/react/components/post_right.jsx +++ b/web/react/components/post_right.jsx @@ -281,11 +281,9 @@ function getStateFromStores() { } module.exports = React.createClass({ - wasForced: false, componentDidMount: function() { PostStore.addSelectedPostChangeListener(this._onChange); PostStore.addChangeListener(this._onChangeAll); - UserStore.addStatusesChangeListener(this._onTimeChange); this.resize(); var self = this; $(window).resize(function(){ @@ -293,15 +291,11 @@ module.exports = React.createClass({ }); }, componentDidUpdate: function() { - if(!this.wasForced){ - this.resize(); - this.wasForced = false; - } + this.resize(); }, componentWillUnmount: function() { PostStore.removeSelectedPostChangeListener(this._onChange); PostStore.removeChangeListener(this._onChangeAll); - UserStore.removeStatusesChangeListener(this._onTimeChange); }, _onChange: function() { if (this.isMounted()) { @@ -341,14 +335,6 @@ module.exports = React.createClass({ this.setState(getStateFromStores()); } }, - _onTimeChange: function() { - this.wasForced = true; - for (var key in this.refs) { - if(this.refs[key].forceUpdate != undefined) { - this.refs[key].forceUpdate(); - } - } - }, getInitialState: function() { return getStateFromStores(); }, @@ -408,7 +394,7 @@ module.exports = React.createClass({
      { posts_array.map(function(cpost) { - return + return })}
      -- cgit v1.2.3-1-g7c22 From 634df1c6242772e44fed5f64ac238adf2d0503a0 Mon Sep 17 00:00:00 2001 From: nickago Date: Tue, 14 Jul 2015 07:54:09 -0700 Subject: Added semicolons --- web/react/components/post_list.jsx | 2 +- web/react/components/post_right.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index e186fb706..99b1b514a 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -269,7 +269,7 @@ module.exports = React.createClass({ _onTimeChange: function() { this.wasForced = true; this.preForcePosision = $(".post-list-holder-by-time").scrollTop(); - this.forceUpdate() + this.forceUpdate(); }, getMorePosts: function(e) { e.preventDefault(); diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx index 0c3754529..ab818c1bd 100644 --- a/web/react/components/post_right.jsx +++ b/web/react/components/post_right.jsx @@ -299,7 +299,7 @@ module.exports = React.createClass({ componentWillUnmount: function() { PostStore.removeSelectedPostChangeListener(this._onChange); PostStore.removeChangeListener(this._onChangeAll); - UserStore.removeStatusesChangeListener(this._onTimeChange) + UserStore.removeStatusesChangeListener(this._onTimeChange); }, _onChange: function() { if (this.isMounted()) { -- cgit v1.2.3-1-g7c22 From 7ff57181b9aa182a7073a923004d63bbbe100e1d Mon Sep 17 00:00:00 2001 From: hmhealey Date: Tue, 14 Jul 2015 11:48:53 -0400 Subject: Changed image resizing for both the preview and thumbnail to use Lanczos interpolation instead of simple nearest neighbour --- api/file.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/file.go b/api/file.go index 0e08567d6..eaba515a4 100644 --- a/api/file.go +++ b/api/file.go @@ -13,9 +13,9 @@ import ( "github.com/mattermost/platform/model" "github.com/mattermost/platform/utils" "github.com/nfnt/resize" + _ "golang.org/x/image/bmp" "image" _ "image/gif" - _ "golang.org/x/image/bmp" "image/jpeg" "io" "net/http" @@ -157,7 +157,7 @@ func fireAndForgetHandleImages(filenames []string, fileData [][]byte, teamId, ch go func() { var thumbnail image.Image if imgConfig.Width > int(utils.Cfg.ImageSettings.ThumbnailWidth) { - thumbnail = resize.Resize(utils.Cfg.ImageSettings.ThumbnailWidth, utils.Cfg.ImageSettings.ThumbnailHeight, img, resize.NearestNeighbor) + thumbnail = resize.Resize(utils.Cfg.ImageSettings.ThumbnailWidth, utils.Cfg.ImageSettings.ThumbnailHeight, img, resize.Lanczos3) } else { thumbnail = img } @@ -182,7 +182,7 @@ func fireAndForgetHandleImages(filenames []string, fileData [][]byte, teamId, ch go func() { var preview image.Image if imgConfig.Width > int(utils.Cfg.ImageSettings.PreviewWidth) { - preview = resize.Resize(utils.Cfg.ImageSettings.PreviewWidth, utils.Cfg.ImageSettings.PreviewHeight, img, resize.NearestNeighbor) + preview = resize.Resize(utils.Cfg.ImageSettings.PreviewWidth, utils.Cfg.ImageSettings.PreviewHeight, img, resize.Lanczos3) } else { preview = img } -- cgit v1.2.3-1-g7c22 From fa4ac0c7890aa148122407feb2575470336099e1 Mon Sep 17 00:00:00 2001 From: nickago Date: Tue, 14 Jul 2015 12:08:00 -0700 Subject: Fixed minor typo --- web/react/components/post_body.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx index 2febcfa04..5f7dbe6c9 100644 --- a/web/react/components/post_body.jsx +++ b/web/react/components/post_body.jsx @@ -75,7 +75,7 @@ module.exports = React.createClass({ if(parentPost.message) { message = utils.replaceHtmlEntities(parentPost.message) } else if (parentPost.filenames.length) { - message = Date: Wed, 15 Jul 2015 08:45:17 -0700 Subject: Fixed typo, returned password flow to standard model --- web/react/components/user_settings.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/react/components/user_settings.jsx b/web/react/components/user_settings.jsx index b4c3747af..06d8d0208 100644 --- a/web/react/components/user_settings.jsx +++ b/web/react/components/user_settings.jsx @@ -626,7 +626,7 @@ var SecurityTab = React.createClass({ client.updatePassword(data, function(data) { - this.updateSection(""); + this.props.updateSection(""); AsyncClient.getMe(); this.setState({ current_password: '', new_password: '', confirm_password: '' }); }.bind(this), -- cgit v1.2.3-1-g7c22 From 42a213c54d0825e72cf5b85b6c379f20cdce7b75 Mon Sep 17 00:00:00 2001 From: Asaad Mahmood Date: Wed, 15 Jul 2015 22:32:08 +0500 Subject: Minor UI changes --- web/sass-files/sass/partials/_files.scss | 2 +- web/sass-files/sass/partials/_headers.scss | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web/sass-files/sass/partials/_files.scss b/web/sass-files/sass/partials/_files.scss index 79142176e..c584c240d 100644 --- a/web/sass-files/sass/partials/_files.scss +++ b/web/sass-files/sass/partials/_files.scss @@ -137,7 +137,7 @@ border: 1px solid #E2E2E2; background-color: #FFF; background-repeat: no-repeat; - background-position: left center; + background-position: top left; } a { text-decoration: none; diff --git a/web/sass-files/sass/partials/_headers.scss b/web/sass-files/sass/partials/_headers.scss index 7b0f24abf..338f5ceb4 100644 --- a/web/sass-files/sass/partials/_headers.scss +++ b/web/sass-files/sass/partials/_headers.scss @@ -75,7 +75,7 @@ // Team Header in Sidebar .sidebar--left, .sidebar--menu { .team__header { - padding: 15px; + padding: 10px; @include legacy-pie-clearfix; a { color: #fff; @@ -83,8 +83,8 @@ .navbar-right { font-size: 0.85em; position: absolute; - top: 24px; - right: 25px; + top: 20px; + right: 22px; .dropdown-toggle { padding: 0 10px; } -- cgit v1.2.3-1-g7c22