Skip to content

Commit ec117ea

Browse files
authored
Merge pull request #11142 from nanaya/artist-originals
Add original tracks filter option on featured artists track search
2 parents 6b5c8ac + 004d9db commit ec117ea

File tree

8 files changed

+100
-10
lines changed

8 files changed

+100
-10
lines changed

app/Libraries/Search/ArtistTrackSearch.php

+8
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,18 @@ public function getQuery()
3333
$this->addQueryStringFilter($query);
3434
$this->addSimpleFilters($query);
3535
$this->addTextFilters($query);
36+
$this->addExclusiveOnlyFilter($query);
3637

3738
return $query;
3839
}
3940

41+
private function addExclusiveOnlyFilter(BoolQuery $query): void
42+
{
43+
if ($this->params->exclusiveOnly) {
44+
$query->filter(['term' => ['exclusive' => true]]);
45+
}
46+
}
47+
4048
private function addQueryStringFilter($query): void
4149
{
4250
$value = $this->params->queryString;

app/Libraries/Search/ArtistTrackSearchParams.php

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class ArtistTrackSearchParams extends SearchParams
2727
public ?string $album;
2828
public ?string $artist;
2929
public ?array $bpm;
30+
public bool $exclusiveOnly = false;
3031
public ?string $genre;
3132
public bool $isDefaultSort = false;
3233
public ?array $length;

app/Libraries/Search/ArtistTrackSearchParamsFromRequest.php

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public static function fromArray(array $rawParams)
1818
'album',
1919
'artist',
2020
'bpm:array',
21+
'exclusive_only:bool',
2122
'genre',
2223
'is_default_sort:bool',
2324
'length:array',
@@ -37,6 +38,10 @@ public static function fromArray(array $rawParams)
3738
$params->parseSort($paramsArray['sort'], $paramsArray['is_default_sort']);
3839
$params->searchAfter = SearchAfterParam::make($params, cursor_from_params($rawParams)); // TODO: enforce value types
3940

41+
if (isset($paramsArray['exclusive_only'])) {
42+
$params->exclusiveOnly = $paramsArray['exclusive_only'];
43+
}
44+
4045
return $params;
4146
}
4247

@@ -46,6 +51,7 @@ public static function toArray(ArtistTrackSearchParams $params)
4651
'album' => $params->album,
4752
'artist' => $params->artist,
4853
'bpm' => $params->bpmInput,
54+
'exclusive_only' => $params->exclusiveOnly,
4955
'genre' => $params->genre,
5056
'is_default_sort' => $params->isDefaultSort,
5157
'length' => $params->lengthInput,

resources/css/bem-index.less

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
@import "bem/artist-sidebar-album";
1717
@import "bem/artist-track";
1818
@import "bem/artist-track-search-form";
19+
@import "bem/artist-track-search-form-switches";
1920
@import "bem/artist-track-search-sort";
2021
@import "bem/audio-player";
2122
@import "bem/audio-player-floating";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
2+
// See the LICENCE file in the repository root for full licence text.
3+
4+
.artist-track-search-form-switches {
5+
display: grid;
6+
gap: 5px;
7+
grid-template-columns: repeat(auto-fill, minmax(125px, 1fr));
8+
9+
&__link {
10+
.link-plain();
11+
font-size: @font-size--normal;
12+
font-weight: bold;
13+
background: hsl(var(--hsl-b3));
14+
color: hsl(var(--hsl-c1));
15+
padding: 2px 15px 3px; // slightly more on the bottom to compensate font vertical alignment
16+
border-radius: 10000px;
17+
transition: none;
18+
text-align: center;
19+
white-space: nowrap;
20+
21+
&:focus, &:active {
22+
color: hsl(var(--hsl-c1));
23+
}
24+
25+
&:hover {
26+
background: hsl(var(--hsl-l1));
27+
color: hsl(var(--hsl-b6));
28+
}
29+
30+
&--active {
31+
background: hsl(var(--hsl-b1));
32+
}
33+
}
34+
}

resources/js/artist-tracks-index/make-link.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,16 @@ import { route } from 'laroute';
55
import { ArtistTrackSearch } from './search-form';
66

77
export default function makeLink(params: ArtistTrackSearch) {
8-
return `${route('artists.tracks.index')}?${$.param(params)}`;
8+
const urlParams: Partial<ArtistTrackSearch> = { ...params };
9+
if (!urlParams.exclusive_only) {
10+
delete urlParams.exclusive_only;
11+
}
12+
if (urlParams.is_default_sort) {
13+
// no need to set sort params if default
14+
delete urlParams.sort;
15+
}
16+
// backend automatically determines this
17+
delete urlParams.is_default_sort;
18+
19+
return route('artists.tracks.index', urlParams);
920
}

resources/js/artist-tracks-index/search-form.tsx

+32-9
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const artistTrackSearchNumberRangeParams = ['bpm', 'length'] as const;
4343
type ArtistTrackSearchNumberRangeParam = typeof artistTrackSearchNumberRangeParams[number];
4444

4545
export type ArtistTrackSearch = {
46+
exclusive_only: boolean;
4647
genre?: Nullable<string>;
4748
is_default_sort: boolean;
4849
sort: ArtistTrackSort;
@@ -63,12 +64,13 @@ export default class SearchForm extends React.Component<Props> {
6364

6465
@computed
6566
private get url() {
66-
return this.makeLink();
67+
return makeLink(this.params);
6768
}
6869

6970
@computed
7071
private get emptySearch() {
7172
return {
73+
exclusive_only: false,
7274
is_default_sort: this.params.is_default_sort,
7375
sort: this.params.sort,
7476
};
@@ -172,17 +174,35 @@ export default class SearchForm extends React.Component<Props> {
172174
</InputContainer>
173175

174176
<InputContainer labelKey='artist.tracks.index.form.genre' modifiers={['4', 'genre']}>
175-
<div className='artist-track-search-form__genres'>
177+
<div className='artist-track-search-form-switches'>
176178
{this.renderGenreLink(trans('artist.tracks.index.form.genre_all'), null)}
177179
{this.props.availableGenres.map((genre) => this.renderGenreLink(genre, genre))}
178180
</div>
179181
</InputContainer>
182+
183+
<InputContainer labelKey='artist.tracks.index.form.exclusive_only' modifiers={['4', 'genre']}>
184+
<div className='artist-track-search-form-switches'>
185+
{([['all', false], ['exclusive_only', true]] as const).map(([label, value]) => (
186+
<a
187+
key={label}
188+
className={classWithModifiers('artist-track-search-form-switches__link', {
189+
active: this.params.exclusive_only === value,
190+
})}
191+
data-value={value}
192+
href={makeLink({ ...this.params, exclusive_only: value })}
193+
onClick={this.handleExclusiveOnlyLinkClick}
194+
>
195+
{trans(`artist.tracks.index.exclusive_only.${label}`)}
196+
</a>
197+
))}
198+
</div>
199+
</InputContainer>
180200
</div>
181201
</div>
182202
<div className='artist-track-search-form__content artist-track-search-form__content--buttons'>
183203
<BigButton
184204
disabled={this.isEmptySearch}
185-
href={this.makeLink(this.emptySearch)}
205+
href={makeLink(this.emptySearch)}
186206
modifiers={['artist-track-search', 'rounded-thin']}
187207
props={{ onClick: this.handleReset }}
188208
text={trans('common.buttons.reset')}
@@ -247,6 +267,13 @@ export default class SearchForm extends React.Component<Props> {
247267
}
248268
};
249269

270+
@action
271+
private readonly handleExclusiveOnlyLinkClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
272+
e.preventDefault();
273+
this.params.exclusive_only = e.currentTarget.dataset.value === '1';
274+
this.props.onNewSearch(e.currentTarget.href);
275+
};
276+
250277
@action
251278
private readonly handleGenreLinkClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
252279
e.preventDefault();
@@ -278,19 +305,15 @@ export default class SearchForm extends React.Component<Props> {
278305
}
279306
};
280307

281-
private makeLink(params: ArtistTrackSearch = this.params) {
282-
return makeLink(params);
283-
}
284-
285308
private renderGenreLink(name: string, value: Nullable<string>) {
286309
return (
287310
<a
288311
key={name}
289-
className={classWithModifiers('artist-track-search-form__genre-link', {
312+
className={classWithModifiers('artist-track-search-form-switches__link', {
290313
active: presence(this.params.genre) === value,
291314
})}
292315
data-value={value ?? ''}
293-
href={this.makeLink({ ...this.params, genre: value })}
316+
href={makeLink({ ...this.params, genre: value })}
294317
onClick={this.handleGenreLinkClick}
295318
>
296319
{name}

resources/lang/en/artist.php

+6
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,19 @@
4545
'index' => [
4646
'_' => 'track search',
4747

48+
'exclusive_only' => [
49+
'all' => 'All',
50+
'exclusive_only' => 'osu! original',
51+
],
52+
4853
'form' => [
4954
'advanced' => 'Advanced Search',
5055
'album' => 'Album',
5156
'artist' => 'Artist',
5257
'bpm_gte' => 'BPM Minimum',
5358
'bpm_lte' => 'BPM Maximum',
5459
'empty' => 'No tracks matching search criteria were found.',
60+
'exclusive_only' => 'Type',
5561
'genre' => 'Genre',
5662
'genre_all' => 'All',
5763
'length_gte' => 'Length Minimum',

0 commit comments

Comments
 (0)