commit
a1ab17f150
|
@ -37,7 +37,7 @@ from regluit.utils.localdatetime import now
|
|||
from . import cc
|
||||
from . import models
|
||||
from .parameters import WORK_IDENTIFIERS
|
||||
from .validation import identifier_cleaner
|
||||
from .validation import identifier_cleaner, unreverse_name
|
||||
from .loaders.scrape import get_scraper, scrape_sitemap
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -517,6 +517,9 @@ def merge_works(w1, w2, user=None):
|
|||
w2source = wishlist.work_source(w2)
|
||||
wishlist.remove_work(w2)
|
||||
wishlist.add_work(w1, w2source)
|
||||
for userprofile in w2.contributors.all():
|
||||
userprofile.works.remove(w2)
|
||||
userprofile.works.add(w1)
|
||||
for identifier in w2.identifiers.all():
|
||||
identifier.work = w1
|
||||
identifier.save()
|
||||
|
@ -735,16 +738,6 @@ IDTABLE = [('librarything', 'ltwk'), ('goodreads', 'gdrd'), ('openlibrary', 'olw
|
|||
('edition_id', 'edid'), ('googlebooks', 'goog'), ('doi', 'doi'),
|
||||
]
|
||||
|
||||
def unreverse(name):
|
||||
if not ',' in name:
|
||||
return name
|
||||
(last, rest) = name.split(',', 1)
|
||||
if not ',' in rest:
|
||||
return '%s %s' % (rest.strip(), last.strip())
|
||||
(first, rest) = rest.split(',', 1)
|
||||
return '%s %s, %s' % (first.strip(), last.strip(), rest.strip())
|
||||
|
||||
|
||||
def load_from_yaml(yaml_url, test_mode=False):
|
||||
"""
|
||||
This really should be called 'load_from_github_yaml'
|
||||
|
@ -877,7 +870,7 @@ class BasePandataLoader(object):
|
|||
rel_code = inverse_marc_rels.get(key, 'aut')
|
||||
creators = creators if isinstance(creators, list) else [creators]
|
||||
for creator in creators:
|
||||
edition.add_author(unreverse(creator.get('agent_name', '')), relation=rel_code)
|
||||
edition.add_author(unreverse_name(creator.get('agent_name', '')), relation=rel_code)
|
||||
for yaml_subject in metadata.subjects: #always add yaml subjects (don't clear)
|
||||
if isinstance(yaml_subject, tuple):
|
||||
(authority, heading) = yaml_subject
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0009_auto_20170808_0846'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='userprofile',
|
||||
name='works',
|
||||
field=models.ManyToManyField(related_name='contributors', to='core.Work', blank=True),
|
||||
),
|
||||
]
|
|
@ -1211,6 +1211,9 @@ class UserProfile(models.Model):
|
|||
librarything_id = models.CharField(max_length=31, blank=True)
|
||||
badges = models.ManyToManyField('Badge', related_name='holders', blank=True)
|
||||
kindle_email = models.EmailField(max_length=254, blank=True)
|
||||
|
||||
# keep track of work the user adds
|
||||
works = models.ManyToManyField('Work', related_name='contributors', blank=True)
|
||||
|
||||
goodreads_user_id = models.CharField(max_length=32, null=True, blank=True)
|
||||
goodreads_user_name = models.CharField(max_length=200, null=True, blank=True)
|
||||
|
|
|
@ -129,6 +129,17 @@ def valid_subject( subject_name ):
|
|||
return False
|
||||
return True
|
||||
|
||||
reverse_name_comma = re.compile(r',(?! *Jr[\., ])')
|
||||
|
||||
def unreverse_name(name):
|
||||
if not reverse_name_comma.search(name):
|
||||
return name
|
||||
(last, rest) = name.split(',', 1)
|
||||
if not ',' in rest:
|
||||
return '%s %s' % (rest.strip(), last.strip())
|
||||
(first, rest) = rest.split(',', 1)
|
||||
return '%s %s, %s' % (first.strip(), last.strip(), rest.strip())
|
||||
|
||||
def authlist_cleaner(authlist):
|
||||
''' given a author string or list of author strings, checks that the author string
|
||||
is not a list of author names and that no author is repeated'''
|
||||
|
@ -144,16 +155,18 @@ def authlist_cleaner(authlist):
|
|||
# Match comma but not ", Jr"
|
||||
comma_list_delim = re.compile(r',(?! *Jr[\., ])')
|
||||
spaces = re.compile(r'\s+')
|
||||
_and_ = re.compile(r',? and ')
|
||||
_and_ = re.compile(r',? (and|\&) ')
|
||||
semicolon_list_delim = re.compile(r'[\;|\&]')
|
||||
|
||||
def auth_cleaner(auth):
|
||||
''' given a author string checks that the author string
|
||||
is not a list of author names'''
|
||||
cleaned = []
|
||||
auth = _and_.sub(',', auth)
|
||||
if ';' in auth:
|
||||
authlist = auth.split(';')
|
||||
authlist = semicolon_list_delim.split(auth)
|
||||
authlist = [unreverse_name(name) for name in authlist]
|
||||
else:
|
||||
auth = _and_.sub(',', auth)
|
||||
authlist = comma_list_delim.split(auth)
|
||||
for auth in authlist:
|
||||
cleaned.append(spaces.sub(' ', auth.strip()))
|
||||
|
|
|
@ -51,7 +51,7 @@ class IdentifierForm(forms.ModelForm):
|
|||
required=False,
|
||||
)
|
||||
make_new = forms.BooleanField(
|
||||
label='There\'s no existing Identifier, so please use an Unglue.it ID',
|
||||
label='There\'s no existing Identifier. ',
|
||||
required=False,
|
||||
)
|
||||
identifier = None
|
||||
|
@ -61,7 +61,7 @@ class IdentifierForm(forms.ModelForm):
|
|||
id_value = self.cleaned_data.get('id_value', '').strip()
|
||||
make_new = self.cleaned_data.get('make_new', False)
|
||||
if not make_new:
|
||||
self.cleaned_data['value'] = identifier_cleaner(id_type)(id_value)
|
||||
self.cleaned_data['id_value'] = identifier_cleaner(id_type)(id_value)
|
||||
return self.cleaned_data
|
||||
|
||||
class Meta:
|
||||
|
|
|
@ -238,7 +238,12 @@ ul.fancytree-container {
|
|||
|
||||
{% else %}
|
||||
{% if edition.work %}
|
||||
<h2><a href="{% url 'work' edition.work.id %}">{{ edition.work.title }}</a> was added to Unglue.it on {{ edition.work.created }}</h2>
|
||||
{% include 'edition_display.html' %}
|
||||
<div class="launch_top pale">
|
||||
Are you the author or other rightsholder for this work?
|
||||
To edit the metadata or add editions, become an Unglue.it <a href="{% url 'rightsholders' %}">rights holder</a>.
|
||||
</div>
|
||||
{% else %}
|
||||
Sorry, there's no work specified.
|
||||
{% endif %}
|
||||
|
|
|
@ -39,11 +39,7 @@
|
|||
web: <a href="{{ edition.http_id }}">{{ edition.http_id }}</a><br />
|
||||
{% endif %}
|
||||
{% if not managing %}
|
||||
{% if user.is_staff %}
|
||||
<a href="{% url 'new_edition' work_id edition.id %}">Edit this edition</a><br />
|
||||
{% elif user in work.last_campaign.managers.all %}
|
||||
<a href="{% url 'new_edition' work_id edition.id %}">Edit this edition</a><br />
|
||||
{% elif user.rights_holder.count and not work.last_campaign %}
|
||||
{% if user_can_edit_work %}
|
||||
<a href="{% url 'new_edition' work_id edition.id %}">Edit this edition</a><br />
|
||||
{% endif %}
|
||||
{% if user.is_authenticated %}
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
|
||||
<p>To add a work and edition to Unglue.it, we need to start with an identifier. We'll see if we can find some metadata based on the identifier you give us. If you give us an ISBN, we'll often be able to find some. If there's no ISBN, give us a URL (a web address) and we'll check the page for bibliographic info. </p>
|
||||
{% if not request.user.rights_holder.all.count %}
|
||||
<p>If someone else has already added the work to unglue.it, you may not be able to edit its metadata.</p>
|
||||
{% endif %}
|
||||
<form id="editform" enctype="multipart/form-data" method="POST" action="#">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
|
|
|
@ -476,7 +476,7 @@
|
|||
<ul id="kw_list"></ul>
|
||||
|
||||
{% endif %}
|
||||
{% if user.is_staff or user in work.last_campaign.managers.all %}
|
||||
{% if user_can_edit_work %}
|
||||
<form method="POST" id="kw_add_form">{% csrf_token %}
|
||||
{{ kwform.add_kw }}<input type="hidden" name="kw_add" value="true"> <input type="submit" name="kw_add_fake" value="add keyword" id="kw_add_form_submit" />
|
||||
</form>
|
||||
|
@ -486,7 +486,7 @@
|
|||
{% if alert %}
|
||||
<div class="yikes"><br />{{ alert }}</div>
|
||||
{% endif %}
|
||||
{% if user.is_staff or user in work.last_campaign.managers.all %}
|
||||
{% if user_can_edit_work %}
|
||||
<div><a href="{% url 'new_edition' work_id edition.id %}">Create a new edition for this work</a><br /><br /></div>
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -397,6 +397,7 @@ def work(request, work_id, action='display'):
|
|||
|
||||
return render(request, 'work.html', {
|
||||
'work': work,
|
||||
'user_can_edit_work': user_can_edit_work(request.user, work),
|
||||
'premiums': premiums,
|
||||
'ungluers': userlists.supporting_users(work, 5),
|
||||
'claimform': claimform,
|
||||
|
@ -642,6 +643,8 @@ def googlebooks(request, googlebooks_id):
|
|||
if edition.new:
|
||||
# add related editions asynchronously
|
||||
tasks.populate_edition.delay(edition.isbn_13)
|
||||
if request.user.is_authenticated():
|
||||
request.user.profile.works.add(edition.work)
|
||||
except bookloader.LookupFailure:
|
||||
logger.warning("failed to load googlebooks_id %s" % googlebooks_id)
|
||||
return HttpResponseNotFound("failed looking up googlebooks id %s" % googlebooks_id)
|
||||
|
|
|
@ -29,15 +29,19 @@ def user_can_edit_work(user, work):
|
|||
'''
|
||||
Check if a user is allowed to edit the work
|
||||
'''
|
||||
if user.is_staff :
|
||||
if user.is_anonymous():
|
||||
return False
|
||||
elif user.is_staff :
|
||||
return True
|
||||
elif work and work.last_campaign():
|
||||
return user in work.last_campaign().managers.all()
|
||||
elif user.rights_holder.count() and (work == None or not work.last_campaign()):
|
||||
# allow rights holders to edit unless there is a campaign
|
||||
return True
|
||||
elif work and work.claim.all():
|
||||
return True if work.claim.filter(user=user) else False
|
||||
else:
|
||||
return False
|
||||
return user.profile in work.contributors.all()
|
||||
|
||||
def safe_get_work(work_id):
|
||||
"""
|
||||
|
@ -68,6 +72,11 @@ def get_edition(edition_id):
|
|||
except models.Edition.DoesNotExist:
|
||||
raise Http404 (duplicate-code)
|
||||
|
||||
def user_edition(edition, user):
|
||||
if user and user.is_authenticated() and edition:
|
||||
user.profile.works.add(edition.work)
|
||||
return edition
|
||||
|
||||
def get_edition_for_id(id_type, id_value, user=None):
|
||||
''' the identifier is assumed to not be in database '''
|
||||
identifiers = {id_type: id_value}
|
||||
|
@ -87,17 +96,18 @@ def get_edition_for_id(id_type, id_value, user=None):
|
|||
if identifiers.has_key('goog'):
|
||||
edition = add_by_googlebooks_id(identifiers['goog'])
|
||||
if edition:
|
||||
return edition
|
||||
|
||||
return user_edition(edition, user)
|
||||
|
||||
if identifiers.has_key('isbn'):
|
||||
edition = add_by_isbn(identifiers['isbn'])
|
||||
if edition:
|
||||
return edition
|
||||
return user_edition(edition, user)
|
||||
|
||||
if identifiers.has_key('oclc'):
|
||||
edition = add_by_oclc(identifiers['oclc'])
|
||||
if edition:
|
||||
return edition
|
||||
return user_edition(edition, user)
|
||||
|
||||
if identifiers.has_key('glue'):
|
||||
try:
|
||||
|
@ -108,7 +118,7 @@ def get_edition_for_id(id_type, id_value, user=None):
|
|||
|
||||
if identifiers.has_key('http'):
|
||||
edition = add_by_webpage(identifiers['http'], user=user)
|
||||
return edition
|
||||
return user_edition(edition, user)
|
||||
|
||||
|
||||
# return a dummy edition and identifier
|
||||
|
@ -126,7 +136,7 @@ def get_edition_for_id(id_type, id_value, user=None):
|
|||
models.Identifier.objects.create(type=key, value=id_value, work=work, edition=None)
|
||||
else:
|
||||
models.Identifier.objects.create(type=key, value=id_value, work=work, edition=edition)
|
||||
return edition
|
||||
return user_edition(edition, user)
|
||||
|
||||
@login_required
|
||||
def new_edition(request, by=None):
|
||||
|
@ -138,7 +148,7 @@ def new_edition(request, by=None):
|
|||
form = IdentifierForm(data=request.POST)
|
||||
if form.is_valid():
|
||||
if form.cleaned_data.get('make_new', False):
|
||||
edition = get_edition_for_id('glue', 'new')
|
||||
edition = get_edition_for_id('glue', 'new', user=request.user)
|
||||
else:
|
||||
id_type = form.cleaned_data['id_type']
|
||||
id_value = form.cleaned_data['id_value']
|
||||
|
@ -238,17 +248,14 @@ def edit_edition(request, work_id, edition_id, by=None):
|
|||
ebookchange = True
|
||||
if ebookchange:
|
||||
form = EditionForm(instance=edition, data=request.POST, files=request.FILES)
|
||||
if request.POST.has_key('add_author_submit') and admin:
|
||||
|
||||
if request.POST.get('add_author', None) and admin:
|
||||
new_author_name = request.POST['add_author'].strip()
|
||||
new_author_relation = request.POST['add_author_relation']
|
||||
try:
|
||||
author = models.Author.objects.get(name=new_author_name)
|
||||
except models.Author.DoesNotExist:
|
||||
author = models.Author.objects.create(name=new_author_name)
|
||||
edition.new_authors.append((new_author_name, new_author_relation))
|
||||
form = EditionForm(instance=edition, data=request.POST, files=request.FILES)
|
||||
elif not form and admin:
|
||||
form = EditionForm(instance=edition, data=request.POST, files=request.FILES)
|
||||
if (new_author_name, new_author_relation) not in edition.new_authors:
|
||||
edition.new_authors.append((new_author_name, new_author_relation))
|
||||
form = EditionForm(instance=edition, data=request.POST, files=request.FILES)
|
||||
if not request.POST.has_key('add_author_submit') and admin:
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
if not work:
|
||||
|
|
Loading…
Reference in New Issue