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(-) (limited to 'web/react') 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 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'web/react') 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 }
-- 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(-) (limited to 'web/react') 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(-) (limited to 'web/react') 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 ++++++++++-- 6 files changed, 99 insertions(+), 97 deletions(-) create mode 100644 web/react/components/loading_screen.jsx (limited to 'web/react') 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); + +}; -- cgit v1.2.3-1-g7c22 From 252d0f3924dd19aa4dd1900c6c00c41c84755d1e Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Sun, 12 Jul 2015 23:36:52 -0800 Subject: Fixes mm-1415 adding email bypass flag --- web/react/components/signup_user_complete.jsx | 33 +++++++++++++-------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'web/react') diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx index fb96cc99f..ef1eb1c62 100644 --- a/web/react/components/signup_user_complete.jsx +++ b/web/react/components/signup_user_complete.jsx @@ -46,25 +46,24 @@ module.exports = React.createClass({ function(data) { client.track('signup', 'signup_user_02_complete'); - if (data.email_verified) { - client.loginByEmail(this.props.domain, this.state.user.email, this.state.user.password, - function(data) { - UserStore.setLastDomain(this.props.domain); - UserStore.setLastEmail(this.state.user.email); - UserStore.setCurrentUser(data); - if (this.props.hash > 0) - BrowserStore.setGlobalItem(this.props.hash, JSON.stringify({wizard: "finished"})); - window.location.href = '/channels/town-square'; - }.bind(this), - function(err) { + client.loginByEmail(this.props.domain, this.state.user.email, this.state.user.password, + function(data) { + UserStore.setLastDomain(this.props.domain); + UserStore.setLastEmail(this.state.user.email); + UserStore.setCurrentUser(data); + if (this.props.hash > 0) + BrowserStore.setGlobalItem(this.props.hash, JSON.stringify({wizard: "finished"})); + window.location.href = '/channels/town-square'; + }.bind(this), + function(err) { + if (err.message == "Login failed because email address has not been verified") { + window.location.href = "/verify?email="+ encodeURIComponent(this.state.user.email) + "&domain=" + encodeURIComponent(this.props.domain); + } else { this.state.server_error = err.message; this.setState(this.state); - }.bind(this) - ); - } - else { - window.location.href = "/verify?email="+ encodeURIComponent(this.state.user.email) + "&domain=" + encodeURIComponent(this.props.domain); - } + } + }.bind(this) + ); }.bind(this), function(err) { this.state.server_error = err.message; -- 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(-) (limited to 'web/react') 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(-) (limited to 'web/react') 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 --- 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 +- 4 files changed, 7 insertions(+), 4 deletions(-) (limited to 'web/react') 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 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(+) (limited to 'web/react') 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(-) (limited to 'web/react') 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 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(-) (limited to 'web/react') 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) --- web/react/components/sidebar.jsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'web/react') 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 6e5126ba1d273e9576923a65d5b614314970f99f Mon Sep 17 00:00:00 2001 From: ralder Date: Mon, 13 Jul 2015 04:23:24 -0700 Subject: fix incorrect call for AsyncClient.dispatchError --- web/react/components/channel_header.jsx | 103 ++++++++++++-------------------- web/react/components/post_list.jsx | 2 +- web/react/components/search_bar.jsx | 37 +++++++----- web/react/components/search_results.jsx | 73 ++++++++++------------ 4 files changed, 92 insertions(+), 123 deletions(-) (limited to 'web/react') diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx index 68de80228..fe381a59e 100644 --- a/web/react/components/channel_header.jsx +++ b/web/react/components/channel_header.jsx @@ -1,6 +1,7 @@ // Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. + var ChannelStore = require('../stores/channel_store.jsx'); var UserStore = require('../stores/user_store.jsx'); var PostStore = require('../stores/post_store.jsx'); @@ -16,7 +17,7 @@ var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; -var ExtraMembers = React.createClass({ +var PopoverListMembers = React.createClass({ componentDidMount: function() { var originalLeave = $.fn.popover.Constructor.prototype.leave; $.fn.popover.Constructor.prototype.leave = function(obj) { @@ -35,30 +36,29 @@ var ExtraMembers = React.createClass({ $("#member_popover").popover({placement : 'bottom', trigger: 'click', html: true}); $('body').on('click', function (e) { - if ($(e.target.parentNode.parentNode)[0] !== $("#member_popover")[0] && $(e.target).parents('.popover.in').length === 0) { + if ($(e.target.parentNode.parentNode)[0] !== $("#member_popover")[0] && $(e.target).parents('.popover.in').length === 0) { $("#member_popover").popover('hide'); } }); - }, + render: function() { - var count = this.props.members.length == 0 ? "-" : this.props.members.length; - count = this.props.members.length > 19 ? "20+" : count; - var data_content = ""; - var sortedMembers = this.props.members; + var popoverHtml = ''; + var members = this.props.members; + var count = (members.length > 20) ? "20+" : (members.length || '-'); - if(sortedMembers) { - sortedMembers.sort(function(a,b) { + if (members) { + members.sort(function(a,b) { return a.username.localeCompare(b.username); - }) + }); - sortedMembers.forEach(function(m) { - data_content += "
        " + m.username + "
        "; + members.forEach(function(m) { + popoverHtml += "
        " + m.username + "
        "; }); } return ( -
        +
        {count}
        @@ -78,6 +78,7 @@ function getStateFromStores() { } module.exports = React.createClass({ + displayName: 'ChannelHeader', componentDidMount: function() { ChannelStore.addChangeListener(this._onChange); ChannelStore.addExtraInfoChangeListener(this._onChange); @@ -99,7 +100,7 @@ module.exports = React.createClass({ $(".channel-header__info .description").popover({placement : 'bottom', trigger: 'hover', html: true, delay: {show: 500, hide: 500}}); }, _onSocketChange: function(msg) { - if(msg.action === "new_user") { + if (msg.action === "new_user") { AsyncClient.getChannelExtraInfo(true); } }, @@ -107,15 +108,14 @@ module.exports = React.createClass({ return getStateFromStores(); }, handleLeave: function(e) { - var self = this; Client.leaveChannel(this.state.channel.id, function(data) { var townsquare = ChannelStore.getByName('town-square'); utils.switchChannel(townsquare); - }.bind(this), + }, function(err) { AsyncClient.dispatchError(err, "handleLeave"); - }.bind(this) + } ); }, searchMentions: function(e) { @@ -131,52 +131,29 @@ module.exports = React.createClass({ AppDispatcher.handleServerAction({ type: ActionTypes.RECIEVED_SEARCH_TERM, term: terms, - do_search: false + do_search: true, + is_mention_search: true }); - - Client.search( - terms, - function(data) { - AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH, - results: data, - is_mention_search: true - }); - }, - function(err) { - dispatchError(err, "search"); - } - ); }, + render: function() { if (this.state.channel == null) { - return ( -
        - ); + return null; } var description = utils.textToJsx(this.state.channel.description, {"singleline": true, "noMentionHighlight": true}); var popoverContent = React.renderToString(); - var channelTitle = ""; + var channelTitle = this.state.channel.display_name; var channelName = this.state.channel.name; var currentId = UserStore.getCurrentId(); var isAdmin = this.state.memberChannel.roles.indexOf("admin") > -1 || this.state.memberTeam.roles.indexOf("admin") > -1; - var searchForm = ; - var isDirect = false; - - if (this.state.channel.type === 'O') { - channelTitle = this.state.channel.display_name; - } else if (this.state.channel.type === 'P') { - channelTitle = this.state.channel.display_name; - } else if (this.state.channel.type === 'D') { - isDirect = true; + var isDirect = (this.state.channel.type === 'D'); + + if (isDirect) { if (this.state.users.length > 1) { - if (this.state.users[0].id === UserStore.getCurrentId()) { - channelTitle = ; - } else { - channelTitle = ; - } + var contact = this.state.users[((this.state.users[0].id === currentId) ? 1 : 0)]; + channelTitle = ; } } @@ -196,21 +173,21 @@ module.exports = React.createClass({
      • Add Members
      • { isAdmin ?
      • Manage Members
      • - : "" + : null } -
      • Set Channel Description...
      • -
      • Notification Preferences
      • +
      • Set Channel Description...
      • +
      • Notification Preferences
      • { isAdmin && channelName != Constants.DEFAULT_CHANNEL ? -
      • Rename Channel...
      • - : "" +
      • Rename Channel...
      • + : null } { isAdmin && channelName != Constants.DEFAULT_CHANNEL ? -
      • Delete Channel...
      • - : "" +
      • Delete Channel...
      • + : null } { channelName != Constants.DEFAULT_CHANNEL ?
      • Leave Channel
      • - : "" + : null }
      @@ -220,14 +197,14 @@ module.exports = React.createClass({ {channelTitle} } - - { searchForm } + + -
      + @@ -237,5 +214,3 @@ module.exports = React.createClass({ ); } }); - - diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index e6e028209..2a01b8089 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -297,7 +297,7 @@ module.exports = React.createClass({ }, function(err) { $(self.refs.loadmore.getDOMNode()).text("Load more messages"); - dispatchError(err, "getPosts"); + AsyncClient.dispatchError(err, "getPosts"); } ); }, diff --git a/web/react/components/search_bar.jsx b/web/react/components/search_bar.jsx index cddb738f9..ab7e99d60 100644 --- a/web/react/components/search_bar.jsx +++ b/web/react/components/search_bar.jsx @@ -3,6 +3,7 @@ var client = require('../utils/client.jsx'); +var AsyncClient = require('../utils/async_client.jsx'); var PostStore = require('../stores/post_store.jsx'); var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); var utils = require('../utils/utils.jsx'); @@ -10,14 +11,14 @@ var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; function getSearchTermStateFromStores() { - term = PostStore.getSearchTerm(); - if (!term) term = ""; + var term = PostStore.getSearchTerm() || ''; return { search_term: term }; } module.exports = React.createClass({ + displayName: 'SearchBar', componentDidMount: function() { PostStore.addSearchTermChangeListener(this._onChange); }, @@ -58,14 +59,14 @@ module.exports = React.createClass({ e.target.select(); }, performSearch: function(terms, isMentionSearch) { - if (terms.length > 0) { - $("#search-spinner").removeClass("hidden"); + if (terms.length) { + this.setState({isSearching: true}); client.search( terms, function(data) { - $("#search-spinner").addClass("hidden"); - if(utils.isMobile()) { - $('#search')[0].value = ""; + this.setState({isSearching: false}); + if (utils.isMobile()) { + React.findDOMNode(this.refs.search).value = ''; } AppDispatcher.handleServerAction({ @@ -73,18 +74,17 @@ module.exports = React.createClass({ results: data, is_mention_search: isMentionSearch }); - }, + }.bind(this), function(err) { - $("#search-spinner").addClass("hidden"); - dispatchError(err, "search"); - } + this.setState({isSearching: false}); + AsyncClient.dispatchError(err, "search"); + }.bind(this) ); } }, handleSubmit: function(e) { e.preventDefault(); - terms = this.state.search_term.trim(); - this.performSearch(terms); + this.performSearch(this.state.search_term.trim()); }, getInitialState: function() { return getSearchTermStateFromStores(); @@ -95,8 +95,15 @@ module.exports = React.createClass({
      - - + + {this.state.isSearching ? : null}
      ); diff --git a/web/react/components/search_results.jsx b/web/react/components/search_results.jsx index 156cf0120..1fd974642 100644 --- a/web/react/components/search_results.jsx +++ b/web/react/components/search_results.jsx @@ -8,12 +8,13 @@ var UserStore = require('../stores/user_store.jsx'); var UserProfile = require( './user_profile.jsx' ); var SearchBox =require('./search_bar.jsx'); var utils = require('../utils/utils.jsx'); -var client =require('../utils/client.jsx'); +var client = require('../utils/client.jsx'); +var AsyncClient = require('../utils/async_client.jsx'); var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; -RhsHeaderSearch = React.createClass({ +var RhsHeaderSearch = React.createClass({ handleClose: function(e) { e.preventDefault(); @@ -32,13 +33,13 @@ RhsHeaderSearch = React.createClass({ return (
      {title} - +
      ); } }); -SearchItem = React.createClass({ +var SearchItem = React.createClass({ handleClick: function(e) { e.preventDefault(); @@ -62,15 +63,16 @@ SearchItem = React.createClass({ }); }, function(err) { - dispatchError(err, "getPost"); + AsyncClient.dispatchError(err, "getPost"); } ); - var postChannel = ChannelStore.get(this.props.post.channel_id); - var teammate = postChannel.type === 'D' ? utils.getDirectTeammate(this.props.post.channel_id).username : ""; + var postChannel = ChannelStore.get(this.props.post.channel_id); + var teammate = postChannel.type === 'D' ? utils.getDirectTeammate(this.props.post.channel_id).username : ""; - utils.switchChannel(postChannel,teammate); + utils.switchChannel(postChannel, teammate); }, + render: function() { var message = utils.textToJsx(this.props.post.message, {searchTerm: this.props.term, noMentionHighlight: !this.props.isMentionSearch}); @@ -79,14 +81,10 @@ SearchItem = React.createClass({ var timestamp = UserStore.getCurrentUser().update_at; if (channel) { - if (channel.type === 'D') { - channelName = "Private Message"; - } else { - channelName = channel.display_name; - } + channelName = (channel.type === 'D') ? "Private Message" : channel.display_name; } - return ( + return (
      { channelName }
      @@ -95,7 +93,11 @@ SearchItem = React.createClass({
      • -
      • +
      • + +
      {message}
      @@ -104,11 +106,13 @@ SearchItem = React.createClass({ } }); + function getStateFromStores() { return { results: PostStore.getSearchResults() }; } module.exports = React.createClass({ + displayName: 'SearchResults', componentDidMount: function() { PostStore.addSearchChangeListener(this._onChange); this.resize(); @@ -144,41 +148,24 @@ module.exports = React.createClass({ var results = this.state.results; var currentId = UserStore.getCurrentId(); - var searchForm = currentId == null ? null : ; - - if (results == null) { - return ( -
      -
      Search Results
      -
      - ); - } + var searchForm = currentId ? : null; + var noResults = (!results || !results.order || !results.order.length); + var searchTerm = PostStore.getSearchTerm(); - if (!results.order || results.order.length == 0) { - return ( -
      -
      {searchForm}
      -
      - -
      -
      No results
      -
      -
      -
      - ); - } - - var self = this; return (
      {searchForm}
      - {results.order.map(function(id) { - var post = results.posts[id]; - return - })} + + { noResults ?
      No results
      + : results.order.map(function(id) { + var post = results.posts[id]; + return + }, this) + } +
      -- 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(+) (limited to 'web/react') 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(-) (limited to 'web/react') 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 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'web/react') 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 } +
      ); -- 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(-) (limited to 'web/react') 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 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(-) (limited to 'web/react') 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 9f816e25545b7487d3078813ffd0e120a3a100cd Mon Sep 17 00:00:00 2001 From: nickago Date: Tue, 14 Jul 2015 11:55:49 -0700 Subject: Need you GDev key for youtube stuff --- web/react/utils/utils.jsx | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'web/react') diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 5ded0e76f..f3fe3a992 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -303,18 +303,25 @@ var getYoutubeEmbed = function(link) { }; var success = function(data) { - $('.video-uploader.'+youtubeId).html(data.data.uploader); - $('.video-title.'+youtubeId).find('a').html(data.data.title); + if(!data.items.length || !data.items[0].snippet) { + return; + } + metadata = data.items[0].snippet; + $('.video-uploader.'+youtubeId).html(metadata.channelTitle); + $('.video-title.'+youtubeId).find('a').html(metadata.title); $(".post-list-holder-by-time").scrollTop($(".post-list-holder-by-time")[0].scrollHeight); $(".post-list-holder-by-time").perfectScrollbar('update'); }; - $.ajax({ - async: true, - url: 'https://gdata.youtube.com/feeds/api/videos/'+youtubeId+'?v=2&alt=jsonc', - type: 'GET', - success: success - }); + if(config.GoogleDeveloperKey) { + $.ajax({ + async: true, + url: "https://www.googleapis.com/youtube/v3/videos", + type: 'GET', + data: {part:"snippet", id:youtubeId, key:config.GoogleDeveloperKey}, + success: success + }); + } return (
      -- 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(-) (limited to 'web/react') 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: Tue, 14 Jul 2015 13:09:14 -0700 Subject: Team admin can now delete any post --- web/react/components/post_info.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'web/react') diff --git a/web/react/components/post_info.jsx b/web/react/components/post_info.jsx index cf01747f0..48efa95ba 100644 --- a/web/react/components/post_info.jsx +++ b/web/react/components/post_info.jsx @@ -11,6 +11,7 @@ module.exports = React.createClass({ render: function() { var post = this.props.post; var isOwner = UserStore.getCurrentId() == post.user_id; + var isAdmin = UserStore.getCurrentUser().roles.indexOf("admin") > -1 var type = "Post" if (post.root_id.length > 0) { @@ -36,7 +37,7 @@ module.exports = React.createClass({
        { isOwner ?
      • Edit
      • : "" } - { isOwner ?
      • Delete
      • + { isOwner || isAdmin ?
      • Delete
      • : "" } { this.props.allowReply === "true" ?
      • Reply
      • : "" } -- cgit v1.2.3-1-g7c22 From 46e076529a15da3b5dd63070fbb8e887dba9b436 Mon Sep 17 00:00:00 2001 From: nickago 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(-) (limited to 'web/react') 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 c1e23faab71443bb7af6a74cc5705e000b66f53f Mon Sep 17 00:00:00 2001 From: nickago Date: Wed, 15 Jul 2015 09:13:34 -0700 Subject: Changed scope of 'metatdata' --- web/react/utils/utils.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'web/react') diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index f3fe3a992..b8747b8fc 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -306,7 +306,7 @@ var getYoutubeEmbed = function(link) { if(!data.items.length || !data.items[0].snippet) { return; } - metadata = data.items[0].snippet; + var metadata = data.items[0].snippet; $('.video-uploader.'+youtubeId).html(metadata.channelTitle); $('.video-title.'+youtubeId).find('a').html(metadata.title); $(".post-list-holder-by-time").scrollTop($(".post-list-holder-by-time")[0].scrollHeight); -- cgit v1.2.3-1-g7c22 From 56db6ad08cf23dbdcee326fa39bda8bcdcdecf9e Mon Sep 17 00:00:00 2001 From: ralder Date: Wed, 15 Jul 2015 09:03:28 -0700 Subject: remove admin's ability to manage members of default channel (fixes #172) --- web/react/components/channel_header.jsx | 33 ++++--- web/react/components/navbar.jsx | 159 ++++++++++++++++---------------- web/react/components/post_list.jsx | 3 +- web/react/components/sidebar_header.jsx | 48 ++++------ web/react/stores/channel_store.jsx | 53 ++++------- web/react/stores/user_store.jsx | 2 +- 6 files changed, 137 insertions(+), 161 deletions(-) (limited to 'web/react') diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx index fe381a59e..6791233d5 100644 --- a/web/react/components/channel_header.jsx +++ b/web/react/components/channel_header.jsx @@ -142,10 +142,10 @@ module.exports = React.createClass({ return null; } - var description = utils.textToJsx(this.state.channel.description, {"singleline": true, "noMentionHighlight": true}); - var popoverContent = React.renderToString(); - var channelTitle = this.state.channel.display_name; - var channelName = this.state.channel.name; + var channel = this.state.channel; + var description = utils.textToJsx(channel.description, {"singleline": true, "noMentionHighlight": true}); + var popoverContent = React.renderToString(); + var channelTitle = channel.display_name; var currentId = UserStore.getCurrentId(); var isAdmin = this.state.memberChannel.roles.indexOf("admin") > -1 || this.state.memberTeam.roles.indexOf("admin") > -1; var isDirect = (this.state.channel.type === 'D'); @@ -169,23 +169,26 @@ module.exports = React.createClass({
          -
        • View Info
        • -
        • Add Members
        • - { isAdmin ? +
        • View Info
        • + { !ChannelStore.isDefault(channel) ? +
        • Add Members
        • + : null + } + { isAdmin && !ChannelStore.isDefault(channel) ?
        • Manage Members
        • : null } -
        • Set Channel Description...
        • -
        • Notification Preferences
        • - { isAdmin && channelName != Constants.DEFAULT_CHANNEL ? -
        • Rename Channel...
        • +
        • Set Channel Description...
        • +
        • Notification Preferences
        • + { isAdmin && !ChannelStore.isDefault(channel) ? +
        • Rename Channel...
        • : null } - { isAdmin && channelName != Constants.DEFAULT_CHANNEL ? -
        • Delete Channel...
        • + { isAdmin && !ChannelStore.isDefault(channel) ? +
        • Delete Channel...
        • : null } - { channelName != Constants.DEFAULT_CHANNEL ? + { !ChannelStore.isDefault(channel) ?
        • Leave Channel
        • : null } @@ -197,7 +200,7 @@ module.exports = React.createClass({ {channelTitle} } - +
          diff --git a/web/react/components/navbar.jsx b/web/react/components/navbar.jsx index 35f7d9044..78cf7d8b8 100644 --- a/web/react/components/navbar.jsx +++ b/web/react/components/navbar.jsx @@ -2,21 +2,20 @@ // See License.txt for license information. -var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); var utils = require('../utils/utils.jsx'); var client = require('../utils/client.jsx'); var AsyncClient = require('../utils/async_client.jsx'); -var Sidebar = require('./sidebar.jsx'); var UserStore = require('../stores/user_store.jsx'); -var SocketStore = require('../stores/socket_store.jsx'); var ChannelStore = require('../stores/channel_store.jsx'); -var Constants = require('../utils/constants.jsx'); + var UserProfile = require('./user_profile.jsx'); var MessageWrapper = require('./message_wrapper.jsx'); + +var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; +var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); function getCountsStateFromStores() { - var count = 0; var channels = ChannelStore.getAll(); var members = ChannelStore.getAllMembers(); @@ -34,7 +33,7 @@ function getCountsStateFromStores() { } }); - return { count: count } + return { count: count }; } var NotifyCounts = React.createClass({ @@ -54,11 +53,10 @@ var NotifyCounts = React.createClass({ return getCountsStateFromStores(); }, render: function() { - if (this.state.count == 0) { - return (); - } - else { - return ({ this.state.count }); + if (this.state.count) { + return { this.state.count }; + } else { + return null; } } }); @@ -66,25 +64,25 @@ var NotifyCounts = React.createClass({ var NavbarLoginForm = React.createClass({ handleSubmit: function(e) { e.preventDefault(); - var state = { } + var state = { }; var domain = this.refs.domain.getDOMNode().value.trim(); if (!domain) { - state.server_error = "A domain is required" + state.server_error = "A domain is required"; this.setState(state); return; } var email = this.refs.email.getDOMNode().value.trim(); if (!email) { - state.server_error = "An email is required" + state.server_error = "An email is required"; this.setState(state); return; } var password = this.refs.password.getDOMNode().value.trim(); if (!password) { - state.server_error = "A password is required" + state.server_error = "A password is required"; this.setState(state); return; } @@ -105,7 +103,7 @@ var NavbarLoginForm = React.createClass({ window.location.href = '/channels/town-square'; } - }.bind(this), + }, function(err) { if (err.message == "Login failed because email address has not been verified") { window.location.href = '/verify?domain=' + encodeURIComponent(domain) + '&email=' + encodeURIComponent(email); @@ -159,13 +157,14 @@ function getStateFromStores() { } module.exports = React.createClass({ + displayName: 'Navbar', + componentDidMount: function() { ChannelStore.addChangeListener(this._onChange); ChannelStore.addExtraInfoChangeListener(this._onChange); - var self = this; - $('.inner__wrap').click(self.hideSidebars); + $('.inner__wrap').click(this.hideSidebars); - $('body').on('click.infopopover', function(e){ + $('body').on('click.infopopover', function(e) { if ($(e.target).attr('data-toggle') !== 'popover' && $(e.target).parents('.popover.in').length === 0) { $('.info-popover').popover('hide'); @@ -181,13 +180,13 @@ module.exports = React.createClass({ }, handleLeave: function(e) { client.leaveChannel(this.state.channel.id, - function(data) { + function() { AsyncClient.getChannels(true); window.location.href = '/channels/town-square'; - }.bind(this), + }, function(err) { AsyncClient.dispatchError(err, "handleLeave"); - }.bind(this) + } ); }, hideSidebars: function(e) { @@ -204,7 +203,7 @@ module.exports = React.createClass({ }); if (e.target.className != 'navbar-toggle' && e.target.className != 'icon-bar') { - $('.inner__wrap').removeClass('move--right').removeClass('move--left').removeClass('move--left-small'); + $('.inner__wrap').removeClass('move--right move--left move--left-small'); $('.sidebar--left').removeClass('move--right'); $('.sidebar--right').removeClass('move--left'); $('.sidebar--menu').removeClass('move--left'); @@ -229,24 +228,22 @@ module.exports = React.createClass({ render: function() { var currentId = UserStore.getCurrentId(); - var channelName = ""; var popoverContent = ""; var channelTitle = this.props.teamName; var isAdmin = false; var isDirect = false; var description = "" + var channel = this.state.channel; - if (this.state.channel) { - var channel = this.state.channel; - description = utils.textToJsx(this.state.channel.description, {"singleline": true, "noMentionHighlight": true}); - popoverContent = React.renderToString(); - channelName = this.state.channel.name; + if (channel) { + description = utils.textToJsx(channel.description, {"singleline": true, "noMentionHighlight": true}); + popoverContent = React.renderToString(); isAdmin = this.state.member.roles.indexOf("admin") > -1; if (channel.type === 'O') { - channelTitle = this.state.channel.display_name; + channelTitle = channel.display_name; } else if (channel.type === 'P') { - channelTitle = this.state.channel.display_name; + channelTitle = channel.display_name; } else if (channel.type === 'D') { isDirect = true; if (this.state.users.length > 1) { @@ -258,12 +255,11 @@ module.exports = React.createClass({ } } - if(this.state.channel.description.length == 0){ - popoverContent = React.renderToString(
          No channel description yet.
          Click here to add one.
          ); + if (channel.description.length == 0) { + popoverContent = React.renderToString(
          No channel description yet.
          Click here to add one.
          ); } } - var loginForm = currentId == null ? : null; var navbar_collapse_button = currentId != null ? null :
          ); -} + } }); - - diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index 98491976f..573799a19 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -6,7 +6,6 @@ var ChannelStore = require('../stores/channel_store.jsx'); var UserStore = require('../stores/user_store.jsx'); 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'); @@ -341,7 +340,7 @@ module.exports = React.createClass({ } } - if (channel.name === Constants.DEFAULT_CHANNEL) { + if (ChannelStore.isDefault(channel)) { more_messages = (

          Welcome

          diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 54858a04d..334fc6780 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -37,17 +37,13 @@ var NavbarDropdown = React.createClass({ var invite_link = ""; var manage_link = ""; var rename_link = ""; - var currentUser = UserStore.getCurrentUser() + var currentUser = UserStore.getCurrentUser(); var isAdmin = false; if (currentUser != null) { isAdmin = currentUser.roles.indexOf("admin") > -1; - invite_link = ( -
        • - Invite New Member -
        • - ); + invite_link = (
        • Invite New Member
        • ); if (this.props.teamType == "O") { team_link = ( @@ -59,16 +55,8 @@ var NavbarDropdown = React.createClass({ } if (isAdmin) { - manage_link = ( -
        • - Manage Team -
        • - ); - rename_link = ( -
        • - Rename -
        • - ); + manage_link = (
        • Manage Team
        • ); + rename_link = (
        • Rename
        • ); } var teams = []; @@ -95,7 +83,7 @@ var NavbarDropdown = React.createClass({
          • Account Settings
          • - { isAdmin ?
          • Team Settings
          • : "" } + { isAdmin ?
          • Team Settings
          • : null } { invite_link } { team_link } { manage_link } @@ -113,28 +101,30 @@ var NavbarDropdown = React.createClass({ }); module.exports = React.createClass({ - handleSubmit: function(e) { - e.preventDefault(); - }, - getInitialState: function() { - return { }; + displayName: 'SidebarHeader', + + getDefaultProps: function() { + return { + teamName: config.SiteName + }; }, + render: function() { - var teamName = this.props.teamName ? this.props.teamName : config.SiteName; - var me = UserStore.getCurrentUser() + var me = UserStore.getCurrentUser(); + + if (!me) { + return null; + } return (
            -
            @{me.username}
            - { teamName } +
            {'@' + me.username}
            + {this.props.teamName}
          ); } }); - - - diff --git a/web/react/stores/channel_store.jsx b/web/react/stores/channel_store.jsx index 4a27e5f17..a97f13391 100644 --- a/web/react/stores/channel_store.jsx +++ b/web/react/stores/channel_store.jsx @@ -44,40 +44,24 @@ var ChannelStore = assign({}, EventEmitter.prototype, { removeExtraInfoChangeListener: function(callback) { this.removeListener(EXTRA_INFO_EVENT, callback); }, - get: function(id) { - var current = null; - var c = this._getChannels(); - - c.some(function(channel) { - if (channel.id == id) { - current = channel; - return true; + findFirstBy: function(field, value) { + var channels = this._getChannels(); + for (var i = 0; i < channels.length; i++) { + if (channels[i][field] == value) { + return channels[i]; } - return false; - }); + } - return current; + return null; + }, + get: function(id) { + return this.findFirstBy('id', id); }, getMember: function(id) { - var current = null; return this.getAllMembers()[id]; }, getByName: function(name) { - var current = null; - var c = this._getChannels(); - - c.some(function(channel) { - if (channel.name == name) { - current = channel; - return true; - } - - return false; - - }); - - return current; - + return this.findFirstBy('name', name); }, getAll: function() { return this._getChannels(); @@ -120,7 +104,7 @@ var ChannelStore = assign({}, EventEmitter.prototype, { getCurrent: function() { var currentId = this.getCurrentId(); - if (currentId != null) + if (currentId) return this.get(currentId); else return null; @@ -128,7 +112,7 @@ var ChannelStore = assign({}, EventEmitter.prototype, { getCurrentMember: function() { var currentId = ChannelStore.getCurrentId(); - if (currentId != null) + if (currentId) return this.getAllMembers()[currentId]; else return null; @@ -143,7 +127,7 @@ var ChannelStore = assign({}, EventEmitter.prototype, { var currentId = ChannelStore.getCurrentId(); var extra = null; - if (currentId != null) + if (currentId) extra = this._getExtraInfos()[currentId]; if (extra == null) @@ -154,7 +138,7 @@ var ChannelStore = assign({}, EventEmitter.prototype, { getExtraInfo: function(channel_id) { var extra = null; - if (channel_id != null) + if (channel_id) extra = this._getExtraInfos()[channel_id]; if (extra == null) @@ -192,7 +176,10 @@ var ChannelStore = assign({}, EventEmitter.prototype, { }, _getExtraInfos: function() { return BrowserStore.getItem("extra_infos", {}); - } + }, + isDefault: function(channel) { + return channel.name == Constants.DEFAULT_CHANNEL; + } }); ChannelStore.dispatchToken = AppDispatcher.register(function(payload) { @@ -231,4 +218,4 @@ ChannelStore.dispatchToken = AppDispatcher.register(function(payload) { } }); -module.exports = ChannelStore; +module.exports = ChannelStore; \ No newline at end of file diff --git a/web/react/stores/user_store.jsx b/web/react/stores/user_store.jsx index 93ddfec70..dd207ca80 100644 --- a/web/react/stores/user_store.jsx +++ b/web/react/stores/user_store.jsx @@ -177,7 +177,7 @@ var UserStore = assign({}, EventEmitter.prototype, { }, getCurrentMentionKeys: function() { var user = this.getCurrentUser(); - if (user.notify_props && user.notify_props.mention_keys) { + if (user && user.notify_props && user.notify_props.mention_keys) { var keys = user.notify_props.mention_keys.split(','); if (user.full_name.length > 0 && user.notify_props.first_name === "true") { -- cgit v1.2.3-1-g7c22 From 6e67be40544f537d624f7f4449b8fcb97e338fb3 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Fri, 19 Jun 2015 16:04:33 -0700 Subject: Added framework for handling up and down arrow key presses to move between different @mention choices --- web/react/components/mention_list.jsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'web/react') diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 103ff29bb..3796d465f 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -56,6 +56,22 @@ module.exports = React.createClass({ this.setState({ mentionText: '-1' }); }, + handleKeyDown: function(e) { + var selectedMention = this.state.selectedMention ? this.state.selectedMention : 1; + + // Need to be able to know number of mentions, use in conditionals & still + // need to figure out how to highlight the mention I want every time. + // Remember separate Mention Ref within for, second if statement in render + // Maybe have the call there instead? Ehhh maybe not but need that to be able + // to "select" it maybe... + if (e.key === "ArrowUp") { + selectedMention = selectedMention === ? 1 : selectedMention++; + } + else if (e.key === "ArrowDown") { + selectedMention = selectedMention === 1 ? : selectedMention--; + } + this.setState({selectedMention: selectedMention}); + } addFirstMention: function() { if (!this.refs.mention0) return; this.refs.mention0.handleClick(); @@ -144,7 +160,7 @@ module.exports = React.createClass({ return (
          -
          +
          { mentions }
          -- cgit v1.2.3-1-g7c22 From f635376aa45e2fbaa30698949a0c991ea06aa320 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Fri, 19 Jun 2015 16:04:56 -0700 Subject: Added comma --- web/react/components/mention_list.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'web/react') diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 3796d465f..a2c6f0ff7 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -71,7 +71,7 @@ module.exports = React.createClass({ selectedMention = selectedMention === 1 ? : selectedMention--; } this.setState({selectedMention: selectedMention}); - } + }, addFirstMention: function() { if (!this.refs.mention0) return; this.refs.mention0.handleClick(); -- cgit v1.2.3-1-g7c22 From 924fd8609bb0b512cd60c1f345ec22dcb6bf0612 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Mon, 22 Jun 2015 17:39:55 -0700 Subject: Changed parts of framework --- web/react/components/mention_list.jsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index a2c6f0ff7..115ab1b2a 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -56,8 +56,8 @@ module.exports = React.createClass({ this.setState({ mentionText: '-1' }); }, - handleKeyDown: function(e) { - var selectedMention = this.state.selectedMention ? this.state.selectedMention : 1; + handleKeyDown: function(e, numMentions) { + var selectedMention = this.state.selectedMention <= nunMentions ? this.state.selectedMention : 1; // Need to be able to know number of mentions, use in conditionals & still // need to figure out how to highlight the mention I want every time. @@ -65,10 +65,10 @@ module.exports = React.createClass({ // Maybe have the call there instead? Ehhh maybe not but need that to be able // to "select" it maybe... if (e.key === "ArrowUp") { - selectedMention = selectedMention === ? 1 : selectedMention++; + selectedMention = selectedMention === numMentions ? 1 : selectedMention++; } else if (e.key === "ArrowDown") { - selectedMention = selectedMention === 1 ? : selectedMention--; + selectedMention = selectedMention === 1 ? numMentions : selectedMention--; } this.setState({selectedMention: selectedMention}); }, @@ -89,7 +89,7 @@ module.exports = React.createClass({ return false; }, getInitialState: function() { - return { excludeUsers: [], mentionText: "-1" }; + return { excludeUsers: [], mentionText: "-1", selectedMention: 1 }; }, render: function() { var mentionText = this.state.mentionText; @@ -158,9 +158,11 @@ module.exports = React.createClass({ left: $mention_tab.offset().left }; + //mentions[this.state.selectedMention].focus(); + return (
          -
          +
          { mentions }
          -- cgit v1.2.3-1-g7c22 From 63b9dd85b6efd9d292d4d79240e00b7d27e6616c Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Fri, 10 Jul 2015 09:49:44 -0700 Subject: Changed model of handling key down and focus change --- web/react/components/mention.jsx | 19 +++++++++++++++++- web/react/components/mention_list.jsx | 38 ++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 17 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx index 520b81cbb..7a8045134 100644 --- a/web/react/components/mention.jsx +++ b/web/react/components/mention.jsx @@ -6,6 +6,23 @@ module.exports = React.createClass({ handleClick: function() { this.props.handleClick(this.props.username); }, + handleKeyDown: function(e) { + var selectedMention = this.state.selectedMention <= nunMentions ? this.state.selectedMention : 1; + + console.log("Here: keyDown"); + + if (e.key === "ArrowUp") { + //selectedMention = selectedMention === numMentions ? 1 : selectedMention++; + this.props.handleFocus(this.props.listId); + } + else if (e.key === "ArrowDown") { + //selectedMention = selectedMention === 1 ? numMentions : selectedMention--; + this.props.handleFocus(this.props.listId); + } + else if (e.key === "Enter") { + this.handleClick(); + } + }, render: function() { var icon; var timestamp = UserStore.getCurrentUser().update_at; @@ -15,7 +32,7 @@ module.exports = React.createClass({ icon = ; } return ( -
          +
          {icon}
          @{this.props.username}{this.props.secondary_text}
          diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 115ab1b2a..c5b4030c8 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -18,6 +18,8 @@ module.exports = React.createClass({ componentDidMount: function() { PostStore.addMentionDataChangeListener(this._onChange); + console.log("here!"); + var self = this; $('body').on('keypress.mentionlist', '#'+this.props.id, function(e) { @@ -26,6 +28,16 @@ module.exports = React.createClass({ e.preventDefault(); self.addFirstMention(); } + if (!self.isEmpty() && self.state.mentionText != '-1' && e.which === 38) { + e.stopPropagation(); + e.preventDefault(); + self.handleFocus(0); + } + if (!self.isEmpty() && self.state.mentionText != '-1' && e.which === 40) { + e.stopPropagation(); + e.preventDefault(); + self.addFirstMention(UserStore.getActiveOnlyProfiles().length - 1); + } } ); $(document).click(function(e) { @@ -56,21 +68,13 @@ module.exports = React.createClass({ this.setState({ mentionText: '-1' }); }, - handleKeyDown: function(e, numMentions) { - var selectedMention = this.state.selectedMention <= nunMentions ? this.state.selectedMention : 1; - - // Need to be able to know number of mentions, use in conditionals & still - // need to figure out how to highlight the mention I want every time. - // Remember separate Mention Ref within for, second if statement in render - // Maybe have the call there instead? Ehhh maybe not but need that to be able - // to "select" it maybe... - if (e.key === "ArrowUp") { - selectedMention = selectedMention === numMentions ? 1 : selectedMention++; - } - else if (e.key === "ArrowDown") { - selectedMention = selectedMention === 1 ? numMentions : selectedMention--; - } - this.setState({selectedMention: selectedMention}); + handleFocus: function(listId) { + console.log("here! 1"); + var mention = this.refs['mention' + index]; + if (!mention) return; + var mentionRef = mention.refs.mention; + mentionRef.getDOMNode().focus(); + console.log("here! 2"); }, addFirstMention: function() { if (!this.refs.mention0) return; @@ -140,6 +144,8 @@ module.exports = React.createClass({ username={users[i].username} secondary_text={users[i].secondary_text} id={users[i].id} + listId={index} + handleFocus={this.handleFocus} handleClick={this.handleClick} /> ); index++; @@ -162,7 +168,7 @@ module.exports = React.createClass({ return (
          -
          +
          { mentions }
          -- cgit v1.2.3-1-g7c22 From 59b2a42ac89ca03a196bf5d20d617174a5bc30bb Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Sat, 11 Jul 2015 12:57:28 -0700 Subject: Have arrow key selection working, but visually does not highlight correct mention. Also if user continues to type things might get weird. --- web/react/components/mention.jsx | 23 ++++++++++++-- web/react/components/mention_list.jsx | 56 ++++++++++++++++++++++++----------- 2 files changed, 59 insertions(+), 20 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx index 7a8045134..abb6ae5c6 100644 --- a/web/react/components/mention.jsx +++ b/web/react/components/mention.jsx @@ -6,22 +6,41 @@ module.exports = React.createClass({ handleClick: function() { this.props.handleClick(this.props.username); }, - handleKeyDown: function(e) { + /*handleUp: function(e) { var selectedMention = this.state.selectedMention <= nunMentions ? this.state.selectedMention : 1; console.log("Here: keyDown"); if (e.key === "ArrowUp") { //selectedMention = selectedMention === numMentions ? 1 : selectedMention++; + e.preventDefault(); this.props.handleFocus(this.props.listId); } else if (e.key === "ArrowDown") { //selectedMention = selectedMention === 1 ? numMentions : selectedMention--; + e.preventDefault(); this.props.handleFocus(this.props.listId); } else if (e.key === "Enter") { + e.preventDefault(); this.handleClick(); } + },*/ + handleFocus: function() { + console.log("Entering " + this.props.listId); + this.setState({ isFocused: "mentions-focus" }) + }, + handleBlur: function() { + console.log("Leaving " + this.props.listId); + this.setState({ isFocused: "" }); + }, + getInitialState: function() { + if (this.props.isFocus) { + return { isFocused: "mentions-focus" }; + } + else { + return { isFocused: "" }; + } }, render: function() { var icon; @@ -32,7 +51,7 @@ module.exports = React.createClass({ icon = ; } return ( -
          +
          {icon}
          @{this.props.username}{this.props.secondary_text}
          diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index c5b4030c8..882b0d6ad 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -17,26 +17,44 @@ module.exports = React.createClass({ displayName: "MentionList", componentDidMount: function() { PostStore.addMentionDataChangeListener(this._onChange); - - console.log("here!"); - var self = this; $('body').on('keypress.mentionlist', '#'+this.props.id, function(e) { - if (!self.isEmpty() && self.state.mentionText != '-1' && e.which === 13) { + if (!self.isEmpty() && self.state.mentionText != '-1' && (e.which === 13 || e.which === 9)) { + e.stopPropagation(); + e.preventDefault(); + self.addCurrentMention(); + } + } + ); + $('body').on('keydown.mentionlist', '#'+this.props.id, + function(e) { + console.log("here! top"); + if (!self.isEmpty() && self.state.mentionText != '-1' && (e.which === 13 || e.which === 9)) { e.stopPropagation(); e.preventDefault(); - self.addFirstMention(); + self.addCurrentMention(); } if (!self.isEmpty() && self.state.mentionText != '-1' && e.which === 38) { + console.log("here! 38"); e.stopPropagation(); e.preventDefault(); - self.handleFocus(0); + + if (self.handleSelection(self.state.selectedMention - 1)) + self.setState({ selectedMention: self.state.selectedMention - 1 }); + else { + self.setState({ selectedMention: 0}); + } } if (!self.isEmpty() && self.state.mentionText != '-1' && e.which === 40) { + console.log("here! 40"); e.stopPropagation(); e.preventDefault(); - self.addFirstMention(UserStore.getActiveOnlyProfiles().length - 1); + + if (self.handleSelection(self.state.selectedMention + 1)) + self.setState({ selectedMention: self.state.selectedMention + 1 }); + else + self.setState({ selectedMention: 0 }); } } ); @@ -68,13 +86,17 @@ module.exports = React.createClass({ this.setState({ mentionText: '-1' }); }, - handleFocus: function(listId) { + handleSelection: function(listId) { console.log("here! 1"); - var mention = this.refs['mention' + index]; - if (!mention) return; - var mentionRef = mention.refs.mention; - mentionRef.getDOMNode().focus(); - console.log("here! 2"); + var mention = this.refs['mention' + listId]; + if (!mention) + return false; + else + return true; + }, + addCurrentMention: function() { + if (!this.refs['mention' + this.state.selectedMention]) return; + this.refs['mention' + this.state.selectedMention].handleClick(); }, addFirstMention: function() { if (!this.refs.mention0) return; @@ -93,7 +115,7 @@ module.exports = React.createClass({ return false; }, getInitialState: function() { - return { excludeUsers: [], mentionText: "-1", selectedMention: 1 }; + return { excludeUsers: [], mentionText: "-1", selectedMention: 0 }; }, render: function() { var mentionText = this.state.mentionText; @@ -138,14 +160,14 @@ module.exports = React.createClass({ if (firstName.lastIndexOf(mentionText,0) === 0 || lastName.lastIndexOf(mentionText,0) === 0 || users[i].username.lastIndexOf(mentionText,0) === 0) { - mentions[i+1] = ( + mentions[index] = ( ); index++; @@ -164,8 +186,6 @@ module.exports = React.createClass({ left: $mention_tab.offset().left }; - //mentions[this.state.selectedMention].focus(); - return (
          -- cgit v1.2.3-1-g7c22 From 9cc3d3428521fbc3a31def4f4780275d763a4011 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Sat, 11 Jul 2015 14:25:18 -0700 Subject: Highlighting now occurs as you arrow key thru mention list. However some small bugs remain. --- web/react/components/mention.jsx | 28 ++---------------- web/react/components/mention_list.jsx | 55 +++++++++++++++++------------------ 2 files changed, 30 insertions(+), 53 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx index abb6ae5c6..4abf8d0df 100644 --- a/web/react/components/mention.jsx +++ b/web/react/components/mention.jsx @@ -6,32 +6,10 @@ module.exports = React.createClass({ handleClick: function() { this.props.handleClick(this.props.username); }, - /*handleUp: function(e) { - var selectedMention = this.state.selectedMention <= nunMentions ? this.state.selectedMention : 1; - - console.log("Here: keyDown"); - - if (e.key === "ArrowUp") { - //selectedMention = selectedMention === numMentions ? 1 : selectedMention++; - e.preventDefault(); - this.props.handleFocus(this.props.listId); - } - else if (e.key === "ArrowDown") { - //selectedMention = selectedMention === 1 ? numMentions : selectedMention--; - e.preventDefault(); - this.props.handleFocus(this.props.listId); - } - else if (e.key === "Enter") { - e.preventDefault(); - this.handleClick(); - } - },*/ - handleFocus: function() { - console.log("Entering " + this.props.listId); + select: function() { this.setState({ isFocused: "mentions-focus" }) }, - handleBlur: function() { - console.log("Leaving " + this.props.listId); + deselect: function() { this.setState({ isFocused: "" }); }, getInitialState: function() { @@ -51,7 +29,7 @@ module.exports = React.createClass({ icon = ; } return ( -
          +
          {icon}
          @{this.props.username}{this.props.secondary_text}
          diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 882b0d6ad..0bef41905 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -18,43 +18,42 @@ module.exports = React.createClass({ componentDidMount: function() { PostStore.addMentionDataChangeListener(this._onChange); var self = this; - $('body').on('keypress.mentionlist', '#'+this.props.id, - function(e) { - if (!self.isEmpty() && self.state.mentionText != '-1' && (e.which === 13 || e.which === 9)) { - e.stopPropagation(); - e.preventDefault(); - self.addCurrentMention(); - } - } - ); + $('body').on('keydown.mentionlist', '#'+this.props.id, function(e) { - console.log("here! top"); if (!self.isEmpty() && self.state.mentionText != '-1' && (e.which === 13 || e.which === 9)) { e.stopPropagation(); e.preventDefault(); self.addCurrentMention(); } - if (!self.isEmpty() && self.state.mentionText != '-1' && e.which === 38) { - console.log("here! 38"); + else if (!self.isEmpty() && self.state.mentionText != '-1' && (e.which === 38 || e.which === 40)) { e.stopPropagation(); e.preventDefault(); - if (self.handleSelection(self.state.selectedMention - 1)) - self.setState({ selectedMention: self.state.selectedMention - 1 }); + if (!self.getSelection(self.state.selectedMention)) { + self.setState({ selectedMention: 0 }); + self.refs['mention' + self.state.selectedMention].deselect(); + } else { - self.setState({ selectedMention: 0}); + self.refs['mention' + self.state.selectedMention].deselect(); + if (e.which === 38) { + if (self.getSelection(self.state.selectedMention - 1)) + self.setState({ selectedMention: self.state.selectedMention - 1 }); + else { + var tempSelectedMention = -1; + while (self.getSelection(++tempSelectedMention)) + ; + self.setState({ selectedMention: tempSelectedMention - 1 }); + } + } + else { + if (self.getSelection(self.state.selectedMention + 1)) + self.setState({ selectedMention: self.state.selectedMention + 1 }); + else + self.setState({ selectedMention: 0 }); + } } - } - if (!self.isEmpty() && self.state.mentionText != '-1' && e.which === 40) { - console.log("here! 40"); - e.stopPropagation(); - e.preventDefault(); - - if (self.handleSelection(self.state.selectedMention + 1)) - self.setState({ selectedMention: self.state.selectedMention + 1 }); - else - self.setState({ selectedMention: 0 }); + self.refs['mention' + self.state.selectedMention].select(); } } ); @@ -86,8 +85,7 @@ module.exports = React.createClass({ this.setState({ mentionText: '-1' }); }, - handleSelection: function(listId) { - console.log("here! 1"); + getSelection: function(listId) { var mention = this.refs['mention' + listId]; if (!mention) return false; @@ -95,7 +93,7 @@ module.exports = React.createClass({ return true; }, addCurrentMention: function() { - if (!this.refs['mention' + this.state.selectedMention]) return; + if (!this.refs['mention' + this.state.selectedMention]) this.addFirstMention(); this.refs['mention' + this.state.selectedMention].handleClick(); }, addFirstMention: function() { @@ -173,6 +171,7 @@ module.exports = React.createClass({ index++; } } + var numMentions = Object.keys(mentions).length; if (numMentions < 1) return null; -- cgit v1.2.3-1-g7c22 From ce9756e44dcdc1dedb46337f492f4ede8719fdd8 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Sun, 12 Jul 2015 12:34:51 -0700 Subject: Improved selection logic when using both the mouse and arrow keys --- web/react/components/mention.jsx | 3 ++- web/react/components/mention_list.jsx | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx index 4abf8d0df..1f6d1bcf1 100644 --- a/web/react/components/mention.jsx +++ b/web/react/components/mention.jsx @@ -21,6 +21,7 @@ module.exports = React.createClass({ } }, render: function() { + var self = this; var icon; var timestamp = UserStore.getCurrentUser().update_at; if (this.props.id != null) { @@ -29,7 +30,7 @@ module.exports = React.createClass({ icon = ; } return ( -
          +
          {icon}
          @{this.props.username}{this.props.secondary_text}
          diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 0bef41905..6b1d98cf6 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -32,7 +32,7 @@ module.exports = React.createClass({ if (!self.getSelection(self.state.selectedMention)) { self.setState({ selectedMention: 0 }); - self.refs['mention' + self.state.selectedMention].deselect(); + //self.refs['mention' + self.state.selectedMention].deselect(); } else { self.refs['mention' + self.state.selectedMention].deselect(); @@ -54,6 +54,8 @@ module.exports = React.createClass({ } } self.refs['mention' + self.state.selectedMention].select(); + + //self.checkIfInView('#'+self.props.id); } } ); @@ -85,6 +87,13 @@ module.exports = React.createClass({ this.setState({ mentionText: '-1' }); }, + handleMouseEnter: function(listId) { + if (this.getSelection(this.state.selectedMention)) { + this.refs['mention' + this.state.selectedMention].deselect(); + } + this.setState({ selectedMention: listId }); + this.refs['mention' + listId].select(); + }, getSelection: function(listId) { var mention = this.refs['mention' + listId]; if (!mention) @@ -103,6 +112,15 @@ module.exports = React.createClass({ isEmpty: function() { return (!this.refs.mention0); }, + checkIfInView: function(element) { + var offset = element.offset().top - $(window).scrollTop(); + if(offset > window.innerHeight){ + // Not in view so scroll to it + $('body').animate({scrollTop: offset}, 1000); + return false; + } + return true; + }, alreadyMentioned: function(username) { var excludeUsers = this.state.excludeUsers; for (var i = 0; i < excludeUsers.length; i++) { @@ -113,7 +131,7 @@ module.exports = React.createClass({ return false; }, getInitialState: function() { - return { excludeUsers: [], mentionText: "-1", selectedMention: 0 }; + return { excludeUsers: [], mentionText: "-1", selectedMention: 0, selectedUsername: "" }; }, render: function() { var mentionText = this.state.mentionText; @@ -166,6 +184,7 @@ module.exports = React.createClass({ id={users[i].id} listId={index} isFocus={this.state.selectedMention === index ? true : false} + handleMouseEnter={this.handleMouseEnter} handleClick={this.handleClick} /> ); index++; -- cgit v1.2.3-1-g7c22 From 6f93cbb490b41ec206b66018090f34e690a145a3 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Sun, 12 Jul 2015 12:49:33 -0700 Subject: When moving from a mention lower in the list to one higher in the list by typing more, now properly highlights --- web/react/components/mention_list.jsx | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'web/react') diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 6b1d98cf6..e6b2f5e04 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -70,6 +70,11 @@ module.exports = React.createClass({ PostStore.removeMentionDataChangeListener(this._onChange); $('body').off('keypress.mentionlist', '#'+this.props.id); }, + componentDidUpdate: function() { + if (this.state.mentionText != "-1" && !this.getSelection(this.state.selectedMention)) { + this.refs.mention0.select(); + } + }, _onChange: function(id, mentionText, excludeList) { if (id !== this.props.id) return; -- cgit v1.2.3-1-g7c22 From da228fc167494962dd222835510ff3a7db2e3a24 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Sun, 12 Jul 2015 18:39:14 -0700 Subject: Minor changes towards getting interior scrolling working with arrow keys --- web/react/components/mention_list.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index e6b2f5e04..92a843bc5 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -55,7 +55,8 @@ module.exports = React.createClass({ } self.refs['mention' + self.state.selectedMention].select(); - //self.checkIfInView('#'+self.props.id); + self.checkIfInView($('#'+self.props.id)); + self.checkIfInView($('#'+self.refs['mention' + self.state.selectedMention].props.id)); } } ); @@ -118,10 +119,10 @@ module.exports = React.createClass({ return (!this.refs.mention0); }, checkIfInView: function(element) { - var offset = element.offset().top - $(window).scrollTop(); + var offset = element.offset().top - $(window).scrollTop(); //$(this.props.id) ?? if(offset > window.innerHeight){ // Not in view so scroll to it - $('body').animate({scrollTop: offset}, 1000); + $('body').animate({scrollTop: offset}, 1000); //$(this.props.id) ?? return false; } return true; @@ -136,7 +137,7 @@ module.exports = React.createClass({ return false; }, getInitialState: function() { - return { excludeUsers: [], mentionText: "-1", selectedMention: 0, selectedUsername: "" }; + return { excludeUsers: [], mentionText: "-1", selectedMention: 0 }; }, render: function() { var mentionText = this.state.mentionText; -- cgit v1.2.3-1-g7c22 From 346f727949866083d8fd94763c6df5660424c850 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Mon, 13 Jul 2015 09:53:39 -0700 Subject: Better handling of previous highlight when you backspace (therefore re-enlarging the number of mentions) --- web/react/components/mention_list.jsx | 57 +++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 12 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 92a843bc5..9dd80ebd5 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -31,32 +31,40 @@ module.exports = React.createClass({ e.preventDefault(); if (!self.getSelection(self.state.selectedMention)) { - self.setState({ selectedMention: 0 }); + //self.setState({ selectedMention: 0, selectedUsername: self.refs.mention0.props.username }); //self.refs['mention' + self.state.selectedMention].deselect(); + var tempSelectedMention = -1 + while (self.getSelection(++tempSelectedMention)) { + if (self.state.selectedUsername === self.refs['mention' + tempSelectedMention].props.username) { + this.refs['mention' + tempSelectedMention].select(); + this.setState({ selectedMention: tempSelectedMention }); + break; + } + } } else { self.refs['mention' + self.state.selectedMention].deselect(); if (e.which === 38) { if (self.getSelection(self.state.selectedMention - 1)) - self.setState({ selectedMention: self.state.selectedMention - 1 }); + self.setState({ selectedMention: self.state.selectedMention - 1, selectedUsername: self.refs['mention' + (self.state.selectedMention - 1)].props.username }); else { var tempSelectedMention = -1; while (self.getSelection(++tempSelectedMention)) ; - self.setState({ selectedMention: tempSelectedMention - 1 }); + self.setState({ selectedMention: tempSelectedMention - 1, selectedUsername: self.refs['mention' + (tempSelectedMention - 1)].props.username }); } } else { if (self.getSelection(self.state.selectedMention + 1)) - self.setState({ selectedMention: self.state.selectedMention + 1 }); + self.setState({ selectedMention: self.state.selectedMention + 1, selectedUsername: self.refs['mention' + (self.state.selectedMention + 1)].props.username }); else - self.setState({ selectedMention: 0 }); + self.setState({ selectedMention: 0, selectedUsername: self.refs.mention0.props.username }); } } self.refs['mention' + self.state.selectedMention].select(); - self.checkIfInView($('#'+self.props.id)); - self.checkIfInView($('#'+self.refs['mention' + self.state.selectedMention].props.id)); + //self.checkIfInView($('#'+self.props.id)); + //self.checkIfInView($('#'+self.refs['mention' + self.state.selectedMention].props.id)); } } ); @@ -69,11 +77,36 @@ module.exports = React.createClass({ }, componentWillUnmount: function() { PostStore.removeMentionDataChangeListener(this._onChange); - $('body').off('keypress.mentionlist', '#'+this.props.id); + $('body').off('keydown.mentionlist', '#'+this.props.id); + }, + componentWillUpdate: function() { + if (this.state.mentionText != "-1" && this.getSelection(this.state.selectedMention)) { + this.refs['mention' + this.state.selectedMention].deselect(); + } }, componentDidUpdate: function() { - if (this.state.mentionText != "-1" && !this.getSelection(this.state.selectedMention)) { - this.refs.mention0.select(); + /*if (this.state.mentionText != "-1" && !this.getSelection(this.state.selectedMention)) { + }*/ + if (this.state.mentionText != "-1" /*&& this.getSelection(this.state.selectedMention)*/) { + if (this.state.selectedUsername !== "" && (!this.getSelection(this.state.selectedMention) || this.state.selectedUsername !== this.refs['mention' + this.state.selectedMention].props.username)) { + var tempSelectedMention = -1; + var foundMatch = false; + while (this.getSelection(++tempSelectedMention)) { + if (this.state.selectedUsername === this.refs['mention' + tempSelectedMention].props.username) { + this.refs['mention' + tempSelectedMention].select(); + this.setState({ selectedMention: tempSelectedMention }); + foundMatch = true; + break; + } + } + if (!foundMatch) { + this.refs.mention0.select(); + this.setState({ selectedMention: 0, selectedUsername: this.refs.mention0.props.username }); + } + } + else { + this.refs['mention' + this.state.selectedMention].select(); + } } }, _onChange: function(id, mentionText, excludeList) { @@ -97,7 +130,7 @@ module.exports = React.createClass({ if (this.getSelection(this.state.selectedMention)) { this.refs['mention' + this.state.selectedMention].deselect(); } - this.setState({ selectedMention: listId }); + this.setState({ selectedMention: listId, selectedUsername: this.refs['mention' + listId].props.username }); this.refs['mention' + listId].select(); }, getSelection: function(listId) { @@ -137,7 +170,7 @@ module.exports = React.createClass({ return false; }, getInitialState: function() { - return { excludeUsers: [], mentionText: "-1", selectedMention: 0 }; + return { excludeUsers: [], mentionText: "-1", selectedMention: 0, selectedUsername: "" }; }, render: function() { var mentionText = this.state.mentionText; -- cgit v1.2.3-1-g7c22 From 4bb2451bd5ac7f570e510a0cb96c14f0b17e4fab Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Mon, 13 Jul 2015 13:11:03 -0700 Subject: Minor changes and tweaks trying to get scrolling to work --- web/react/components/mention_list.jsx | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 9dd80ebd5..ab511e424 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -50,7 +50,7 @@ module.exports = React.createClass({ else { var tempSelectedMention = -1; while (self.getSelection(++tempSelectedMention)) - ; + ; //Need to find the top of the list self.setState({ selectedMention: tempSelectedMention - 1, selectedUsername: self.refs['mention' + (tempSelectedMention - 1)].props.username }); } } @@ -64,7 +64,10 @@ module.exports = React.createClass({ self.refs['mention' + self.state.selectedMention].select(); //self.checkIfInView($('#'+self.props.id)); - //self.checkIfInView($('#'+self.refs['mention' + self.state.selectedMention].props.id)); + self.checkIfInView(); + //console.log('#'+self.refs['mention' + self.state.selectedMention].props.id); + //console.log($('#'+self.refs['mention' + self.state.selectedMention].props.id)); + //console.log($('#'+self.props.id)); } } ); @@ -85,9 +88,7 @@ module.exports = React.createClass({ } }, componentDidUpdate: function() { - /*if (this.state.mentionText != "-1" && !this.getSelection(this.state.selectedMention)) { - }*/ - if (this.state.mentionText != "-1" /*&& this.getSelection(this.state.selectedMention)*/) { + if (this.state.mentionText != "-1") { if (this.state.selectedUsername !== "" && (!this.getSelection(this.state.selectedMention) || this.state.selectedUsername !== this.refs['mention' + this.state.selectedMention].props.username)) { var tempSelectedMention = -1; var foundMatch = false; @@ -141,8 +142,10 @@ module.exports = React.createClass({ return true; }, addCurrentMention: function() { - if (!this.refs['mention' + this.state.selectedMention]) this.addFirstMention(); - this.refs['mention' + this.state.selectedMention].handleClick(); + if (!this.refs['mention' + this.state.selectedMention]) + this.addFirstMention(); + else + this.refs['mention' + this.state.selectedMention].handleClick(); }, addFirstMention: function() { if (!this.refs.mention0) return; @@ -151,14 +154,20 @@ module.exports = React.createClass({ isEmpty: function() { return (!this.refs.mention0); }, - checkIfInView: function(element) { - var offset = element.offset().top - $(window).scrollTop(); //$(this.props.id) ?? - if(offset > window.innerHeight){ + checkIfInView: function() { + var element = $('#'+this.refs['mention' + this.state.selectedMention].props.id); + //var top = $('.mentions-box').position().bottom; + //$(".mentions-box").css("bottom", top+303); + //$("#"+this.props.id).scrollTop($("#"+this.props.id).scrollTop() + $("div.mentions-name.mentions-focused").position().top); + console.log(element.length); + console.log(element + " " + element.offset()); + var offset = element.offset().bottom - $('#'+this.props.id).scrollTop(); //$(this.props.id) ?? + if(offset > $('#'+this.props.id).innerHeight){ // Not in view so scroll to it $('body').animate({scrollTop: offset}, 1000); //$(this.props.id) ?? return false; } - return true; + return true; }, alreadyMentioned: function(username) { var excludeUsers = this.state.excludeUsers; -- cgit v1.2.3-1-g7c22 From 61e7b9b2be969212dbb3577ef734a27620a525be Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Tue, 14 Jul 2015 16:13:31 -0700 Subject: Getting scrolling working with the arrow keys --- web/react/components/mention.jsx | 2 +- web/react/components/mention_list.jsx | 57 ++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 16 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx index 1f6d1bcf1..3f6ec4a7b 100644 --- a/web/react/components/mention.jsx +++ b/web/react/components/mention.jsx @@ -30,7 +30,7 @@ module.exports = React.createClass({ icon = ; } return ( -
          +
          {icon}
          @{this.props.username}{this.props.secondary_text}
          diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index ab511e424..2f4f92e24 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -30,6 +30,8 @@ module.exports = React.createClass({ e.stopPropagation(); e.preventDefault(); + var tempSelectedMention = -1 + if (!self.getSelection(self.state.selectedMention)) { //self.setState({ selectedMention: 0, selectedUsername: self.refs.mention0.props.username }); //self.refs['mention' + self.state.selectedMention].deselect(); @@ -64,7 +66,7 @@ module.exports = React.createClass({ self.refs['mention' + self.state.selectedMention].select(); //self.checkIfInView($('#'+self.props.id)); - self.checkIfInView(); + self.checkIfInView(e.which, tempSelectedMention); //console.log('#'+self.refs['mention' + self.state.selectedMention].props.id); //console.log($('#'+self.refs['mention' + self.state.selectedMention].props.id)); //console.log($('#'+self.props.id)); @@ -154,20 +156,43 @@ module.exports = React.createClass({ isEmpty: function() { return (!this.refs.mention0); }, - checkIfInView: function() { - var element = $('#'+this.refs['mention' + this.state.selectedMention].props.id); - //var top = $('.mentions-box').position().bottom; - //$(".mentions-box").css("bottom", top+303); - //$("#"+this.props.id).scrollTop($("#"+this.props.id).scrollTop() + $("div.mentions-name.mentions-focused").position().top); - console.log(element.length); - console.log(element + " " + element.offset()); - var offset = element.offset().bottom - $('#'+this.props.id).scrollTop(); //$(this.props.id) ?? - if(offset > $('#'+this.props.id).innerHeight){ - // Not in view so scroll to it - $('body').animate({scrollTop: offset}, 1000); //$(this.props.id) ?? - return false; + checkIfInView: function(keyPressed, ifLoopUp) { + var element = $('#'+this.refs['mention' + this.state.selectedMention].props.id +"_mentions"); + var offset = element.offset().top - $("#mentionsbox").scrollTop(); + var direction = keyPressed === 38 ? "up" : "down"; + console.log("element offset top: " + $(element).offset().top + " box offset top: " + $("#mentionsbox").offset().top); + var scrollAmount; + if (direction === "up" && ifLoopUp !== -1) { + /*$("#mentionsbox").animate({ + scrollTop: ("#mentionsbox").offset().top + }, 50);*/ + scrollAmount = $("#mentionsbox").offset().top; + } + else if (direction === "down" && !this.refs['mention' + this.state.selectedMention].props.listId) { + /*$("#mentionsbox").animate({ + scrollTop: 0 + }, 50);*/ + scrollAmount = 0; + } + else if (direction === "up") { + /*$("#mentionsbox").animate({ + scrollTop: '-=28' + }, 50);*/ + scrollAmount = "-=28"; + } + else if (direction === "down") { + /*$("#mentionsbox").animate({ + scrollTop: '+=28' + }, 50);*/ + scrollAmount = "+=28"; } - return true; + $("#mentionsbox").animate({ + scrollTop: scrollAmount + }, 50); + /*$("#mentionsbox").animate({ + scrollTop: $(element).offset().top - $("#mentionsbox").offset().top + //scrollTop: $(element).offset().top - $("#mentionsbox").offset().top + }, 50);*/ }, alreadyMentioned: function(username) { var excludeUsers = this.state.excludeUsers; @@ -195,12 +220,14 @@ module.exports = React.createClass({ all.username = "all"; all.full_name = ""; all.secondary_text = "Notifies everyone in the team"; + all.id = "allmention"; users.push(all); var channel = {}; channel.username = "channel"; channel.full_name = ""; channel.secondary_text = "Notifies everyone in the channel"; + channel.id = "channelmention"; users.push(channel); users.sort(function(a,b) { @@ -254,7 +281,7 @@ module.exports = React.createClass({ return (
          -
          +
          { mentions }
          -- cgit v1.2.3-1-g7c22 From 9747053a4e017e64a21278981fe43573385488a0 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Tue, 14 Jul 2015 18:36:54 -0700 Subject: Fixes not selecting an element that hasn't been scrolled to --- web/react/components/mention.jsx | 4 +- web/react/components/mention_list.jsx | 70 ++++++++++++----------------------- 2 files changed, 27 insertions(+), 47 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx index 3f6ec4a7b..24098516e 100644 --- a/web/react/components/mention.jsx +++ b/web/react/components/mention.jsx @@ -24,7 +24,9 @@ module.exports = React.createClass({ var self = this; var icon; var timestamp = UserStore.getCurrentUser().update_at; - if (this.props.id != null) { + if (this.props.id === "allmention" || this.props.id === "channelmention") { + icon = ; + } else if (this.props.id != null) { icon = ; diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 2f4f92e24..7cc90e36f 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -33,9 +33,6 @@ module.exports = React.createClass({ var tempSelectedMention = -1 if (!self.getSelection(self.state.selectedMention)) { - //self.setState({ selectedMention: 0, selectedUsername: self.refs.mention0.props.username }); - //self.refs['mention' + self.state.selectedMention].deselect(); - var tempSelectedMention = -1 while (self.getSelection(++tempSelectedMention)) { if (self.state.selectedUsername === self.refs['mention' + tempSelectedMention].props.username) { this.refs['mention' + tempSelectedMention].select(); @@ -50,7 +47,6 @@ module.exports = React.createClass({ if (self.getSelection(self.state.selectedMention - 1)) self.setState({ selectedMention: self.state.selectedMention - 1, selectedUsername: self.refs['mention' + (self.state.selectedMention - 1)].props.username }); else { - var tempSelectedMention = -1; while (self.getSelection(++tempSelectedMention)) ; //Need to find the top of the list self.setState({ selectedMention: tempSelectedMention - 1, selectedUsername: self.refs['mention' + (tempSelectedMention - 1)].props.username }); @@ -65,11 +61,10 @@ module.exports = React.createClass({ } self.refs['mention' + self.state.selectedMention].select(); - //self.checkIfInView($('#'+self.props.id)); - self.checkIfInView(e.which, tempSelectedMention); - //console.log('#'+self.refs['mention' + self.state.selectedMention].props.id); - //console.log($('#'+self.refs['mention' + self.state.selectedMention].props.id)); - //console.log($('#'+self.props.id)); + self.scrollToMention(e.which, tempSelectedMention); + } + else if (e.which === 46 || e.which === 8) { + self.setState({ lessText: true }); } } ); @@ -94,7 +89,7 @@ module.exports = React.createClass({ if (this.state.selectedUsername !== "" && (!this.getSelection(this.state.selectedMention) || this.state.selectedUsername !== this.refs['mention' + this.state.selectedMention].props.username)) { var tempSelectedMention = -1; var foundMatch = false; - while (this.getSelection(++tempSelectedMention)) { + while (!this.state.lessText && this.getSelection(++tempSelectedMention)) { if (this.state.selectedUsername === this.refs['mention' + tempSelectedMention].props.username) { this.refs['mention' + tempSelectedMention].select(); this.setState({ selectedMention: tempSelectedMention }); @@ -102,15 +97,18 @@ module.exports = React.createClass({ break; } } - if (!foundMatch) { + if (this.refs.mention0 != undefined && !foundMatch) { this.refs.mention0.select(); - this.setState({ selectedMention: 0, selectedUsername: this.refs.mention0.props.username }); + this.setState({ selectedMention: 0, selectedUsername: this.refs.mention0.props.username, lessText: false }); } } - else { + else if (this.refs['mention' + this.state.selectedMention] != undefined) { this.refs['mention' + this.state.selectedMention].select(); } } + else if (this.state.selectedMention !== 0) { + this.setState({ selectedMention: 0, selectedUsername: "" }); + } }, _onChange: function(id, mentionText, excludeList) { if (id !== this.props.id) return; @@ -118,6 +116,7 @@ module.exports = React.createClass({ var newState = this.state; if (mentionText != null) newState.mentionText = mentionText; if (excludeList != null) newState.excludeUsers = excludeList; + this.setState(newState); }, handleClick: function(name) { @@ -156,43 +155,22 @@ module.exports = React.createClass({ isEmpty: function() { return (!this.refs.mention0); }, - checkIfInView: function(keyPressed, ifLoopUp) { - var element = $('#'+this.refs['mention' + this.state.selectedMention].props.id +"_mentions"); - var offset = element.offset().top - $("#mentionsbox").scrollTop(); + scrollToMention: function(keyPressed, ifLoopUp) { var direction = keyPressed === 38 ? "up" : "down"; - console.log("element offset top: " + $(element).offset().top + " box offset top: " + $("#mentionsbox").offset().top); - var scrollAmount; - if (direction === "up" && ifLoopUp !== -1) { - /*$("#mentionsbox").animate({ - scrollTop: ("#mentionsbox").offset().top - }, 50);*/ - scrollAmount = $("#mentionsbox").offset().top; - } - else if (direction === "down" && !this.refs['mention' + this.state.selectedMention].props.listId) { - /*$("#mentionsbox").animate({ - scrollTop: 0 - }, 50);*/ + var scrollAmount = 0; + + if (direction === "up" && ifLoopUp !== -1) + scrollAmount = $("#mentionsbox").innerHeight() + 10000000; //innerHeight is not the real height of the box in the RHS sometimes; this compensates as it should always go to the bottom anyway + else if (direction === "down" && this.refs['mention' + this.state.selectedMention].props.listId === 0) scrollAmount = 0; - } - else if (direction === "up") { - /*$("#mentionsbox").animate({ - scrollTop: '-=28' - }, 50);*/ - scrollAmount = "-=28"; - } - else if (direction === "down") { - /*$("#mentionsbox").animate({ - scrollTop: '+=28' - }, 50);*/ - scrollAmount = "+=28"; - } + else if (direction === "up") + scrollAmount = "-=" + ($('#'+this.refs['mention' + this.state.selectedMention].props.id +"_mentions").innerHeight() - 5); + else if (direction === "down") + scrollAmount = "+=" + ($('#'+this.refs['mention' + this.state.selectedMention].props.id +"_mentions").innerHeight() - 5); + $("#mentionsbox").animate({ scrollTop: scrollAmount }, 50); - /*$("#mentionsbox").animate({ - scrollTop: $(element).offset().top - $("#mentionsbox").offset().top - //scrollTop: $(element).offset().top - $("#mentionsbox").offset().top - }, 50);*/ }, alreadyMentioned: function(username) { var excludeUsers = this.state.excludeUsers; @@ -204,7 +182,7 @@ module.exports = React.createClass({ return false; }, getInitialState: function() { - return { excludeUsers: [], mentionText: "-1", selectedMention: 0, selectedUsername: "" }; + return { excludeUsers: [], mentionText: "-1", selectedMention: 0, selectedUsername: "", lessText: false }; }, render: function() { var mentionText = this.state.mentionText; -- cgit v1.2.3-1-g7c22 From c5c4c0b4de6275ca3f4188c07d2d0d88ba230bd1 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Tue, 14 Jul 2015 19:59:09 -0700 Subject: Few minor bug fixes --- web/react/components/mention_list.jsx | 50 ++++++++++++----------------------- 1 file changed, 17 insertions(+), 33 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 7cc90e36f..17c513714 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -31,41 +31,26 @@ module.exports = React.createClass({ e.preventDefault(); var tempSelectedMention = -1 - - if (!self.getSelection(self.state.selectedMention)) { - while (self.getSelection(++tempSelectedMention)) { - if (self.state.selectedUsername === self.refs['mention' + tempSelectedMention].props.username) { - this.refs['mention' + tempSelectedMention].select(); - this.setState({ selectedMention: tempSelectedMention }); - break; - } + self.refs['mention' + self.state.selectedMention].deselect(); + if (e.which === 38) { + if (self.getSelection(self.state.selectedMention - 1)) + self.setState({ selectedMention: self.state.selectedMention - 1, selectedUsername: self.refs['mention' + (self.state.selectedMention - 1)].props.username }); + else { + while (self.getSelection(++tempSelectedMention)) + ; //Need to find the top of the list + self.setState({ selectedMention: tempSelectedMention - 1, selectedUsername: self.refs['mention' + (tempSelectedMention - 1)].props.username }); } } else { - self.refs['mention' + self.state.selectedMention].deselect(); - if (e.which === 38) { - if (self.getSelection(self.state.selectedMention - 1)) - self.setState({ selectedMention: self.state.selectedMention - 1, selectedUsername: self.refs['mention' + (self.state.selectedMention - 1)].props.username }); - else { - while (self.getSelection(++tempSelectedMention)) - ; //Need to find the top of the list - self.setState({ selectedMention: tempSelectedMention - 1, selectedUsername: self.refs['mention' + (tempSelectedMention - 1)].props.username }); - } - } - else { - if (self.getSelection(self.state.selectedMention + 1)) - self.setState({ selectedMention: self.state.selectedMention + 1, selectedUsername: self.refs['mention' + (self.state.selectedMention + 1)].props.username }); - else - self.setState({ selectedMention: 0, selectedUsername: self.refs.mention0.props.username }); - } + if (self.getSelection(self.state.selectedMention + 1)) + self.setState({ selectedMention: self.state.selectedMention + 1, selectedUsername: self.refs['mention' + (self.state.selectedMention + 1)].props.username }); + else + self.setState({ selectedMention: 0, selectedUsername: self.refs.mention0.props.username }); } - self.refs['mention' + self.state.selectedMention].select(); + self.refs['mention' + self.state.selectedMention].select(); self.scrollToMention(e.which, tempSelectedMention); } - else if (e.which === 46 || e.which === 8) { - self.setState({ lessText: true }); - } } ); $(document).click(function(e) { @@ -89,7 +74,7 @@ module.exports = React.createClass({ if (this.state.selectedUsername !== "" && (!this.getSelection(this.state.selectedMention) || this.state.selectedUsername !== this.refs['mention' + this.state.selectedMention].props.username)) { var tempSelectedMention = -1; var foundMatch = false; - while (!this.state.lessText && this.getSelection(++tempSelectedMention)) { + while (tempSelectedMention < this.state.selectedMention && this.getSelection(++tempSelectedMention)) { if (this.state.selectedUsername === this.refs['mention' + tempSelectedMention].props.username) { this.refs['mention' + tempSelectedMention].select(); this.setState({ selectedMention: tempSelectedMention }); @@ -99,7 +84,7 @@ module.exports = React.createClass({ } if (this.refs.mention0 != undefined && !foundMatch) { this.refs.mention0.select(); - this.setState({ selectedMention: 0, selectedUsername: this.refs.mention0.props.username, lessText: false }); + this.setState({ selectedMention: 0, selectedUsername: this.refs.mention0.props.username }); } } else if (this.refs['mention' + this.state.selectedMention] != undefined) { @@ -136,8 +121,7 @@ module.exports = React.createClass({ this.refs['mention' + listId].select(); }, getSelection: function(listId) { - var mention = this.refs['mention' + listId]; - if (!mention) + if (!this.refs['mention' + listId]) return false; else return true; @@ -182,7 +166,7 @@ module.exports = React.createClass({ return false; }, getInitialState: function() { - return { excludeUsers: [], mentionText: "-1", selectedMention: 0, selectedUsername: "", lessText: false }; + return { excludeUsers: [], mentionText: "-1", selectedMention: 0, selectedUsername: "" }; }, render: function() { var mentionText = this.state.mentionText; -- cgit v1.2.3-1-g7c22 From cbcf44ac8506d316d57a7e0bb30baad258618bdb Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Tue, 14 Jul 2015 20:14:23 -0700 Subject: Minor changes to scroll 'feel' and logic flow --- web/react/components/mention_list.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 17c513714..1852a3ebc 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -41,7 +41,7 @@ module.exports = React.createClass({ self.setState({ selectedMention: tempSelectedMention - 1, selectedUsername: self.refs['mention' + (tempSelectedMention - 1)].props.username }); } } - else { + else if (e.which === 40) { if (self.getSelection(self.state.selectedMention + 1)) self.setState({ selectedMention: self.state.selectedMention + 1, selectedUsername: self.refs['mention' + (self.state.selectedMention + 1)].props.username }); else @@ -82,12 +82,12 @@ module.exports = React.createClass({ break; } } - if (this.refs.mention0 != undefined && !foundMatch) { + if (this.getSelection(0) && !foundMatch) { this.refs.mention0.select(); this.setState({ selectedMention: 0, selectedUsername: this.refs.mention0.props.username }); } } - else if (this.refs['mention' + this.state.selectedMention] != undefined) { + else if (this.getSelection(this.state.selectedMention)) { this.refs['mention' + this.state.selectedMention].select(); } } @@ -144,7 +144,7 @@ module.exports = React.createClass({ var scrollAmount = 0; if (direction === "up" && ifLoopUp !== -1) - scrollAmount = $("#mentionsbox").innerHeight() + 10000000; //innerHeight is not the real height of the box in the RHS sometimes; this compensates as it should always go to the bottom anyway + scrollAmount = $("#mentionsbox").height() * 100; //Makes sure that it scrolls all the way to the bottom else if (direction === "down" && this.refs['mention' + this.state.selectedMention].props.listId === 0) scrollAmount = 0; else if (direction === "up") @@ -154,7 +154,7 @@ module.exports = React.createClass({ $("#mentionsbox").animate({ scrollTop: scrollAmount - }, 50); + }, 75); }, alreadyMentioned: function(username) { var excludeUsers = this.state.excludeUsers; -- cgit v1.2.3-1-g7c22 From 15b90ff72f7db4d611c5c5035e2d8cd310d4deff Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Tue, 14 Jul 2015 20:35:52 -0700 Subject: Added missing semi-colons --- web/react/components/mention.jsx | 2 +- web/react/components/mention_list.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx index 24098516e..f5ca4ce6d 100644 --- a/web/react/components/mention.jsx +++ b/web/react/components/mention.jsx @@ -7,7 +7,7 @@ module.exports = React.createClass({ this.props.handleClick(this.props.username); }, select: function() { - this.setState({ isFocused: "mentions-focus" }) + this.setState({ isFocused: "mentions-focus" }); }, deselect: function() { this.setState({ isFocused: "" }); diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 1852a3ebc..1df7a8298 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -30,7 +30,7 @@ module.exports = React.createClass({ e.stopPropagation(); e.preventDefault(); - var tempSelectedMention = -1 + var tempSelectedMention = -1; self.refs['mention' + self.state.selectedMention].deselect(); if (e.which === 38) { if (self.getSelection(self.state.selectedMention - 1)) -- cgit v1.2.3-1-g7c22 From 139f6611d6162158ea88c679aee710f7a6c76c49 Mon Sep 17 00:00:00 2001 From: nickago Date: Thu, 16 Jul 2015 08:55:37 -0700 Subject: Added last updated for pictures --- web/react/components/user_settings.jsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'web/react') diff --git a/web/react/components/user_settings.jsx b/web/react/components/user_settings.jsx index 06d8d0208..b1ccd125a 100644 --- a/web/react/components/user_settings.jsx +++ b/web/react/components/user_settings.jsx @@ -820,6 +820,7 @@ var GeneralTab = React.createClass({ client.uploadProfileImage(formData, function(data) { this.submitActive = false; + AsyncClient.getMe(); window.location.reload(); }.bind(this), function(err) { @@ -989,7 +990,7 @@ var GeneralTab = React.createClass({ ); -- cgit v1.2.3-1-g7c22 From cb4cd741a45fc86a7c2d96e61abd65ad4bd728e1 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Thu, 16 Jul 2015 09:21:51 -0700 Subject: Code simplification and rebasing --- web/react/components/mention.jsx | 15 ++------------- web/react/components/mention_list.jsx | 23 ++++------------------- 2 files changed, 6 insertions(+), 32 deletions(-) (limited to 'web/react') diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx index f5ca4ce6d..114dc183f 100644 --- a/web/react/components/mention.jsx +++ b/web/react/components/mention.jsx @@ -6,19 +6,8 @@ module.exports = React.createClass({ handleClick: function() { this.props.handleClick(this.props.username); }, - select: function() { - this.setState({ isFocused: "mentions-focus" }); - }, - deselect: function() { - this.setState({ isFocused: "" }); - }, getInitialState: function() { - if (this.props.isFocus) { - return { isFocused: "mentions-focus" }; - } - else { - return { isFocused: "" }; - } + return null; }, render: function() { var self = this; @@ -32,7 +21,7 @@ module.exports = React.createClass({ icon = ; } return ( -
          +
          {icon}
          @{this.props.username}{this.props.secondary_text}
          diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index 1df7a8298..fff0c10b8 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -31,7 +31,6 @@ module.exports = React.createClass({ e.preventDefault(); var tempSelectedMention = -1; - self.refs['mention' + self.state.selectedMention].deselect(); if (e.which === 38) { if (self.getSelection(self.state.selectedMention - 1)) self.setState({ selectedMention: self.state.selectedMention - 1, selectedUsername: self.refs['mention' + (self.state.selectedMention - 1)].props.username }); @@ -48,7 +47,6 @@ module.exports = React.createClass({ self.setState({ selectedMention: 0, selectedUsername: self.refs.mention0.props.username }); } - self.refs['mention' + self.state.selectedMention].select(); self.scrollToMention(e.which, tempSelectedMention); } } @@ -64,11 +62,6 @@ module.exports = React.createClass({ PostStore.removeMentionDataChangeListener(this._onChange); $('body').off('keydown.mentionlist', '#'+this.props.id); }, - componentWillUpdate: function() { - if (this.state.mentionText != "-1" && this.getSelection(this.state.selectedMention)) { - this.refs['mention' + this.state.selectedMention].deselect(); - } - }, componentDidUpdate: function() { if (this.state.mentionText != "-1") { if (this.state.selectedUsername !== "" && (!this.getSelection(this.state.selectedMention) || this.state.selectedUsername !== this.refs['mention' + this.state.selectedMention].props.username)) { @@ -76,20 +69,15 @@ module.exports = React.createClass({ var foundMatch = false; while (tempSelectedMention < this.state.selectedMention && this.getSelection(++tempSelectedMention)) { if (this.state.selectedUsername === this.refs['mention' + tempSelectedMention].props.username) { - this.refs['mention' + tempSelectedMention].select(); this.setState({ selectedMention: tempSelectedMention }); foundMatch = true; break; } } if (this.getSelection(0) && !foundMatch) { - this.refs.mention0.select(); this.setState({ selectedMention: 0, selectedUsername: this.refs.mention0.props.username }); } } - else if (this.getSelection(this.state.selectedMention)) { - this.refs['mention' + this.state.selectedMention].select(); - } } else if (this.state.selectedMention !== 0) { this.setState({ selectedMention: 0, selectedUsername: "" }); @@ -114,11 +102,7 @@ module.exports = React.createClass({ this.setState({ mentionText: '-1' }); }, handleMouseEnter: function(listId) { - if (this.getSelection(this.state.selectedMention)) { - this.refs['mention' + this.state.selectedMention].deselect(); - } this.setState({ selectedMention: listId, selectedUsername: this.refs['mention' + listId].props.username }); - this.refs['mention' + listId].select(); }, getSelection: function(listId) { if (!this.refs['mention' + listId]) @@ -127,7 +111,7 @@ module.exports = React.createClass({ return true; }, addCurrentMention: function() { - if (!this.refs['mention' + this.state.selectedMention]) + if (!this.getSelection(this.state.selectedMention)) this.addFirstMention(); else this.refs['mention' + this.state.selectedMention].handleClick(); @@ -169,6 +153,7 @@ module.exports = React.createClass({ return { excludeUsers: [], mentionText: "-1", selectedMention: 0, selectedUsername: "" }; }, render: function() { + var self = this; var mentionText = this.state.mentionText; if (mentionText === '-1') return null; @@ -220,8 +205,8 @@ module.exports = React.createClass({ secondary_text={users[i].secondary_text} id={users[i].id} listId={index} - isFocus={this.state.selectedMention === index ? true : false} - handleMouseEnter={this.handleMouseEnter} + isFocused={this.state.selectedMention === index ? "mentions-focus" : ""} + handleMouseEnter={function(value) { return function() { self.handleMouseEnter(value); } }(index)} handleClick={this.handleClick} /> ); index++; -- cgit v1.2.3-1-g7c22 From 1f87c46360b434335ee4b8eae5162b8d37de6f4b Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Thu, 16 Jul 2015 09:27:18 -0700 Subject: Minor code change for clarity --- web/react/components/mention_list.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'web/react') diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index fff0c10b8..c5ff82346 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -129,7 +129,7 @@ module.exports = React.createClass({ if (direction === "up" && ifLoopUp !== -1) scrollAmount = $("#mentionsbox").height() * 100; //Makes sure that it scrolls all the way to the bottom - else if (direction === "down" && this.refs['mention' + this.state.selectedMention].props.listId === 0) + else if (direction === "down" && this.state.selectedMention === 0) scrollAmount = 0; else if (direction === "up") scrollAmount = "-=" + ($('#'+this.refs['mention' + this.state.selectedMention].props.id +"_mentions").innerHeight() - 5); -- cgit v1.2.3-1-g7c22 From 43368061d5bfd433c8bbb71fba5da45faf8119d9 Mon Sep 17 00:00:00 2001 From: Asaad Mahmood Date: Fri, 17 Jul 2015 01:30:30 +0500 Subject: MM-1401 - Removing most inline styles and other UI changes --- web/react/components/channel_header.jsx | 11 +++++------ web/react/components/edit_channel_modal.jsx | 2 +- web/react/components/get_link_modal.jsx | 2 +- web/react/components/member_list_item.jsx | 2 +- web/react/components/member_list_team.jsx | 2 +- web/react/components/new_channel.jsx | 2 +- web/react/components/post_right.jsx | 2 +- web/react/components/sidebar_header.jsx | 2 +- web/react/components/user_profile.jsx | 4 ++-- web/react/components/user_settings.jsx | 12 ++++++------ 10 files changed, 20 insertions(+), 21 deletions(-) (limited to 'web/react') diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx index fe381a59e..836454b46 100644 --- a/web/react/components/channel_header.jsx +++ b/web/react/components/channel_header.jsx @@ -53,12 +53,12 @@ var PopoverListMembers = React.createClass({ }); members.forEach(function(m) { - popoverHtml += "
          " + m.username + "
          "; + popoverHtml += "
          " + m.username + "
          "; }); } return ( -
          +
          {count}
          @@ -200,11 +200,10 @@ module.exports = React.createClass({ -
          +
          - - -
          diff --git a/web/react/components/edit_channel_modal.jsx b/web/react/components/edit_channel_modal.jsx index 255654fd5..c0818959a 100644 --- a/web/react/components/edit_channel_modal.jsx +++ b/web/react/components/edit_channel_modal.jsx @@ -43,7 +43,7 @@ module.exports = React.createClass({

          Edit {this.state.title} Description

          - +
          diff --git a/web/react/components/get_link_modal.jsx b/web/react/components/get_link_modal.jsx index bbfdce63a..af5314e64 100644 --- a/web/react/components/get_link_modal.jsx +++ b/web/react/components/get_link_modal.jsx @@ -38,7 +38,7 @@ module.exports = React.createClass({

          {"The link below is used for open " + strings.TeamPlural + " or if you allowed your " + strings.Team + " members to sign up using their " + strings.Company + " email addresses."}

          - +
          diff --git a/web/react/components/member_list_item.jsx b/web/react/components/member_list_item.jsx index cf8c71d7e..a5279909b 100644 --- a/web/react/components/member_list_item.jsx +++ b/web/react/components/member_list_item.jsx @@ -49,7 +49,7 @@ module.exports = React.createClass({
          ); } else { - invite =
          {member.roles || 'Member'}
          ; + invite =
          {member.roles || 'Member'}
          ; } return ( diff --git a/web/react/components/member_list_team.jsx b/web/react/components/member_list_team.jsx index aa53c5db6..89b5e49d5 100644 --- a/web/react/components/member_list_team.jsx +++ b/web/react/components/member_list_team.jsx @@ -59,7 +59,7 @@ var MemberListTeamItem = React.createClass({ return {}; }, render: function() { - var server_error = this.state.server_error ?
          : null; + var server_error = this.state.server_error ?
          : null; var user = this.props.user; var currentRoles = "Member"; var timestamp = UserStore.getCurrentUser().update_at; diff --git a/web/react/components/new_channel.jsx b/web/react/components/new_channel.jsx index 160241c1c..069e0d6b1 100644 --- a/web/react/components/new_channel.jsx +++ b/web/react/components/new_channel.jsx @@ -122,7 +122,7 @@ module.exports = React.createClass({
          - +
          { server_error } diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx index 408fbf83a..dca05051d 100644 --- a/web/react/components/post_right.jsx +++ b/web/react/components/post_right.jsx @@ -43,7 +43,7 @@ RhsHeaderPost = React.createClass({ }); }, render: function() { - var back = this.props.fromSearch ? {"< "} : ""; + var back = this.props.fromSearch ? : ""; return (
          diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 54858a04d..83ad4470e 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -91,7 +91,7 @@ var NavbarDropdown = React.createClass({