Skip to content

Commit

Permalink
Merge branch 'master' into beta
Browse files Browse the repository at this point in the history
* master:
  Relationship editor required field style redux (#2830)
  MBS-12665: Widen DNB regex (#2686)
  MBS-12853: Disallow IPI that is all zeros (#2833)
  MBS-12814: Remove animationsong.com from the lyrics whitelist (#2791)
  MBS-12899: Add TMDB to the otherdbs whitelist for artists (#2838)
  MBS-12829: Use link type phrases in autocomplete input value (#2840)
  MBS-12641: Relationship dialog initial focus improvements
  Autocomplete2: Wait for recent items before showing menu
  MBS-12882: Adding & removing a relationship date shows pending edits (#2831)
  Clarify what to do for batch operations on tracks
  MBS-11770: Always list related entities for events
  MBS-11770: Always list events/labels for releases
  MBS-12904: Fix another error submitting a recording artist relationship
  Catch prepareHtmlFormSubmission errors
  MBS-12875: Disable selecting incomplete mediums
  Fix selecting mediums with no recordings
  MBS-12873: Avoid unloaded tracks to change credits
  MBS-11770: Always list ISRC/RGs for recordings
  Refactor: Move hasUnloadedTracks to a function
  MBS-11770: Always list related artists for works
  MBS-12891 / MBS-7971: Show more info for inline artist/label search (#2839)
  MBS-12890: Show disambiguation in label/genre autocompletes (#2834)
  MBS-12901: Show user website an bio on the admin user views (#2841)
  • Loading branch information
mwiencek committed Feb 16, 2023
2 parents fadb8a7 + 7ed5451 commit 1594f25
Show file tree
Hide file tree
Showing 47 changed files with 706 additions and 159 deletions.
51 changes: 50 additions & 1 deletion lib/MusicBrainz/Server/Controller/WS/js.pm
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,23 @@ sub entity : Chained('root') PathPart('entity') Args(1)
$data->{relationships} = $relationships if @$relationships;
};

if ($type eq 'Event') {
my %related_entities =
$c->model('Event')->find_related_entities([$entity], 3);
$data->{related_entities} = $related_entities{$entity->id};
}

if ($type eq 'Recording') {
$c->model('ISRC')->load_for_recordings($entity);
my $appears_on = $c->model('Recording')->appears_on([$entity], 3, 1);
$data->{appearsOn} = $appears_on->{$entity->id};
}

if ($type eq 'Work') {
my %artists = $c->model('Work')->find_artists([$entity], 3);
$data->{related_artists} = $artists{$entity->id};
}

$c->res->content_type($c->stash->{serializer}->mime_type . '; charset=utf-8');
$c->res->body(encode_json($data));
}
Expand Down Expand Up @@ -636,13 +653,45 @@ sub entities : Chained('root') PathPart('entities') Args(2)
$c->model('Area')->load_containment(@entities);
}

my %related_entities;
if ($type_name eq 'event') {
%related_entities = $c->model('Event')->find_related_entities(\@entities, 3);
}

if ($type_name eq 'place') {
$c->model('Area')->load(@entities);
$c->model('Area')->load_containment(map { $_->area } @entities);
}

my $appears_on;
if ($type_name eq 'recording') {
$c->model('ISRC')->load_for_recordings(@entities);
$appears_on = $c->model('Recording')->appears_on(\@entities, 3, 1);
}

if ($type_name eq 'release') {
$c->model('Release')->load_release_events(@entities);
$c->model('ReleaseLabel')->load(@entities);
$c->model('Label')->load(map { $_->all_labels } @entities);
}

my %artists;
if ($type_name eq 'work') {
%artists = $c->model('Work')->find_artists(\@entities, 3);
}

while (my ($id, $entity) = each %{$results}) {
$results->{$id} = $entity->TO_JSON;
my $json_entity = $entity->TO_JSON;
if ($type_name eq 'event') {
$json_entity->{related_entities} = $related_entities{$entity->id};
}
if ($type_name eq 'recording') {
$json_entity->{appearsOn} = $appears_on->{$entity->id};
}
if ($type_name eq 'work') {
$json_entity->{related_artists} = $artists{$entity->id};
}
$results->{$id} = $json_entity;
}

$c->res->content_type($serializer->mime_type . '; charset=utf-8');
Expand Down
5 changes: 5 additions & 0 deletions lib/MusicBrainz/Server/Controller/WS/js/Artist.pm
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,9 @@ sub search : Chained('root') PathPart('artist')
$self->dispatch_search($c);
}

after _load_entities => sub {
my ($self, $c, @entities) = @_;
$c->model('ArtistType')->load(@entities);
};

1;
5 changes: 5 additions & 0 deletions lib/MusicBrainz/Server/Controller/WS/js/Label.pm
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,9 @@ sub search : Chained('root') PathPart('label')
$self->dispatch_search($c);
}

after _load_entities => sub {
my ($self, $c, @entities) = @_;
$c->model('LabelType')->load(@entities);
};

1;
2 changes: 1 addition & 1 deletion lib/MusicBrainz/Server/Data/URL.pm
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ my %URL_SPECIALIZATIONS = (
'45worlds' => qr{^https?://(?:www\.)?45worlds\.com/}i,
'Allmusic' => qr{^https?://(?:www\.)?allmusic\.com/}i,
'AmazonMusic' => qr{^https:\/\/music\.amazon\.(?:ae|at|com\.au|com\.br|ca|cn|com|de|es|fr|in|it|jp|co\.jp|com\.mx|nl|pl|se|sg|com\.tr|co\.uk)/}i,
'Animationsong' => qr{^https?://(?:www\.)?animationsong\.com/}i,
'AnimeNewsNetwork' => qr{^https?://(?:www\.)?animenewsnetwork\.com/}i,
'AnisonGeneration' => qr{^https?://anison\.info/}i,
'AppleBooks' => qr{^https?://books\.apple\.com/}i,
Expand Down Expand Up @@ -177,6 +176,7 @@ my %URL_SPECIALIZATIONS = (
'Tidal' => qr{^https?://(?:[^/]+\.)?tidal\.com/}i,
'TikTok' => qr{^https?://(?:www\.)?tiktok\.com/}i,
'Tipeee' => qr{^https?://(?:www\.)?tipeee\.com/}i,
'TMDB' => qr{^https?://(?:www\.)?themoviedb\.org/}i,
'TobaranDualchais' => qr{^https?://(?:www\.)?tobarandualchais\.co\.uk/}i,
'TouhouDB' => qr{^https?://(?:www\.)?touhoudb\.com/}i,
'Tower' => qr{^https?://(?:www\.)?tower\.jp/}i,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package MusicBrainz::Server::Entity::URL::Animationsong;
package MusicBrainz::Server::Entity::URL::TMDB;

use Moose;
use utf8;

extends 'MusicBrainz::Server::Entity::URL';
with 'MusicBrainz::Server::Entity::URL::Sidebar';

sub sidebar_name { 'アニ歌詞PV アニソン' }
sub sidebar_name { 'TMDB' }

__PACKAGE__->meta->make_immutable;
no Moose;
1;

=head1 COPYRIGHT AND LICENSE
Copyright (C) 2019 MetaBrainz Foundation
Copyright (C) 2023 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
Expand Down
1 change: 1 addition & 0 deletions lib/MusicBrainz/Server/Validation.pm
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ sub format_iswc
sub is_valid_ipi
{
my $ipi = shift;
return 0 if $ipi =~ /^0{11}$/;
return $ipi =~ /^[0-9]{11}$/;
}

Expand Down
8 changes: 8 additions & 0 deletions root/admin/components/UserList.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ const UserList = ({users}: Props): React.Element<'table'> => {
<tr>
<th>{l('Editor')}</th>
<th>{l('Member since')}</th>
<th>{l('Website')}</th>
<th>{l('Email')}</th>
<th>{l('Verified on')}</th>
<th>{l('Last login')}</th>
<th>{l('Bio')}</th>
</tr>
</thead>
<tbody>
Expand All @@ -54,6 +56,9 @@ const UserList = ({users}: Props): React.Element<'table'> => {
)}
</td>
<td>{formatUserDate($c, user.registration_date)}</td>
<td>
{nonEmpty(user.website) ? user.website : null}
</td>
<td>{user.email}</td>
<td>
{nonEmpty(user.email_confirmation_date) ? (
Expand All @@ -65,6 +70,9 @@ const UserList = ({users}: Props): React.Element<'table'> => {
formatUserDate($c, user.last_login_date)
) : null}
</td>
<td>
{nonEmpty(user.biography) ? user.biography : null}
</td>
</tr>
))}
</tbody>
Expand Down
Binary file added root/static/images/external-favicons/tmdb-32.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 0 additions & 22 deletions root/static/lib/jquery.ui/ui/jquery-ui.custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -5055,9 +5055,6 @@ $.widget( "ui.autocomplete", {
},

__response: function( content ) {
if ( content ) {
content = this._normalize( content );
}
this._trigger( "response", null, { content: content } );
if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
this._suggest( content );
Expand Down Expand Up @@ -5088,25 +5085,6 @@ $.widget( "ui.autocomplete", {
}
},

_normalize: function( items ) {
// assume all items have the right format when the first item is complete
if ( items.length && items[0].label && items[0].value ) {
return items;
}
return $.map( items, function( item ) {
if ( typeof item === "string" ) {
return {
label: item,
value: item
};
}
return $.extend({
label: item.label || item.value,
value: item.value || item.label
}, item );
});
},

_suggest: function( items ) {
var ul = this.menu.element.empty();
this._renderMenu( ul, items );
Expand Down
21 changes: 16 additions & 5 deletions root/static/scripts/common/components/Autocomplete2.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@ const Autocomplete2 = (React.memo(<+T: EntityItemT>(
const inputTimeout = React.useRef<TimeoutID | null>(null);
const containerRef = React.useRef<HTMLDivElement | null>(null);
const shouldUpdateScrollPositionRef = React.useRef<boolean>(false);
const recentItemsPromise =
React.useRef<Promise<$ReadOnlyArray<OptionItemT<T>>> | null>(null);

const highlightedItem = highlightedIndex >= 0
? (items[highlightedIndex] ?? null)
Expand Down Expand Up @@ -501,17 +503,23 @@ const Autocomplete2 = (React.memo(<+T: EntityItemT>(
}
}

function showAvailableItems() {
if (items.length && !isOpen) {
async function showAvailableItems() {
const recentItems = await recentItemsPromise.current;
/*
* Normally `items` should comprise `recentItems` after the
* `set-recent-items` action runs, but this event may trigger before that
* action is run and thus while `items` has yet to be updated.
*/
if ((items.length || recentItems?.length) && !isOpen) {
shouldUpdateScrollPositionRef.current = true;
dispatch(SHOW_MENU);
return true;
}
return false;
}

function showAvailableItemsOrBeginLookupOrSearch() {
if (showAvailableItems()) {
async function showAvailableItemsOrBeginLookupOrSearch() {
if (await showAvailableItems()) {
return;
}
/*
Expand Down Expand Up @@ -627,14 +635,15 @@ const Autocomplete2 = (React.memo(<+T: EntityItemT>(

React.useEffect(() => {
if (!recentItems) {
getOrFetchRecentItems<T>(
recentItemsPromise.current = getOrFetchRecentItems<T>(
entityType,
state.recentItemsKey,
).then((loadedRecentItems) => {
dispatch({
items: loadedRecentItems,
type: 'set-recent-items',
});
return loadedRecentItems;
});
}

Expand Down Expand Up @@ -744,13 +753,15 @@ const Autocomplete2 = (React.memo(<+T: EntityItemT>(
aria-expanded={isOpen ? 'true' : 'false'}
aria-haspopup="listbox"
aria-owns={menuId}
className={state.required ? 'required' : undefined}
role="combobox"
>
<input
aria-activedescendant={activeDescendant}
aria-autocomplete="list"
aria-controls={menuId}
aria-labelledby={labelId}
aria-required={state.required ? 'true' : 'false'}
autoComplete="off"
className={
(
Expand Down

0 comments on commit 1594f25

Please sign in to comment.