Skip to content

Commit b06b776

Browse files
committed
[WIP] MBS-12761: Convert recording edit form to React
1 parent 7cec36a commit b06b776

File tree

14 files changed

+477
-13
lines changed

14 files changed

+477
-13
lines changed

eslint.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,7 @@ export default [
969969
'root/static/scripts/edit/components/UrlRelationshipCreditFieldset.js',
970970
'root/static/scripts/edit/externalLinks.js',
971971
'root/static/scripts/event/components/EventEditForm.js',
972+
'root/static/scripts/recording/components/RecordingEditForm.js',
972973
'root/static/scripts/relationship-editor/components/DialogPreview.js',
973974
],
974975
rules: {

lib/MusicBrainz/Server/Controller/Recording.pm

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@ with 'MusicBrainz::Server::Controller::Role::Create' => {
198198
$ret{form_args} = { used_by_tracks => 0 };
199199
return %ret;
200200
},
201-
dialog_template => 'recording/edit_form.tt',
202201
};
203202

204203
sub _merge_load_entities {

lib/MusicBrainz/Server/Controller/Role/Create.pm

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,12 @@ role {
6060
my $model = $self->config->{model};
6161
my $entity;
6262
my %props;
63+
my %edit_arguments = $params->edit_arguments->($self, $c);
6364

64-
if ($model eq 'Event' || $model eq 'Genre') {
65+
if ($model eq 'Event' || $model eq 'Genre' || $model eq 'Recording') {
6566
my $type = model_to_type($model);
66-
my $form = $c->form( form => $params->form );
67+
my %form_args = %{ $edit_arguments{form_args} || {}};
68+
my $form = $c->form( form => $params->form, ctx => $c, %form_args );
6769
%props = ( form => $form->TO_JSON );
6870

6971
$c->stash(
@@ -98,23 +100,29 @@ role {
98100
delete $c->flash->{message};
99101
},
100102
pre_validation => sub {
103+
my $form = shift;
104+
101105
if ($model eq 'Event') {
102-
my $form = shift;
103106
my %event_descriptions = map {
104107
$_->id => $_->l_description
105108
} $c->model('EventType')->get_all();
106109

107110
$props{eventTypes} = $form->options_type_id;
108111
$props{eventDescriptions} = \%event_descriptions;
109112
}
113+
114+
if ($model eq 'Recording') {
115+
$props{usedByTracks} = $form->used_by_tracks;
116+
}
117+
110118
},
111119
redirect => sub {
112120
$c->response->redirect($c->uri_for_action(
113121
$self->action_for('show'), [ $entity->gid ]));
114122
},
115123
no_redirect => $args{within_dialog},
116124
edit_rels => 1,
117-
$params->edit_arguments->($self, $c),
125+
%edit_arguments,
118126
);
119127
};
120128
};

lib/MusicBrainz/Server/Controller/Role/Edit.pm

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,22 @@ role {
3434
method 'edit' => sub {
3535
my ($self, $c) = @_;
3636

37-
my @react_models = qw( Event Genre);
37+
my @react_models = qw( Event Genre Recording );
3838
my $entity_name = $self->{entity_name};
3939
my $edit_entity = $c->stash->{ $entity_name };
4040
my $model = $self->{model};
4141
my %props;
42+
my %edit_arguments = $params->edit_arguments->($self, $c, $edit_entity);
4243

4344
if (any { $_ eq $model } @react_models) {
4445
my $type = model_to_type($model);
4546

47+
my %form_args = %{ $edit_arguments{form_args} || {}};
4648
my $form = $c->form(
4749
form => $params->form,
50+
ctx => $c,
4851
init_object => $edit_entity,
52+
%form_args,
4953
);
5054

5155
%props = (
@@ -69,21 +73,26 @@ role {
6973
edit_args => { to_edit => $edit_entity },
7074
edit_rels => 1,
7175
pre_validation => sub {
76+
my $form = shift;
77+
7278
if ($model eq 'Event') {
73-
my $form = shift;
7479
my %event_descriptions = map {
7580
$_->id => $_->l_description
7681
} $c->model('EventType')->get_all();
7782

7883
$props{eventTypes} = $form->options_type_id;
7984
$props{eventDescriptions} = \%event_descriptions;
8085
}
86+
87+
if ($model eq 'Recording') {
88+
$props{usedByTracks} = $form->used_by_tracks;
89+
}
8190
},
8291
redirect => sub {
8392
$c->response->redirect(
8493
$c->uri_for_action($self->action_for('show'), [ $edit_entity->gid ]));
8594
},
86-
$params->edit_arguments->($self, $c, $edit_entity),
95+
%edit_arguments,
8796
);
8897
};
8998
};

root/recording/CreateRecording.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* @flow strict-local
3+
* Copyright (C) 2024 MetaBrainz Foundation
4+
*
5+
* This file is part of MusicBrainz, the open internet music database,
6+
* and is licensed under the GPL version 2, or (at your option) any
7+
* later version: http://www.gnu.org/licenses/gpl-2.0.txt
8+
*/
9+
10+
import Layout from '../layout/index.js';
11+
import manifest from '../static/manifest.mjs';
12+
import RecordingEditForm
13+
from '../static/scripts/recording/components/RecordingEditForm.js';
14+
15+
import type {RecordingFormT} from './types.js';
16+
17+
component CreateRecording(form: RecordingFormT, usedByTracks: boolean) {
18+
return (
19+
<Layout fullWidth title={lp('Add recording', 'header')}>
20+
<div id="content">
21+
<h1>{lp('Add recording', 'header')}</h1>
22+
<RecordingEditForm form={form} usedByTracks={usedByTracks} />
23+
</div>
24+
{manifest('recording/components/RecordingEditForm', {async: 'async'})}
25+
{manifest('relationship-editor', {async: 'async'})}
26+
</Layout>
27+
);
28+
}
29+
30+
export default CreateRecording;

root/recording/EditRecording.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* @flow strict-local
3+
* Copyright (C) 2024 MetaBrainz Foundation
4+
*
5+
* This file is part of MusicBrainz, the open internet music database,
6+
* and is licensed under the GPL version 2, or (at your option) any
7+
* later version: http://www.gnu.org/licenses/gpl-2.0.txt
8+
*/
9+
10+
import manifest from '../static/manifest.mjs';
11+
import RecordingEditForm
12+
from '../static/scripts/recording/components/RecordingEditForm.js';
13+
14+
import RecordingLayout from './RecordingLayout.js';
15+
import type {RecordingFormT} from './types.js';
16+
17+
component EditRecording(
18+
entity: RecordingWithArtistCreditT,
19+
form: RecordingFormT,
20+
usedByTracks: boolean,
21+
) {
22+
return (
23+
<RecordingLayout
24+
entity={entity}
25+
fullWidth
26+
page="edit"
27+
title={lp('Edit recording', 'header')}
28+
>
29+
<RecordingEditForm form={form} usedByTracks={usedByTracks} />
30+
{manifest('recording/components/RecordingEditForm', {async: 'async'})}
31+
{manifest('relationship-editor', {async: 'async'})}
32+
</RecordingLayout>
33+
);
34+
}
35+
36+
export default EditRecording;

root/recording/types.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* @flow strict
3+
* Copyright (C) 2024 MetaBrainz Foundation
4+
*
5+
* This file is part of MusicBrainz, the open internet music database,
6+
* and is licensed under the GPL version 2, or (at your option) any
7+
* later version: http://www.gnu.org/licenses/gpl-2.0.txt
8+
*/
9+
10+
export type RecordingFormT = FormT<{
11+
+artist_credit: ArtistCreditFieldT,
12+
+comment: FieldT<string>,
13+
+edit_note: FieldT<string>,
14+
+isrcs: RepeatableFieldT<FieldT<string>>,
15+
+length: FieldT<string>,
16+
+make_votable: FieldT<boolean>,
17+
+name: FieldT<string | null>,
18+
+video: FieldT<boolean>,
19+
}>;

root/server/components.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ export default {
185185
'place/PlaceMap': (): Promise<mixed> => import('../place/PlaceMap.js'),
186186
'place/PlaceMerge': (): Promise<mixed> => import('../place/PlaceMerge.js'),
187187
'place/PlacePerformances': (): Promise<mixed> => import('../place/PlacePerformances.js'),
188+
'recording/CreateRecording': (): Promise<mixed> => import('../recording/CreateRecording.js'),
188189
'recording/DeleteRecording': (): Promise<mixed> => import('../recording/DeleteRecording.js'),
190+
'recording/EditRecording': (): Promise<mixed> => import('../recording/EditRecording.js'),
189191
'recording/RecordingFingerprints': (): Promise<mixed> => import('../recording/RecordingFingerprints.js'),
190192
'recording/RecordingIndex': (): Promise<mixed> => import('../recording/RecordingIndex.js'),
191193
'recording/RecordingMerge': (): Promise<mixed> => import('../recording/RecordingMerge.js'),

root/static/scripts/common/entity2.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ export function createRecordingObject(
242242
}>,
243243
): RecordingT {
244244
return {
245+
artist: '',
246+
artistCredit: {
247+
names: ([]: $ReadOnlyArray<ArtistCreditNameT>),
248+
},
245249
comment: '',
246250
editsPending: false,
247251
entityType: 'recording',

root/static/scripts/common/utility/catalyst.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ export function maybeGetCatalystContext(): ?SanitizedCatalystContextT {
3030
return globalThis[GLOBAL_JS_NAMESPACE]?.$c;
3131
}
3232

33-
export function getSourceEntityData():
33+
export function getSourceEntityData(
34+
passedContext?: SanitizedCatalystContextT,
35+
):
3436
| RelatableEntityT
3537
| {
3638
+entityType: RelatableEntityTypeT,
@@ -39,12 +41,14 @@ export function getSourceEntityData():
3941
+orderingTypeID?: number,
4042
}
4143
| null {
42-
const $c = getCatalystContext();
44+
const $c = passedContext ?? getCatalystContext();
4345
return $c.stash.source_entity ?? null;
4446
}
4547

46-
export function getSourceEntityDataForRelationshipEditor(): RelatableEntityT {
47-
let source = getSourceEntityData();
48+
export function getSourceEntityDataForRelationshipEditor(
49+
$c?: SanitizedCatalystContextT,
50+
): RelatableEntityT {
51+
let source = getSourceEntityData($c);
4852
invariant(
4953
source,
5054
'Source entity data not found in global Catalyst stash',

0 commit comments

Comments
 (0)