[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,16 +65,27 @@ ImmutableHashtag.propTypes = {
 | 
				
			|||||||
  hashtag: ImmutablePropTypes.map.isRequired,
 | 
					  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={classNames('trends__item', className)}>
 | 
				
			||||||
    <div className='trends__item__name'>
 | 
					    <div className='trends__item__name'>
 | 
				
			||||||
      <Permalink href={href} to={to}>
 | 
					      <Permalink href={href} to={to}>
 | 
				
			||||||
        {name ? <React.Fragment>#<span>{name}</span></React.Fragment> : <Skeleton width={50} />}
 | 
					        {name ? <React.Fragment>#<span>{name}</span></React.Fragment> : <Skeleton width={50} />}
 | 
				
			||||||
      </Permalink>
 | 
					      </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>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {typeof uses !== 'undefined' && (
 | 
				
			||||||
 | 
					      <div className='trends__item__current'>
 | 
				
			||||||
 | 
					        <ShortNumber value={uses} />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {withGraph && (
 | 
				
			||||||
      <div className='trends__item__sparkline'>
 | 
					      <div className='trends__item__sparkline'>
 | 
				
			||||||
        <SilentErrorBoundary>
 | 
					        <SilentErrorBoundary>
 | 
				
			||||||
          <Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}>
 | 
					          <Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}>
 | 
				
			||||||
@@ -82,6 +93,7 @@ const Hashtag = ({ name, href, to, people, history, className }) => (
 | 
				
			|||||||
          </Sparklines>
 | 
					          </Sparklines>
 | 
				
			||||||
        </SilentErrorBoundary>
 | 
					        </SilentErrorBoundary>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
 | 
					    )}
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -90,9 +102,15 @@ Hashtag.propTypes = {
 | 
				
			|||||||
  href: PropTypes.string,
 | 
					  href: PropTypes.string,
 | 
				
			||||||
  to: PropTypes.string,
 | 
					  to: PropTypes.string,
 | 
				
			||||||
  people: PropTypes.number,
 | 
					  people: PropTypes.number,
 | 
				
			||||||
 | 
					  description: PropTypes.node,
 | 
				
			||||||
  uses: PropTypes.number,
 | 
					  uses: PropTypes.number,
 | 
				
			||||||
  history: PropTypes.arrayOf(PropTypes.number),
 | 
					  history: PropTypes.arrayOf(PropTypes.number),
 | 
				
			||||||
  className: PropTypes.string,
 | 
					  className: PropTypes.string,
 | 
				
			||||||
 | 
					  withGraph: PropTypes.bool,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hashtag.defaultProps = {
 | 
				
			||||||
 | 
					  withGraph: true,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Hashtag;
 | 
					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 React from 'react';
 | 
				
			||||||
import { connect } from 'react-redux';
 | 
					 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
					import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
				
			||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
					import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
				
			||||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
					import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
				
			||||||
import classNames from 'classnames';
 | 
					import Hashtag from 'flavours/glitch/components/hashtag';
 | 
				
			||||||
import Permalink from 'flavours/glitch/components/permalink';
 | 
					 | 
				
			||||||
import ShortNumber from 'flavours/glitch/components/short_number';
 | 
					 | 
				
			||||||
import { List as ImmutableList } from 'immutable';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
  hashtag_all: { id: 'account.hashtag_all', defaultMessage: 'All' },
 | 
					  lastStatusAt: { id: 'account.featured_tags.last_status_at', defaultMessage: 'Last post on {date}' },
 | 
				
			||||||
  hashtag_all_description: { id: 'account.hashtag_all_description', defaultMessage: 'All posts (deselect hashtags)' },
 | 
					  empty: { id: 'account.featured_tags.last_status_never', defaultMessage: 'No posts' },
 | 
				
			||||||
  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}}' },
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const mapStateToProps = (state, { account }) => ({
 | 
					export default @injectIntl
 | 
				
			||||||
  featuredTags: state.getIn(['user_lists', 'featured_tags', account.get('id'), 'items'], ImmutableList()),
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default @connect(mapStateToProps)
 | 
					 | 
				
			||||||
@injectIntl
 | 
					 | 
				
			||||||
class FeaturedTags extends ImmutablePureComponent {
 | 
					class FeaturedTags extends ImmutablePureComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static contextTypes = {
 | 
					  static contextTypes = {
 | 
				
			||||||
@@ -36,34 +25,27 @@ class FeaturedTags extends ImmutablePureComponent {
 | 
				
			|||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  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;
 | 
					      return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const suspended = account.get('suspended');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className={classNames('account__header', 'advanced', { inactive: !!account.get('moved') })}>
 | 
					      <div className='getting-started__trends'>
 | 
				
			||||||
        <div className='account__header__extra'>
 | 
					        <h4><FormattedMessage id='account.featured_tags.title' defaultMessage="{name}'s featured hashtags" values={{ name: <bdi dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} /> }} /></h4>
 | 
				
			||||||
          <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');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
              return (
 | 
					        {featuredTags.map(featuredTag => (
 | 
				
			||||||
                <Permalink key={`#${name}`} className={classNames('account__hashtag-link', { active: this.context.router.history.location.pathname === to })} title={desc} href={url} to={to}>
 | 
					          <Hashtag
 | 
				
			||||||
                  #{name} <span title={intl.formatMessage(messages.statuses_counter, { count: count, counter: intl.formatNumber(count) })}>({<ShortNumber value={count} />})</span>
 | 
					            key={featuredTag.get('name')}
 | 
				
			||||||
                </Permalink>
 | 
					            name={featuredTag.get('name')}
 | 
				
			||||||
              );
 | 
					            href={featuredTag.get('url')}
 | 
				
			||||||
            })}
 | 
					            to={`/@${account.get('acct')}/tagged/${featuredTag.get('name')}`}
 | 
				
			||||||
          </div>
 | 
					            uses={featuredTag.get('statuses_count')}
 | 
				
			||||||
        </div>
 | 
					            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>
 | 
					      </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,
 | 
					    hideTabs: PropTypes.bool,
 | 
				
			||||||
    domain: PropTypes.string.isRequired,
 | 
					    domain: PropTypes.string.isRequired,
 | 
				
			||||||
    hidden: PropTypes.bool,
 | 
					    hidden: PropTypes.bool,
 | 
				
			||||||
    tagged: PropTypes.string,
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static contextTypes = {
 | 
					  static contextTypes = {
 | 
				
			||||||
@@ -104,7 +103,7 @@ export default class Header extends ImmutablePureComponent {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    const { account, hidden, hideTabs, tagged } = this.props;
 | 
					    const { account, hidden, hideTabs } = this.props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (account === null) {
 | 
					    if (account === null) {
 | 
				
			||||||
      return null;
 | 
					      return null;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,14 +2,14 @@ import React from 'react';
 | 
				
			|||||||
import PropTypes from 'prop-types';
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
					import { defineMessages, injectIntl } from 'react-intl';
 | 
				
			||||||
import { Link } from 'react-router-dom';
 | 
					import { Link } from 'react-router-dom';
 | 
				
			||||||
import TrendsContainer from 'flavours/glitch/features/getting_started/containers/trends_container';
 | 
					import { timelinePreview } from 'flavours/glitch/initial_state';
 | 
				
			||||||
import { showTrends, timelinePreview } from 'flavours/glitch/initial_state';
 | 
					 | 
				
			||||||
import ColumnLink from 'flavours/glitch/features/ui/components/column_link';
 | 
					import ColumnLink from 'flavours/glitch/features/ui/components/column_link';
 | 
				
			||||||
import FollowRequestsColumnLink from './follow_requests_column_link';
 | 
					import FollowRequestsColumnLink from './follow_requests_column_link';
 | 
				
			||||||
import ListPanel from './list_panel';
 | 
					import ListPanel from './list_panel';
 | 
				
			||||||
import NotificationsCounterIcon from './notifications_counter_icon';
 | 
					import NotificationsCounterIcon from './notifications_counter_icon';
 | 
				
			||||||
import SignInBanner from './sign_in_banner';
 | 
					import SignInBanner from './sign_in_banner';
 | 
				
			||||||
import { preferencesLink, relationshipsLink } from 'flavours/glitch/utils/backend_links';
 | 
					import { preferencesLink, relationshipsLink } from 'flavours/glitch/utils/backend_links';
 | 
				
			||||||
 | 
					import NavigationPortal from 'flavours/glitch/components/navigation_portal';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
  home: { id: 'tabs_bar.home', defaultMessage: 'Home' },
 | 
					  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)} />
 | 
					          <ColumnLink transparent to='/about' icon='ellipsis-h' text={intl.formatMessage(messages.about)} />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {showTrends && (
 | 
					        <NavigationPortal />
 | 
				
			||||||
          <React.Fragment>
 | 
					 | 
				
			||||||
            <div className='flex-spacer' />
 | 
					 | 
				
			||||||
            <TrendsContainer />
 | 
					 | 
				
			||||||
          </React.Fragment>
 | 
					 | 
				
			||||||
        )}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -173,12 +173,6 @@
 | 
				
			|||||||
      margin-left: 5px;
 | 
					      margin-left: 5px;
 | 
				
			||||||
      color: $secondary-text-color;
 | 
					      color: $secondary-text-color;
 | 
				
			||||||
      text-decoration: none;
 | 
					      text-decoration: none;
 | 
				
			||||||
 | 
					 | 
				
			||||||
      &__asterisk {
 | 
					 | 
				
			||||||
        color: $darker-text-color;
 | 
					 | 
				
			||||||
        font-size: 18px;
 | 
					 | 
				
			||||||
        vertical-align: super;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    &__sparkline {
 | 
					    &__sparkline {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user