diff options
Diffstat (limited to 'web/react')
-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_channel_modal.jsx | 2 | ||||
-rw-r--r-- | web/react/components/edit_post_modal.jsx | 2 | ||||
-rw-r--r-- | web/react/components/get_link_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/mention_list.jsx | 5 | ||||
-rw-r--r-- | web/react/components/new_channel.jsx | 2 | ||||
-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 |
21 files changed, 272 insertions, 144 deletions
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_channel_modal.jsx b/web/react/components/edit_channel_modal.jsx index f1f4eca40..255654fd5 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({ <h4 className="modal-title" ref="title">Edit {this.state.title} Description</h4> </div> <div className="modal-body"> - <textarea className="form-control" rows="6" ref="channelDesc" maxLength="1024" value={this.state.description} onChange={this.handleUserInput}></textarea> + <textarea className="form-control" style={{resize: "none"}} rows="6" ref="channelDesc" maxLength="1024" value={this.state.description} onChange={this.handleUserInput}></textarea> </div> <div className="modal-footer"> <button type="button" className="btn btn-default" data-dismiss="modal">Close</button> 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/get_link_modal.jsx b/web/react/components/get_link_modal.jsx index 69e565185..bbfdce63a 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({ <div className="modal-body"> <p>{"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."} </p> - <textarea className="form-control" readOnly="true" value={this.state.value}></textarea> + <textarea className="form-control" style={{resize: "none"}} readOnly="true" value={this.state.value}></textarea> </div> <div className="modal-footer"> <button type="button" className="btn btn-default" data-dismiss="modal">Close</button> 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/mention_list.jsx b/web/react/components/mention_list.jsx index b666fcfae..3fac41073 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -23,8 +23,9 @@ module.exports = React.createClass({ } } ); - $(document).click(function() { - if($('#'+self.props.id).length && $('#'+self.props.id).get(0) !== $(':focus').get(0)) { + $(document).click(function(e) { + if (!($('#'+self.props.id).is(e.target) || $('#'+self.props.id).has(e.target).length || + ('mentionlist' in self.refs && $(self.refs['mentionlist'].getDOMNode()).has(e.target).length))) { self.setState({mentionText: "-1"}) } }); diff --git a/web/react/components/new_channel.jsx b/web/react/components/new_channel.jsx index 13fa5b2cc..160241c1c 100644 --- a/web/react/components/new_channel.jsx +++ b/web/react/components/new_channel.jsx @@ -122,7 +122,7 @@ module.exports = React.createClass({ </div> <div className="form-group"> <label className='control-label'>Description</label> - <textarea className="form-control" ref="channel_desc" rows="3" placeholder="Description" maxLength="1024"></textarea> + <textarea className="form-control" style={{resize: "none"}} ref="channel_desc" rows="3" placeholder="Description" maxLength="1024"></textarea> </div> { server_error } </form> 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 3f259bc7d..77ab69ef8 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); |