Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,9 @@ export default [
'root/search/components/WorkResults.js',
'root/static/scripts/account/components/EditProfileForm.js',
'root/static/scripts/account/components/RegisterForm.js',
'root/static/scripts/common/components/CDTocMediumListRow.js',
'root/static/scripts/common/components/CDTocPossibleMediumListRow.js',
'root/static/scripts/common/components/CDTocReleaseListRow.js',
'root/static/scripts/common/components/TagEditor.js',
'root/static/scripts/edit/check-duplicates.js',
'root/static/scripts/edit/components/ExternalLinkAttributeDialog.js',
Expand Down
61 changes: 46 additions & 15 deletions lib/MusicBrainz/Server/Controller/CDTOC.pm
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,15 @@ sub show : Chained('load') PathPart('')
my $cdtoc = $c->stash->{cdtoc};
my $medium_cdtocs = $self->_load_releases($c, $cdtoc);

my %props = (
mediumCDTocs => to_json_array($medium_cdtocs),
cdToc => $cdtoc->TO_JSON,
);

$c->stash(
medium_cdtocs => $medium_cdtocs,
template => 'cdtoc/index.tt',
current_view => 'Node',
component_path => 'cdtoc/CDTocIndex.js',
component_props => \%props,
);
}

Expand Down Expand Up @@ -287,6 +293,7 @@ sub _attach_list {
$c->model('Release')->find_for_cdtoc($artist_id, $cdtoc->track_count, shift, shift);
});
$c->model('Release')->load_related_info(@$releases);
$c->model('ArtistCredit')->load(@$releases);

my @mediums = grep { !$_->format || $_->format->has_discids }
map { $_->all_mediums } @$releases;
Expand All @@ -298,11 +305,20 @@ sub _attach_list {
my @rgs = $c->model('ReleaseGroup')->load(@$releases);
$c->model('ReleaseGroup')->load_meta(@rgs);

my %props = (
artist => $artist->TO_JSON,
cdToc => $cdtoc->TO_JSON,
pager => serialize_pager($c->stash->{pager}),
releases => to_json_array($releases),
tocString => $c->stash->{toc},
);

$c->stash(
artist => $artist,
releases => $releases,
template => 'cdtoc/attach_artist_releases.tt',
current_view => 'Node',
component_path => 'cdtoc/AttachCDTocToArtistRelease.js',
component_props => \%props,
);
$c->detach;
}
else {
my $search_artist = $c->form( query_artist => 'Search::Query', name => 'filter-artist' );
Expand All @@ -311,6 +327,8 @@ sub _attach_list {
my ($initial_artist, $initial_release) = map { $c->req->query_params->{$_} }
qw( artist-name release-name );

my $cdstub;
my @possible_mediums;
# One of these must have been submitted to get here
if ($c->form_submitted_and_valid($search_artist, $c->req->query_params)) {
my $artists = $self->_load_paged($c, sub {
Expand Down Expand Up @@ -393,26 +411,27 @@ sub _attach_list {
component_path => 'cdtoc/AttachCDTocToRelease.js',
component_props => \%props,
);
$c->detach;
}
else {
my $cdstub = $c->model('CDStub')->get_by_discid($cdtoc->discid);
$cdstub = $c->model('CDStub')->get_by_discid($cdtoc->discid);
if ($cdstub) {
$c->model('CDStubTrack')->load_for_cdstub($cdstub);
$cdstub->update_track_lengths;

$initial_artist ||= $cdstub->artist;
$initial_release ||= $cdstub->title;

my @mediums = $c->model('Medium')->find_for_cdstub($cdstub);
$c->model('MediumFormat')->load(@mediums);
$c->model('Track')->load_for_mediums(@mediums);
my @tracks = map { $_->all_tracks } @mediums;
@possible_mediums = $c->model('Medium')->find_for_cdstub($cdstub);
$c->model('MediumFormat')->load(@possible_mediums);
$c->model('Track')->load_for_mediums(@possible_mediums);
my @tracks = map { $_->all_tracks } @possible_mediums;
$c->model('Recording')->load(@tracks);
my @releases = map { $_->release } @mediums;
my @releases = map { $_->release } @possible_mediums;
$c->model('Release')->load_related_info(@releases);
$c->model('ArtistCredit')->load(@releases);
$c->stash(
possible_mediums => [ @mediums ],
possible_mediums => [ @possible_mediums ],
cdstub => $cdstub,
);
}
Expand All @@ -424,10 +443,22 @@ sub _attach_list {
$search_release->process(params => { 'filter-release.query' => $initial_release })
if $initial_release;

my $medium_cdtocs = $self->_load_releases($c, $cdtoc);

my %props = (
$cdstub ? (cdStub => $cdstub->TO_JSON) : (),
cdToc => $cdtoc->TO_JSON,
mediumCDTocs => to_json_array($medium_cdtocs),
possibleMediums => to_json_array(\@possible_mediums),
searchArtistForm => $search_artist->TO_JSON,
searchReleaseForm => $search_release->TO_JSON,
tocString => $c->stash->{toc},
);

$c->stash(
medium_cdtocs => $self->_load_releases($c, $cdtoc),
cdtoc => $cdtoc,
template => 'cdtoc/lookup.tt',
current_view => 'Node',
component_path => 'cdtoc/CDTocLookup.js',
component_props => \%props,
);
}
}
Expand Down
108 changes: 108 additions & 0 deletions root/cdtoc/AttachCDTocToArtistRelease.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* @flow strict
* Copyright (C) 2025 MetaBrainz Foundation
*
* This file is part of MusicBrainz, the open internet music database,
* and is licensed under the GPL version 2, or (at your option) any
* later version: http://www.gnu.org/licenses/gpl-2.0.txt
*/

import * as React from 'react';

import PaginatedResults from '../components/PaginatedResults.js';
import Layout from '../layout/index.js';
import manifest from '../static/manifest.mjs';
import CDTocArtistReleaseListTable
from '../static/scripts/common/components/CDTocArtistReleaseListTable.js';
import EntityLink from '../static/scripts/common/components/EntityLink.js';
import FormSubmit from '../static/scripts/edit/components/FormSubmit.js';
import type {ReleaseWithMediumsAndReleaseGroupT}
from '../static/scripts/relationship-editor/types.js';

component AttachCDTocToArtistRelease(
artist: ArtistT,
cdToc: CDTocT,
pager?: PagerT,
releases: $ReadOnlyArray<ReleaseWithMediumsAndReleaseGroupT>,
tocString: StrOrNum,
) {
const title = lp('Attach CD TOC', 'header');
const cdTocTrackCount = cdToc.track_count;

return (
<Layout fullWidth title={title}>
<h1>{title}</h1>

<p>
{exp.l(
'You are viewing releases by {artist}.',
{artist: <EntityLink entity={artist} />},
)}
</p>

{releases.length > 0 ? (
<>
<p>
{l('Please select the medium you wish to attach this CD TOC to.')}
</p>

<form method="GET">
<input name="toc" type="hidden" value={tocString} />
<input name="artist" type="hidden" value={artist.id} />

{pager ? (
<PaginatedResults pager={pager}>
<CDTocArtistReleaseListTable
cdTocTrackCount={cdTocTrackCount}
releases={releases}
/>
{manifest(
'common/components/CDTocArtistReleaseListTable',
{async: true},
)}
{manifest(
'common/components/ReleaseEvents',
{async: true},
)}
</PaginatedResults>
) : null}
<p>
<FormSubmit label={lp('Attach CD TOC', 'interactive')} />
</p>
</form>
</>
) : (
<p>
{exp.ln(
'{artist} has no releases which have only {n} track.',
'{artist} has no releases which have {n} tracks.',
cdTocTrackCount,
{artist: <EntityLink entity={artist} />, n: cdTocTrackCount},
)}
</p>
)}

<h2>{l('Add a new release')}</h2>
<p>
{l(`If you don't see the release you are looking for,
you can still add a new one, using this CD TOC:`)}
</p>

<form action="/release/add" method="post">
<input
name="artist_credit.names.0.mbid"
type="hidden"
value={artist.gid}
/>
<input
name="mediums.0.toc"
type="hidden"
value={tocString}
/>
<FormSubmit label={l('Add a new release')} />
</form>
</Layout>
);
}

export default AttachCDTocToArtistRelease;
56 changes: 56 additions & 0 deletions root/cdtoc/CDTocIndex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* @flow strict
* Copyright (C) 2025 MetaBrainz Foundation
*
* This file is part of MusicBrainz, the open internet music database,
* and is licensed under the GPL version 2, or (at your option) any
* later version: http://www.gnu.org/licenses/gpl-2.0.txt
*/

import Layout from '../layout/index.js';
import manifest from '../static/manifest.mjs';
import CDTocLink from '../static/scripts/common/components/CDTocLink.js';
import CDTocMediumListTable
from '../static/scripts/common/components/CDTocMediumListTable.js';
import linkedEntities from '../static/scripts/common/linkedEntities.mjs';

import CDTocInfo from './CDTocInfo.js';

component CDTocIndex(
cdToc: CDTocT,
mediumCDTocs: $ReadOnlyArray<MediumCDTocT>,
) {
return (
<Layout
fullWidth
title={texp.l('Disc ID “{discid}”', {discid: cdToc.discid})}
>
<h1>
{exp.l(
'Disc ID “<code>{discid}</code>”',
{discid: <CDTocLink cdToc={cdToc} />},
)}
</h1>

<CDTocInfo cdToc={cdToc} />

<h2>{l('Attached to releases')}</h2>
<CDTocMediumListTable
mediumCDTocs={mediumCDTocs}
releaseMap={linkedEntities.release}
showEditColumn
/>
{manifest(
'common/components/CDTocMediumListTable',
{async: true},
)}
{manifest(
'common/components/ReleaseEvents',
{async: true},
)}

</Layout>
);
}

export default CDTocIndex;
Loading
Loading