From 801919fc9b7ab12ca6652b03cce027224df59718 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 20 Aug 2018 11:29:42 +0200 Subject: [PATCH] Add hashtag trendline support to glitch-soc flavour Port Mastodon's hashtag stats thing to glitch-soc. This doesn't change how hashtags are ordered, and doesn't add a trending hashtags section, but it does change how hashtag searches are rendered, displaying a trend line alongside each hashtag. --- .../flavours/glitch/actions/search.js | 2 +- .../flavours/glitch/components/hashtag.js | 34 ++++++++ .../glitch/features/drawer/results/index.js | 11 +-- .../flavours/glitch/reducers/search.js | 4 +- .../glitch/styles/components/search.scss | 84 ++++++++++++++++--- .../flavours/glitch/util/numbers.js | 10 +++ 6 files changed, 123 insertions(+), 22 deletions(-) create mode 100644 app/javascript/flavours/glitch/components/hashtag.js create mode 100644 app/javascript/flavours/glitch/util/numbers.js diff --git a/app/javascript/flavours/glitch/actions/search.js b/app/javascript/flavours/glitch/actions/search.js index 13885c600..ec65bdf28 100644 --- a/app/javascript/flavours/glitch/actions/search.js +++ b/app/javascript/flavours/glitch/actions/search.js @@ -32,7 +32,7 @@ export function submitSearch() { dispatch(fetchSearchRequest()); - api(getState).get('/api/v1/search', { + api(getState).get('/api/v2/search', { params: { q: value, resolve: true, diff --git a/app/javascript/flavours/glitch/components/hashtag.js b/app/javascript/flavours/glitch/components/hashtag.js new file mode 100644 index 000000000..88689cc6c --- /dev/null +++ b/app/javascript/flavours/glitch/components/hashtag.js @@ -0,0 +1,34 @@ +import React from 'react'; +import { Sparklines, SparklinesCurve } from 'react-sparklines'; +import { Link } from 'react-router-dom'; +import { FormattedMessage } from 'react-intl'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { shortNumberFormat } from 'flavours/glitch/util/numbers'; + +const Hashtag = ({ hashtag }) => ( +
+
+ + #{hashtag.get('name')} + + + {shortNumberFormat(hashtag.getIn(['history', 0, 'accounts']))} }} /> +
+ +
+ {shortNumberFormat(hashtag.getIn(['history', 0, 'uses']))} +
+ +
+ day.get('uses')).toArray()}> + + +
+
+); + +Hashtag.propTypes = { + hashtag: ImmutablePropTypes.map.isRequired, +}; + +export default Hashtag; diff --git a/app/javascript/flavours/glitch/features/drawer/results/index.js b/app/javascript/flavours/glitch/features/drawer/results/index.js index 23dc0e3cf..ac7a14ef4 100644 --- a/app/javascript/flavours/glitch/features/drawer/results/index.js +++ b/app/javascript/flavours/glitch/features/drawer/results/index.js @@ -12,6 +12,7 @@ import { Link } from 'react-router-dom'; // Components. import AccountContainer from 'flavours/glitch/containers/account_container'; import StatusContainer from 'flavours/glitch/containers/status_container'; +import Hashtag from 'flavours/glitch/components/hashtag'; // Utils. import Motion from 'flavours/glitch/util/optional_motion'; @@ -98,15 +99,7 @@ export default function DrawerResults ({
- {hashtags.map( - hashtag => ( - #{hashtag} - ) - )} + {hashtags.map(hashtag => )}
) : null} diff --git a/app/javascript/flavours/glitch/reducers/search.js b/app/javascript/flavours/glitch/reducers/search.js index dc6be97e2..9a525bf47 100644 --- a/app/javascript/flavours/glitch/reducers/search.js +++ b/app/javascript/flavours/glitch/reducers/search.js @@ -9,7 +9,7 @@ import { COMPOSE_REPLY, COMPOSE_DIRECT, } from 'flavours/glitch/actions/compose'; -import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; +import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable'; const initialState = ImmutableMap({ value: '', @@ -39,7 +39,7 @@ export default function search(state = initialState, action) { return state.set('results', ImmutableMap({ accounts: ImmutableList(action.results.accounts.map(item => item.id)), statuses: ImmutableList(action.results.statuses.map(item => item.id)), - hashtags: ImmutableList(action.results.hashtags), + hashtags: fromJS(action.results.hashtags), })).set('submitted', true); default: return state; diff --git a/app/javascript/flavours/glitch/styles/components/search.scss b/app/javascript/flavours/glitch/styles/components/search.scss index 91861ea19..f9e4b5883 100644 --- a/app/javascript/flavours/glitch/styles/components/search.scss +++ b/app/javascript/flavours/glitch/styles/components/search.scss @@ -90,16 +90,80 @@ font-weight: 500; } -.search-results__hashtag { - display: block; - padding: 10px; - color: $secondary-text-color; - text-decoration: none; +.trends { + &__header { + color: $dark-text-color; + background: lighten($ui-base-color, 2%); + border-bottom: 1px solid darken($ui-base-color, 4%); + font-weight: 500; + padding: 15px; + font-size: 16px; + cursor: default; - &:hover, - &:active, - &:focus { - color: lighten($secondary-text-color, 4%); - text-decoration: underline; + .fa { + display: inline-block; + margin-right: 5px; + } + } + + &__item { + display: flex; + align-items: center; + padding: 15px; + border-bottom: 1px solid lighten($ui-base-color, 8%); + + &:last-child { + border-bottom: 0; + } + + &__name { + flex: 1 1 auto; + color: $dark-text-color; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + strong { + font-weight: 500; + } + + a { + color: $darker-text-color; + text-decoration: none; + font-size: 14px; + font-weight: 500; + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + &:hover, + &:focus, + &:active { + span { + text-decoration: underline; + } + } + } + } + + &__current { + flex: 0 0 auto; + width: 100px; + font-size: 24px; + line-height: 36px; + font-weight: 500; + text-align: center; + color: $secondary-text-color; + } + + &__sparkline { + flex: 0 0 auto; + width: 50px; + + path { + stroke: lighten($highlight-text-color, 6%) !important; + } + } } } diff --git a/app/javascript/flavours/glitch/util/numbers.js b/app/javascript/flavours/glitch/util/numbers.js new file mode 100644 index 000000000..fdd8269ae --- /dev/null +++ b/app/javascript/flavours/glitch/util/numbers.js @@ -0,0 +1,10 @@ +import React, { Fragment } from 'react'; +import { FormattedNumber } from 'react-intl'; + +export const shortNumberFormat = number => { + if (number < 1000) { + return ; + } else { + return K; + } +};