Skip to content

Commit

Permalink
MBS-13870: Add filter for recordings not related to works
Browse files Browse the repository at this point in the history
This allows filtering an artist's recording list by whether the recordings
have at least one work related to them, or they have none.

This is admittedly mostly useful for editing, but it can be *very* useful
for that, allowing users to easily find recordings that still need work
relationships - it would make it much easier to improve the discographies
of prolific classical performers, such as orchestras and conductors,
and probably be of use also for popular music.
  • Loading branch information
reosarevok committed Jan 9, 2025
1 parent 3708859 commit 1c21bc9
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 7 deletions.
16 changes: 16 additions & 0 deletions lib/MusicBrainz/Server/Data/Recording.pm
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,22 @@ sub find_by_artist
push @where_query, 'recording.artist_credit = ?';
push @where_args, $filter{artist_credit_id};
}
if (exists $filter{works}) {
my $works_query = <<~'SQL';
EXISTS (
SELECT TRUE
FROM l_recording_work lrw
WHERE lrw.entity0 = recording.id
)
SQL
if ($filter{works} == 1) {
# Show only recordings with works
push @where_query, $works_query;
} elsif ($filter{works} == 2) {
# Show only recordings without works
push @where_query, "NOT $works_query";
}
}
if (exists $filter{hide_bootlegs}) {
push @where_query, <<~'SQL';
(
Expand Down
14 changes: 13 additions & 1 deletion lib/MusicBrainz/Server/Form/Filter/Recording.pm
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ has_field 'video' => (
type => 'Select',
);

has_field 'works' => (
type => 'Select',
);

has_field 'hide_bootlegs' => (
type => 'Checkbox',
);

sub filter_field_names {
return qw/ disambiguation name artist_credit_id hide_bootlegs video /;
return qw/ disambiguation name artist_credit_id hide_bootlegs video works /;
}

sub options_artist_credit_id {
Expand All @@ -44,12 +48,20 @@ sub options_video {
];
}

sub options_works {
return [
{ value => 1, label => l('Related to works') },
{ value => 2, label => l('Not related to works') },
];
}

around TO_JSON => sub {
my ($orig, $self) = @_;

my $json = $self->$orig;
$json->{options_artist_credit_id} = $self->options_artist_credit_id;
$json->{options_video} = $self->options_video;
$json->{options_works} = $self->options_works;
return $json;
};

Expand Down
18 changes: 18 additions & 0 deletions root/static/scripts/common/components/FilterForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ type RecordingFilterFormT = FormT<{
+artist_credit_id: FieldT<number>,
+hide_bootlegs: FieldT<boolean>,
+video: FieldT<number>,
+works: FieldT<number>,
}>;

export type RecordingFilterT = $ReadOnly<{
...RecordingFilterFormT,
+entity_type: 'recording',
+options_artist_credit_id: SelectOptionsT,
+options_video: SelectOptionsT,
+options_works: SelectOptionsT,
}>;

type ReleaseFilterFormT = FormT<{
Expand Down Expand Up @@ -224,6 +226,22 @@ component FilterForm(form: FilterFormT) {
/>
</td>
</tr>
<tr>
<td>
{addColonText(l('Works'))}
</td>
<td>
<SelectField
field={form.field.works}
options={{
grouped: false,
options: form.options_works,
}}
style={{maxWidth: '40em'}}
uncontrolled
/>
</td>
</tr>
<tr>
<td
title={l(`Hide recordings that only appear
Expand Down
39 changes: 34 additions & 5 deletions t/lib/t/MusicBrainz/Server/Controller/Artist/Filtering.pm
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ test 'Recording page filtering' => sub {
my $tx = test_xpath_html($mech->content);
$tx->is(
'count(//table[@class="tbl"]/tbody/tr)',
'4',
'5',
'There are four entries in the unfiltered recording table',
);

Expand Down Expand Up @@ -527,8 +527,37 @@ test 'Recording page filtering' => sub {
$tx = test_xpath_html($mech->content);
$tx->is(
'count(//table[@class="tbl"]/tbody/tr)',
'3',
'There are three entries in the recording table after filtering by non-videos only',
'4',
'There are four entries in the recording table after filtering by non-videos only',
);

$mech->get_ok(
'/artist/af4c43d3-c0e0-421e-ac64-000329af0435/recordings?filter.works=1',
'Fetched artist recordings page with related works option',
);

$tx = test_xpath_html($mech->content);
$tx->is(
'count(//table[@class="tbl"]/tbody/tr)',
'4',
'There are four entries in the recording table after filtering to show recordings with works only',
);

$mech->get_ok(
'/artist/af4c43d3-c0e0-421e-ac64-000329af0435/recordings?filter.works=2',
'Fetched artist recordings page with no related works option',
);

$tx = test_xpath_html($mech->content);
$tx->is(
'count(//table[@class="tbl"]/tbody/tr)',
'1',
'There is one entry in the recording table after filtering to show recordings without works only',
);
$tx->is(
'//table[@class="tbl"]/tbody/tr/td[1]',
'Improvisation (No work here)',
'The entry is named "Improvisation"',
);

$mech->get_ok(
Expand All @@ -551,8 +580,8 @@ test 'Recording page filtering' => sub {
$tx = test_xpath_html($mech->content);
$tx->is(
'count(//table[@class="tbl"]/tbody/tr)',
'3',
'There are three entries in the recording table after filtering by non-bootleg only',
'4',
'There are four entries in the recording table after filtering by non-bootleg only',
);
};

Expand Down
3 changes: 2 additions & 1 deletion t/sql/filtering.sql
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ INSERT INTO recording (id, gid, name, artist_credit, video, comment)
VALUES (3400, 'ce82bfa1-733a-494a-aaa0-fc5de79bd54f', 'Interludium', 3402, 't', 'Testy'),
(3401, 'd9c7a74e-3c08-48b1-be2f-5d9a144f2c08', 'Symphony no. 3', 3401, 'f', 'Testy 2'),
(3402, 'd9c7a74e-3c08-48b1-be2f-5d9a144f2c01', 'Brandenburg Concerto no. 5', 3401, 'f', ''),
(3403, 'd9c7a74e-3c08-48b1-be2f-5d9a144f2c02', 'Brandenburg Concerto no. 5', 3402, 'f', '');
(3403, 'd9c7a74e-3c08-48b1-be2f-5d9a144f2c02', 'Brandenburg Concerto no. 5', 3402, 'f', ''),
(3405, 'd9c7a74e-3c08-48b1-be2f-5d9a144f2c09', 'Improvisation', 3401, 'f', 'No work here');

INSERT INTO track (id, gid, recording, medium, position, number, name, artist_credit)
VALUES (3400, 'ce82bfa1-aaaa-494a-aaa0-fc5de79bd54f', 3400, 3400, 1, 1, 'Interludium', 3402), -- to make recording not bootleg-only
Expand Down

0 comments on commit 1c21bc9

Please sign in to comment.