Skip to content

Commit

Permalink
[WIP] MBS-12761: Convert recording edit form to React
Browse files Browse the repository at this point in the history
  • Loading branch information
reosarevok committed Sep 17, 2024
1 parent 7cec36a commit 7ee0573
Show file tree
Hide file tree
Showing 15 changed files with 480 additions and 14 deletions.
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,7 @@ export default [
'root/static/scripts/edit/components/UrlRelationshipCreditFieldset.js',
'root/static/scripts/edit/externalLinks.js',
'root/static/scripts/event/components/EventEditForm.js',
'root/static/scripts/recording/components/RecordingEditForm.js',
'root/static/scripts/relationship-editor/components/DialogPreview.js',
],
rules: {
Expand Down
1 change: 0 additions & 1 deletion lib/MusicBrainz/Server/Controller/Recording.pm
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ with 'MusicBrainz::Server::Controller::Role::Create' => {
$ret{form_args} = { used_by_tracks => 0 };
return %ret;
},
dialog_template => 'recording/edit_form.tt',
};

sub _merge_load_entities {
Expand Down
16 changes: 12 additions & 4 deletions lib/MusicBrainz/Server/Controller/Role/Create.pm
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ role {
my $model = $self->config->{model};
my $entity;
my %props;
my %edit_arguments = $params->edit_arguments->($self, $c);

if ($model eq 'Event' || $model eq 'Genre') {
if ($model eq 'Event' || $model eq 'Genre' || $model eq 'Recording') {
my $type = model_to_type($model);
my $form = $c->form( form => $params->form );
my %form_args = %{ $edit_arguments{form_args} || {}};
my $form = $c->form( form => $params->form, ctx => $c, %form_args );
%props = ( form => $form->TO_JSON );

$c->stash(
Expand Down Expand Up @@ -98,23 +100,29 @@ role {
delete $c->flash->{message};
},
pre_validation => sub {
my $form = shift;

if ($model eq 'Event') {
my $form = shift;
my %event_descriptions = map {
$_->id => $_->l_description
} $c->model('EventType')->get_all();

$props{eventTypes} = $form->options_type_id;
$props{eventDescriptions} = \%event_descriptions;
}

if ($model eq 'Recording') {
$props{usedByTracks} = $form->used_by_tracks;
}

},
redirect => sub {
$c->response->redirect($c->uri_for_action(
$self->action_for('show'), [ $entity->gid ]));
},
no_redirect => $args{within_dialog},
edit_rels => 1,
$params->edit_arguments->($self, $c),
%edit_arguments,
);
};
};
Expand Down
15 changes: 12 additions & 3 deletions lib/MusicBrainz/Server/Controller/Role/Edit.pm
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,22 @@ role {
method 'edit' => sub {
my ($self, $c) = @_;

my @react_models = qw( Event Genre);
my @react_models = qw( Event Genre Recording );
my $entity_name = $self->{entity_name};
my $edit_entity = $c->stash->{ $entity_name };
my $model = $self->{model};
my %props;
my %edit_arguments = $params->edit_arguments->($self, $c, $edit_entity);

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

my %form_args = %{ $edit_arguments{form_args} || {}};
my $form = $c->form(
form => $params->form,
ctx => $c,
init_object => $edit_entity,
%form_args,
);

%props = (
Expand All @@ -69,21 +73,26 @@ role {
edit_args => { to_edit => $edit_entity },
edit_rels => 1,
pre_validation => sub {
my $form = shift;

if ($model eq 'Event') {
my $form = shift;
my %event_descriptions = map {
$_->id => $_->l_description
} $c->model('EventType')->get_all();

$props{eventTypes} = $form->options_type_id;
$props{eventDescriptions} = \%event_descriptions;
}

if ($model eq 'Recording') {
$props{usedByTracks} = $form->used_by_tracks;
}
},
redirect => sub {
$c->response->redirect(
$c->uri_for_action($self->action_for('show'), [ $edit_entity->gid ]));
},
$params->edit_arguments->($self, $c, $edit_entity),
%edit_arguments,
);
};
};
Expand Down
30 changes: 30 additions & 0 deletions root/recording/CreateRecording.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* @flow strict-local
* Copyright (C) 2024 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 RecordingEditForm
from '../static/scripts/recording/components/RecordingEditForm.js';

import type {RecordingFormT} from './types.js';

component CreateRecording(form: RecordingFormT, usedByTracks: boolean) {
return (
<Layout fullWidth title={lp('Add recording', 'header')}>
<div id="content">
<h1>{lp('Add recording', 'header')}</h1>
<RecordingEditForm form={form} usedByTracks={usedByTracks} />
</div>
{manifest('recording/components/RecordingEditForm', {async: 'async'})}
{manifest('relationship-editor', {async: 'async'})}
</Layout>
);
}

export default CreateRecording;
36 changes: 36 additions & 0 deletions root/recording/EditRecording.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* @flow strict-local
* Copyright (C) 2024 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 manifest from '../static/manifest.mjs';
import RecordingEditForm
from '../static/scripts/recording/components/RecordingEditForm.js';

import RecordingLayout from './RecordingLayout.js';
import type {RecordingFormT} from './types.js';

component EditRecording(
entity: RecordingWithArtistCreditT,
form: RecordingFormT,
usedByTracks: boolean,
) {
return (
<RecordingLayout
entity={entity}
fullWidth
page="edit"
title={lp('Edit recording', 'header')}
>
<RecordingEditForm form={form} usedByTracks={usedByTracks} />
{manifest('recording/components/RecordingEditForm', {async: 'async'})}
{manifest('relationship-editor', {async: 'async'})}
</RecordingLayout>
);
}

export default EditRecording;
19 changes: 19 additions & 0 deletions root/recording/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* @flow strict
* Copyright (C) 2024 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
*/

export type RecordingFormT = FormT<{
+artist_credit: ArtistCreditFieldT,
+comment: FieldT<string>,
+edit_note: FieldT<string>,
+isrcs: RepeatableFieldT<FieldT<string>>,
+length: FieldT<string>,
+make_votable: FieldT<boolean>,
+name: FieldT<string | null>,
+video: FieldT<boolean>,
}>;
2 changes: 2 additions & 0 deletions root/server/components.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ export default {
'place/PlaceMap': (): Promise<mixed> => import('../place/PlaceMap.js'),
'place/PlaceMerge': (): Promise<mixed> => import('../place/PlaceMerge.js'),
'place/PlacePerformances': (): Promise<mixed> => import('../place/PlacePerformances.js'),
'recording/CreateRecording': (): Promise<mixed> => import('../recording/CreateRecording.js'),
'recording/DeleteRecording': (): Promise<mixed> => import('../recording/DeleteRecording.js'),
'recording/EditRecording': (): Promise<mixed> => import('../recording/EditRecording.js'),
'recording/RecordingFingerprints': (): Promise<mixed> => import('../recording/RecordingFingerprints.js'),
'recording/RecordingIndex': (): Promise<mixed> => import('../recording/RecordingIndex.js'),
'recording/RecordingMerge': (): Promise<mixed> => import('../recording/RecordingMerge.js'),
Expand Down
4 changes: 4 additions & 0 deletions root/static/scripts/common/entity2.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ export function createRecordingObject(
}>,
): RecordingT {
return {
artist: '',
artistCredit: {
names: ([]: $ReadOnlyArray<ArtistCreditNameT>),
},
comment: '',
editsPending: false,
entityType: 'recording',
Expand Down
12 changes: 8 additions & 4 deletions root/static/scripts/common/utility/catalyst.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export function maybeGetCatalystContext(): ?SanitizedCatalystContextT {
return globalThis[GLOBAL_JS_NAMESPACE]?.$c;
}

export function getSourceEntityData():
export function getSourceEntityData(
passedContext?: SanitizedCatalystContextT,
):
| RelatableEntityT
| {
+entityType: RelatableEntityTypeT,
Expand All @@ -39,12 +41,14 @@ export function getSourceEntityData():
+orderingTypeID?: number,
}
| null {
const $c = getCatalystContext();
const $c = passedContext ?? getCatalystContext();
return $c.stash.source_entity ?? null;
}

export function getSourceEntityDataForRelationshipEditor(): RelatableEntityT {
let source = getSourceEntityData();
export function getSourceEntityDataForRelationshipEditor(
$c?: SanitizedCatalystContextT,
): RelatableEntityT {
let source = getSourceEntityData($c);
invariant(
source,
'Source entity data not found in global Catalyst stash',
Expand Down
7 changes: 6 additions & 1 deletion root/static/scripts/edit/components/FormRowTextList.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ component TextListRow(
dispatch: (ActionT) => void,
fieldId: number,
name: string,
onFocus?: (event: SyntheticEvent<HTMLSelectElement>) => void,
removeButtonLabel: string,
value: string,
) {
Expand All @@ -49,6 +50,7 @@ component TextListRow(
className="value with-button"
name={name}
onChange={updateRow}
onFocus={onFocus}
type="text"
value={value}
/>
Expand Down Expand Up @@ -112,6 +114,7 @@ component FormRowTextList(
addButtonLabel: string,
addButtonId: string,
label: string,
onFocus?: (event: SyntheticEvent<HTMLSelectElement>) => void,
removeButtonLabel: string,
repeatable: RepeatableFieldT<FieldT<string>>,
required: boolean = false,
Expand All @@ -138,6 +141,7 @@ component FormRowTextList(
fieldId={field.id}
key={field.id}
name={field.html_name}
onFocus={onFocus}
removeButtonLabel={removeButtonLabel}
value={field.value}
/>
Expand All @@ -158,10 +162,11 @@ component FormRowTextList(
}

export component NonHydratedFormRowTextList(
rowRef?: {-current: HTMLDivElement | null},
...props: React.PropsOf<FormRowTextList>
) {
return (
<FormRow className="form-row-text-list-container">
<FormRow className="form-row-text-list-container" rowRef={rowRef}>
<FormRowTextList {...props} />
</FormRow>
);
Expand Down
Loading

0 comments on commit 7ee0573

Please sign in to comment.