summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrei Stanciu <andrei.stanciu@geminisols.ro>2017-02-10 16:56:48 +0200
committerCorey Hulen <corey@hulen.com>2017-02-10 06:56:48 -0800
commit1bbed1cb2bf1248e9ca8a1511cfe8a385c5f21f7 (patch)
treee61c54cc13a6d7975cce69322bae6f6f5c7c9300
parent1359f7f3918befd2463103379d17bd2eb846654d (diff)
downloadchat-1bbed1cb2bf1248e9ca8a1511cfe8a385c5f21f7.tar.gz
chat-1bbed1cb2bf1248e9ca8a1511cfe8a385c5f21f7.tar.bz2
chat-1bbed1cb2bf1248e9ca8a1511cfe8a385c5f21f7.zip
Add permalink to timestamp (#5206)
* Add permalink to timestamp * Add permalink to timestamp * Add permalink to timestamp * Add permalink to timestamp * fix error with duplicated import * underline permalink on hover
-rw-r--r--webapp/components/post_view/components/post_info.jsx1
-rw-r--r--webapp/components/post_view/components/post_time.jsx35
-rw-r--r--webapp/components/rhs_comment.jsx53
-rw-r--r--webapp/components/rhs_root_post.jsx52
-rw-r--r--webapp/components/search_results_item.jsx56
-rw-r--r--webapp/sass/layout/_post.scss13
-rw-r--r--webapp/sass/responsive/_tablet.scss4
-rw-r--r--webapp/utils/utils.jsx4
8 files changed, 191 insertions, 27 deletions
diff --git a/webapp/components/post_view/components/post_info.jsx b/webapp/components/post_view/components/post_info.jsx
index 3f38bdffe..e368e65f4 100644
--- a/webapp/components/post_view/components/post_info.jsx
+++ b/webapp/components/post_view/components/post_info.jsx
@@ -376,6 +376,7 @@ export default class PostInfo extends React.Component {
sameUser={this.props.sameUser}
compactDisplay={this.props.compactDisplay}
useMilitaryTime={this.props.useMilitaryTime}
+ postId={post.id}
/>
{flagTrigger}
</li>
diff --git a/webapp/components/post_view/components/post_time.jsx b/webapp/components/post_view/components/post_time.jsx
index caad12d4a..25d533e0a 100644
--- a/webapp/components/post_view/components/post_time.jsx
+++ b/webapp/components/post_view/components/post_time.jsx
@@ -6,26 +6,40 @@ import React from 'react';
import Constants from 'utils/constants.jsx';
import PureRenderMixin from 'react-addons-pure-render-mixin';
-import {getDateForUnixTicks} from 'utils/utils.jsx';
+import {getDateForUnixTicks, isMobile, updateWindowDimensions} from 'utils/utils.jsx';
+
+import {Link} from 'react-router/es6';
+import TeamStore from 'stores/team_store.jsx';
export default class PostTime extends React.Component {
constructor(props) {
super(props);
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
+ this.state = {
+ currentTeamDisplayName: TeamStore.getCurrent().name,
+ width: '',
+ height: ''
+ };
}
componentDidMount() {
this.intervalId = setInterval(() => {
this.forceUpdate();
}, Constants.TIME_SINCE_UPDATE_INTERVAL);
+ window.addEventListener('resize', () => {
+ updateWindowDimensions(this);
+ });
}
componentWillUnmount() {
clearInterval(this.intervalId);
+ window.removeEventListener('resize', () => {
+ updateWindowDimensions(this);
+ });
}
- render() {
+ renderTimeTag() {
return (
<time
className='post__time'
@@ -35,6 +49,20 @@ export default class PostTime extends React.Component {
</time>
);
}
+
+ render() {
+ return isMobile() ?
+ this.renderTimeTag() :
+ (
+ <Link
+ to={`/${this.state.currentTeamDisplayName}/pl/${this.props.postId}`}
+ target='_blank'
+ className='post__permalink'
+ >
+ {this.renderTimeTag()}
+ </Link>
+ );
+ }
}
PostTime.defaultProps = {
@@ -46,5 +74,6 @@ PostTime.propTypes = {
eventTime: React.PropTypes.number.isRequired,
sameUser: React.PropTypes.bool,
compactDisplay: React.PropTypes.bool,
- useMilitaryTime: React.PropTypes.bool.isRequired
+ useMilitaryTime: React.PropTypes.bool.isRequired,
+ postId: React.PropTypes.string
};
diff --git a/webapp/components/rhs_comment.jsx b/webapp/components/rhs_comment.jsx
index 24baaa09c..67fd394b9 100644
--- a/webapp/components/rhs_comment.jsx
+++ b/webapp/components/rhs_comment.jsx
@@ -12,6 +12,8 @@ import RhsDropdown from 'components/rhs_dropdown.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
import {flagPost, unflagPost} from 'actions/post_actions.jsx';
+import TeamStore from 'stores/team_store.jsx';
+
import * as Utils from 'utils/utils.jsx';
import * as PostUtils from 'utils/post_utils.jsx';
@@ -24,6 +26,7 @@ import {FormattedMessage} from 'react-intl';
import loadingGif from 'images/load.gif';
import React from 'react';
+import {Link} from 'react-router/es6';
export default class RhsComment extends React.Component {
constructor(props) {
@@ -38,7 +41,23 @@ export default class RhsComment extends React.Component {
this.canDelete = false;
this.editDisableAction = new DelayedAction(this.handleEditDisable);
- this.state = {};
+ this.state = {
+ currentTeamDisplayName: TeamStore.getCurrent().name,
+ width: '',
+ height: ''
+ };
+ }
+
+ componentDidMount() {
+ window.addEventListener('resize', () => {
+ Utils.updateWindowDimensions(this);
+ });
+ }
+
+ componentWillUnmount() {
+ window.removeEventListener('resize', () => {
+ Utils.updateWindowDimensions(this);
+ });
}
handlePermalink(e) {
@@ -235,6 +254,31 @@ export default class RhsComment extends React.Component {
);
}
+ timeTag(post, timeOptions) {
+ return (
+ <time
+ className='post__time'
+ dateTime={Utils.getDateForUnixTicks(post.create_at).toISOString()}
+ >
+ {Utils.getDateForUnixTicks(post.create_at).toLocaleString('en', timeOptions)}
+ </time>
+ );
+ }
+
+ renderTimeTag(post, timeOptions) {
+ return Utils.isMobile() ?
+ this.timeTag(post, timeOptions) :
+ (
+ <Link
+ to={`/${this.state.currentTeamDisplayName}/pl/${post.id}`}
+ target='_blank'
+ className='post__permalink'
+ >
+ {this.timeTag(post, timeOptions)}
+ </Link>
+ );
+ }
+
render() {
const post = this.props.post;
const flagIcon = Constants.FLAG_ICON_SVG;
@@ -479,12 +523,7 @@ export default class RhsComment extends React.Component {
</li>
{botIndicator}
<li className='col'>
- <time
- className='post__time'
- dateTime={Utils.getDateForUnixTicks(post.create_at).toISOString()}
- >
- {Utils.getDateForUnixTicks(post.create_at).toLocaleString('en', timeOptions)}
- </time>
+ {this.renderTimeTag(post, timeOptions)}
{flagTrigger}
</li>
{options}
diff --git a/webapp/components/rhs_root_post.jsx b/webapp/components/rhs_root_post.jsx
index 5ab0a3956..0c1037501 100644
--- a/webapp/components/rhs_root_post.jsx
+++ b/webapp/components/rhs_root_post.jsx
@@ -11,6 +11,7 @@ import RhsDropdown from 'components/rhs_dropdown.jsx';
import ChannelStore from 'stores/channel_store.jsx';
import UserStore from 'stores/user_store.jsx';
+import TeamStore from 'stores/team_store.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
import {flagPost, unflagPost} from 'actions/post_actions.jsx';
@@ -25,6 +26,7 @@ import {Tooltip, OverlayTrigger} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import React from 'react';
+import {Link} from 'react-router/es6';
export default class RhsRootPost extends React.Component {
constructor(props) {
@@ -38,7 +40,23 @@ export default class RhsRootPost extends React.Component {
this.canDelete = false;
this.editDisableAction = new DelayedAction(this.handleEditDisable);
- this.state = {};
+ this.state = {
+ currentTeamDisplayName: TeamStore.getCurrent().name,
+ width: '',
+ height: ''
+ };
+ }
+
+ componentDidMount() {
+ window.addEventListener('resize', () => {
+ Utils.updateWindowDimensions(this);
+ });
+ }
+
+ componentWillUnmount() {
+ window.removeEventListener('resize', () => {
+ Utils.updateWindowDimensions(this);
+ });
}
handlePermalink(e) {
@@ -100,6 +118,31 @@ export default class RhsRootPost extends React.Component {
unflagPost(this.props.post.id);
}
+ timeTag(post, timeOptions) {
+ return (
+ <time
+ className='post__time'
+ dateTime={Utils.getDateForUnixTicks(post.create_at).toISOString()}
+ >
+ {Utils.getDateForUnixTicks(post.create_at).toLocaleString('en', timeOptions)}
+ </time>
+ );
+ }
+
+ renderTimeTag(post, timeOptions) {
+ return Utils.isMobile() ?
+ this.timeTag(post, timeOptions) :
+ (
+ <Link
+ to={`/${this.state.currentTeamDisplayName}/pl/${post.id}`}
+ target='_blank'
+ className='post__permalink'
+ >
+ {this.timeTag(post, timeOptions)}
+ </Link>
+ );
+ }
+
render() {
const post = this.props.post;
const user = this.props.user;
@@ -426,12 +469,7 @@ export default class RhsRootPost extends React.Component {
<li className='col__name'>{userProfile}</li>
{botIndicator}
<li className='col'>
- <time
- className='post__time'
- dateTime={Utils.getDateForUnixTicks(post.create_at).toISOString()}
- >
- {Utils.getDateForUnixTicks(post.create_at).toLocaleString('en', timeOptions)}
- </time>
+ {this.renderTimeTag(post, timeOptions)}
<OverlayTrigger
key={'rootpostflagtooltipkey' + flagVisible}
delayShow={Constants.OVERLAY_TIME_DELAY}
diff --git a/webapp/components/search_results_item.jsx b/webapp/components/search_results_item.jsx
index f0096a324..f2bca109a 100644
--- a/webapp/components/search_results_item.jsx
+++ b/webapp/components/search_results_item.jsx
@@ -22,7 +22,7 @@ const ActionTypes = Constants.ActionTypes;
import React from 'react';
import {FormattedMessage, FormattedDate} from 'react-intl';
-import {browserHistory} from 'react-router/es6';
+import {browserHistory, Link} from 'react-router/es6';
export default class SearchResultsItem extends React.Component {
constructor(props) {
@@ -32,6 +32,24 @@ export default class SearchResultsItem extends React.Component {
this.shrinkSidebar = this.shrinkSidebar.bind(this);
this.unflagPost = this.unflagPost.bind(this);
this.flagPost = this.flagPost.bind(this);
+
+ this.state = {
+ currentTeamDisplayName: TeamStore.getCurrent().name,
+ width: '',
+ height: ''
+ };
+ }
+
+ componentDidMount() {
+ window.addEventListener('resize', () => {
+ Utils.updateWindowDimensions(this);
+ });
+ }
+
+ componentWillUnmount() {
+ window.removeEventListener('resize', () => {
+ Utils.updateWindowDimensions(this);
+ });
}
hideSidebar() {
@@ -59,6 +77,33 @@ export default class SearchResultsItem extends React.Component {
unflagPost(this.props.post.id);
}
+ timeTag(post) {
+ return (
+ <time className='search-item-time'>
+ <FormattedDate
+ value={post.create_at}
+ hour12={!this.props.useMilitaryTime}
+ hour='2-digit'
+ minute='2-digit'
+ />
+ </time>
+ );
+ }
+
+ renderTimeTag(post) {
+ return Utils.isMobile() ?
+ this.timeTag(post) :
+ (
+ <Link
+ to={`/${this.state.currentTeamDisplayName}/pl/${post.id}`}
+ target='_blank'
+ className='post__permalink'
+ >
+ {this.timeTag(post)}
+ </Link>
+ );
+ }
+
render() {
let channelName = null;
const channel = this.props.channel;
@@ -276,14 +321,7 @@ export default class SearchResultsItem extends React.Component {
</strong></li>
{botIndicator}
<li className='col'>
- <time className='search-item-time'>
- <FormattedDate
- value={post.create_at}
- hour12={!this.props.useMilitaryTime}
- hour='2-digit'
- minute='2-digit'
- />
- </time>
+ {this.renderTimeTag(post)}
{flagContent}
</li>
{rhsControls}
diff --git a/webapp/sass/layout/_post.scss b/webapp/sass/layout/_post.scss
index 06a3967cc..5d6c12421 100644
--- a/webapp/sass/layout/_post.scss
+++ b/webapp/sass/layout/_post.scss
@@ -1199,6 +1199,19 @@
font-size: .9em;
}
+ .post__permalink {
+ color: #333;
+ &:hover, &:focus {
+ color: #333;
+ }
+ &:focus {
+ text-decoration: none;
+ }
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+
.post-loading-gif {
height: 10px;
margin-top: 6px;
diff --git a/webapp/sass/responsive/_tablet.scss b/webapp/sass/responsive/_tablet.scss
index 79a22aa30..f8ca019e0 100644
--- a/webapp/sass/responsive/_tablet.scss
+++ b/webapp/sass/responsive/_tablet.scss
@@ -366,7 +366,9 @@
text-rendering: auto;
top: -2px;
width: 51px;
-
+ &:hover {
+ text-decoration: underline;
+ }
}
}
}
diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx
index c639abc56..2fd7bf99b 100644
--- a/webapp/utils/utils.jsx
+++ b/webapp/utils/utils.jsx
@@ -1287,3 +1287,7 @@ export function isEmptyObject(object) {
return false;
}
+
+export function updateWindowDimensions(component) {
+ component.setState({width: window.innerWidth, height: window.innerHeight});
+}