summaryrefslogtreecommitdiffstats
path: root/webapp/components
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2016-03-24 20:04:40 -0400
committerChristopher Speller <crspeller@gmail.com>2016-03-29 09:54:55 -0400
commit5ce1a4368bafbd2ed50b1953658fca285cfd349b (patch)
tree9609d2ee90371ee0393a95f5fe67d27b5621257c /webapp/components
parentbf636404d25e943d869a32d8fe145eaa57a64039 (diff)
downloadchat-5ce1a4368bafbd2ed50b1953658fca285cfd349b.tar.gz
chat-5ce1a4368bafbd2ed50b1953658fca285cfd349b.tar.bz2
chat-5ce1a4368bafbd2ed50b1953658fca285cfd349b.zip
Refactoring center panel away. Moving tutorial to a route. Fixing a
bunch of bugs.
Diffstat (limited to 'webapp/components')
-rw-r--r--webapp/components/center_panel.jsx145
-rw-r--r--webapp/components/channel_header.jsx15
-rw-r--r--webapp/components/channel_view.jsx67
-rw-r--r--webapp/components/logged_in.jsx35
-rw-r--r--webapp/components/more_channels.jsx4
-rw-r--r--webapp/components/more_direct_channels.jsx3
-rw-r--r--webapp/components/navbar.jsx5
-rw-r--r--webapp/components/new_channel_flow.jsx7
-rw-r--r--webapp/components/permalink_view.jsx109
-rw-r--r--webapp/components/popover_list_members.jsx3
-rw-r--r--webapp/components/removed_from_channel_modal.jsx4
-rw-r--r--webapp/components/rename_channel_modal.jsx5
-rw-r--r--webapp/components/search_results_item.jsx23
-rw-r--r--webapp/components/sidebar.jsx74
-rw-r--r--webapp/components/sidebar_right.jsx4
-rw-r--r--webapp/components/tutorial/tutorial_intro_screens.jsx6
-rw-r--r--webapp/components/tutorial/tutorial_view.jsx19
17 files changed, 280 insertions, 248 deletions
diff --git a/webapp/components/center_panel.jsx b/webapp/components/center_panel.jsx
deleted file mode 100644
index 62b12c1d2..000000000
--- a/webapp/components/center_panel.jsx
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import TutorialIntroScreens from './tutorial/tutorial_intro_screens.jsx';
-import CreatePost from './create_post.jsx';
-import PostsViewContainer from './posts_view_container.jsx';
-import PostFocusView from './post_focus_view.jsx';
-import ChannelHeader from './channel_header.jsx';
-import Navbar from './navbar.jsx';
-import FileUploadOverlay from './file_upload_overlay.jsx';
-
-import PreferenceStore from 'stores/preference_store.jsx';
-import ChannelStore from 'stores/channel_store.jsx';
-import UserStore from 'stores/user_store.jsx';
-
-import * as Utils from 'utils/utils.jsx';
-
-import {FormattedMessage} from 'react-intl';
-
-import Constants from 'utils/constants.jsx';
-const TutorialSteps = Constants.TutorialSteps;
-const Preferences = Constants.Preferences;
-
-import React from 'react';
-import {Link} from 'react-router';
-
-export default class CenterPanel extends React.Component {
- constructor(props) {
- super(props);
-
- this.getStateFromStores = this.getStateFromStores.bind(this);
- this.validState = this.validState.bind(this);
- this.onStoresChange = this.onStoresChange.bind(this);
-
- this.state = this.getStateFromStores();
- }
- getStateFromStores() {
- const tutorialStep = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), 999);
- return {
- showTutorialScreens: tutorialStep <= TutorialSteps.INTRO_SCREENS,
- showPostFocus: ChannelStore.getPostMode() === ChannelStore.POST_MODE_FOCUS,
- user: UserStore.getCurrentUser(),
- channel: ChannelStore.getCurrent(),
- profiles: JSON.parse(JSON.stringify(UserStore.getProfiles()))
- };
- }
- validState() {
- return this.state.user && this.state.channel && this.state.profiles;
- }
- onStoresChange() {
- this.setState(this.getStateFromStores());
- }
- componentDidMount() {
- PreferenceStore.addChangeListener(this.onStoresChange);
- ChannelStore.addChangeListener(this.onStoresChange);
- UserStore.addChangeListener(this.onStoresChange);
- }
- componentWillUnmount() {
- PreferenceStore.removeChangeListener(this.onStoresChange);
- ChannelStore.removeChangeListener(this.onStoresChange);
- UserStore.removeChangeListener(this.onStoresChange);
- }
- render() {
- if (!this.validState()) {
- return null;
- }
- const channel = this.state.channel;
- var handleClick = null;
- let postsContainer;
- let createPost;
- if (this.state.showTutorialScreens) {
- postsContainer = <TutorialIntroScreens/>;
- createPost = null;
- } else if (this.state.showPostFocus) {
- postsContainer = <PostFocusView profiles={this.state.profiles}/>;
-
- handleClick = function clickHandler(e) {
- e.preventDefault();
- Utils.switchChannel(channel);
- };
-
- createPost = (
- <div
- id='archive-link-home'
- onClick={handleClick}
- >
- <Link to=''>
- <FormattedMessage
- id='center_panel.recent'
- defaultMessage='Click here to jump to recent messages. '
- />
- <i className='fa fa-arrow-down'></i>
- </Link>
- </div>
- );
- } else {
- postsContainer = <PostsViewContainer profiles={this.state.profiles}/>;
- createPost = (
- <div
- className='post-create__container'
- id='post-create'
- >
- <CreatePost/>
- </div>
- );
- }
-
- return (
- <div className='inner-wrap channel__wrap'>
- <div className='row header'>
- <div id='navbar'>
- <Navbar/>
- </div>
- </div>
- <div className='row main'>
- <FileUploadOverlay
- id='file_upload_overlay'
- overlayType='center'
- />
- <div
- id='app-content'
- className='app__content'
- >
- <div
- id='channel-header'
- className='channel-header'
- >
- <ChannelHeader
- user={this.state.user}
- />
- </div>
- {postsContainer}
- {createPost}
- </div>
- </div>
- </div>
- );
- }
-}
-
-CenterPanel.defaultProps = {
-};
-
-CenterPanel.propTypes = {
-};
diff --git a/webapp/components/channel_header.jsx b/webapp/components/channel_header.jsx
index 369fa2dbb..6bb466c3e 100644
--- a/webapp/components/channel_header.jsx
+++ b/webapp/components/channel_header.jsx
@@ -26,6 +26,7 @@ import * as Utils from 'utils/utils.jsx';
import * as TextFormatting from 'utils/text_formatting.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
import * as Client from 'utils/client.jsx';
+import * as GlobalActions from 'action_creators/global_actions.jsx';
import Constants from 'utils/constants.jsx';
import {FormattedMessage} from 'react-intl';
@@ -53,11 +54,11 @@ export default class ChannelHeader extends React.Component {
this.state = state;
}
getStateFromStores() {
- const extraInfo = ChannelStore.getCurrentExtraInfo();
+ const extraInfo = ChannelStore.getExtraInfo(this.props.channelId);
return {
- channel: ChannelStore.getCurrent(),
- memberChannel: ChannelStore.getCurrentMember(),
+ channel: ChannelStore.get(this.props.channelId),
+ memberChannel: ChannelStore.getMember(this.props.channelId),
users: extraInfo.members,
userCount: extraInfo.member_count,
searchVisible: SearchStore.getSearchResults() !== null,
@@ -105,7 +106,7 @@ export default class ChannelHeader extends React.Component {
});
const townsquare = ChannelStore.getByName('town-square');
- Utils.switchChannel(townsquare);
+ GlobalActions.emitChannelClickEvent(townsquare);
},
(err) => {
AsyncClient.dispatchError(err, 'handleLeave');
@@ -433,7 +434,10 @@ export default class ChannelHeader extends React.Component {
}
return (
- <div>
+ <div
+ id='channel-header'
+ className='channel-header'
+ >
<table className='channel-header alt'>
<tbody>
<tr>
@@ -518,4 +522,5 @@ export default class ChannelHeader extends React.Component {
}
ChannelHeader.propTypes = {
+ channelId: React.PropTypes.string.isRequired
};
diff --git a/webapp/components/channel_view.jsx b/webapp/components/channel_view.jsx
index 34e1666d0..54d796ac1 100644
--- a/webapp/components/channel_view.jsx
+++ b/webapp/components/channel_view.jsx
@@ -1,14 +1,73 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import CenterPanel from 'components/center_panel.jsx';
-
import React from 'react';
+import ChannelHeader from 'components/channel_header.jsx';
+import PostsViewContainer from 'components/posts_view_container.jsx';
+import CreatePost from 'components/create_post.jsx';
+
+import ChannelStore from 'stores/channel_store.jsx';
+import UserStore from 'stores/user_store.jsx';
+
export default class ChannelView extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.getStateFromStores = this.getStateFromStores.bind(this);
+ this.isStateValid = this.isStateValid.bind(this);
+ this.updateState = this.updateState.bind(this);
+
+ this.state = this.getStateFromStores(props);
+ }
+ getStateFromStores(props) {
+ const channel = ChannelStore.getByName(props.params.channel);
+ const channelId = channel ? channel.id : '';
+ const profiles = JSON.parse(JSON.stringify(UserStore.getProfiles()));
+ return {
+ channelId,
+ profiles
+ };
+ }
+ isStateValid() {
+ return this.state.channelId !== '' && this.state.profiles;
+ }
+ updateState() {
+ this.setState(this.getStateFromStores(this.props));
+ }
+ componentDidMount() {
+ ChannelStore.addChangeListener(this.updateState);
+ }
+ componentWillUnmount() {
+ ChannelStore.removeChangeListener(this.updateState);
+ }
+ componentWillReceiveProps(nextProps) {
+ this.setState(this.getStateFromStores(nextProps));
+ }
+ shouldComponentUpdate(nextProps, nextState) {
+ if (nextState.channelId !== this.state.channelId) {
+ return true;
+ }
+
+ return false;
+ }
render() {
return (
- <CenterPanel/>
+ <div
+ id='app-content'
+ className='app__content'
+ >
+ <ChannelHeader
+ channelId={this.state.channelId}
+ />
+ <PostsViewContainer profiles={this.state.profiles}/>
+ <div
+ className='post-create__container'
+ id='post-create'
+ >
+ <CreatePost/>
+ </div>
+ </div>
);
}
}
@@ -16,5 +75,5 @@ ChannelView.defaultProps = {
};
ChannelView.propTypes = {
- params: React.PropTypes.object
+ params: React.PropTypes.object.isRequired
};
diff --git a/webapp/components/logged_in.jsx b/webapp/components/logged_in.jsx
index c6f7b50b1..53db501bf 100644
--- a/webapp/components/logged_in.jsx
+++ b/webapp/components/logged_in.jsx
@@ -10,6 +10,8 @@ import BrowserStore from 'stores/browser_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
+const TutorialSteps = Constants.TutorialSteps;
+const Preferences = Constants.Preferences;
import ErrorBar from 'components/error_bar.jsx';
import * as Websockets from 'action_creators/websocket_actions.jsx';
@@ -17,6 +19,7 @@ import {browserHistory} from 'react-router';
import SidebarRight from 'components/sidebar_right.jsx';
import SidebarRightMenu from 'components/sidebar_right_menu.jsx';
+import Navbar from 'components/navbar.jsx';
// Modals
import GetPostLinkModal from 'components/get_post_link_modal.jsx';
@@ -66,6 +69,12 @@ export default class LoggedIn extends React.Component {
Utils.applyTheme(Constants.THEMES.default);
}
}
+
+ // Go to tutorial if we are first arrivign
+ const tutorialStep = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), 999);
+ if (tutorialStep <= TutorialSteps.INTRO_SCREENS) {
+ browserHistory.push(Utils.getTeamURLFromAddressBar() + '/tutorial');
+ }
}
componentWillMount() {
// Emit view action
@@ -186,14 +195,36 @@ export default class LoggedIn extends React.Component {
$(window).off('keydown.preventBackspace');
}
render() {
+ let content = [];
+ if (this.props.children) {
+ content = this.props.children;
+ } else {
+ content.push(
+ this.props.sidebar
+ );
+ content.push(
+ <div
+ key='inner-wrap'
+ className='inner-wrap channel__wrap'
+ >
+ <div className='row header'>
+ <div id='navbar'>
+ <Navbar/>
+ </div>
+ </div>
+ <div className='row main'>
+ {this.props.center}
+ </div>
+ </div>
+ );
+ }
return (
<div className='channel-view'>
<ErrorBar/>
<div className='container-fluid'>
<SidebarRight/>
<SidebarRightMenu/>
- {this.props.sidebar}
- {this.props.center}
+ {content}
<GetPostLinkModal/>
<GetTeamInviteLinkModal/>
diff --git a/webapp/components/more_channels.jsx b/webapp/components/more_channels.jsx
index d0eeec1ef..811bb8101 100644
--- a/webapp/components/more_channels.jsx
+++ b/webapp/components/more_channels.jsx
@@ -9,6 +9,7 @@ import * as AsyncClient from 'utils/async_client.jsx';
import ChannelStore from 'stores/channel_store.jsx';
import LoadingScreen from './loading_screen.jsx';
import NewChannelFlow from './new_channel_flow.jsx';
+import * as GlobalActions from 'action_creators/global_actions.jsx';
import {FormattedMessage} from 'react-intl';
@@ -64,8 +65,7 @@ export default class MoreChannels extends React.Component {
client.joinChannel(channel.id,
() => {
$(ReactDOM.findDOMNode(this.refs.modal)).modal('hide');
- AsyncClient.getChannel(channel.id);
- Utils.switchChannel(channel);
+ GlobalActions.emitChannelClickEvent(channel);
this.setState({joiningChannel: -1});
},
(err) => {
diff --git a/webapp/components/more_direct_channels.jsx b/webapp/components/more_direct_channels.jsx
index d1446059d..feab8c9db 100644
--- a/webapp/components/more_direct_channels.jsx
+++ b/webapp/components/more_direct_channels.jsx
@@ -5,6 +5,7 @@ import {Modal} from 'react-bootstrap';
import FilteredUserList from './filtered_user_list.jsx';
import UserStore from 'stores/user_store.jsx';
import * as Utils from 'utils/utils.jsx';
+import * as GlobalActions from 'action_creators/global_actions.jsx';
import {FormattedMessage} from 'react-intl';
import SpinnerButton from 'components/spinner_button.jsx';
@@ -68,7 +69,7 @@ export default class MoreDirectChannels extends React.Component {
Utils.openDirectChannelToUser(
teammate,
(channel) => {
- Utils.switchChannel(channel);
+ GlobalActions.emitChannelClickEvent(channel);
this.setState({loadingDMChannel: -1});
this.handleHide();
},
diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx
index e58e142d0..5afd7e683 100644
--- a/webapp/components/navbar.jsx
+++ b/webapp/components/navbar.jsx
@@ -45,6 +45,7 @@ export default class Navbar extends React.Component {
this.showEditChannelHeaderModal = this.showEditChannelHeaderModal.bind(this);
this.showRenameChannelModal = this.showRenameChannelModal.bind(this);
this.hideRenameChannelModal = this.hideRenameChannelModal.bind(this);
+ this.isStateValid = this.isStateValid.bind(this);
this.createCollapseButtons = this.createCollapseButtons.bind(this);
this.createDropdown = this.createDropdown.bind(this);
@@ -64,7 +65,7 @@ export default class Navbar extends React.Component {
currentUser: UserStore.getCurrentUser()
};
}
- stateValid() {
+ isStateValid() {
return this.state.channel && this.state.member && this.state.users && this.state.currentUser;
}
componentDidMount() {
@@ -422,7 +423,7 @@ export default class Navbar extends React.Component {
return buttons;
}
render() {
- if (!this.stateValid()) {
+ if (!this.isStateValid()) {
return null;
}
diff --git a/webapp/components/new_channel_flow.jsx b/webapp/components/new_channel_flow.jsx
index 30035ee5d..8c66ef3ce 100644
--- a/webapp/components/new_channel_flow.jsx
+++ b/webapp/components/new_channel_flow.jsx
@@ -2,9 +2,9 @@
// See License.txt for license information.
import * as Utils from 'utils/utils.jsx';
-import * as AsyncClient from 'utils/async_client.jsx';
import * as Client from 'utils/client.jsx';
import UserStore from 'stores/user_store.jsx';
+import * as GlobalActions from 'action_creators/global_actions.jsx';
import NewChannelModal from './new_channel_modal.jsx';
import ChangeURLModal from './change_url_modal.jsx';
@@ -110,8 +110,7 @@ class NewChannelFlow extends React.Component {
Client.createChannel(channel,
(data) => {
this.props.onModalDismissed();
- AsyncClient.getChannel(data.id);
- Utils.switchChannel(data);
+ GlobalActions.emitChannelClickEvent(data);
},
(err) => {
if (err.id === 'model.channel.is_valid.2_or_more.app_error') {
@@ -247,4 +246,4 @@ NewChannelFlow.propTypes = {
onModalDismissed: React.PropTypes.func.isRequired
};
-export default injectIntl(NewChannelFlow); \ No newline at end of file
+export default injectIntl(NewChannelFlow);
diff --git a/webapp/components/permalink_view.jsx b/webapp/components/permalink_view.jsx
new file mode 100644
index 000000000..8e49019ee
--- /dev/null
+++ b/webapp/components/permalink_view.jsx
@@ -0,0 +1,109 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import React from 'react';
+
+import ChannelHeader from 'components/channel_header.jsx';
+import PostFocusView from 'components/post_focus_view.jsx';
+
+import ChannelStore from 'stores/channel_store.jsx';
+import UserStore from 'stores/user_store.jsx';
+import TeamStore from 'stores/team_store.jsx';
+
+import {Link} from 'react-router';
+import {FormattedMessage} from 'react-intl';
+
+export default class PermalinkView extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.getStateFromStores = this.getStateFromStores.bind(this);
+ this.isStateValid = this.isStateValid.bind(this);
+ this.updateState = this.updateState.bind(this);
+
+ this.state = this.getStateFromStores(props);
+ }
+ getStateFromStores(props) {
+ const postId = props.params.postid;
+ const channel = ChannelStore.getCurrent();
+ const channelId = channel ? channel.id : '';
+ const channelName = channel ? channel.name : '';
+ const teamURL = TeamStore.getCurrentTeamUrl();
+ const profiles = JSON.parse(JSON.stringify(UserStore.getProfiles()));
+ return {
+ channelId,
+ channelName,
+ profiles,
+ teamURL,
+ postId
+ };
+ }
+ isStateValid() {
+ return this.state.channelId !== '' && this.state.profiles && this.state.teamURL;
+ }
+ updateState() {
+ this.setState(this.getStateFromStores(this.props));
+ }
+ componentDidMount() {
+ ChannelStore.addChangeListener(this.updateState);
+ TeamStore.addChangeListener(this.updateState);
+ }
+ componentWillUnmount() {
+ ChannelStore.removeChangeListener(this.updateState);
+ TeamStore.removeChangeListener(this.updateState);
+ }
+ componentWillReceiveProps(nextProps) {
+ this.setState(this.getStateFromStores(nextProps));
+ }
+ shouldComponentUpdate(nextProps, nextState) {
+ if (nextState.postId !== this.state.postId) {
+ return true;
+ }
+
+ if (nextState.channelId !== this.state.channelId) {
+ return true;
+ }
+
+ if (nextState.teamURL !== this.state.teamURL) {
+ return true;
+ }
+
+ return false;
+ }
+ render() {
+ if (!this.isStateValid()) {
+ return null;
+ }
+ return (
+ <div
+ id='app-content'
+ className='app__content'
+ >
+ <ChannelHeader
+ channelId={this.state.channelId}
+ />
+ <PostFocusView profiles={this.state.profiles}/>
+ <div
+ id='archive-link-home'
+ >
+ <Link
+ to={this.state.teamURL + '/channels/' + this.state.channelName}
+ >
+ <FormattedMessage
+ id='center_panel.recent'
+ defaultMessage='Click here to jump to recent messages. '
+ />
+ <i className='fa fa-arrow-down'></i>
+ </Link>
+ </div>
+ </div>
+ );
+ }
+}
+
+PermalinkView.defaultProps = {
+};
+
+PermalinkView.propTypes = {
+ params: React.PropTypes.object.isRequired
+};
diff --git a/webapp/components/popover_list_members.jsx b/webapp/components/popover_list_members.jsx
index 819c7f590..cd583e4c3 100644
--- a/webapp/components/popover_list_members.jsx
+++ b/webapp/components/popover_list_members.jsx
@@ -6,6 +6,7 @@ import $ from 'jquery';
import UserStore from 'stores/user_store.jsx';
import {Popover, Overlay} from 'react-bootstrap';
import * as Utils from 'utils/utils.jsx';
+import * as GlobalActions from 'action_creators/global_actions.jsx';
import Constants from 'utils/constants.jsx';
import ChannelStore from 'stores/channel_store.jsx';
@@ -36,7 +37,7 @@ export default class PopoverListMembers extends React.Component {
Utils.openDirectChannelToUser(
teammate,
(channel, channelAlreadyExisted) => {
- Utils.switchChannel(channel);
+ GlobalActions.emitChannelClickEvent(channel);
if (channelAlreadyExisted) {
this.closePopover();
}
diff --git a/webapp/components/removed_from_channel_modal.jsx b/webapp/components/removed_from_channel_modal.jsx
index cdd51bd6e..45018ac99 100644
--- a/webapp/components/removed_from_channel_modal.jsx
+++ b/webapp/components/removed_from_channel_modal.jsx
@@ -6,7 +6,7 @@ import ReactDOM from 'react-dom';
import ChannelStore from 'stores/channel_store.jsx';
import UserStore from 'stores/user_store.jsx';
import BrowserStore from 'stores/browser_store.jsx';
-import * as utils from 'utils/utils.jsx';
+import * as GlobalActions from 'action_creators/global_actions.jsx';
import {FormattedMessage} from 'react-intl';
@@ -33,7 +33,7 @@ export default class RemovedFromChannelModal extends React.Component {
}
var townSquare = ChannelStore.getByName('town-square');
- setTimeout(() => utils.switchChannel(townSquare), 1);
+ setTimeout(() => GlobalActions.emitChannelClickEvent(townSquare), 1);
this.setState(newState);
}
diff --git a/webapp/components/rename_channel_modal.jsx b/webapp/components/rename_channel_modal.jsx
index 72828984c..ced3c2d2b 100644
--- a/webapp/components/rename_channel_modal.jsx
+++ b/webapp/components/rename_channel_modal.jsx
@@ -4,7 +4,7 @@
import ReactDOM from 'react-dom';
import * as Utils from 'utils/utils.jsx';
import * as Client from 'utils/client.jsx';
-import * as AsyncClient from 'utils/async_client.jsx';
+import * as GlobalActions from 'action_creators/global_actions.jsx';
import Constants from 'utils/constants.jsx';
import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'react-intl';
@@ -165,8 +165,7 @@ export default class RenameChannelModal extends React.Component {
Client.updateChannel(
channel,
() => {
- AsyncClient.getChannel(channel.id);
- Utils.updateAddressBar(channel.name);
+ GlobalActions.emitChannelClickEvent(channel);
this.handleHide();
},
diff --git a/webapp/components/search_results_item.jsx b/webapp/components/search_results_item.jsx
index 35769d06b..219aa7093 100644
--- a/webapp/components/search_results_item.jsx
+++ b/webapp/components/search_results_item.jsx
@@ -1,37 +1,25 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import $ from 'jquery';
import UserStore from 'stores/user_store.jsx';
import UserProfile from './user_profile.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
import * as TextFormatting from 'utils/text_formatting.jsx';
+import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
import {FormattedMessage, FormattedDate} from 'react-intl';
-
import React from 'react';
+import {Link} from 'react-router';
export default class SearchResultsItem extends React.Component {
constructor(props) {
super(props);
- this.handleClick = this.handleClick.bind(this);
this.handleFocusRHSClick = this.handleFocusRHSClick.bind(this);
}
- handleClick(e) {
- e.preventDefault();
-
- GlobalActions.emitPostFocusEvent(this.props.post.id);
-
- if ($(window).width() < 768) {
- $('.sidebar--right').removeClass('move--left');
- $('.inner-wrap').removeClass('move--left');
- }
- }
-
handleFocusRHSClick(e) {
e.preventDefault();
GlobalActions.emitPostFocusRightHandSideFromSearch(this.props.post, this.props.isMentionSearch);
@@ -99,16 +87,15 @@ export default class SearchResultsItem extends React.Component {
</time>
</li>
<li>
- <a
- href='#'
+ <Link
+ to={Utils.getTeamURLFromAddressBar() + '/pl/' + this.props.post.id}
className='search-item__jump'
- onClick={this.handleClick}
>
<FormattedMessage
id='search_item.jump'
defaultMessage='Jump'
/>
- </a>
+ </Link>
</li>
<li>
<a
diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx
index c0d4755ed..bf51fa102 100644
--- a/webapp/components/sidebar.jsx
+++ b/webapp/components/sidebar.jsx
@@ -15,7 +15,6 @@ import TeamStore from 'stores/team_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
-import * as Client from 'utils/client.jsx';
import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
@@ -29,7 +28,7 @@ import {Tooltip, OverlayTrigger} from 'react-bootstrap';
import loadingGif from 'images/load.gif';
import React from 'react';
-import {browserHistory} from 'react-router';
+import {browserHistory, Link} from 'react-router';
import favicon from 'images/favicon/favicon-16x16.png';
import redFavicon from 'images/favicon/redfavicon-16x16.png';
@@ -259,7 +258,7 @@ export default class Sidebar extends React.Component {
}
if (channel.id === this.state.activeId) {
- Utils.switchChannel(ChannelStore.getByName(Constants.DEFAULT_CHANNEL));
+ browserHistory.push(TeamStore.getCurrentTeamUrl() + '/channels/town-square');
}
}
@@ -406,48 +405,6 @@ export default class Sidebar extends React.Component {
icon = <div className='status'><i className='fa fa-lock'></i></div>;
}
- // set up click handler to switch channels (or create a new channel for non-existant ones)
- var handleClick = null;
-
- if (!channel.fake) {
- handleClick = function clickHandler(e) {
- if (e.target.attributes.getNamedItem('data-close')) {
- handleClose(channel);
- } else {
- Utils.switchChannel(channel);
- }
-
- e.preventDefault();
- };
- } else if (channel.fake) {
- // It's a direct message channel that doesn't exist yet so let's create it now
- var otherUserId = Utils.getUserIdFromChannelName(channel);
-
- if (this.state.loadingDMChannel === -1) {
- handleClick = function clickHandler(e) {
- e.preventDefault();
-
- if (e.target.attributes.getNamedItem('data-close')) {
- handleClose(channel);
- } else {
- this.setState({loadingDMChannel: index});
-
- Client.createDirectChannel(channel, otherUserId,
- (data) => {
- this.setState({loadingDMChannel: -1});
- AsyncClient.getChannel(data.id);
- Utils.switchChannel(data);
- },
- () => {
- this.setState({loadingDMChannel: -1});
- browserHistory('/' + this.state.currentTeam.name);
- }
- );
- }
- }.bind(this);
- }
- }
-
let closeButton = null;
const removeTooltip = (
<Tooltip id='remove-dm-tooltip'>
@@ -464,12 +421,12 @@ export default class Sidebar extends React.Component {
placement='top'
overlay={removeTooltip}
>
- <span
- className='btn-close'
- data-close='true'
- >
- {'×'}
- </span>
+ <span
+ onClick={() => handleClose(channel)}
+ className='btn-close'
+ >
+ {'×'}
+ </span>
</OverlayTrigger>
);
@@ -481,23 +438,29 @@ export default class Sidebar extends React.Component {
tutorialTip = this.createTutorialTip();
}
+ let link = '';
+ if (channel.fake) {
+ link = TeamStore.getCurrentTeamUrl() + '/channels/' + channel.name + '?fakechannel=' + encodeURIComponent(JSON.stringify(channel));
+ } else {
+ link = TeamStore.getCurrentTeamUrl() + '/channels/' + channel.name;
+ }
+
return (
<li
key={channel.name}
ref={channel.name}
className={linkClass}
>
- <a
+ <Link
+ to={link}
className={rowClass}
- href={'#'}
- onClick={handleClick}
>
{icon}
{status}
{channel.display_name}
{badge}
{closeButton}
- </a>
+ </Link>
{tutorialTip}
</li>
);
@@ -600,6 +563,7 @@ export default class Sidebar extends React.Component {
<div
className='sidebar--left'
id='sidebar-left'
+ key='sidebar-left'
>
<NewChannelFlow
show={showChannelModal}
diff --git a/webapp/components/sidebar_right.jsx b/webapp/components/sidebar_right.jsx
index a2e3914f3..594674929 100644
--- a/webapp/components/sidebar_right.jsx
+++ b/webapp/components/sidebar_right.jsx
@@ -29,7 +29,7 @@ export default class SidebarRight extends React.Component {
this.doStrangeThings = this.doStrangeThings.bind(this);
this.state = {
- searchVisible: !!SearchStore.getSearchResults(),
+ searchVisible: SearchStore.getSearchResults() !== null,
isMentionSearch: SearchStore.getIsMentionSearch(),
postRightVisible: !!PostStore.getSelectedPost(),
fromSearch: false,
@@ -111,7 +111,7 @@ export default class SidebarRight extends React.Component {
}
onSearchChange() {
this.setState({
- searchVisible: !!SearchStore.getSearchResults(),
+ searchVisible: SearchStore.getSearchResults() !== null,
isMentionSearch: SearchStore.getIsMentionSearch()
});
}
diff --git a/webapp/components/tutorial/tutorial_intro_screens.jsx b/webapp/components/tutorial/tutorial_intro_screens.jsx
index 913a30483..bad426cfc 100644
--- a/webapp/components/tutorial/tutorial_intro_screens.jsx
+++ b/webapp/components/tutorial/tutorial_intro_screens.jsx
@@ -2,7 +2,6 @@
// See License.txt for license information.
import UserStore from 'stores/user_store.jsx';
-import ChannelStore from 'stores/channel_store.jsx';
import TeamStore from 'stores/team_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import * as Utils from 'utils/utils.jsx';
@@ -11,6 +10,7 @@ import * as AsyncClient from 'utils/async_client.jsx';
import Constants from 'utils/constants.jsx';
import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
+import {browserHistory} from 'react-router';
const Preferences = Constants.Preferences;
@@ -34,7 +34,7 @@ export default class TutorialIntroScreens extends React.Component {
return;
}
- Utils.switchChannel(ChannelStore.getByName(Constants.DEFAULT_CHANNEL));
+ browserHistory.push(TeamStore.getCurrentTeamUrl() + '/channels/town-square');
const step = PreferenceStore.getInt(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), 0);
@@ -52,6 +52,8 @@ export default class TutorialIntroScreens extends React.Component {
UserStore.getCurrentId(),
'999'
);
+
+ browserHistory.push(TeamStore.getCurrentTeamUrl() + '/channels/town-square');
}
createScreen() {
switch (this.state.currentScreen) {
diff --git a/webapp/components/tutorial/tutorial_view.jsx b/webapp/components/tutorial/tutorial_view.jsx
new file mode 100644
index 000000000..d9e0ef40d
--- /dev/null
+++ b/webapp/components/tutorial/tutorial_view.jsx
@@ -0,0 +1,19 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import React from 'react';
+
+import TutorialIntroScreens from './tutorial_intro_screens.jsx';
+
+export default class TutorialView extends React.Component {
+ render() {
+ return (
+ <div
+ id='app-content'
+ className='app__content'
+ >
+ <TutorialIntroScreens/>
+ </div>
+ );
+ }
+}