diff options
Diffstat (limited to 'app/javascript/flavours/glitch/components/hashtag.jsx')
-rw-r--r-- | app/javascript/flavours/glitch/components/hashtag.jsx | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/app/javascript/flavours/glitch/components/hashtag.jsx b/app/javascript/flavours/glitch/components/hashtag.jsx new file mode 100644 index 000000000..422b9a8fa --- /dev/null +++ b/app/javascript/flavours/glitch/components/hashtag.jsx @@ -0,0 +1,115 @@ +// @ts-check +import React from 'react'; +import { Sparklines, SparklinesCurve } from 'react-sparklines'; +import { FormattedMessage } from 'react-intl'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import Permalink from './permalink'; +import ShortNumber from 'flavours/glitch/components/short_number'; +import Skeleton from 'flavours/glitch/components/skeleton'; +import classNames from 'classnames'; + +class SilentErrorBoundary extends React.Component { + + static propTypes = { + children: PropTypes.node, + }; + + state = { + error: false, + }; + + componentDidCatch () { + this.setState({ error: true }); + } + + render () { + if (this.state.error) { + return null; + } + + return this.props.children; + } + +} + +/** + * Used to render counter of how much people are talking about hashtag + * + * @type {(displayNumber: JSX.Element, pluralReady: number) => JSX.Element} + */ +export const accountsCountRenderer = (displayNumber, pluralReady) => ( + <FormattedMessage + id='trends.counter_by_accounts' + defaultMessage='{count, plural, one {{counter} person} other {{counter} people}} in the past {days, plural, one {day} other {{days} days}}' + values={{ + count: pluralReady, + counter: <strong>{displayNumber}</strong>, + days: 2, + }} + /> +); + +export const ImmutableHashtag = ({ hashtag }) => ( + <Hashtag + name={hashtag.get('name')} + href={hashtag.get('url')} + to={`/tags/${hashtag.get('name')}`} + people={hashtag.getIn(['history', 0, 'accounts']) * 1 + hashtag.getIn(['history', 1, 'accounts']) * 1} + history={hashtag.get('history').reverse().map((day) => day.get('uses')).toArray()} + /> +); + +ImmutableHashtag.propTypes = { + hashtag: ImmutablePropTypes.map.isRequired, +}; + +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> + + {description ? ( + <span>{description}</span> + ) : ( + typeof people !== 'undefined' ? <ShortNumber value={people} renderer={accountsCountRenderer} /> : <Skeleton width={100} /> + )} + </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> +); + +Hashtag.propTypes = { + name: PropTypes.string, + 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; |