Skip to content

Commit 595110d

Browse files
authored
Merge pull request metabrainz#266 from spellew/work-entity-support
CB-270: Implemented the reviewal of works
2 parents 6bfb8d4 + 8d72578 commit 595110d

File tree

25 files changed

+478
-8
lines changed

25 files changed

+478
-8
lines changed

Diff for: admin/schema_changes/19.sql

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TYPE entity_types ADD VALUE 'work' AFTER 'recording';

Diff for: admin/sql/create_types.sql

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ CREATE TYPE entity_types AS ENUM (
99
'release_group',
1010
'event',
1111
'place',
12+
'work',
1213
'artist',
1314
'label'
1415
);

Diff for: critiquebrainz/db/review.py

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"event",
2020
"place",
2121
"release_group",
22+
"work",
2223
"artist",
2324
"label",
2425
]

Diff for: critiquebrainz/frontend/__init__.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,12 @@ def create_app(debug=None, config_path=None):
115115
# TODO (code-master5): disabled no-member warnings just as a workaround to deal with failing tests till the
116116
# issue [https://github.com/PyCQA/pylint/issues/2563] with pylint is resolved
117117
app.jinja_env.add_extension('jinja2.ext.do')
118-
from critiquebrainz.utils import reformat_date, reformat_datetime, track_length, parameterize
118+
from critiquebrainz.utils import reformat_date, reformat_datetime, track_length, track_length_ms, parameterize
119119
from critiquebrainz.frontend.external.musicbrainz_db.entities import get_entity_by_id
120120
app.jinja_env.filters['date'] = reformat_date
121121
app.jinja_env.filters['datetime'] = reformat_datetime
122122
app.jinja_env.filters['track_length'] = track_length
123+
app.jinja_env.filters['track_length_ms'] = track_length_ms
123124
app.jinja_env.filters['parameterize'] = parameterize
124125
app.jinja_env.filters['entity_details'] = get_entity_by_id
125126
from flask_babel import Locale, get_locale
@@ -134,6 +135,7 @@ def create_app(debug=None, config_path=None):
134135
from critiquebrainz.frontend.views.label import label_bp
135136
from critiquebrainz.frontend.views.release_group import release_group_bp
136137
from critiquebrainz.frontend.views.release import release_bp
138+
from critiquebrainz.frontend.views.work import work_bp
137139
from critiquebrainz.frontend.views.event import event_bp
138140
from critiquebrainz.frontend.views.mapping import mapping_bp
139141
from critiquebrainz.frontend.views.user import user_bp
@@ -156,6 +158,7 @@ def create_app(debug=None, config_path=None):
156158
app.register_blueprint(label_bp, url_prefix='/label')
157159
app.register_blueprint(release_group_bp, url_prefix='/release-group')
158160
app.register_blueprint(release_bp, url_prefix='/release')
161+
app.register_blueprint(work_bp, url_prefix='/work')
159162
app.register_blueprint(event_bp, url_prefix='/event')
160163
app.register_blueprint(place_bp, url_prefix='/place')
161164
app.register_blueprint(mapping_bp, url_prefix='/mapping')

Diff for: critiquebrainz/frontend/external/musicbrainz.py

+6
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ def search_places(query='', limit=None, offset=None):
4646
return api_resp.get('place-count'), api_resp.get('place-list')
4747

4848

49+
def search_works(query='', limit=None, offset=None):
50+
"""Search for works."""
51+
api_resp = musicbrainzngs.search_works(query=query, limit=limit, offset=offset)
52+
return api_resp.get('work-count'), api_resp.get('work-list')
53+
54+
4955
def search_labels(query='', limit=None, offset=None):
5056
"""Search for labels."""
5157
api_resp = musicbrainzngs.search_labels(query=query, limit=limit, offset=offset)

Diff for: critiquebrainz/frontend/external/musicbrainz_db/entities.py

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from brainzutils.musicbrainz_db.work import fetch_multiple_works
12
from brainzutils.musicbrainz_db.artist import fetch_multiple_artists
23
from brainzutils.musicbrainz_db.label import fetch_multiple_labels
34
from brainzutils.musicbrainz_db.place import fetch_multiple_places
@@ -8,6 +9,7 @@
89
from critiquebrainz.frontend.external.musicbrainz_db.event import get_event_by_id
910
from critiquebrainz.frontend.external.musicbrainz_db.label import get_label_by_id
1011
from critiquebrainz.frontend.external.musicbrainz_db.artist import get_artist_by_id
12+
from critiquebrainz.frontend.external.musicbrainz_db.work import get_work_by_id
1113

1214

1315
def get_multiple_entities(entities):
@@ -31,6 +33,7 @@ def get_multiple_entities(entities):
3133
label_mbids = [entity[0] for entity in filter(lambda entity: entity[1] == 'label', entities)]
3234
place_mbids = [entity[0] for entity in filter(lambda entity: entity[1] == 'place', entities)]
3335
event_mbids = [entity[0] for entity in filter(lambda entity: entity[1] == 'event', entities)]
36+
work_mbids = [entity[0] for entity in filter(lambda entity: entity[1] == 'work', entities)]
3437
entities_info.update(fetch_multiple_release_groups(
3538
release_group_mbids,
3639
includes=['artists'],
@@ -47,6 +50,9 @@ def get_multiple_entities(entities):
4750
entities_info.update(fetch_multiple_events(
4851
event_mbids,
4952
))
53+
entities_info.update(fetch_multiple_works(
54+
work_mbids,
55+
))
5056
return entities_info
5157

5258

@@ -62,4 +68,6 @@ def get_entity_by_id(id, type='release_group'):
6268
entity = get_place_by_id(str(id))
6369
elif type == 'event':
6470
entity = get_event_by_id(str(id))
71+
elif type == 'work':
72+
entity = get_work_by_id(str(id))
6573
return entity
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from brainzutils import cache
2+
from brainzutils.musicbrainz_db.work import fetch_multiple_works
3+
from critiquebrainz.frontend.external.musicbrainz_db import DEFAULT_CACHE_EXPIRATION
4+
5+
6+
def get_work_by_id(mbid):
7+
"""Get work with MusicBrainz ID.
8+
9+
Args:
10+
mbid (uuid): MBID(gid) of the work.
11+
Returns:
12+
Dictionary containing the work information
13+
"""
14+
key = cache.gen_key(mbid)
15+
work = cache.get(key)
16+
if not work:
17+
work = fetch_multiple_works(
18+
[mbid],
19+
includes=['artist-rels', 'recording-rels'],
20+
).get(mbid)
21+
cache.set(key=key, val=work, time=DEFAULT_CACHE_EXPIRATION)
22+
return work

Diff for: critiquebrainz/frontend/static/styles/main.less

+17-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
@artist-color: @blue;
1414
@event-color: @green;
1515
@place-color: @yellow;
16+
@work-color: @blue;
1617
@label-color: @blue;
1718

1819
body {
@@ -126,11 +127,17 @@ ul.sharing {
126127
&.release-group {
127128
background-color: fade(@rg-color, 70%);
128129
}
130+
&.place {
131+
background-color: fade(@place-color, 70%);
132+
}
133+
&.event {
134+
background-color: fade(@event-color, 70%);
135+
}
129136
&.artist {
130137
background-color: fade(@artist-color, 70%);
131138
}
132-
&.place {
133-
background-color: fade(@place-color, 70%);
139+
&.work {
140+
background-color: fade(@work-color, 70%);
134141
}
135142
&.label {
136143
background-color: fade(@label-color, 70%);
@@ -491,11 +498,17 @@ a#edit-review { margin-top: 20px; }
491498
&.release-group {
492499
background-color: fade(@rg-color, 70%);
493500
}
501+
&.place {
502+
background-color: fade(@place-color, 70%);
503+
}
504+
&.event {
505+
background-color: fade(@event-color, 70%);
506+
}
494507
&.artist {
495508
background-color: fade(@artist-color, 70%);
496509
}
497-
&.place {
498-
background-color: fade(@place-color, 70%);
510+
&.work {
511+
background-color: fade(@work-color, 70%);
499512
}
500513
&.label {
501514
background-color: fade(@label-color, 70%);

Diff for: critiquebrainz/frontend/templates/entity_review.html

+2
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@
1111
{{ _('%(event)s', event = '<b>'|safe + entity.name | default(_('[Unknown event]')) + '</b>'|safe) }}
1212
{% elif review.entity_type == 'place' %}
1313
{{ _('%(place)s', place = '<b>'|safe + entity.name | default(_('[Unknown place]')) + '</b>'|safe) }}
14+
{% elif review.entity_type == 'work' %}
15+
{{ _('%(work)s', work = '<b>'|safe + entity.name | default(_('[Unknown work]')) + '</b>'|safe) }}
1416
{% endif %}
1517
</a>

Diff for: critiquebrainz/frontend/templates/macros.html

+7
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@
4646
{{ _('Place') }}
4747
</span>
4848
{% endif %}
49+
{% elif entity_type == 'work' %}
50+
<img src="{{ get_static_path('images/placeholder_place.svg') }}" {{ attributes }} />
51+
{% if overlay_type %}
52+
<span class="entity-type work">
53+
{{ _('Work') }}
54+
</span>
55+
{% endif %}
4956
{% elif entity_type == 'artist' %}
5057
<img src="{{ get_static_path('images/placeholder_place.svg') }}" {{ attributes }} />
5158
{% if overlay_type %}

Diff for: critiquebrainz/frontend/templates/navbar.html

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
<div class="form-group">
9696
<select id="type-selector" name="type" class="form-control input-sm">
9797
<option value="artist">{{ _('Artist') }}</option>
98+
<option value="work">{{ _('Work') }}</option>
9899
<option value="label">{{ _('Label') }}</option>
99100
<option value="event">{{ _('Event') }}</option>
100101
<option value="place">{{ _('Place') }}</option>

Diff for: critiquebrainz/frontend/templates/release_group/entity.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ <h4>{{ _('Tracklist') }}</h4>
119119
</td>
120120
<td>
121121
{% if track.length %}
122-
{{ track.length | track_length }}
122+
{{ track.length | track_length_ms }}
123123
{% else %}
124124
-
125125
{% endif %}

Diff for: critiquebrainz/frontend/templates/review/browse.html

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ <h2>{{ _('Reviews') }}</h2>
1919
<a href="{{ url_for('review.browse', entity_type='event') }}">{{ _('Event') }}</a></li>
2020
<li role="presentation" {{ "class=active" if entity_type == 'place' }}>
2121
<a href="{{ url_for('review.browse', entity_type='place') }}">{{ _('Place') }}</a></li>
22+
<li role="presentation" {{ "class=active" if entity_type == 'work' }}>
23+
<a href="{{ url_for('review.browse', entity_type='work') }}">{{ _('Work') }}</a></li>
2224
</ul>
2325

2426
<div id="reviews-browse" class="row">
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{% extends 'review/entity/base.html' %}
2+
3+
{% set work = review.entity_id | entity_details(type='work') %}
4+
5+
{% block title %}
6+
{% set work_title = work.name | default(_('[Unknown work]')) %}
7+
{{ _('Review of "%(work)s" by %(user)s', work=work_title, user=review.user.display_name) }} - CritiqueBrainz
8+
{% endblock %}
9+
10+
{% block entity_title %}
11+
<h2 id="title">
12+
{% if work %}
13+
{% set work_name = '<a href="%s">' | safe % url_for('work.entity', id=review.entity_id) ~ work.name ~ '</a>'|safe %}
14+
{% else %}
15+
{% set work_name = _('[Unknown work]') %}
16+
{% endif %}
17+
18+
{{ _('%(work)s', work=work_name) }}
19+
20+
{% if work['life-span'] %}
21+
<small>{{ work['life-span']['begin'][:4] }}</small>
22+
{% endif %}
23+
</h2>
24+
{% endblock %}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{% if entity is not defined %}
2+
{% set entity = review.entity_id | entity_details(type=entity_type) %}
3+
{% endif %}
4+
<div class="col-md-12">
5+
<dl class="dl-horizontal">
6+
<dt>{{ _('Work') }}</dt>
7+
<dd>
8+
{{ entity['name'] | default(_('[Unknown work]')) }}
9+
</dd>
10+
<dt>{{ _('Type') }}</dt>
11+
<dd>{{ entity['type'] or '-' }}</dd>
12+
<dt>{{ _('Artists') }}</dt>
13+
<dd>
14+
{% if entity['artist-rels'] %}
15+
{{ entity['artist-rels'][0]['artist']['name'] or '-' }}
16+
{% set count = entity['artist-rels'] | length %}
17+
{% if count > 1 %}
18+
+ {{ count - 1 }} {{ _("more") }}
19+
{% endif %}
20+
{% else %}
21+
-
22+
{% endif %}
23+
</dd>
24+
{% block more_info %}
25+
{# Information like creation date, votes etc. #}
26+
{% endblock %}
27+
</dl>
28+
</div>

Diff for: critiquebrainz/frontend/templates/search/index.html

+8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ <h3>{{ _('Search') }}</h3>
2828
<option value="event" {% if type=="event" %}selected="selected"{% endif %}>{{ _('Event') }}</option>
2929
<option value="label" {% if type=="label" %}selected="selected"{% endif %}>{{ _('Label') }}</option>
3030
<option value="place" {% if type=="place" %}selected="selected"{% endif %}>{{ _('Place') }}</option>
31+
<option value="work" {% if type=="work" %}selected="selected"{% endif %}>{{ _('Work') }}</option>
3132
</select>
3233
</div>
3334
</div>
@@ -77,6 +78,13 @@ <h3>{{ _('Search') }}</h3>
7778
<th>{{ _('Type') }}</th>
7879
<th>{{ _('Country') }}</th>
7980
</tr>
81+
{% elif type=="work" %}
82+
<tr>
83+
<th>{{ _('Title') }}</th>
84+
<th>{{ _('Artists') }}</th>
85+
<th>{{ _('Type') }}</th>
86+
<th>{{ _('Language') }}</th>
87+
</tr>
8088
{% endif %}
8189
</thead>
8290
<tbody id="results">{% include 'search/results.html' %}</tbody>

Diff for: critiquebrainz/frontend/templates/search/results.html

+24
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,30 @@
6464
</td>
6565
</tr>
6666

67+
{% elif type=="work" %}
68+
<tr>
69+
<td>
70+
<a href="{{ url_for('work.entity', id=result.id) }}">{{ result['title'] }}</a>
71+
</td>
72+
<td>
73+
{% if result['artist-relation-list'] %}
74+
<a href="{{ url_for('artist.entity', mbid=result['artist-relation-list'][0].artist.id) }}">{{ result['artist-relation-list'][0]['artist']['name'] or '-' }}</a>
75+
{% set count = result['artist-relation-list'] | length %}
76+
{% if count > 1 %}
77+
+ {{ count - 1 }} {{ _("more") }}
78+
{% endif %}
79+
{% else %}
80+
-
81+
{% endif %}
82+
</td>
83+
<td>
84+
{{ result['type'] or '-' }}
85+
</td>
86+
<td>
87+
{{ result['language'] or '-' }}
88+
</td>
89+
</tr>
90+
6791
{% elif type=="label" %}
6892
<tr>
6993
<td>

Diff for: critiquebrainz/frontend/templates/search/selector.html

+32
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
<li {% if type=="place" %}class="active"{% endif %}>
1919
<a href="#place" data-toggle="tab">Place</a>
2020
</li>
21+
<li {% if type=="work" %}class="active"{% endif %}>
22+
<a href="#work" data-toggle="tab">{{ _('Work') }}</a>
23+
</li>
2124
<li {% if type=="label" %}class="active"{% endif %}>
2225
<a href="#label" data-toggle="tab">{{ _('Label') }}</a>
2326
</li>
@@ -104,6 +107,26 @@ <h3>{{ _('Place selection') }}</h3>
104107
</form>
105108
</div>
106109

110+
<div id="work" class="tab-pane {% if type=="work" %}active{% endif %}">
111+
<h3>{{ _('Work selection') }}</h3>
112+
<form method="GET" class="form-horizontal" role="form">
113+
<div class="form-group">
114+
<label for="input-release-group" class="col-sm-2 control-label">{{ _('Work') }}</label>
115+
<div class="col-sm-4">
116+
<input id="input-release-group" class="form-control" name="work" type="text"
117+
value="{{ request.args.get('work', default='') }}">
118+
</div>
119+
</div>
120+
<div class="form-group">
121+
<div class="col-sm-offset-2 col-sm-10">
122+
<button type="submit" class="btn btn-default">{{ _('Search') }}</button>
123+
</div>
124+
</div>
125+
<input type="hidden" name="next" value="{{ next }}" />
126+
<input type="hidden" name="type" value="work" />
127+
</form>
128+
</div>
129+
107130
<div id="label" class="tab-pane {% if type=="label" %}active{% endif %}">
108131
<h3>{{ _('Label selection') }}</h3>
109132
<form method="GET" class="form-horizontal" role="form">
@@ -132,6 +155,7 @@ <h3>{{ _('Label selection') }}</h3>
132155
or request.args.get('release_group', default=False)
133156
or request.args.get('event', default=False)
134157
or request.args.get('place', default=False)
158+
or request.args.get('work', default=False)
135159
or request.args.get('label', default=False)
136160
%}
137161
<hr />
@@ -177,6 +201,14 @@ <h3>{{ _('Label selection') }}</h3>
177201
<th>{{ _('Country') }}</th>
178202
<th></th>
179203
</tr>
204+
{% elif type=="work" %}
205+
<tr>
206+
<th>{{ _('Title') }}</th>
207+
<th>{{ _('Artists') }}</th>
208+
<th>{{ _('Type') }}</th>
209+
<th>{{ _('Language') }}</th>
210+
<th></th>
211+
</tr>
180212
{% endif %}
181213
</thead>
182214
<tbody id="results">{% include 'search/selector_results.html' %}</tbody>

0 commit comments

Comments
 (0)