diff options
author | Asaad Mahmood <Unknowngi@live.com> | 2015-07-09 21:00:29 +0500 |
---|---|---|
committer | Asaad Mahmood <Unknowngi@live.com> | 2015-07-09 21:00:29 +0500 |
commit | b61f653626df4183ddf2f3d26a4dd955436f15de (patch) | |
tree | 2c274b5f5c112f49ca175fe053a2743bbb75218f /web/react | |
parent | a533ff4d71cd6416d959ae970cded679242ba3e8 (diff) | |
parent | b6fb6ea3be059d3c54027267760ccca0f95535ee (diff) | |
download | chat-b61f653626df4183ddf2f3d26a4dd955436f15de.tar.gz chat-b61f653626df4183ddf2f3d26a4dd955436f15de.tar.bz2 chat-b61f653626df4183ddf2f3d26a4dd955436f15de.zip |
Merge branch 'master' of https://github.com/mattermost/platform
Diffstat (limited to 'web/react')
-rw-r--r-- | web/react/components/channel_invite_modal.jsx | 127 | ||||
-rw-r--r-- | web/react/components/channel_loader.jsx | 4 | ||||
-rw-r--r-- | web/react/components/delete_post_modal.jsx | 7 | ||||
-rw-r--r-- | web/react/components/edit_post_modal.jsx | 2 | ||||
-rw-r--r-- | web/react/components/invite_member_modal.jsx | 7 | ||||
-rw-r--r-- | web/react/components/login.jsx | 5 | ||||
-rw-r--r-- | web/react/components/member_list_item.jsx | 32 | ||||
-rw-r--r-- | web/react/components/signup_team_complete.jsx | 11 | ||||
-rw-r--r-- | web/react/components/signup_user_complete.jsx | 6 | ||||
-rw-r--r-- | web/react/package.json | 1 | ||||
-rw-r--r-- | web/react/stores/browser_store.jsx | 77 | ||||
-rw-r--r-- | web/react/stores/channel_store.jsx | 50 | ||||
-rw-r--r-- | web/react/stores/error_store.jsx | 8 | ||||
-rw-r--r-- | web/react/stores/post_store.jsx | 45 | ||||
-rw-r--r-- | web/react/stores/socket_store.jsx | 2 | ||||
-rw-r--r-- | web/react/stores/team_store.jsx | 16 | ||||
-rw-r--r-- | web/react/stores/user_store.jsx | 107 | ||||
-rw-r--r-- | web/react/utils/client.jsx | 3 | ||||
-rw-r--r-- | web/react/utils/utils.jsx | 54 |
19 files changed, 332 insertions, 232 deletions
diff --git a/web/react/components/channel_invite_modal.jsx b/web/react/components/channel_invite_modal.jsx index d41453fab..1b8fe4199 100644 --- a/web/react/components/channel_invite_modal.jsx +++ b/web/react/components/channel_invite_modal.jsx @@ -10,111 +10,95 @@ var AsyncClient = require('../utils/async_client.jsx'); function getStateFromStores() { var users = UserStore.getActiveOnlyProfiles(); - var member_list = ChannelStore.getCurrentExtraInfo().members; + var memberIds = ChannelStore.getCurrentExtraInfo().members.map(function(user) { return user.id; }); - var nonmember_list = []; + var nonmembers = []; for (var id in users) { - var found = false; - for (var i = 0; i < member_list.length; i++) { - if (member_list[i].id === id) { - found = true; - break; - } - } - if (!found) { - nonmember_list.push(users[id]); + if (memberIds.indexOf(id) == -1) { + nonmembers.push(users[id]); } } - member_list.sort(function(a,b) { - if (a.username < b.username) return -1; - if (a.username > b.username) return 1; - return 0; - }); - - nonmember_list.sort(function(a,b) { - if (a.username < b.username) return -1; - if (a.username > b.username) return 1; - return 0; + nonmembers.sort(function(a,b) { + return a.username.localeCompare(b.username); }); var channel_name = ChannelStore.getCurrent() ? ChannelStore.getCurrent().display_name : ""; return { - nonmember_list: nonmember_list, - member_list: member_list, + nonmembers: nonmembers, + memberIds: memberIds, channel_name: channel_name }; } module.exports = React.createClass({ + displayName: "ChannelInviteModal", + + isShown: false, + getInitialState: function() { + return {}; + }, + componentDidMount: function() { + $(React.findDOMNode(this)) + .on('hidden.bs.modal', this._onHide) + .on('show.bs.modal', this._onShow); + }, + + _onShow: function() { ChannelStore.addExtraInfoChangeListener(this._onChange); ChannelStore.addChangeListener(this._onChange); - - var self = this; - $(this.refs.modal.getDOMNode()).on('hidden.bs.modal', function(e) { - self.setState({ render_members: false }); - }); - - $(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) { - self.setState({ render_members: true }); - }); + this.isShown = true; + this._onChange(); }, - componentWillUnmount: function() { + + _onHide: function() { ChannelStore.removeExtraInfoChangeListener(this._onChange); ChannelStore.removeChangeListener(this._onChange); + this.isShown = false; }, + _onChange: function() { - var new_state = getStateFromStores(); - if (!utils.areStatesEqual(this.state, new_state)) { - this.setState(new_state); - } + this.setState(getStateFromStores()); }, + handleInvite: function(user_id) { // Make sure the user isn't already a member of the channel - var member_list = this.state.member_list; - for (var i = 0; i < member_list; i++) { - if (member_list[i].id === user_id) { - return; - } + if (this.state.memberIds.indexOf(user_id) > -1) { + return; } var data = {}; - data['user_id'] = user_id; + data.user_id = user_id; client.addChannelMember(ChannelStore.getCurrentId(), data, - function(data) { - var nonmember_list = this.state.nonmember_list; - var new_member; - for (var i = 0; i < nonmember_list.length; i++) { - if (user_id === nonmember_list[i].id) { - nonmember_list[i].invited = true; - new_member = nonmember_list[i]; + function() { + var nonmembers = this.state.nonmembers; + var memberIds = this.state.memberIds; + + for (var i = 0; i < nonmembers.length; i++) { + if (user_id === nonmembers[i].id) { + nonmembers[i].invited = true; + memberIds.push(user_id); break; } } - if (new_member) { - member_list.push(new_member); - member_list.sort(function(a,b) { - if (a.username < b.username) return -1; - if (a.username > b.username) return 1; - return 0; - }); - } - - this.setState({ invite_error: null, member_list: member_list, nonmember_list: nonmember_list }); + this.setState({ invite_error: null, memberIds: memberIds, nonmembers: nonmembers }); AsyncClient.getChannelExtraInfo(true); }.bind(this), + function(err) { this.setState({ invite_error: err.message }); }.bind(this) ); }, - getInitialState: function() { - return getStateFromStores(); + + shouldComponentUpdate: function(nextProps, nextState) { + return this.isShown && !utils.areStatesEqual(this.state, nextState); }, + render: function() { var invite_error = this.state.invite_error ? <label className='has-error control-label'>{this.state.invite_error}</label> : null; @@ -125,22 +109,19 @@ module.exports = React.createClass({ } return ( - <div className="modal fade" ref="modal" id="channel_invite" role="dialog" aria-hidden="true"> - <div className="modal-dialog"> + <div className="modal fade" id="channel_invite" tabIndex="-1" role="dialog" aria-hidden="true"> + <div className="modal-dialog" role="document"> <div className="modal-content"> <div className="modal-header"> - <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 className="modal-title">Add New Members to {this.state.channel_name}</h4> </div> <div className="modal-body"> { invite_error } - { this.state.render_members ? <MemberList - memberList={this.state.nonmember_list} - isAdmin={isAdmin} - handleInvite={this.handleInvite} - /> - : "" } + memberList={this.state.nonmembers} + isAdmin={isAdmin} + handleInvite={this.handleInvite} /> </div> <div className="modal-footer"> <button type="button" className="btn btn-default" data-dismiss="modal">Close</button> @@ -151,7 +132,3 @@ module.exports = React.createClass({ ); } }); - - - - diff --git a/web/react/components/channel_loader.jsx b/web/react/components/channel_loader.jsx index 537a41d03..1b389aa1d 100644 --- a/web/react/components/channel_loader.jsx +++ b/web/react/components/channel_loader.jsx @@ -5,12 +5,16 @@ to the server on page load. This is to prevent other React controls from spamming AsyncClient with requests. */ +var BrowserStore = require('../stores/browser_store.jsx'); var AsyncClient = require('../utils/async_client.jsx'); var SocketStore = require('../stores/socket_store.jsx'); var Constants = require('../utils/constants.jsx'); module.exports = React.createClass({ componentDidMount: function() { + // Initalize stores + BrowserStore.initalize(); + /* Start initial aysnc loads */ AsyncClient.getMe(); AsyncClient.getPosts(true); diff --git a/web/react/components/delete_post_modal.jsx b/web/react/components/delete_post_modal.jsx index c88b548d1..fefac12d7 100644 --- a/web/react/components/delete_post_modal.jsx +++ b/web/react/components/delete_post_modal.jsx @@ -3,6 +3,7 @@ var Client = require('../utils/client.jsx'); var PostStore = require('../stores/post_store.jsx'); +var BrowserStore = require('../stores/browser_store.jsx'); var utils = require('../utils/utils.jsx'); var AsyncClient = require('../utils/async_client.jsx'); var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); @@ -54,9 +55,9 @@ module.exports = React.createClass({ var self = this; $(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) { var newState = {}; - if(sessionStorage.getItem('edit_state_transfer')) { - newState = JSON.parse(sessionStorage.getItem('edit_state_transfer')); - sessionStorage.removeItem('edit_state_transfer'); + if(BrowserStore.getItem('edit_state_transfer')) { + newState = JSON.parse(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') }; diff --git a/web/react/components/edit_post_modal.jsx b/web/react/components/edit_post_modal.jsx index 24c2d7322..d741e189b 100644 --- a/web/react/components/edit_post_modal.jsx +++ b/web/react/components/edit_post_modal.jsx @@ -13,7 +13,7 @@ module.exports = React.createClass({ if (updatedPost.message.length === 0) { var tempState = this.state; delete tempState.editText; - sessionStorage.setItem('edit_state_transfer', JSON.stringify(tempState)); + BrowserStore.setItem('edit_state_transfer', JSON.stringify(tempState)); $("#edit_post").modal('hide'); $("#delete_post").modal('show'); return; diff --git a/web/react/components/invite_member_modal.jsx b/web/react/components/invite_member_modal.jsx index d1672126d..9ff67ae1b 100644 --- a/web/react/components/invite_member_modal.jsx +++ b/web/react/components/invite_member_modal.jsx @@ -89,7 +89,12 @@ module.exports = React.createClass({ $(this.refs.modal.getDOMNode()).modal('hide'); }.bind(this), function(err) { - this.setState({ server_error: err }); + if (err.message === "This person is already on your team") { + email_errors[err.detailed_error] = err.message; + this.setState({ email_errors: email_errors }); + } + else + this.setState({ server_error: err.message}); }.bind(this) ); diff --git a/web/react/components/login.jsx b/web/react/components/login.jsx index 3b6f96c2d..74c7d4065 100644 --- a/web/react/components/login.jsx +++ b/web/react/components/login.jsx @@ -7,6 +7,7 @@ var utils = require('../utils/utils.jsx'); var client = require('../utils/client.jsx'); var UserStore = require('../stores/user_store.jsx'); +var BrowserStore = require('../stores/browser_store.jsx'); var FindTeamDomain = React.createClass({ @@ -21,7 +22,7 @@ var FindTeamDomain = React.createClass({ return; } - if (!utils.isLocalStorageSupported()) { + if (!BrowserStore.isLocalStorageSupported()) { state.server_error = "This service requires local storage to be enabled. Please enable it or exit private browsing."; this.setState(state); return; @@ -114,7 +115,7 @@ module.exports = React.createClass({ return; } - if (!utils.isLocalStorageSupported()) { + if (!BrowserStore.isLocalStorageSupported()) { state.server_error = "This service requires local storage to be enabled. Please enable it or exit private browsing."; this.setState(state); return; diff --git a/web/react/components/member_list_item.jsx b/web/react/components/member_list_item.jsx index f0bbff8bd..357fd49a8 100644 --- a/web/react/components/member_list_item.jsx +++ b/web/react/components/member_list_item.jsx @@ -5,13 +5,17 @@ var ChannelStore = require('../stores/channel_store.jsx'); var UserStore = require('../stores/user_store.jsx'); module.exports = React.createClass({ - handleInvite: function() { + displayName: 'MemberListItem', + handleInvite: function(e) { + e.preventDefault(); this.props.handleInvite(this.props.member.id); }, - handleRemove: function() { + handleRemove: function(e) { + e.preventDefault(); this.props.handleRemove(this.props.member.id); }, - handleMakeAdmin: function() { + handleMakeAdmin: function(e) { + e.preventDefault(); this.props.handleMakeAdmin(this.props.member.id); }, render: function() { @@ -20,12 +24,6 @@ module.exports = React.createClass({ var isAdmin = this.props.isAdmin; var isMemberAdmin = member.roles.indexOf("admin") > -1; - if (member.roles === '') { - member.roles = 'Member'; - } else { - member.roles = member.roles.charAt(0).toUpperCase() + member.roles.slice(1); - } - var invite; if (member.invited && this.props.handleInvite) { invite = <span className="member-role">Added</span>; @@ -36,30 +34,28 @@ module.exports = React.createClass({ invite = ( <div className="dropdown member-drop"> <a href="#" className="dropdown-toggle theme" type="button" id="channel_header_dropdown" data-toggle="dropdown" aria-expanded="true"> - <span>{member.roles} </span> + <span className="text-capitalize">{member.roles || 'Member'} </span> <span className="caret"></span> </a> <ul className="dropdown-menu member-menu" role="menu" aria-labelledby="channel_header_dropdown"> { this.props.handleMakeAdmin ? - <li role="presentation"><a role="menuitem" onClick={self.handleMakeAdmin}>Make Admin</a></li> - : "" } + <li role="presentation"><a href="" role="menuitem" onClick={self.handleMakeAdmin}>Make Admin</a></li> + : null } { this.props.handleRemove ? - <li role="presentation"><a role="menuitem" onClick={self.handleRemove}>Remove Member</a></li> - : "" } + <li role="presentation"><a href="" role="menuitem" onClick={self.handleRemove}>Remove Member</a></li> + : null } </ul> </div> ); } else { - invite = <div className="member-drop"><span>{member.roles} </span><span className="caret invisible"></span></div>; + invite = <div className="member-role text-capitalize" style={{marginRight: 15}}>{member.roles || 'Member'}</div>; } - var email = member.email.length > 0 ? member.email : ""; - return ( <div className="row member-div"> <img className="post-profile-img pull-left" src={"/api/v1/users/" + member.id + "/image"} height="36" width="36" /> <span className="member-name">{member.username}</span> - <span className="member-email">{email}</span> + <span className="member-email">{member.email}</span> { invite } </div> ); diff --git a/web/react/components/signup_team_complete.jsx b/web/react/components/signup_team_complete.jsx index 587d8cb82..500ee231e 100644 --- a/web/react/components/signup_team_complete.jsx +++ b/web/react/components/signup_team_complete.jsx @@ -5,11 +5,12 @@ var utils = require('../utils/utils.jsx'); var client = require('../utils/client.jsx'); var UserStore = require('../stores/user_store.jsx'); -var constants = require('../utils/constants.jsx') +var BrowserStore = require('../stores/browser_store.jsx'); +var constants = require('../utils/constants.jsx'); WelcomePage = React.createClass({ submitNext: function (e) { - if (!utils.isLocalStorageSupported()) { + if (!BrowserStore.isLocalStorageSupported()) { this.setState({ storage_error: "This service requires local storage to be enabled. Please enable it or exit private browsing."} ); return; } @@ -32,7 +33,7 @@ WelcomePage = React.createClass({ this.setState(state); return; } - else if (!utils.isLocalStorageSupported()) { + else if (!BrowserStore.isLocalStorageSupported()) { state.email_error = "This service requires local storage to be enabled. Please enable it or exit private browsing."; this.setState(state); return; @@ -595,7 +596,7 @@ PasswordPage = React.createClass({ module.exports = React.createClass({ updateParent: function(state, skipSet) { - localStorage.setItem(this.props.hash, JSON.stringify(state)); + BrowserStore.setGlobalItem(this.props.hash, JSON.stringify(state)); if (!skipSet) { this.setState(state); @@ -604,7 +605,7 @@ module.exports = React.createClass({ getInitialState: function() { var props = null; try { - props = JSON.parse(localStorage.getItem(this.props.hash)); + props = JSON.parse(BrowserStore.getGlobalItem(this.props.hash)); } catch(parse_error) { } diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx index b9f32f0bc..124e617bd 100644 --- a/web/react/components/signup_user_complete.jsx +++ b/web/react/components/signup_user_complete.jsx @@ -5,7 +5,7 @@ var utils = require('../utils/utils.jsx'); var client = require('../utils/client.jsx'); var UserStore = require('../stores/user_store.jsx'); - +var BrowserStore = require('../stores/browser_store.jsx'); module.exports = React.createClass({ handleSubmit: function(e) { @@ -53,7 +53,7 @@ module.exports = React.createClass({ UserStore.setLastEmail(this.state.user.email); UserStore.setCurrentUser(data); if (this.props.hash > 0) - localStorage.setItem(this.props.hash, JSON.stringify({wizard: "finished"})); + BrowserStore.setGlobalItem(this.props.hash, JSON.stringify({wizard: "finished"})); window.location.href = '/channels/town-square'; }.bind(this), function(err) { @@ -75,7 +75,7 @@ module.exports = React.createClass({ getInitialState: function() { var props = null; try { - props = JSON.parse(localStorage.getItem(this.props.hash)); + props = JSON.parse(BrowserStore.getGlobalItem(this.props.hash)); } catch(parse_error) { } diff --git a/web/react/package.json b/web/react/package.json index 055530fea..8d9d57fab 100644 --- a/web/react/package.json +++ b/web/react/package.json @@ -8,7 +8,6 @@ "object-assign": "^1.0.0", "react": "^0.12.0", "autolinker": "^0.15.2", - "linkify-it": "^1.1.0", "react-zeroclipboard-mixin": "^0.1.0" }, "devDependencies": { diff --git a/web/react/stores/browser_store.jsx b/web/react/stores/browser_store.jsx new file mode 100644 index 000000000..b3e54cad5 --- /dev/null +++ b/web/react/stores/browser_store.jsx @@ -0,0 +1,77 @@ +// 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'; + +module.exports.initalize = function() { + var currentVersion = localStorage.getItem("local_storage_version"); + if (currentVersion !== BROWSER_STORE_VERSION) { + localStorage.clear(); + sessionStorage.clear(); + localStorage.setItem("local_storage_version", BROWSER_STORE_VERSION); + } +} + +module.exports.setItem = function(name, value) { + var user_id = UserStore.getCurrentId(); + localStorage.setItem(user_id + "_" + name, value); +}; + +module.exports.getItem = function(name) { + var user_id = UserStore.getCurrentId(); + return localStorage.getItem(user_id + "_" + name); +}; + +module.exports.removeItem = function(name) { + var user_id = UserStore.getCurrentId(); + localStorage.removeItem(user_id + "_" + name); +}; + +module.exports.setGlobalItem = function(name, value) { + localStorage.setItem(name, value); +}; + +module.exports.getGlobalItem = function(name) { + return localStorage.getItem(name); +}; + +module.exports.removeGlobalItem = function(name) { + localStorage.removeItem(name); +}; + +module.exports.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) +module.exports.actionOnItemsWithPrefix = function (prefix, action) { + var user_id = UserStore.getCurrentId(); + var id_len = user_id.length; + var prefix_len = prefix.length; + for (key in localStorage) { + if (key.substring(id_len, id_len + prefix_len) === prefix) { + var userkey = key.substring(id_len); + action(userkey, BrowserStore.getItem(key)); + } + } +}; + +module.exports.isLocalStorageSupported = function() { + try { + sessionStorage.setItem("testSession", '1'); + sessionStorage.removeItem("testSession"); + + localStorage.setItem("testLocal", '1'); + 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 387d52628..340ce9922 100644 --- a/web/react/stores/channel_store.jsx +++ b/web/react/stores/channel_store.jsx @@ -8,6 +8,8 @@ var assign = require('object-assign'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; +var BrowserStore = require('../stores/browser_store.jsx'); + var CHANGE_EVENT = 'change'; var MORE_CHANGE_EVENT = 'change'; @@ -87,18 +89,18 @@ var ChannelStore = assign({}, EventEmitter.prototype, { }, setCurrentId: function(id) { if (id == null) - sessionStorage.removeItem("current_channel_id"); + BrowserStore.removeItem("current_channel_id"); else - sessionStorage.setItem("current_channel_id", id); + BrowserStore.setItem("current_channel_id", id); }, setLastVisitedName: function(name) { if (name == null) - localStorage.removeItem("last_visited_name"); + BrowserStore.removeItem("last_visited_name"); else - localStorage.setItem("last_visited_name", name); + BrowserStore.setItem("last_visited_name", name); }, getLastVisitedName: function() { - return localStorage.getItem("last_visited_name"); + return BrowserStore.getItem("last_visited_name"); }, resetCounts: function(id) { var cm = this._getChannelMembers(); @@ -115,7 +117,7 @@ var ChannelStore = assign({}, EventEmitter.prototype, { this._storeChannelMembers(cm); }, getCurrentId: function() { - return sessionStorage.getItem("current_channel_id"); + return BrowserStore.getItem("current_channel_id"); }, getCurrent: function() { var currentId = ChannelStore.getCurrentId(); @@ -163,54 +165,70 @@ var ChannelStore = assign({}, EventEmitter.prototype, { return extra; }, _storeChannels: function(channels) { - sessionStorage.setItem("channels", JSON.stringify(channels)); + BrowserStore.setItem("channels", JSON.stringify(channels)); }, _getChannels: function() { var channels = []; try { - channels = JSON.parse(sessionStorage.channels); + channels = JSON.parse(BrowserStore.getItem("channels")); } catch (err) { } + if (channels == null) { + channels = []; + } + return channels; }, _storeChannelMembers: function(channelMembers) { - sessionStorage.setItem("channel_members", JSON.stringify(channelMembers)); + BrowserStore.setItem("channel_members", JSON.stringify(channelMembers)); }, _getChannelMembers: function() { var members = {}; try { - members = JSON.parse(sessionStorage.channel_members); + members = JSON.parse(BrowserStore.getItem("channel_members")); } catch (err) { } + if (members == null) { + members = {}; + } + return members; }, _storeMoreChannels: function(channels) { - sessionStorage.setItem("more_channels", JSON.stringify(channels)); + BrowserStore.setItem("more_channels", JSON.stringify(channels)); }, _getMoreChannels: function() { var channels; try { - channels = JSON.parse(sessionStorage.more_channels); + channels = JSON.parse(BrowserStore.getItem("more_channels")); } catch (err) { - } + } + + if (channels == null) { + channels = []; + } return channels; }, _storeExtraInfos: function(extraInfos) { - sessionStorage.setItem("extra_infos", JSON.stringify(extraInfos)); + BrowserStore.setItem("extra_infos", JSON.stringify(extraInfos)); }, _getExtraInfos: function() { var members = {}; try { - members = JSON.parse(sessionStorage.extra_infos); + members = JSON.parse(BrowserStore.getItem("extra_infos")); } catch (err) { - } + } + + if (members == null) { + members = {}; + } return members; } diff --git a/web/react/stores/error_store.jsx b/web/react/stores/error_store.jsx index 82170034a..c20e15680 100644 --- a/web/react/stores/error_store.jsx +++ b/web/react/stores/error_store.jsx @@ -8,6 +8,8 @@ var assign = require('object-assign'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; +var BrowserStore = require('../stores/browser_store.jsx'); + var CHANGE_EVENT = 'change'; var ErrorStore = assign({}, EventEmitter.prototype, { @@ -24,12 +26,12 @@ var ErrorStore = assign({}, EventEmitter.prototype, { this.removeListener(CHANGE_EVENT, callback); }, handledError: function() { - sessionStorage.removeItem("last_error"); + BrowserStore.removeItem("last_error"); }, getLastError: function() { var error = null; try { - error = JSON.parse(sessionStorage.last_error); + error = JSON.parse(BrowserStore.last_error); } catch (err) { } @@ -38,7 +40,7 @@ var ErrorStore = assign({}, EventEmitter.prototype, { }, _storeLastError: function(error) { - sessionStorage.setItem("last_error", JSON.stringify(error)); + BrowserStore.setItem("last_error", JSON.stringify(error)); }, }); diff --git a/web/react/stores/post_store.jsx b/web/react/stores/post_store.jsx index 05479f444..8bf3fdcb2 100644 --- a/web/react/stores/post_store.jsx +++ b/web/react/stores/post_store.jsx @@ -7,6 +7,7 @@ var assign = require('object-assign'); var ChannelStore = require('../stores/channel_store.jsx'); var UserStore = require('../stores/user_store.jsx'); +var BrowserStore = require('../stores/browser_store.jsx'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; @@ -105,12 +106,12 @@ var PostStore = assign({}, EventEmitter.prototype, { this.emitChange(); }, _storePosts: function(channelId, posts) { - sessionStorage.setItem("posts_" + channelId, JSON.stringify(posts)); + BrowserStore.setItem("posts_" + channelId, JSON.stringify(posts)); }, getPosts: function(channelId) { var posts = null; try { - posts = JSON.parse(sessionStorage.getItem("posts_" + channelId)); + posts = JSON.parse(BrowserStore.getItem("posts_" + channelId)); } catch (err) { } @@ -118,14 +119,14 @@ var PostStore = assign({}, EventEmitter.prototype, { return posts; }, storeSearchResults: function(results, is_mention_search) { - sessionStorage.setItem("search_results", JSON.stringify(results)); + BrowserStore.setItem("search_results", JSON.stringify(results)); is_mention_search = is_mention_search ? true : false; // force to bool - sessionStorage.setItem("is_mention_search", JSON.stringify(is_mention_search)); + BrowserStore.setItem("is_mention_search", JSON.stringify(is_mention_search)); }, getSearchResults: function() { var results = null; try { - results = JSON.parse(sessionStorage.getItem("search_results")); + results = JSON.parse(BrowserStore.getItem("search_results")); } catch (err) { } @@ -135,7 +136,7 @@ var PostStore = assign({}, EventEmitter.prototype, { getIsMentionSearch: function() { var result = false; try { - result = JSON.parse(sessionStorage.getItem("is_mention_search")); + result = JSON.parse(BrowserStore.getItem("is_mention_search")); } catch (err) { } @@ -143,12 +144,12 @@ var PostStore = assign({}, EventEmitter.prototype, { return result; }, storeSelectedPost: function(post_list) { - sessionStorage.setItem("select_post", JSON.stringify(post_list)); + BrowserStore.setItem("select_post", JSON.stringify(post_list)); }, getSelectedPost: function() { var post_list = null; try { - post_list = JSON.parse(sessionStorage.getItem("select_post")); + post_list = JSON.parse(BrowserStore.getItem("select_post")); } catch (err) { } @@ -156,37 +157,35 @@ var PostStore = assign({}, EventEmitter.prototype, { return post_list; }, storeSearchTerm: function(term) { - sessionStorage.setItem("search_term", term); + BrowserStore.setItem("search_term", term); }, getSearchTerm: function() { - return sessionStorage.getItem("search_term"); + return BrowserStore.getItem("search_term"); }, storeCurrentDraft: function(draft) { var channel_id = ChannelStore.getCurrentId(); var user_id = UserStore.getCurrentId(); - localStorage.setItem("draft_" + channel_id + "_" + user_id, JSON.stringify(draft)); + BrowserStore.setItem("draft_" + channel_id + "_" + user_id, JSON.stringify(draft)); }, getCurrentDraft: function() { var channel_id = ChannelStore.getCurrentId(); var user_id = UserStore.getCurrentId(); - return JSON.parse(localStorage.getItem("draft_" + channel_id + "_" + user_id)); + return JSON.parse(BrowserStore.getItem("draft_" + channel_id + "_" + user_id)); }, storeDraft: function(channel_id, user_id, draft) { - localStorage.setItem("draft_" + channel_id + "_" + user_id, JSON.stringify(draft)); + BrowserStore.setItem("draft_" + channel_id + "_" + user_id, JSON.stringify(draft)); }, getDraft: function(channel_id, user_id) { - return JSON.parse(localStorage.getItem("draft_" + channel_id + "_" + user_id)); + return JSON.parse(BrowserStore.getItem("draft_" + channel_id + "_" + user_id)); }, clearDraftUploads: function() { - for (key in localStorage) { - if (key.substring(0,6) === "draft_") { - var d = JSON.parse(localStorage.getItem(key)); - if (d) { - d['uploadsInProgress'] = 0; - localStorage.setItem(key, JSON.stringify(d)); - } - } - } + BrowserStore.actionOnItemsWithPrefix("draft_", function (key, value) { + var d = JSON.parse(value); + if (d) { + d['uploadsInProgress'] = 0; + BrowserStore.setItem(key, JSON.stringify(d)); + } + }); } }); diff --git a/web/react/stores/socket_store.jsx b/web/react/stores/socket_store.jsx index 8ebb854c9..39800ead5 100644 --- a/web/react/stores/socket_store.jsx +++ b/web/react/stores/socket_store.jsx @@ -10,6 +10,8 @@ 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 e95daeeba..c494cb5b5 100644 --- a/web/react/stores/team_store.jsx +++ b/web/react/stores/team_store.jsx @@ -7,7 +7,7 @@ var assign = require('object-assign'); var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; - +var BrowserStore = require('../stores/browser_store.jsx'); var CHANGE_EVENT = 'change'; @@ -42,12 +42,12 @@ var TeamStore = assign({}, EventEmitter.prototype, { }, setCurrentId: function(id) { if (id == null) - sessionStorage.removeItem("current_team_id"); + BrowserStore.removeItem("current_team_id"); else - sessionStorage.setItem("current_team_id", id); + BrowserStore.setItem("current_team_id", id); }, getCurrentId: function() { - return sessionStorage.getItem("current_team_id"); + return BrowserStore.getItem("current_team_id"); }, getCurrent: function() { var currentId = TeamStore.getCurrentId(); @@ -63,17 +63,21 @@ var TeamStore = assign({}, EventEmitter.prototype, { this._storeTeams(teams); }, _storeTeams: function(teams) { - sessionStorage.setItem("user_teams", JSON.stringify(teams)); + BrowserStore.setItem("user_teams", JSON.stringify(teams)); }, _getTeams: function() { var teams = {}; try { - teams = JSON.parse(sessionStorage.user_teams); + teams = JSON.parse(BrowserStore.getItem("user_teams")); } catch (err) { } + if (teams == null) { + teams = {}; + } + return teams; } }); diff --git a/web/react/stores/user_store.jsx b/web/react/stores/user_store.jsx index e1df4879f..e832b34c7 100644 --- a/web/react/stores/user_store.jsx +++ b/web/react/stores/user_store.jsx @@ -8,6 +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 CHANGE_EVENT = 'change'; var CHANGE_EVENT_SESSIONS = 'change_sessions'; @@ -64,12 +65,12 @@ var UserStore = assign({}, EventEmitter.prototype, { }, setCurrentId: function(id) { if (id == null) - sessionStorage.removeItem("current_user_id"); + BrowserStore.removeGlobalItem("current_user_id"); else - sessionStorage.setItem("current_user_id", id); + BrowserStore.setGlobalItem("current_user_id", id); }, getCurrentId: function(skipFetch) { - var current_id = sessionStorage.current_user_id; + var current_id = BrowserStore.getGlobalItem("current_user_id"); // this is a speical case to force fetch the // current user if it's missing @@ -96,16 +97,24 @@ var UserStore = assign({}, EventEmitter.prototype, { this.setCurrentId(user.id); }, getLastDomain: function() { - return localStorage.last_domain; + var last_domain = BrowserStore.getItem("last_domain"); + if (last_domain == null) { + last_domain = ""; + } + return last_domain; }, setLastDomain: function(domain) { - localStorage.setItem("last_domain", domain); + BrowserStore.setItem("last_domain", domain); }, getLastEmail: function() { - return localStorage.last_email; + var last_email = BrowserStore.getItem("last_email"); + if (last_email == null) { + last_email = ""; + } + return last_email; }, setLastEmail: function(email) { - localStorage.setItem("last_email", email); + BrowserStore.setItem("last_email", email); }, removeCurrentUser: function() { this.setCurrentId(null); @@ -144,89 +153,89 @@ var UserStore = assign({}, EventEmitter.prototype, { this._storeProfiles(ps); }, _storeProfiles: function(profiles) { - sessionStorage.setItem("profiles", JSON.stringify(profiles)); + BrowserStore.setGlobalItem("profiles", JSON.stringify(profiles)); var profileUsernameMap = {}; for (var id in profiles) { profileUsernameMap[profiles[id].username] = profiles[id]; } - sessionStorage.setItem("profileUsernameMap", JSON.stringify(profileUsernameMap)); + BrowserStore.setGlobalItem("profileUsernameMap", JSON.stringify(profileUsernameMap)); }, _getProfiles: function() { var profiles = {}; try { - profiles = JSON.parse(sessionStorage.getItem("profiles")); - - if (profiles == null) { - profiles = {}; - } + profiles = JSON.parse(BrowserStore.getGlobalItem("profiles")); } catch (err) { } + if (profiles == null) { + profiles = {}; + } + return profiles; }, _getProfilesUsernameMap: function() { var profileUsernameMap = {}; try { - profileUsernameMap = JSON.parse(sessionStorage.getItem("profileUsernameMap")); - - if (profileUsernameMap == null) { - profileUsernameMap = {}; - } + profileUsernameMap = JSON.parse(BrowserStore.getGlobalItem("profileUsernameMap")); } catch (err) { } + if (profileUsernameMap == null) { + profileUsernameMap = {}; + } + return profileUsernameMap; }, setSessions: function(sessions) { - sessionStorage.setItem("sessions", JSON.stringify(sessions)); + BrowserStore.setItem("sessions", JSON.stringify(sessions)); }, getSessions: function() { var sessions = []; try { - sessions = JSON.parse(sessionStorage.getItem("sessions")); - - if (sessions == null) { - sessions = []; - } + sessions = JSON.parse(BrowserStore.getItem("sessions")); } catch (err) { - } + } + if (sessions == null) { + sessions = []; + } return sessions; }, setAudits: function(audits) { - sessionStorage.setItem("audits", JSON.stringify(audits)); + BrowserStore.setItem("audits", JSON.stringify(audits)); }, getAudits: function() { var audits = []; try { - audits = JSON.parse(sessionStorage.getItem("audits")); - - if (audits == null) { - audits = []; - } + audits = JSON.parse(BrowserStore.getItem("audits")); } catch (err) { - } + } + + if (audits == null) { + audits = []; + } return audits; }, setTeams: function(teams) { - sessionStorage.setItem("teams", JSON.stringify(teams)); + BrowserStore.setItem("teams", JSON.stringify(teams)); }, getTeams: function() { var teams = []; try { - teams = JSON.parse(sessionStorage.getItem("teams")); + teams = JSON.parse(BrowserStore.getItem("teams")); - if (teams == null) { - teams = []; - } } catch (err) { - } + } + + if (teams == null) { + teams = []; + } return teams; }, @@ -249,17 +258,21 @@ var UserStore = assign({}, EventEmitter.prototype, { } }, getLastVersion: function() { - return sessionStorage.last_version; + var last_version = BrowserStore.getItem("last_version"); + if (last_version == null) { + last_version = ""; + } + return last_version; }, setLastVersion: function(version) { - sessionStorage.setItem("last_version", version); + BrowserStore.setItem("last_version", version); }, setStatuses: function(statuses) { this._setStatuses(statuses); this.emitStatusesChange(); }, _setStatuses: function(statuses) { - sessionStorage.setItem("statuses", JSON.stringify(statuses)); + BrowserStore.setItem("statuses", JSON.stringify(statuses)); }, setStatus: function(user_id, status) { var statuses = this.getStatuses(); @@ -270,15 +283,15 @@ var UserStore = assign({}, EventEmitter.prototype, { getStatuses: function() { var statuses = {}; try { - statuses = JSON.parse(sessionStorage.getItem("statuses")); - - if (statuses == null) { - statuses = {}; - } + statuses = JSON.parse(BrowserStore.getItem("statuses")); } catch (err) { } + if (statuses == null) { + statuses = {}; + } + return statuses; }, getStatus: function(id) { diff --git a/web/react/utils/client.jsx b/web/react/utils/client.jsx index b4030baac..11d4c2601 100644 --- a/web/react/utils/client.jsx +++ b/web/react/utils/client.jsx @@ -1,6 +1,7 @@ // Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. +var BrowserStore = require('../stores/browser_store.jsx'); module.exports.track = function(category, action, label, prop, val) { global.window.snowplow('trackStructEvent', category, action, label, prop, val); @@ -204,7 +205,7 @@ module.exports.resetPassword = function(data, success, error) { module.exports.logout = function() { module.exports.track('api', 'api_users_logout'); - sessionStorage.clear(); + BrowserStore.clear(); window.location.href = "/logout"; }; diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index f8a7d6450..5ded0e76f 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -8,7 +8,7 @@ var Constants = require('../utils/constants.jsx'); var ActionTypes = Constants.ActionTypes; var AsyncClient = require('./async_client.jsx'); var client = require('./client.jsx'); -var LinkifyIt = require('linkify-it'); +var Autolinker = require('autolinker'); module.exports.isEmail = function(email) { var regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; @@ -97,20 +97,6 @@ module.exports.getCookie = function(name) { if (parts.length == 2) return parts.pop().split(";").shift(); } -module.exports.isLocalStorageSupported = function() { - try { - sessionStorage.setItem("testSession", '1'); - sessionStorage.removeItem("testSession"); - - localStorage.setItem("testLocal", '1'); - localStorage.removeItem("testLocal", '1'); - - return true; - } - catch (e) { - return false; - } -} module.exports.notifyMe = function(title, body, channel) { if ("Notification" in window && Notification.permission !== 'denied') { @@ -211,16 +197,31 @@ module.exports.getTimestamp = function() { return Date.now(); } +var testUrlMatch = function(text) { + var urlMatcher = new Autolinker.matchParser.MatchParser; + var result = []; + var replaceFn = function(match) { + var linkData = {}; + var matchText = match.getMatchedText(); + + linkData.text = matchText; + linkData.link = matchText.trim().indexOf("http") !== 0 ? "http://" + matchText : matchText; + + result.push(linkData); + } + urlMatcher.replace(text,replaceFn,this); + return result; +} + module.exports.extractLinks = function(text) { var repRegex = new RegExp("<br>", "g"); - var linkMatcher = new LinkifyIt(); - var matches = linkMatcher.match(text.replace(repRegex, "\n")); + var matches = testUrlMatch(text.replace(repRegex, "\n")); - if (!matches) return { "links": null, "text": text }; + if (!matches.length) return { "links": null, "text": text }; - var links = [] + var links = []; for (var i = 0; i < matches.length; i++) { - links.push(matches[i].url) + links.push(matches[i].link); } return { "links": links, "text": text }; @@ -402,7 +403,6 @@ module.exports.textToJsx = function(text, options) { var implicitKeywords = UserStore.getCurrentMentionKeys(); var lines = text.split("\n"); - var urlMatcher = new LinkifyIt(); for (var i = 0; i < lines.length; i++) { var line = lines[i]; var words = line.split(" "); @@ -434,14 +434,14 @@ module.exports.textToJsx = function(text, options) { } inner.push(<span key={name+i+z+"_span"}>{prefix}<a className={mClass + highlightSearchClass + " mention-link"} key={name+i+z+"_link"} href="#" onClick={function(value) { return function() { module.exports.searchForTerm(value); } }(name)}>@{name}</a>{suffix} </span>); - } else if (urlMatcher.test(word)) { - var match = urlMatcher.match(word)[0]; - var link = match.url; + } else if (testUrlMatch(word).length) { + var match = testUrlMatch(word)[0]; + var link = match.link; - var prefix = word.substring(0,word.indexOf(match.raw)) - var suffix = word.substring(word.indexOf(match.raw)+match.raw.length); + var prefix = word.substring(0,word.indexOf(match.text)); + var suffix = word.substring(word.indexOf(match.text)+match.text.length); - inner.push(<span key={word+i+z+"_span"}>{prefix}<a key={word+i+z+"_link"} className={"theme" + highlightSearchClass} target="_blank" href={link}>{match.raw}</a>{suffix} </span>); + inner.push(<span key={word+i+z+"_span"}>{prefix}<a key={word+i+z+"_link"} className={"theme" + highlightSearchClass} target="_blank" href={link}>{match.text}</a>{suffix} </span>); } else if (trimWord.match(hashRegex)) { var suffix = word.match(puncEndRegex); |