Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GET /api/v2/search which returns rich tag objects, adjust web UI #7661

Merged
merged 1 commit into from May 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions app/controllers/api/v2/search_controller.rb
@@ -0,0 +1,8 @@
# frozen_string_literal: true

class Api::V2::SearchController < Api::V1::SearchController
def index
@search = Search.new(search)
render json: @search, serializer: REST::V2::SearchSerializer
end
end
2 changes: 1 addition & 1 deletion app/javascript/mastodon/actions/search.js
Expand Up @@ -33,7 +33,7 @@ export function submitSearch() {

dispatch(fetchSearchRequest());

api(getState).get('/api/v1/search', {
api(getState).get('/api/v2/search', {
params: {
q: value,
resolve: true,
Expand Down
Expand Up @@ -16,6 +16,28 @@ const shortNumberFormat = number => {
}
};

const renderHashtag = hashtag => (
<div className='trends__item' key={hashtag.get('name')}>
<div className='trends__item__name'>
<Link to={`/timelines/tag/${hashtag.get('name')}`}>
#<span>{hashtag.get('name')}</span>
</Link>

<FormattedMessage id='trends.count_by_accounts' defaultMessage='{count} {rawCount, plural, one {person} other {people}} talking' values={{ rawCount: hashtag.getIn(['history', 0, 'accounts']), count: <strong>{shortNumberFormat(hashtag.getIn(['history', 0, 'accounts']))}</strong> }} />
</div>

<div className='trends__item__current'>
{shortNumberFormat(hashtag.getIn(['history', 0, 'uses']))}
</div>

<div className='trends__item__sparkline'>
<Sparklines width={50} height={28} data={hashtag.get('history').reverse().map(day => day.get('uses')).toArray()}>
<SparklinesCurve style={{ fill: 'none' }} />
</Sparklines>
</div>
</div>
);

export default class SearchResults extends ImmutablePureComponent {

static propTypes = {
Expand Down Expand Up @@ -44,27 +66,7 @@ export default class SearchResults extends ImmutablePureComponent {
<FormattedMessage id='trends.header' defaultMessage='Trending now' />
</div>

{trends && trends.map(hashtag => (
<div className='trends__item' key={hashtag.get('name')}>
<div className='trends__item__name'>
<Link to={`/timelines/tag/${hashtag.get('name')}`}>
#<span>{hashtag.get('name')}</span>
</Link>

<FormattedMessage id='trends.count_by_accounts' defaultMessage='{count} {rawCount, plural, one {person} other {people}} talking' values={{ rawCount: hashtag.getIn(['history', 0, 'accounts']), count: <strong>{shortNumberFormat(hashtag.getIn(['history', 0, 'accounts']))}</strong> }} />
</div>

<div className='trends__item__current'>
{shortNumberFormat(hashtag.getIn(['history', 0, 'uses']))}
</div>

<div className='trends__item__sparkline'>
<Sparklines width={50} height={28} data={hashtag.get('history').reverse().map(day => day.get('uses')).toArray()}>
<SparklinesCurve style={{ fill: 'none' }} />
</Sparklines>
</div>
</div>
))}
{trends && trends.map(hashtag => renderHashtag(hashtag))}
</div>
</div>
);
Expand All @@ -74,7 +76,7 @@ export default class SearchResults extends ImmutablePureComponent {
count += results.get('accounts').size;
accounts = (
<div className='search-results__section'>
<h5><FormattedMessage id='search_results.accounts' defaultMessage='People' /></h5>
<h5><i className='fa fa-fw fa-users' /><FormattedMessage id='search_results.accounts' defaultMessage='People' /></h5>

{results.get('accounts').map(accountId => <AccountContainer key={accountId} id={accountId} />)}
</div>
Expand All @@ -85,7 +87,7 @@ export default class SearchResults extends ImmutablePureComponent {
count += results.get('statuses').size;
statuses = (
<div className='search-results__section'>
<h5><FormattedMessage id='search_results.statuses' defaultMessage='Toots' /></h5>
<h5><i className='fa fa-fw fa-quote-right' /><FormattedMessage id='search_results.statuses' defaultMessage='Toots' /></h5>

{results.get('statuses').map(statusId => <StatusContainer key={statusId} id={statusId} />)}
</div>
Expand All @@ -96,13 +98,9 @@ export default class SearchResults extends ImmutablePureComponent {
count += results.get('hashtags').size;
hashtags = (
<div className='search-results__section'>
<h5><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></h5>
<h5><i className='fa fa-fw fa-hashtag' /><FormattedMessage id='search_results.hashtags' defaultMessage='Hashtags' /></h5>

{results.get('hashtags').map(hashtag => (
<Link key={hashtag} className='search-results__hashtag' to={`/timelines/tag/${hashtag}`}>
{hashtag}
</Link>
))}
{results.get('hashtags').map(hashtag => renderHashtag(hashtag))}
</div>
);
}
Expand Down
4 changes: 2 additions & 2 deletions app/javascript/mastodon/reducers/search.js
Expand Up @@ -9,7 +9,7 @@ import {
COMPOSE_REPLY,
COMPOSE_DIRECT,
} from '../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: '',
Expand Down Expand Up @@ -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;
Expand Down
44 changes: 20 additions & 24 deletions app/javascript/styles/mastodon/components.scss
Expand Up @@ -3284,6 +3284,15 @@ a.status-card {
}

.search__icon {
&::-moz-focus-inner {
border: 0;
}

&::-moz-focus-inner,
&:focus {
outline: 0 !important;
}

.fa {
position: absolute;
top: 10px;
Expand Down Expand Up @@ -3333,7 +3342,6 @@ a.status-card {
.search-results__header {
color: $dark-text-color;
background: lighten($ui-base-color, 2%);
border-bottom: 1px solid darken($ui-base-color, 4%);
padding: 15px;
font-weight: 500;
font-size: 16px;
Expand All @@ -3346,33 +3354,21 @@ a.status-card {
}

.search-results__section {
margin-bottom: 20px;
margin-bottom: 5px;

h5 {
position: relative;

&::before {
content: "";
display: block;
position: absolute;
left: 0;
right: 0;
top: 50%;
width: 100%;
height: 0;
border-top: 1px solid lighten($ui-base-color, 8%);
}
background: darken($ui-base-color, 4%);
border-bottom: 1px solid lighten($ui-base-color, 8%);
cursor: default;
display: flex;
padding: 15px;
font-weight: 500;
font-size: 16px;
color: $dark-text-color;

span {
.fa {
display: inline-block;
background: $ui-base-color;
color: $darker-text-color;
font-size: 14px;
font-weight: 500;
padding: 10px;
position: relative;
z-index: 1;
cursor: default;
margin-right: 5px;
}
}

Expand Down
7 changes: 7 additions & 0 deletions app/serializers/rest/v2/search_serializer.rb
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class REST::V2::SearchSerializer < ActiveModel::Serializer
has_many :accounts, serializer: REST::AccountSerializer
has_many :statuses, serializer: REST::StatusSerializer
has_many :hashtags, serializer: REST::TagSerializer
end
4 changes: 4 additions & 0 deletions config/routes.rb
Expand Up @@ -315,6 +315,10 @@
end
end

namespace :v2 do
get '/search', to: 'search#index', as: :search
end

namespace :web do
resource :settings, only: [:update]
resource :embed, only: [:create]
Expand Down