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

Convert the Release index page to React + add track paging #2131

Merged
merged 9 commits into from
Jun 18, 2021
Merged
3 changes: 2 additions & 1 deletion lib/MusicBrainz/Server/Constants.pm
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ our @EXPORT_OK = (
%PART_OF_SERIES $PART_OF_AREA_LINK_TYPE $PART_OF_AREA_LINK_TYPE_ID
$SERIES_ORDERING_TYPE_AUTOMATIC $SERIES_ORDERING_TYPE_MANUAL
$SERIES_ORDERING_ATTRIBUTE
$MAX_INITIAL_MEDIUMS
$MAX_INITIAL_MEDIUMS $MAX_INITIAL_TRACKS
$MAX_POSTGRES_INT $MAX_POSTGRES_BIGINT
@FULL_TABLE_LIST
@CORE_TABLE_LIST
Expand Down Expand Up @@ -405,6 +405,7 @@ Readonly our $PART_OF_AREA_LINK_TYPE => 'de7cc874-8b1b-3a05-8272-f3834c968fb7';
Readonly our $PART_OF_AREA_LINK_TYPE_ID => 356;

Readonly our $MAX_INITIAL_MEDIUMS => 10;
Readonly our $MAX_INITIAL_TRACKS => 100;

Readonly our $MAX_POSTGRES_INT => 2147483647;
Readonly our $MAX_POSTGRES_BIGINT => 9223372036854775807;
Expand Down
2 changes: 1 addition & 1 deletion lib/MusicBrainz/Server/Controller/Area.pm
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ sub places : Chained('load')
my $json = $_->TO_JSON;
# These arguments aren't needed at all to render the map,
# and only increase the page size.
delete @{$json}{qw(annotation unaccented_name)};
delete @{$json}{qw(annotation)};
$json;
} grep { $_->coordinates } @$places
],
Expand Down
28 changes: 0 additions & 28 deletions lib/MusicBrainz/Server/Controller/Medium.pm

This file was deleted.

124 changes: 98 additions & 26 deletions lib/MusicBrainz/Server/Controller/Release.pm
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,31 @@ use List::Util qw( first );
use List::MoreUtils qw( uniq );
use List::UtilsBy 'nsort_by';
use MusicBrainz::Server::Translation qw( l );
use MusicBrainz::Server::Constants qw( :edit_type $MAX_INITIAL_MEDIUMS );
use MusicBrainz::Server::Constants qw(
:edit_type
$MAX_INITIAL_MEDIUMS
$MAX_INITIAL_TRACKS
);
use MusicBrainz::Server::Validation qw(
is_integer
is_positive_integer
);
use MusicBrainz::Server::ControllerUtils::Delete qw( cancel_or_action );
use MusicBrainz::Server::ControllerUtils::JSON qw( serialize_pager );
use MusicBrainz::Server::Entity::Util::JSON qw( to_json_array );
use MusicBrainz::Server::Form::Utils qw(
build_grouped_options
select_options
language_options
build_type_info
);
use POSIX qw( ceil );
use Scalar::Util qw( looks_like_number );
use MusicBrainz::Server::Data::Utils qw( partial_date_to_hash artist_credit_to_ref );
use MusicBrainz::Server::Data::Utils qw(
artist_credit_to_ref
boolean_to_json
partial_date_to_hash
);

=head1 NAME

Expand Down Expand Up @@ -112,25 +126,6 @@ after 'load' => sub {
}
};

before show => sub {
my ($self, $c, @args) = @_;

if (@args && $args[0] eq 'disc') {
my $position = $args[1];
my @mediums = $c->stash->{release}->all_mediums;

if (@mediums > $MAX_INITIAL_MEDIUMS) {
my %mediums_by_position = map { $_->position => $_ } @mediums;
my $medium = $mediums_by_position{$position} if looks_like_number($position);

if ($medium) {
my $user_id = $c->user->id if $c->user_exists;
$c->model('Medium')->load_related_info($user_id, $medium);
}
}
}
};

# Stuff that has the side bar and thus needs to display collection information
after [qw( show collections details tags aliases
discids cover_art add_cover_art edit_cover_art reorder_cover_art )] => sub {
Expand Down Expand Up @@ -160,17 +155,94 @@ tags, tracklisting, release events, etc.
=cut

sub show : Chained('load') PathPart('') {
my ($self, $c) = @_;
my ($self, $c, @args) = @_;

my $release = $c->stash->{release};
my @mediums = $release->all_mediums;
my $paged_medium;
my $medium_page_number = 1;
my $no_script = 0;

# Individual medium selected via /disc/n.
#
# This subpath is only linked where JavaScript is disabled, so
# $no_script is set to 1 if we hit it.
if (@args && $args[0] eq 'disc') {
my $position = scalar(@args) > 1 ? $args[1] : undef;

if (defined $position) {
$c->detach('/error_400') unless is_positive_integer($position);

$paged_medium = first { $_->position == $position } @mediums;

if ($paged_medium) {
$no_script = 1;

my $page = $c->req->query_params->{page};
if (defined $page) {
$c->detach('/error_400') unless is_integer($page);

if (@mediums <= $MAX_INITIAL_MEDIUMS) {
my $user_id = $c->user->id if $c->user_exists;
$c->model('Medium')->load_related_info($user_id, @mediums);
my $max_page = ceil($paged_medium->track_count / $MAX_INITIAL_TRACKS);
if ($page > $max_page) {
$c->detach('/error_404');
}
$medium_page_number = $page;
}
} else {
$c->detach('/error_404');
}
}
}

my $user_id = $c->user->id if $c->user_exists;

if (@mediums && !defined $paged_medium) {
my $medium_counter = 0;
my $track_counter = 0;
my @preloaded_mediums;

for my $medium (@mediums) {
$medium_counter += 1;
last if $medium_counter > $MAX_INITIAL_MEDIUMS;
$track_counter += $medium->track_count;
last if $track_counter > $MAX_INITIAL_TRACKS;
push @preloaded_mediums, $medium;
}

if (@preloaded_mediums) {
$c->model('Medium')->load_related_info($user_id, @preloaded_mediums);
} else {
# If even the first medium exceeds $MAX_INITIAL_TRACKS, page that
# instead of loading nothing. This is equivalent to navigating to
# the /disc/1 subpath, except $no_script will remain 0.
$paged_medium = $mediums[0];
}
}

$c->stash->{template} = 'release/index.tt';
if ($paged_medium) {
$c->model('Medium')->load_related_info_paged(
$user_id,
$paged_medium,
$medium_page_number,
);
}

my $bottom_credits = $c->req->cookies->{'bottom-credits'};
my $credits_mode = defined $bottom_credits &&
$bottom_credits->value eq '1' ? 'bottom' : 'inline';

my %props = (
creditsMode => $credits_mode,
release => $release->TO_JSON,
noScript => boolean_to_json($no_script),
numberOfRevisions => $c->stash->{number_of_revisions},
);

$c->stash(
component_path => 'release/ReleaseIndex',
component_props => \%props,
current_view => 'Node',
);
}

sub _load_related : Private {
Expand Down
39 changes: 38 additions & 1 deletion lib/MusicBrainz/Server/Controller/WS/js.pm
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,18 @@ use List::MoreUtils qw( part );
use List::UtilsBy qw( uniq_by );
use MusicBrainz::Errors qw( capture_exceptions );
use MusicBrainz::Server::WebService::Validator;
use MusicBrainz::Server::Entity::Util::JSON qw( to_json_array );
use MusicBrainz::Server::Filters;
use MusicBrainz::Server::Data::Search qw( escape_query );
use MusicBrainz::Server::Data::Utils qw( type_to_model );
use MusicBrainz::Server::Constants qw( entities_with %ENTITIES $CONTACT_URL );
use MusicBrainz::Server::ControllerUtils::JSON qw( serialize_pager );
use MusicBrainz::Server::Translation qw( l );
use MusicBrainz::Server::Validation qw( is_database_row_id is_guid );
use MusicBrainz::Server::Validation qw(
is_database_row_id
is_guid
is_positive_integer
);
use Readonly;
use Scalar::Util qw( blessed );
use Text::Trim;
Expand All @@ -33,6 +39,10 @@ my $ws_defs = Data::OptList::mkopt([
inc => [ qw(recordings rels) ],
optional => [ qw(q artist tracks limit page timestamp) ]
},
"tracks" => {
method => 'GET',
optional => [ qw(q page ) ]
},
"cdstub" => {
method => 'GET',
optional => [ qw(q artist tracks limit page timestamp) ]
Expand Down Expand Up @@ -89,6 +99,33 @@ sub medium : Chained('root') PathPart Args(1) {
$c->res->body(encode_json($medium->TO_JSON));
}

sub tracks : Chained('root') PathPart Args(1) {
my ($self, $c, $medium_id) = @_;

$self->detach_with_error($c, "malformed medium id: $medium_id", 400)
unless is_database_row_id($medium_id);

my $page = $c->stash->{args}{page} || 1;
$self->detach_with_error($c, "malformed page: $page", 400)
unless is_positive_integer($page);

my ($pager, $tracks) = $c->model('Track')->load_for_medium_paged($medium_id, $page);
$c->model('Track')->load_related_info($c->user_exists ? $c->user->id : undef, @$tracks);

my $tracks_json_array = to_json_array($tracks);
my $linked_entities = $MusicBrainz::Server::Entity::Util::JSON::linked_entities;

$c->res->content_type($c->stash->{serializer}->mime_type . '; charset=utf-8');
$c->res->body(encode_json({
linked_entities => {
link_attribute_type => ($linked_entities->{link_attribute_type} // {}),
link_type => ($linked_entities->{link_type} // {}),
},
pager => serialize_pager($pager),
tracks => $tracks_json_array,
}));
}

sub cdstub : Chained('root') PathPart Args(1) {
my ($self, $c, $id) = @_;

Expand Down
1 change: 0 additions & 1 deletion lib/MusicBrainz/Server/Data/Artist.pm
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ sub _column_mapping
id => 'id',
gid => 'gid',
name => 'name',
unaccented_name => 'unaccented_name',
sort_name => 'sort_name',
type_id => 'type',
area_id => 'area',
Expand Down
1 change: 0 additions & 1 deletion lib/MusicBrainz/Server/Data/Label.pm
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ sub _column_mapping
id => 'id',
gid => 'gid',
name => 'name',
unaccented_name => 'unaccented_name',
type_id => 'type',
area_id => 'area',
label_code => 'label_code',
Expand Down
25 changes: 14 additions & 11 deletions lib/MusicBrainz/Server/Data/Medium.pm
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use MusicBrainz::Server::Data::Utils qw(
object_to_ids
placeholders
);
use aliased 'MusicBrainz::Server::Entity::Work';

extends 'MusicBrainz::Server::Data::Entity';
with 'MusicBrainz::Server::Data::Role::Editable' => { table => 'medium' };
Expand Down Expand Up @@ -298,20 +297,24 @@ sub load_related_info {
$self->c->model('Track')->load_for_mediums(@mediums);

my @tracks = map { $_->all_tracks } @mediums;
$self->c->model('ArtistCredit')->load(@tracks);
$self->c->model('Track')->load_related_info($user_id, @tracks);
}

my @recordings = $self->c->model('Recording')->load(@tracks);
$self->c->model('ArtistCredit')->load(@recordings);
$self->c->model('Recording')->load_meta(@recordings);
$self->c->model('Recording')->load_gid_redirects(@recordings);
$self->c->model('Recording')->rating->load_user_ratings($user_id, @recordings) if $user_id;
sub load_related_info_paged {
my ($self, $user_id, $medium, $page) = @_;

$self->c->model('Relationship')->load_cardinal(@recordings);
$self->c->model('Relationship')->load_cardinal(grep { $_->isa(Work) } map { $_->target } map { $_->all_relationships } @recordings);
$self->c->model('MediumFormat')->load($medium);
$self->c->model('Release')->load($medium);

$self->c->model('ArtistType')->load(map { $_->target } map { @{ $_->relationships_by_type('artist') } } @recordings);
my ($pager, $tracks) = $self->c->model('Track')->load_for_medium_paged(
$medium->id,
$page,
);

$self->c->model('ISRC')->load_for_recordings(@recordings);
$self->c->model('Track')->load_related_info($user_id, @$tracks);
$medium->tracks($tracks);
$medium->has_loaded_tracks(1);
$medium->tracks_pager($pager);
}

__PACKAGE__->meta->make_immutable;
Expand Down
1 change: 0 additions & 1 deletion lib/MusicBrainz/Server/Data/Place.pm
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ sub _column_mapping
id => 'id',
gid => 'gid',
name => 'name',
unaccented_name => 'unaccented_name',
type_id => 'type',
address => 'address',
area_id => 'area',
Expand Down
2 changes: 1 addition & 1 deletion lib/MusicBrainz/Server/Data/Role/Alias.pm
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ role
" JOIN search ON lower(musicbrainz_unaccent(${type}_alias.name)) = lower(musicbrainz_unaccent(term))" .
" UNION SELECT term, id FROM $type " .
" JOIN search ON lower(musicbrainz_unaccent(${type}.name)) = lower(musicbrainz_unaccent(term)))" .
" SELECT term AS search_term, musicbrainz_unaccent(name) AS unaccented_name, ".$self->_columns.
" SELECT term AS search_term, ".$self->_columns.
" FROM ". $self->_table ." JOIN entity_matches ON entity_matches.entity = $type.id";

my %ret;
Expand Down
1 change: 0 additions & 1 deletion lib/MusicBrainz/Server/Data/Series.pm
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ sub _column_mapping {
id => 'id',
gid => 'gid',
name => 'name',
unaccented_name => 'unaccented_name',
comment => 'comment',
type_id => 'type',
ordering_type_id => 'ordering_type',
Expand Down
Loading