[Glitch] Change featured hashtags to be displayed in navigation panel
Port aefa9253d6 to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
			
			
This commit is contained in:
		| @@ -65,23 +65,35 @@ ImmutableHashtag.propTypes = { | ||||
|   hashtag: ImmutablePropTypes.map.isRequired, | ||||
| }; | ||||
|  | ||||
| const Hashtag = ({ name, href, to, people, history, className }) => ( | ||||
| const Hashtag = ({ name, href, to, people, uses, history, className, description, withGraph }) => ( | ||||
|   <div className={classNames('trends__item', className)}> | ||||
|     <div className='trends__item__name'> | ||||
|       <Permalink href={href} to={to}> | ||||
|         {name ? <React.Fragment>#<span>{name}</span></React.Fragment> : <Skeleton width={50} />} | ||||
|       </Permalink> | ||||
|  | ||||
|       {typeof people !== 'undefined' ? <ShortNumber value={people} renderer={accountsCountRenderer} /> : <Skeleton width={100} />} | ||||
|       {description ? ( | ||||
|         <span>{description}</span> | ||||
|       ) : ( | ||||
|         typeof people !== 'undefined' ? <ShortNumber value={people} renderer={accountsCountRenderer} /> : <Skeleton width={100} /> | ||||
|       )} | ||||
|     </div> | ||||
|  | ||||
|     <div className='trends__item__sparkline'> | ||||
|       <SilentErrorBoundary> | ||||
|         <Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}> | ||||
|           <SparklinesCurve style={{ fill: 'none' }} /> | ||||
|         </Sparklines> | ||||
|       </SilentErrorBoundary> | ||||
|     </div> | ||||
|     {typeof uses !== 'undefined' && ( | ||||
|       <div className='trends__item__current'> | ||||
|         <ShortNumber value={uses} /> | ||||
|       </div> | ||||
|     )} | ||||
|  | ||||
|     {withGraph && ( | ||||
|       <div className='trends__item__sparkline'> | ||||
|         <SilentErrorBoundary> | ||||
|           <Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}> | ||||
|             <SparklinesCurve style={{ fill: 'none' }} /> | ||||
|           </Sparklines> | ||||
|         </SilentErrorBoundary> | ||||
|       </div> | ||||
|     )} | ||||
|   </div> | ||||
| ); | ||||
|  | ||||
| @@ -90,9 +102,15 @@ Hashtag.propTypes = { | ||||
|   href: PropTypes.string, | ||||
|   to: PropTypes.string, | ||||
|   people: PropTypes.number, | ||||
|   description: PropTypes.node, | ||||
|   uses: PropTypes.number, | ||||
|   history: PropTypes.arrayOf(PropTypes.number), | ||||
|   className: PropTypes.string, | ||||
|   withGraph: PropTypes.bool, | ||||
| }; | ||||
|  | ||||
| Hashtag.defaultProps = { | ||||
|   withGraph: true, | ||||
| }; | ||||
|  | ||||
| export default Hashtag; | ||||
|   | ||||
| @@ -0,0 +1,30 @@ | ||||
| import React from 'react'; | ||||
| import { Switch, Route, withRouter } from 'react-router-dom'; | ||||
| import { showTrends } from 'flavours/glitch/initial_state'; | ||||
| import Trends from 'flavours/glitch/features/getting_started/containers/trends_container'; | ||||
| import AccountNavigation from 'flavours/glitch/features/account/navigation'; | ||||
|  | ||||
| const DefaultNavigation = () => ( | ||||
|   <> | ||||
|     {showTrends && ( | ||||
|       <> | ||||
|         <div className='flex-spacer' /> | ||||
|         <Trends /> | ||||
|       </> | ||||
|     )} | ||||
|   </> | ||||
| ); | ||||
|  | ||||
| export default @withRouter | ||||
| class NavigationPortal extends React.PureComponent { | ||||
|  | ||||
|   render () { | ||||
|     return ( | ||||
|       <Switch> | ||||
|         <Route path='/@:acct/(tagged/:tagged?)?' component={AccountNavigation} /> | ||||
|         <Route component={DefaultNavigation} /> | ||||
|       </Switch> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -1,27 +1,16 @@ | ||||
| import React from 'react'; | ||||
| import { connect } from 'react-redux'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import ImmutablePropTypes from 'react-immutable-proptypes'; | ||||
| import ImmutablePureComponent from 'react-immutable-pure-component'; | ||||
| import { defineMessages, injectIntl } from 'react-intl'; | ||||
| import classNames from 'classnames'; | ||||
| import Permalink from 'flavours/glitch/components/permalink'; | ||||
| import ShortNumber from 'flavours/glitch/components/short_number'; | ||||
| import { List as ImmutableList } from 'immutable'; | ||||
| import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; | ||||
| import Hashtag from 'flavours/glitch/components/hashtag'; | ||||
|  | ||||
| const messages = defineMessages({ | ||||
|   hashtag_all: { id: 'account.hashtag_all', defaultMessage: 'All' }, | ||||
|   hashtag_all_description: { id: 'account.hashtag_all_description', defaultMessage: 'All posts (deselect hashtags)' }, | ||||
|   hashtag_select_description: { id: 'account.hashtag_select_description', defaultMessage: 'Select hashtag #{name}' }, | ||||
|   statuses_counter: { id: 'account.statuses_counter', defaultMessage: '{count, plural, one {{counter} Post} other {{counter} Posts}}' }, | ||||
|   lastStatusAt: { id: 'account.featured_tags.last_status_at', defaultMessage: 'Last post on {date}' }, | ||||
|   empty: { id: 'account.featured_tags.last_status_never', defaultMessage: 'No posts' }, | ||||
| }); | ||||
|  | ||||
| const mapStateToProps = (state, { account }) => ({ | ||||
|   featuredTags: state.getIn(['user_lists', 'featured_tags', account.get('id'), 'items'], ImmutableList()), | ||||
| }); | ||||
|  | ||||
| export default @connect(mapStateToProps) | ||||
| @injectIntl | ||||
| export default @injectIntl | ||||
| class FeaturedTags extends ImmutablePureComponent { | ||||
|  | ||||
|   static contextTypes = { | ||||
| @@ -36,34 +25,27 @@ class FeaturedTags extends ImmutablePureComponent { | ||||
|   }; | ||||
|  | ||||
|   render () { | ||||
|     const { account, featuredTags, tagged, intl } = this.props; | ||||
|     const { account, featuredTags, intl } = this.props; | ||||
|  | ||||
|     if (!account || featuredTags.isEmpty()) { | ||||
|     if (!account || account.get('suspended') || featuredTags.isEmpty()) { | ||||
|       return null; | ||||
|     } | ||||
|  | ||||
|     const suspended = account.get('suspended'); | ||||
|  | ||||
|     return ( | ||||
|       <div className={classNames('account__header', 'advanced', { inactive: !!account.get('moved') })}> | ||||
|         <div className='account__header__extra'> | ||||
|           <div className='account__header__extra__hashtag-links'> | ||||
|             <Permalink key='all' className={classNames('account__hashtag-link', { active: !tagged })} title={intl.formatMessage(messages.hashtag_all_description)} href={account.get('url')} to={`/@${account.get('acct')}`}>{intl.formatMessage(messages.hashtag_all)}</Permalink> | ||||
|             {!suspended && featuredTags.map(featuredTag => { | ||||
|               const name  = featuredTag.get('name'); | ||||
|               const url   = featuredTag.get('url'); | ||||
|               const to    = `/@${account.get('acct')}/tagged/${name}`; | ||||
|               const desc  = intl.formatMessage(messages.hashtag_select_description, { name }); | ||||
|               const count = featuredTag.get('statuses_count'); | ||||
|       <div className='getting-started__trends'> | ||||
|         <h4><FormattedMessage id='account.featured_tags.title' defaultMessage="{name}'s featured hashtags" values={{ name: <bdi dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} /> }} /></h4> | ||||
|  | ||||
|               return ( | ||||
|                 <Permalink key={`#${name}`} className={classNames('account__hashtag-link', { active: this.context.router.history.location.pathname === to })} title={desc} href={url} to={to}> | ||||
|                   #{name} <span title={intl.formatMessage(messages.statuses_counter, { count: count, counter: intl.formatNumber(count) })}>({<ShortNumber value={count} />})</span> | ||||
|                 </Permalink> | ||||
|               ); | ||||
|             })} | ||||
|           </div> | ||||
|         </div> | ||||
|         {featuredTags.map(featuredTag => ( | ||||
|           <Hashtag | ||||
|             key={featuredTag.get('name')} | ||||
|             name={featuredTag.get('name')} | ||||
|             href={featuredTag.get('url')} | ||||
|             to={`/@${account.get('acct')}/tagged/${featuredTag.get('name')}`} | ||||
|             uses={featuredTag.get('statuses_count')} | ||||
|             withGraph={false} | ||||
|             description={((featuredTag.get('statuses_count') * 1) > 0) ? intl.formatMessage(messages.lastStatusAt, { date: intl.formatDate(featuredTag.get('last_status_at'), { month: 'short', day: '2-digit' }) }) : intl.formatMessage(messages.empty)} | ||||
|           /> | ||||
|         ))} | ||||
|       </div> | ||||
|     ); | ||||
|   } | ||||
|   | ||||
| @@ -0,0 +1,15 @@ | ||||
| import { connect } from 'react-redux'; | ||||
| import FeaturedTags from '../components/featured_tags'; | ||||
| import { makeGetAccount } from 'flavours/glitch/selectors'; | ||||
| import { List as ImmutableList } from 'immutable'; | ||||
|  | ||||
| const mapStateToProps = () => { | ||||
|   const getAccount = makeGetAccount(); | ||||
|  | ||||
|   return (state, { accountId }) => ({ | ||||
|     account: getAccount(state, accountId), | ||||
|     featuredTags: state.getIn(['user_lists', 'featured_tags', accountId, 'items'], ImmutableList()), | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export default connect(mapStateToProps)(FeaturedTags); | ||||
| @@ -0,0 +1,51 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { connect } from 'react-redux'; | ||||
| import FeaturedTags from 'flavours/glitch/features/account/containers/featured_tags_container'; | ||||
|  | ||||
| const mapStateToProps = (state, { match: { params: { acct } } }) => { | ||||
|   const accountId = state.getIn(['accounts_map', acct]); | ||||
|  | ||||
|   if (!accountId) { | ||||
|     return { | ||||
|       isLoading: true, | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   return { | ||||
|     accountId, | ||||
|     isLoading: false, | ||||
|   }; | ||||
| }; | ||||
|  | ||||
| export default @connect(mapStateToProps) | ||||
| class AccountNavigation extends React.PureComponent { | ||||
|  | ||||
|   static propTypes = { | ||||
|     match: PropTypes.shape({ | ||||
|       params: PropTypes.shape({ | ||||
|         acct: PropTypes.string, | ||||
|         tagged: PropTypes.string, | ||||
|       }).isRequired, | ||||
|     }).isRequired, | ||||
|  | ||||
|     accountId: PropTypes.string, | ||||
|     isLoading: PropTypes.bool, | ||||
|   }; | ||||
|  | ||||
|   render () { | ||||
|     const { accountId, isLoading, match: { params: { tagged } } } = this.props; | ||||
|  | ||||
|     if (isLoading) { | ||||
|       return null; | ||||
|     } | ||||
|  | ||||
|     return ( | ||||
|       <> | ||||
|         <div className='flex-spacer' /> | ||||
|         <FeaturedTags accountId={accountId} tagged={tagged} /> | ||||
|       </> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -28,7 +28,6 @@ export default class Header extends ImmutablePureComponent { | ||||
|     hideTabs: PropTypes.bool, | ||||
|     domain: PropTypes.string.isRequired, | ||||
|     hidden: PropTypes.bool, | ||||
|     tagged: PropTypes.string, | ||||
|   }; | ||||
|  | ||||
|   static contextTypes = { | ||||
| @@ -104,7 +103,7 @@ export default class Header extends ImmutablePureComponent { | ||||
|   } | ||||
|  | ||||
|   render () { | ||||
|     const { account, hidden, hideTabs, tagged } = this.props; | ||||
|     const { account, hidden, hideTabs } = this.props; | ||||
|  | ||||
|     if (account === null) { | ||||
|       return null; | ||||
|   | ||||
| @@ -2,14 +2,14 @@ import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { defineMessages, injectIntl } from 'react-intl'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| import TrendsContainer from 'flavours/glitch/features/getting_started/containers/trends_container'; | ||||
| import { showTrends, timelinePreview } from 'flavours/glitch/initial_state'; | ||||
| import { timelinePreview } from 'flavours/glitch/initial_state'; | ||||
| import ColumnLink from 'flavours/glitch/features/ui/components/column_link'; | ||||
| import FollowRequestsColumnLink from './follow_requests_column_link'; | ||||
| import ListPanel from './list_panel'; | ||||
| import NotificationsCounterIcon from './notifications_counter_icon'; | ||||
| import SignInBanner from './sign_in_banner'; | ||||
| import { preferencesLink, relationshipsLink } from 'flavours/glitch/utils/backend_links'; | ||||
| import NavigationPortal from 'flavours/glitch/components/navigation_portal'; | ||||
|  | ||||
| const messages = defineMessages({ | ||||
|   home: { id: 'tabs_bar.home', defaultMessage: 'Home' }, | ||||
| @@ -89,13 +89,7 @@ class NavigationPanel extends React.Component { | ||||
|           <ColumnLink transparent to='/about' icon='ellipsis-h' text={intl.formatMessage(messages.about)} /> | ||||
|         </div> | ||||
|  | ||||
|         {showTrends && ( | ||||
|           <React.Fragment> | ||||
|             <div className='flex-spacer' /> | ||||
|             <TrendsContainer /> | ||||
|           </React.Fragment> | ||||
|         )} | ||||
|  | ||||
|         <NavigationPortal /> | ||||
|       </div> | ||||
|     ); | ||||
|   } | ||||
|   | ||||
| @@ -173,12 +173,6 @@ | ||||
|       margin-left: 5px; | ||||
|       color: $secondary-text-color; | ||||
|       text-decoration: none; | ||||
|  | ||||
|       &__asterisk { | ||||
|         color: $darker-text-color; | ||||
|         font-size: 18px; | ||||
|         vertical-align: super; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     &__sparkline { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user