Merge branch 'master' into sysadmin
commit
723c8e3ec8
|
@ -7,7 +7,7 @@ import unicodedata
|
||||||
|
|
||||||
from regluit.core.models import Work, Edition, Author, PublisherName, Identifier, Subject
|
from regluit.core.models import Work, Edition, Author, PublisherName, Identifier, Subject
|
||||||
from regluit.core.isbn import ISBN
|
from regluit.core.isbn import ISBN
|
||||||
from regluit.core.bookloader import add_by_isbn_from_google
|
from regluit.core.bookloader import add_by_isbn_from_google, merge_works
|
||||||
from regluit.api.crosswalks import inv_relator_contrib
|
from regluit.api.crosswalks import inv_relator_contrib
|
||||||
from regluit.bisac.models import BisacHeading
|
from regluit.bisac.models import BisacHeading
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ def utf8_general_ci_norm(s):
|
||||||
|
|
||||||
def get_authors(book):
|
def get_authors(book):
|
||||||
authors=[]
|
authors=[]
|
||||||
|
if book.get('AuthorsList',''):
|
||||||
|
#UMich
|
||||||
for i in range(1,3):
|
for i in range(1,3):
|
||||||
fname=u'Author{}First'.format(i)
|
fname=u'Author{}First'.format(i)
|
||||||
lname=u'Author{}Last'.format(i)
|
lname=u'Author{}Last'.format(i)
|
||||||
|
@ -50,19 +52,33 @@ def get_authors(book):
|
||||||
if len(authlist)>3:
|
if len(authlist)>3:
|
||||||
for authname in authlist[3:]:
|
for authname in authlist[3:]:
|
||||||
authors.append((authname, 'A01'))
|
authors.append((authname, 'A01'))
|
||||||
|
else:
|
||||||
|
#OBP
|
||||||
|
for i in range(1,6):
|
||||||
|
fname= book.get(u'Contributor {} first name'.format(i), '')
|
||||||
|
lname= book.get(u'Contributor {} surname'.format(i), '')
|
||||||
|
role= book.get(u'ONIX Role Code (List 17){}'.format(i), '')
|
||||||
|
authname = u'{} {}'.format(fname,lname)
|
||||||
|
if authname != u' ':
|
||||||
|
role = role if role.strip() else 'A01'
|
||||||
|
authors.append((authname,role))
|
||||||
|
else:
|
||||||
|
break
|
||||||
return authors
|
return authors
|
||||||
|
|
||||||
def get_subjects(book):
|
def get_subjects(book):
|
||||||
subjects=[]
|
subjects=[]
|
||||||
for i in range(1,3):
|
for i in range(1,5):
|
||||||
key=u'BISACCode{}'.format(i)
|
key = u'BISACCode{}'.format(i) #UMich dialect
|
||||||
if book[key] != '':
|
key2 = u'BISAC subject code {}'.format(i) #OBP dialect
|
||||||
|
code = book.get(key,'')
|
||||||
|
code = code if code else book.get(key2,'')
|
||||||
|
if code != '':
|
||||||
try:
|
try:
|
||||||
bisac=BisacHeading.objects.get(notation=book[key])
|
bisac=BisacHeading.objects.get(notation=code)
|
||||||
subjects.append(bisac)
|
subjects.append(bisac)
|
||||||
except BisacHeading.DoesNotExist:
|
except BisacHeading.DoesNotExist:
|
||||||
logger.warning( "Please add BISAC {}".format(book[key]))
|
logger.warning( "Please add BISAC {}".format(code))
|
||||||
return subjects
|
return subjects
|
||||||
|
|
||||||
def add_subject(subject_name, work, authority=''):
|
def add_subject(subject_name, work, authority=''):
|
||||||
|
@ -72,7 +88,21 @@ def add_subject(subject_name, work, authority=''):
|
||||||
subject=Subject.objects.create(name=subject_name, authority=authority)
|
subject=Subject.objects.create(name=subject_name, authority=authority)
|
||||||
subject.works.add(work)
|
subject.works.add(work)
|
||||||
|
|
||||||
|
def get_title(book):
|
||||||
|
title = book.get('FullTitle','') #UMICH
|
||||||
|
if title:
|
||||||
|
return title
|
||||||
|
title = book.get('Title','') #OBP
|
||||||
|
sub = book.get('Subtitle','')
|
||||||
|
if sub:
|
||||||
|
return u'{}: {}'.format(title,sub)
|
||||||
|
else:
|
||||||
|
return title
|
||||||
|
|
||||||
def get_cover(book):
|
def get_cover(book):
|
||||||
|
cover_url = book.get('Cover URL','') #OBP
|
||||||
|
if cover_url:
|
||||||
|
return cover_url
|
||||||
url = book['URL']
|
url = book['URL']
|
||||||
if "10.3998" in url:
|
if "10.3998" in url:
|
||||||
# code for umich books; can generalize, of course!
|
# code for umich books; can generalize, of course!
|
||||||
|
@ -94,8 +124,9 @@ def get_cover(book):
|
||||||
def get_isbns(book):
|
def get_isbns(book):
|
||||||
isbns = []
|
isbns = []
|
||||||
edition = None
|
edition = None
|
||||||
for code in ['eISBN','PaperISBN','ClothISBN']:
|
#'ISBN 1' is OBP, others are UMICH
|
||||||
if book[code] not in ('','N/A'):
|
for code in ['eISBN', 'ISBN 3','PaperISBN', 'ISBN 2', 'ClothISBN', 'ISBN 1', 'ISBN 4', 'ISBN 5']:
|
||||||
|
if book.get(code, '') not in ('','N/A'):
|
||||||
values = book[code].split(',')
|
values = book[code].split(',')
|
||||||
for value in values:
|
for value in values:
|
||||||
isbn = ISBN(value).to_string()
|
isbn = ISBN(value).to_string()
|
||||||
|
@ -106,15 +137,53 @@ def get_isbns(book):
|
||||||
edition = Edition.get_by_isbn(isbn)
|
edition = Edition.get_by_isbn(isbn)
|
||||||
return (isbns, edition )
|
return (isbns, edition )
|
||||||
|
|
||||||
|
def get_pubdate(book):
|
||||||
|
value = book.get('CopyrightYear','') #UMICH
|
||||||
|
if value:
|
||||||
|
return value
|
||||||
|
value = book.get('publication year','') #OBP
|
||||||
|
sub = book.get('publication month','')
|
||||||
|
sub2 = book.get('publication day','')
|
||||||
|
if sub2:
|
||||||
|
return u'{}-{}-{}'.format(value,sub,sub2)
|
||||||
|
elif sub:
|
||||||
|
return u'{}-{}'.format(value,sub,sub2)
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
def get_publisher(book):
|
||||||
|
value = book.get('Publisher','')
|
||||||
|
if value:
|
||||||
|
return value
|
||||||
|
if book.get('DOI prefix','')=='10.11647':
|
||||||
|
return "Open Book Publishers"
|
||||||
|
|
||||||
|
def get_url(book):
|
||||||
|
url = book.get('URL','')
|
||||||
|
url = url if url else u'https://dx.doi.org/{}/{}'.format( book.get('DOI prefix',''),book.get('DOI suffix',''))
|
||||||
|
return url
|
||||||
|
|
||||||
|
def get_description(book):
|
||||||
|
value = book.get('DescriptionBrief','')
|
||||||
|
value = value if value else book.get('Plain Text Blurb','')
|
||||||
|
return value
|
||||||
|
|
||||||
|
def get_language(book):
|
||||||
|
value = book.get('ISO Language Code','')
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
def load_from_books(books):
|
def load_from_books(books):
|
||||||
''' books is an iterator of book dicts.
|
''' books is an iterator of book dicts.
|
||||||
each book must have attributes
|
each book must have attributes
|
||||||
|
(umich dialect)
|
||||||
eISBN, ClothISBN, PaperISBN, Publisher, FullTitle, Title, Subtitle, AuthorsList,
|
eISBN, ClothISBN, PaperISBN, Publisher, FullTitle, Title, Subtitle, AuthorsList,
|
||||||
Author1Last, Author1First, Author1Role, Author2Last, Author2First, Author2Role, Author3Last,
|
Author1Last, Author1First, Author1Role, Author2Last, Author2First, Author2Role, Author3Last,
|
||||||
Author3First, Author3Role, AuthorBio, TableOfContents, Excerpt, DescriptionLong,
|
Author3First, Author3Role, AuthorBio, TableOfContents, Excerpt, DescriptionLong,
|
||||||
DescriptionBrief, BISACCode1, BISACCode2, BISACCode3, CopyrightYear, ePublicationDate,
|
DescriptionBrief, BISACCode1, BISACCode2, BISACCode3, CopyrightYear, ePublicationDate,
|
||||||
eListPrice, ListPriceCurrencyType, List Price in USD (paper ISBN), eTerritoryRights,
|
eListPrice, ListPriceCurrencyType, List Price in USD (paper ISBN), eTerritoryRights,
|
||||||
SubjectListMARC, , Book-level DOI, URL, License
|
SubjectListMARC, , Book-level DOI, URL, License
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# Goal: get or create an Edition and Work for each given book
|
# Goal: get or create an Edition and Work for each given book
|
||||||
|
@ -125,12 +194,14 @@ def load_from_books(books):
|
||||||
|
|
||||||
# try first to get an Edition already in DB with by one of the ISBNs in book
|
# try first to get an Edition already in DB with by one of the ISBNs in book
|
||||||
(isbns, edition) = get_isbns(book)
|
(isbns, edition) = get_isbns(book)
|
||||||
title=book['FullTitle']
|
if len(isbns)==0:
|
||||||
|
continue
|
||||||
|
title=get_title(book)
|
||||||
authors = get_authors(book)
|
authors = get_authors(book)
|
||||||
|
|
||||||
# if matching by ISBN doesn't work, then create a Work and Edition
|
# if matching by ISBN doesn't work, then create a Work and Edition
|
||||||
# with a title and the first ISBN
|
# with a title and the first ISBN
|
||||||
if not edition and len(isbns):
|
if not edition:
|
||||||
work = Work(title=title)
|
work = Work(title=title)
|
||||||
work.save()
|
work.save()
|
||||||
edition= Edition(title=title, work=work)
|
edition= Edition(title=title, work=work)
|
||||||
|
@ -140,14 +211,18 @@ def load_from_books(books):
|
||||||
work=edition.work
|
work=edition.work
|
||||||
|
|
||||||
# at this point, work and edition exist
|
# at this point, work and edition exist
|
||||||
|
url = get_url(book)
|
||||||
if book.get('URL'):
|
if url:
|
||||||
Identifier.set(type='http', value=book['URL'], edition=edition, work=work)
|
Identifier.set(type='http', value=url, edition=edition, work=work)
|
||||||
|
|
||||||
# make sure each isbn is represented by an Edition
|
# make sure each isbn is represented by an Edition
|
||||||
# also associate authors, publication date, cover, publisher
|
# also associate authors, publication date, cover, publisher
|
||||||
for isbn in isbns:
|
for isbn in isbns:
|
||||||
edition = add_by_isbn_from_google(isbn)
|
edition = add_by_isbn_from_google(isbn, work=work)
|
||||||
|
if edition and edition.work != work:
|
||||||
|
merge_works(work, edition.work)
|
||||||
|
work = work if work.pk is not None else edition.work
|
||||||
|
edition.work=work # because integrity errors if not
|
||||||
if not edition:
|
if not edition:
|
||||||
edition= Edition(title=title, work=work)
|
edition= Edition(title=title, work=work)
|
||||||
edition.save()
|
edition.save()
|
||||||
|
@ -156,15 +231,22 @@ def load_from_books(books):
|
||||||
edition.authors.clear()
|
edition.authors.clear()
|
||||||
for (author, role) in authors:
|
for (author, role) in authors:
|
||||||
edition.add_author(author, inv_relator_contrib.get(role, 'aut'))
|
edition.add_author(author, inv_relator_contrib.get(role, 'aut'))
|
||||||
edition.publication_date = book['CopyrightYear']
|
edition.publication_date = get_pubdate(book)
|
||||||
edition.cover_image = get_cover(book)
|
edition.cover_image = get_cover(book)
|
||||||
edition.set_publisher(book['Publisher'])
|
|
||||||
edition.save()
|
edition.save()
|
||||||
|
edition.set_publisher(get_publisher(book))
|
||||||
|
|
||||||
# possibly replace work.description
|
# possibly replace work.description
|
||||||
description = book['DescriptionBrief']
|
description = get_description(book)
|
||||||
if len(description)>len (work.description):
|
if len(description)>len (work.description):
|
||||||
work.description = description
|
work.description = description
|
||||||
|
work.save()
|
||||||
|
|
||||||
|
# set language
|
||||||
|
lang= get_language(book)
|
||||||
|
if lang:
|
||||||
|
work.language = lang
|
||||||
|
work.save()
|
||||||
|
|
||||||
# add a bisac subject (and ancestors) to work
|
# add a bisac subject (and ancestors) to work
|
||||||
for bisacsh in get_subjects(book):
|
for bisacsh in get_subjects(book):
|
||||||
|
@ -178,9 +260,9 @@ def load_from_books(books):
|
||||||
results.append((book, work, edition))
|
results.append((book, work, edition))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logger.info ("{} {} {}\n".format(i, title, loading_ok))
|
logger.info (u"{} {} {}\n".format(i, title, loading_ok))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info ("{} {}\n".format(i, title, str(e) ))
|
logger.info (u"{} {}\n".format(i, title, str(e) ))
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
@ -195,9 +277,9 @@ def loaded_book_ok(book, work, edition):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
url_id = Identifier.objects.get(type='http', value=book['URL'])
|
url_id = Identifier.objects.get(type='http', value=get_url(book))
|
||||||
if url_id is None:
|
if url_id is None:
|
||||||
logger.info ("url_id problem: work.id {}, url: {}".format(work.id, book['URL']))
|
logger.info ("url_id problem: work.id {}, url: {}".format(work.id, get_url(book)))
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info (str(e))
|
logger.info (str(e))
|
||||||
|
@ -224,14 +306,14 @@ def loaded_book_ok(book, work, edition):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
edition_for_isbn.publication_date = book['CopyrightYear']
|
edition_for_isbn.publication_date = get_pubdate(book)
|
||||||
edition_for_isbn.cover_image = get_cover(book)
|
edition_for_isbn.cover_image = get_cover(book)
|
||||||
edition_for_isbn.set_publisher(book['Publisher'])
|
edition_for_isbn.set_publisher(get_publisher(book))
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# work description
|
# work description
|
||||||
description = book['DescriptionBrief']
|
description = get_description(book)
|
||||||
if not ((work.description == description) or (len(description) <len (work.description))):
|
if not ((work.description == description) or (len(description) <len (work.description))):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
"""
|
||||||
|
print user emails
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
from regluit.core import models
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "claim books for rights_holder based on a text file of ISBNs"
|
||||||
|
args = "<rights_holder_id> <filename>"
|
||||||
|
|
||||||
|
def handle(self, rights_holder_id, filename, **options):
|
||||||
|
try:
|
||||||
|
rh = models.RightsHolder.objects.get(id=int(rights_holder_id))
|
||||||
|
except models.Identifier.DoesNotExist:
|
||||||
|
print '{} not a rights_holder'.format(rights_holder_id)
|
||||||
|
return
|
||||||
|
with open(filename) as f:
|
||||||
|
for isbn in f:
|
||||||
|
isbn = isbn.strip()
|
||||||
|
try:
|
||||||
|
work = models.Identifier.objects.get(type='isbn',value=isbn).work
|
||||||
|
try:
|
||||||
|
c = models.Claim.objects.get(work=work)
|
||||||
|
print '{} already claimed by {}'.format(work, c.rights_holder)
|
||||||
|
except models.Claim.DoesNotExist:
|
||||||
|
c = models.Claim.objects.create(
|
||||||
|
work=work,
|
||||||
|
rights_holder=rh,
|
||||||
|
user=rh.owner,
|
||||||
|
status='active')
|
||||||
|
print '{} claimed for {}'.format(work, rh)
|
||||||
|
except models.Identifier.DoesNotExist:
|
||||||
|
print '{} not loaded'.format(isbn)
|
||||||
|
continue
|
|
@ -8,6 +8,6 @@ class Command(BaseCommand):
|
||||||
args = "<filename>"
|
args = "<filename>"
|
||||||
|
|
||||||
def handle(self, filename, **options):
|
def handle(self, filename, **options):
|
||||||
sheetreader= UnicodeDictReader(open(filename,'rU'), dialect=csv.excel_tab)
|
sheetreader= UnicodeDictReader(open(filename,'rU'), dialect=csv.excel)
|
||||||
load_from_books(sheetreader)
|
load_from_books(sheetreader)
|
||||||
print "finished loading"
|
print "finished loading"
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import csv
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
from regluit.core.loaders.utils import UnicodeDictReader, load_from_books
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = "load books based on a csv spreadsheet of onix data"
|
||||||
|
args = "<filename>"
|
||||||
|
|
||||||
|
def handle(self, filename, **options):
|
||||||
|
sheetreader= UnicodeDictReader(open(filename,'rU'), dialect=csv.excel_tab)
|
||||||
|
load_from_books(sheetreader)
|
||||||
|
print "finished loading"
|
|
@ -1123,8 +1123,12 @@ class Work(models.Model):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def googlebooks_id(self):
|
def googlebooks_id(self):
|
||||||
|
try:
|
||||||
preferred_id=self.preferred_edition.googlebooks_id
|
preferred_id=self.preferred_edition.googlebooks_id
|
||||||
# note that there's always a preferred edition
|
# note that there should always be a preferred edition
|
||||||
|
except AttributeError:
|
||||||
|
# this work has no edition.
|
||||||
|
return ''
|
||||||
if preferred_id:
|
if preferred_id:
|
||||||
return preferred_id
|
return preferred_id
|
||||||
try:
|
try:
|
||||||
|
@ -1307,6 +1311,7 @@ class Work(models.Model):
|
||||||
return WasWork.objects.get(was=self.id).work.preferred_edition
|
return WasWork.objects.get(was=self.id).work.preferred_edition
|
||||||
except WasWork.DoesNotExist:
|
except WasWork.DoesNotExist:
|
||||||
#should not happen
|
#should not happen
|
||||||
|
logger.warning('work {} has no edition'.format(self.id))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def last_campaign_status(self):
|
def last_campaign_status(self):
|
||||||
|
@ -2064,7 +2069,7 @@ class Ebook(models.Model):
|
||||||
return ebf.file
|
return ebf.file
|
||||||
except IndexError:
|
except IndexError:
|
||||||
# response has no Content-Length header probably a bad link
|
# response has no Content-Length header probably a bad link
|
||||||
logging.error( 'Bad link error: {}'.format(ebook.url) )
|
logging.error( 'Bad link error: {}'.format(self.url) )
|
||||||
except IOError:
|
except IOError:
|
||||||
logger.error(u'could not open {}'.format(self.url) )
|
logger.error(u'could not open {}'.format(self.url) )
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1133,7 +1133,64 @@ class OnixLoaderTests(TestCase):
|
||||||
'eISBN': u'N/A',
|
'eISBN': u'N/A',
|
||||||
'eListPrice': u'N/A',
|
'eListPrice': u'N/A',
|
||||||
'ePublicationDate': u'',
|
'ePublicationDate': u'',
|
||||||
'eTerritoryRights': u''}
|
'eTerritoryRights': u''},
|
||||||
|
{'': u'',
|
||||||
|
'CAD price eub': u'9.95',
|
||||||
|
'Title': u'That Greece Might Still Be Free',
|
||||||
|
'USD price epub': u'9.95',
|
||||||
|
'ISBN 2 with dashes': u'978-1-906924-01-0',
|
||||||
|
'Plain Text Blurb': u'When in 1821, the Greeks rose in violent revolution against the rule of the Ottoman Turks, waves of sympathy spread across Western Europe and the United States. More than a thousand volunteers set out to fight for the cause. The Philhellenes, whether they set out to recreate the Athens of Pericles, start a new crusade, or make money out of a war, all felt that Greece had unique claim on the sympathy of the world. As Lord Byron wrote, "I dreamed that Greece might still be Free"; and he died at Missolonghi trying to translate that dream into reality. William St Clair\'s meticulously researched and highly readable account of their aspirations and experiences was hailed as definitive when it was first published. Long out of print, it remains the standard account of the Philhellenic movement and essential reading for any students of the Greek War of Independence, Byron, and European Romanticism. Its relevance to more modern ethnic and religious conflicts is becoming increasingly appreciated by scholars worldwide. This revised edition includes a new introduction by Roderick Beaton, an updated bibliography and many new illustrations.',
|
||||||
|
'Cover URL': u'http://www.openbookpublishers.com/shopimages/products/cover/3',
|
||||||
|
'keywords': u'Greece; Greek History; Lord Byron; War of Independence; Philhellenes; war; history; Romanticism',
|
||||||
|
'Publication type': u'Monograph', 'GBP price epub': u'5.95', 'publication month': u'11', 'no of tables': u'',
|
||||||
|
'GBP price paperback': u'15.95', 'AUD price epub': u'9.95', 'ISBN 4 with dashes': u'978-1-906924-02-7-epub',
|
||||||
|
'DOI prefix': u'10.11647', 'License URL (human-readable summary)': u'http://creativecommons.org/licenses/by-nc-nd/2.0/',
|
||||||
|
'Contributor 5 surname': u'', 'Contributor 1 first name': u'William', 'Contributor 6 first name': u'',
|
||||||
|
'ONIX Role Code (List 17)6': u'', 'ONIX Role Code (List 17)5': u'', 'ONIX Role Code (List 17)4': u'',
|
||||||
|
'ONIX Role Code (List 17)3': u'', 'ONIX Role Code (List 17)2': u'A24', 'ONIX Role Code (List 17)1': u'A01',
|
||||||
|
'GBP price hardback': u'29.95', 'Subtitle': u'The Philhellenes in the War of Independence', 'ONIX tag6': u'',
|
||||||
|
'ISBN 3 with dashes': u'978-1-906924-02-7', 'Countries excluded': u'None', 'first edition publication date': u'39753',
|
||||||
|
'Original Language': u'English', 'ISBN 1 with dashes': u'978-1-906924-00-3', 'Contributor 4 first name': u'',
|
||||||
|
'ISBN 5 with dashes': u'978-1-906924-02-7-mobi', 'Contributor 2 surname': u'Beaton',
|
||||||
|
'License URL (our copyright tab)': u'http://www.openbookpublishers.com/isbn/9781906924003#copyright',
|
||||||
|
'BISAC subject code 1': u'HIS042000', 'BISAC subject code 3': u'HIS037060',
|
||||||
|
'BISAC subject code 2': u'HIS054000', 'BISAC subject code 5': u'',
|
||||||
|
'BISAC subject code 4': u'', 'Status': u'Active', 'Geographic rights': u'Worldwide',
|
||||||
|
'Series Name': u'', 'Contributor 5 first name': u'', 'ISSN Print with dashes': u'',
|
||||||
|
'ISBN 5': u'9781906924027mobi', 'Contributor 1 surname': u'St Clair',
|
||||||
|
'Contributor 2 first name': u'Roderick',
|
||||||
|
'Book-page permanent URL': u'http://www.openbookpublishers.com/isbn/9781906924003',
|
||||||
|
'EUR price hardback': u'36.95', 'EUR price epub': u'7.95', 'Contributor 6 surname': u'',
|
||||||
|
'current edition number (integers only)': u'1',
|
||||||
|
'Table of Content': u"Introduction by Roderick Beaton\n1. The Outbreak\n2. The Return of the Ancient Hellenes\n3. The Regiment\n4. Two Kinds of War\n5. The Cause of Greece, the Cause of Europe\n6. The Road to Marseilles\n7. Chios\n8. The Battalion of Philhellenes\n9. The Battle of Peta\n10. The Triumph of the Captains\n11. The Return Home\n12. The German Legion\n13. Knights and Crusaders\n14. Secrets of State\n15. Enter the British\n16. Lord Byron joins the Cause\n17. 'To bring Freedom and Knowledge to Greece'\n18. Arrivals at Missolonghi\n19. The Byron Brigade\n20. Essays in Regeneration\n21. The New Apostles\n22. The English Gold\n23. The Coming of the Arabs\n24. The Shade of Napoleon\n25. 'No freedom to fight for at home'\n26. French Idealism and French Cynicism\n27. Regulars Again\n28. A New Fleet\n29. Athens and Navarino\n30. America to the Rescue\n31. Later\nAppendix I: Remarks on Numbers\nAppendix II: The Principal Philhellenic Expeditions\nNotes on the Select Bibliography\nSelect Bibliography\nBibliography of Primary and Secondary Material Since 1972\nNotes\nIndex",
|
||||||
|
'no of illustrations': u'41', 'OBP Role Name6': u'', 'GBP price PDF': u'5.95',
|
||||||
|
'OBP Role Name4': u'', 'OBP Role Name5': u'', 'OBP Role Name2': u'Introduction',
|
||||||
|
'OBP Role Name3': u'', 'OBP Role Name1': u'Author', 'ONIX Status code': u'04',
|
||||||
|
'LLC (Library of Congress Codes)': u'', 'publication day': u'1',
|
||||||
|
'Copyright holder 2': u'', 'Language': u'English', 'Contributor 3 first name': u'',
|
||||||
|
'CAD price hardback': u'54.95', 'USD price paperback': u'26.95', 'ONIX tag1': u'By (author)',
|
||||||
|
'ONIX tag3': u'', 'ONIX tag2': u'Introduction by', 'ONIX tag5': u'',
|
||||||
|
'ONIX tag4': u'', 'no of audio/video': u'0', 'EUR price mobi': u'7.95',
|
||||||
|
'Version of the license': u'2.0', 'publication year': u'2008',
|
||||||
|
'CAD price paperback': u'29.95', 'Full-text URL - PDF': u'http://www.openbookpublishers.com/reader/3',
|
||||||
|
'Copyright holder 1': u'William St Clair', 'Copyright holder 3': u'',
|
||||||
|
'Short Blurb (less than 100 words)': u'When in 1821, the Greeks rose in violent revolution against Ottoman rule, waves of sympathy spread across western Europe and the USA. Inspired by a belief that Greece had a unique claim on the sympathy of the world, more than a thousand Philhellenes set out to fight for the cause. This meticulously researched and highly readable account of their aspirations and experiences has long been the standard account of the Philhellenic movement and essential reading for students of the Greek War of Independence, Byron and European Romanticism. Its relevance to more modern conflicts is also becoming increasingly appreciated.',
|
||||||
|
'BIC subject code 3': u'3JH', 'BIC subject code 2': u'1DVG', 'BIC subject code 1': u'HBJD',
|
||||||
|
'ISSN Digital with dashes': u'', 'USD price mobi': u'9.95', 'BIC subject code 5': u'',
|
||||||
|
'BIC subject code 4': u'', 'ONIX Language Code': u'eng', 'AUD price paperback': u'29.95',
|
||||||
|
'AUD price mobi': u'9.95', 'No. in the Series': u'', 'CAD price PDF': u'9.95',
|
||||||
|
'CAD price mobi': u'9.95', 'DOI suffix': u'OBP.0001', 'USD price PDF': u'9.95',
|
||||||
|
'Book-page URL': u'http://www.openbookpublishers.com/product/3',
|
||||||
|
'Academic discipline (OBP)': u'History and Biography', 'EUR price paperback': u'19.95',
|
||||||
|
'License': u'CC BY-NC-ND', 'AUD price PDF': u'9.95', 'Contributor 3 surname': u'',
|
||||||
|
'AUD price hardback': u'54.95', 'ISBN 4': u'9781906924027epub', 'no of pages': u'440',
|
||||||
|
'ISBN 2': u'9781906924010', 'ISBN 3': u'9781906924027', 'ISBN 1': u'9781906924003',
|
||||||
|
'pages': u'xxi + 419', 'Contributor 4 surname': u'', 'USD price hardback': u'48.95',
|
||||||
|
'Full-text URL - HTML': u'http://www.openbookpublishers.com/htmlreader/978-1-906924-00-3/main.html',
|
||||||
|
'GBP price mobi': u'5.95', 'Format 1': u'Paperback ', 'EUR price PDF': u'7.95', 'Format 3': u'pdf',
|
||||||
|
'Format 2': u'Hardback', 'Format 5': u'mobi', 'Format 4': u'epub', 'MARC Code1': u'aut',
|
||||||
|
'MARC Code2': u'aui', 'MARC Code3': u'', 'MARC Code4': u'', 'MARC Code5': u'',
|
||||||
|
'MARC Code6': u'', 'ISO Language Code': u'en'}
|
||||||
]
|
]
|
||||||
|
|
||||||
results = load_from_books(TEST_BOOKS)
|
results = load_from_books(TEST_BOOKS)
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
{% block title %}{{ block.super }}Questionnaire{% endblock title %}
|
{% block title %}{{ block.super }}Questionnaire{% endblock title %}
|
||||||
{% block search_box %}
|
{% block search_box %}
|
||||||
{% render_with_landing '' %}
|
{% render_with_landing '' %}
|
||||||
<a href="{{landing_object.publishers.0.url}}"><img style="float:left;margin:10px" src="{{landing_object.publishers.0.logo_url}}" /></a>
|
<a href="{{landing_object.publishers.0.url}}"><img style="float:left;margin:10px" src="{{landing_object.publishers.0.logo_url}}" alt="{{landing_object.publishers.0.name}}" /></a>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block signin %}
|
{% block signin %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block extra_css %}
|
{% block extra_css %}
|
||||||
<link rel="stylesheet" href="/static/bootstrap/bootstrap.min.css" type="text/css" />
|
<link rel="stylesheet" href="/static/bootstrap/bootstrap.min.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="/static/questionnaire.css"></script>
|
<link rel="stylesheet" href="/static/questionnaire.css" />
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
{% block styleextra %}
|
{% block styleextra %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
<div class="js-topmenu" id="authenticated">
|
<div class="js-topmenu" id="authenticated">
|
||||||
<ul class="menu">
|
<ul class="menu">
|
||||||
<li>
|
<li>
|
||||||
<a class="notbutton" href="#"><span id="welcome">Hi, {{ user.username }} <i class="fa fa-chevron-down"> </span></i></a>
|
<a class="notbutton" href="#"><span id="welcome">Hi, {{ user.username }} <i class="fa fa-chevron-down"> </i></span></a>
|
||||||
</li>
|
</li>
|
||||||
<li>{% block avatar %}
|
<li>{% block avatar %}
|
||||||
<img class="user-avatar" src="{{ user.profile.avatar_url }}" height=36 width="36" alt="Avatar for {{ user.username }}" title="{{ user.username }}" />{% endblock %}
|
<img class="user-avatar" src="{{ user.profile.avatar_url }}" height=36 width="36" alt="Avatar for {{ user.username }}" title="{{ user.username }}" />{% endblock %}
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="js-topmenu">
|
<div class="js-topmenu">
|
||||||
<ul class="menu">
|
<ul class="menu">
|
||||||
<li><a class="notbutton" href="{% url 'superlogin' %}?next={% if request.GET.next %}{{ request.GET.next|urlencode }}{% else %}{{ request.get_full_path|urlencode}}{% endif %}" class="hijax"><span>Sign In</span></a></li>
|
<li><a class="notbutton hijax" href="{% url 'superlogin' %}?next={% if request.GET.next %}{{ request.GET.next|urlencode }}{% else %}{{ request.get_full_path|urlencode}}{% endif %}"><span>Sign In</span></a></li>
|
||||||
{% if not suppress_search_box %}
|
{% if not suppress_search_box %}
|
||||||
{% ifnotequal request.get_full_path "/accounts/register/" %}
|
{% ifnotequal request.get_full_path "/accounts/register/" %}
|
||||||
<li class="last"><a class="btn btn-signup" href="{% url 'registration_register' %}?next={% if request.GET.next %}{{ request.GET.next|urlencode }}{% else %}{{ request.get_full_path|urlencode}}{% endif %}">Sign Up <i class="fa fa-chevron-right"></i></a></li>
|
<li class="last"><a class="btn btn-signup" href="{% url 'registration_register' %}?next={% if request.GET.next %}{{ request.GET.next|urlencode }}{% else %}{{ request.get_full_path|urlencode}}{% endif %}">Sign Up <i class="fa fa-chevron-right"></i></a></li>
|
||||||
|
|
|
@ -391,7 +391,16 @@ Unglue.it signs agreements assuring the copyright status of every work we unglue
|
||||||
|
|
||||||
<dt>How can I claim a work for which I am the rights holder?</dt>
|
<dt>How can I claim a work for which I am the rights holder?</dt>
|
||||||
|
|
||||||
<dd>On every book page there is a More... tab. If you have a signed Platform Services Agreement on file, one of the options on the More... tab will be "Claim This Work". If you represent more than one rights holder, choose the correct one for this work and click "Claim".<br /><br />If you expect to see a "Claim" button and do not, either we do not have a PSA from you yet, or we have not yet verified and filed it. Please contact us at <a href="mailto:rights@gluejar.com">rights@gluejar.com</a>.</dd>
|
<dd>On every book page there is a More... tab. If you have a signed Platform Services Agreement on file, one of the options on the More... tab will be "Claim This Work". If you represent more than one rights holder, choose the correct one for this work and click "Claim".
|
||||||
|
<br /><br />If the book is not already in Unglue.it or in Google Books, you'll need to enter the metatadata for the book by hand or work with us to load the data from a spreadsheet or Onix file.
|
||||||
|
|
||||||
|
<ul class="bullets">
|
||||||
|
<li>Use <a href="{% url 'new_edition' '' '' %}">this form</a> to enter the metadata.</li>
|
||||||
|
<li>Your ebooks must have ISBNs or OCLC numbers assigned.</li>
|
||||||
|
<li>Your metadata should have title, authors, language, description.</li>
|
||||||
|
<li>If you have a lot of books to enter, <a href="{% url 'feedback' %}?page={{request.build_absolute_uri|urlencode:""}}">contact us</a> to load ONIX or CSV files for you.</li>
|
||||||
|
</ul>
|
||||||
|
<br /><br />If you expect to see a "Claim" button and do not, either we do not have a PSA from you yet, or we have not yet verified and filed it. Please contact us at <a href="mailto:rights@gluejar.com">rights@gluejar.com</a>.</dd>
|
||||||
|
|
||||||
<dt>Why should I claim my works?</dt>
|
<dt>Why should I claim my works?</dt>
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
{% if work.num_wishes %}
|
{% if work.num_wishes %}
|
||||||
<a href="{% if workid %}{% url 'work' workid %}{% else %}{% url 'googlebooks' googlebooks_id %}{% endif %}?tab=3" class="nobold"><span class="rounded"><span class="grey"><span class="">Faved by </span>{{ work.num_wishes }}</span></span></a>
|
<a href="{% if workid %}{% url 'work' workid %}{% else %}{% url 'googlebooks' googlebooks_id %}{% endif %}?tab=3" class="nobold"><span class="rounded"><span class="grey"><span class="">Faved by </span>{{ work.num_wishes }}</span></span></a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{% if workid %}{% url 'work' workid %}{% else %}{% url 'googlebooks' googlebooks_id %}{% endif %}?tab=3" class="nobold"><span class="rounded"><span class="grey"><span class="">No Faves</span></span></a>
|
<a href="{% if workid %}{% url 'work' workid %}{% else %}{% url 'googlebooks' googlebooks_id %}{% endif %}?tab=3" class="nobold"><span class="rounded"><span class="grey">No Faves</span></span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
|
@ -106,7 +106,7 @@ $j(document).ready(function() {
|
||||||
loader: '<img src="/static/images/loading.gif" alt="loading..." />',
|
loader: '<img src="/static/images/loading.gif" alt="loading..." />',
|
||||||
callback: function(p) {
|
callback: function(p) {
|
||||||
page += 1;
|
page += 1;
|
||||||
var url = "?q={{ q }}&gbo={{ gbo }}&page=" + page;
|
var url = "?q={{ q|urlencode }}&gbo={{ gbo }}&ty={{ ty }}&page=" + page;
|
||||||
$j.get(url, function(html) {
|
$j.get(url, function(html) {
|
||||||
var view = $j(".listview").length > 0 ? "list" : "panel";
|
var view = $j(".listview").length > 0 ? "list" : "panel";
|
||||||
var results = $j(html).find(".book");
|
var results = $j(html).find(".book");
|
||||||
|
@ -133,17 +133,17 @@ $j(document).ready(function() {
|
||||||
<div id="content-block">
|
<div id="content-block">
|
||||||
{% if campaign_works %}
|
{% if campaign_works %}
|
||||||
<div class="content-block-heading">
|
<div class="content-block-heading">
|
||||||
<h2 class="content-heading">These books are Free, or want to be!</span></h2>
|
<h2 class="content-heading">These books are Free, or want to be!</h2>
|
||||||
<ul class="book-list-view">
|
<ul class="book-list-view">
|
||||||
<li>View As:</li>
|
<li>View As:</li>
|
||||||
<li class="view-list">
|
<li class="view-list">
|
||||||
<a href="#" id="toggle-list">
|
<a href="#" id="toggle-list">
|
||||||
<img src="/static/images/booklist/view-list.png" align="view list" title="view list" height="21" width="24" alt="use list view" />
|
<img src="/static/images/booklist/view-list.png" title="view list" height="21" width="24" alt="use list view" />
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="view-list">
|
<li class="view-list">
|
||||||
<a href="#" id="toggle-panel">
|
<a href="#" id="toggle-panel">
|
||||||
<img src="/static/images/booklist/view-icon.png" align="view icon" title="view icon" height="22" width="22" alt="use panel view" />
|
<img src="/static/images/booklist/view-icon.png" title="view icon" height="22" width="22" alt="use panel view" />
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -167,7 +167,7 @@ $j(document).ready(function() {
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="content-block-heading">
|
<div class="content-block-heading">
|
||||||
|
|
||||||
<h2 class="content-heading"><a href="https://www.google.com/search?q={{q }}&tbm=bks">Google Books</a> search results</span></h2>
|
<h2 class="content-heading"><a href="https://www.google.com/search?q={{q|urlencode }}&tbm=bks">Google Books</a> search results</h2>
|
||||||
|
|
||||||
{% if not campaign_works %}
|
{% if not campaign_works %}
|
||||||
<ul class="book-list-view">
|
<ul class="book-list-view">
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
<dl>
|
<dl>
|
||||||
{% for landing in work.landings.all %}
|
{% for landing in work.landings.all %}
|
||||||
<dt>Configured survey: {{ landing }} </dt>
|
<dt>Configured survey: {{ landing }} </dt>
|
||||||
<dd>Link: {{ landing.url }}</dd>
|
<dd>Link: {{ landing.url }}<br />
|
||||||
|
Completed {{ landing.runinfohistory_set.all.count }} times</dd>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</dl>
|
</dl>
|
||||||
<a href="{% url 'new_survey' work.id %}">Set up a new survey</a> for this work.
|
<a href="{% url 'new_survey' work.id %}">Set up a new survey</a> for this work.
|
||||||
|
@ -32,5 +33,10 @@
|
||||||
<dd>To run a survey for a book, you need to be an unglue.it rights holder and claim the book</dd>
|
<dd>To run a survey for a book, you need to be an unglue.it rights holder and claim the book</dd>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</dl>
|
</dl>
|
||||||
|
<p>
|
||||||
<a href="{% url 'new_survey' '' %}">Set up a survey</a> using isbn.
|
<a href="{% url 'new_survey' '' %}">Set up a survey</a> using isbn.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Add "?next=https://example.com/any_url" to the end of a survey url to add a redirect on completion of the survey.
|
||||||
|
</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -96,9 +96,9 @@
|
||||||
<div>
|
<div>
|
||||||
<div class="pubinfo">
|
<div class="pubinfo">
|
||||||
<h3 class="book-author">
|
<h3 class="book-author">
|
||||||
<span itemprop="author">{{ work.relators.0.name }}</span>{% ifequal work.authors.count 2 %}
|
<span itemprop="author"><a href="{% url 'search' %}?q={{ work.relators.0.author.name|urlencode }}&ty=au" />{{ work.relators.0.name }}</a></span>{% ifequal work.authors.count 2 %}
|
||||||
and <span itemprop="author">{{ work.relators.1.name }}</span>
|
and <span itemprop="author"><a href="{% url 'search' %}?q={{ work.relators.1.author.name|urlencode }}&ty=au" />{{ work.relators.1.name }}</a></span>
|
||||||
{% endifequal %}{% if work.relators.count > 2 %}{% for author in work.relators %}{% if not forloop.first %}, <span itemprop="author">{{ author.name }}</span>{% endif %}{% endfor %}
|
{% endifequal %}{% if work.relators.count > 2 %}{% for author in work.relators %}{% if not forloop.first %}, <span itemprop="author"><a href="{% url 'search' %}?q={{ author.author.name|urlencode }}&ty=au" />{{ author.name }}</a></span>{% endif %}{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h3>
|
</h3>
|
||||||
<h3 class="book-year">
|
<h3 class="book-year">
|
||||||
|
|
|
@ -2218,14 +2218,21 @@ class ManageAccount(FormView):
|
||||||
|
|
||||||
def search(request):
|
def search(request):
|
||||||
q = request.GET.get('q', '')
|
q = request.GET.get('q', '')
|
||||||
|
ty = request.GET.get('ty', 'g') # ge= 'general, au= 'author'
|
||||||
request.session['q']=q
|
request.session['q']=q
|
||||||
|
try:
|
||||||
page = int(request.GET.get('page', 1))
|
page = int(request.GET.get('page', 1))
|
||||||
|
except ValueError:
|
||||||
|
# garbage in page
|
||||||
|
page = 1
|
||||||
gbo = request.GET.get('gbo', 'n') # gbo is flag for google books only
|
gbo = request.GET.get('gbo', 'n') # gbo is flag for google books only
|
||||||
our_stuff = Q(is_free=True) | Q(campaigns__isnull=False )
|
our_stuff = Q(is_free=True) | Q(campaigns__isnull=False )
|
||||||
if q != '' and page==1 and not gbo=='y':
|
if q != '' and page==1 and not gbo=='y':
|
||||||
isbnq = ISBN(q)
|
isbnq = ISBN(q)
|
||||||
if isbnq.valid:
|
if isbnq.valid:
|
||||||
work_query = Q(identifiers__value=str(isbnq), identifiers__type="isbn")
|
work_query = Q(identifiers__value=str(isbnq), identifiers__type="isbn")
|
||||||
|
elif ty=='au':
|
||||||
|
work_query = Q(editions__authors__name=q)
|
||||||
else:
|
else:
|
||||||
work_query = Q(title__icontains=q) | Q(editions__authors__name__icontains=q) | Q(subjects__name__iexact=q)
|
work_query = Q(title__icontains=q) | Q(editions__authors__name__icontains=q) | Q(subjects__name__iexact=q)
|
||||||
campaign_works = models.Work.objects.filter(our_stuff).filter(work_query).distinct()
|
campaign_works = models.Work.objects.filter(our_stuff).filter(work_query).distinct()
|
||||||
|
@ -2252,6 +2259,7 @@ def search(request):
|
||||||
context = {
|
context = {
|
||||||
"q": q,
|
"q": q,
|
||||||
"gbo": gbo,
|
"gbo": gbo,
|
||||||
|
"ty": ty,
|
||||||
"results": works,
|
"results": works,
|
||||||
"campaign_works": campaign_works
|
"campaign_works": campaign_works
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ from .. import add_type, question_proc, answer_proc, AnswerException
|
||||||
from ..utils import get_runid_from_request
|
from ..utils import get_runid_from_request
|
||||||
|
|
||||||
|
|
||||||
@question_proc('choice', 'choice-freeform', 'dropdown')
|
@question_proc('choice', 'choice-freeform', 'dropdown', 'choice-optional', 'choice-freeform-optional')
|
||||||
def question_choice(request, question):
|
def question_choice(request, question):
|
||||||
choices = []
|
choices = []
|
||||||
jstriggers = []
|
jstriggers = []
|
||||||
|
@ -27,22 +27,25 @@ def question_choice(request, question):
|
||||||
for choice in question.choices():
|
for choice in question.choices():
|
||||||
choices.append( ( choice.value == val, choice, ) )
|
choices.append( ( choice.value == val, choice, ) )
|
||||||
|
|
||||||
if question.type == 'choice-freeform':
|
if question.type in ( 'choice-freeform','choice-freeform-optional'):
|
||||||
jstriggers.append('%s_comment' % question.number)
|
jstriggers.append('%s_comment' % question.number)
|
||||||
|
template = question.type[:-9] if question.type.endswith('-optional') else question.type
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'choices' : choices,
|
'choices' : choices,
|
||||||
'sel_entry' : val == '_entry_',
|
'sel_entry' : val == '_entry_',
|
||||||
'qvalue' : val or '',
|
'qvalue' : val or '',
|
||||||
'required' : True,
|
"template" : "questionnaire/{}.html".format(template),
|
||||||
|
'required' : not question.type in ( 'choice-optional', 'choice-freeform-optional'),
|
||||||
'comment' : request.POST.get(key2, ""),
|
'comment' : request.POST.get(key2, ""),
|
||||||
'jstriggers': jstriggers,
|
'jstriggers': jstriggers,
|
||||||
}
|
}
|
||||||
|
|
||||||
@answer_proc('choice', 'choice-freeform', 'dropdown')
|
@answer_proc('choice', 'choice-freeform', 'dropdown', 'choice-optional', 'choice-freeform-optional')
|
||||||
def process_choice(question, answer):
|
def process_choice(question, answer):
|
||||||
opt = answer['ANSWER'] or ''
|
opt = answer['ANSWER'] or ''
|
||||||
if not opt:
|
if not opt and not question.type.endswith( '-optional'):
|
||||||
raise AnswerException(_(u'You must select an option'))
|
raise AnswerException(_(u'You must select an option'))
|
||||||
if opt == '_entry_' and question.type == 'choice-freeform':
|
if opt == '_entry_' and question.type == 'choice-freeform':
|
||||||
opt = answer.get('comment','')
|
opt = answer.get('comment','')
|
||||||
|
@ -51,11 +54,13 @@ def process_choice(question, answer):
|
||||||
return dumps([[opt]])
|
return dumps([[opt]])
|
||||||
else:
|
else:
|
||||||
valid = [c.value for c in question.choices()]
|
valid = [c.value for c in question.choices()]
|
||||||
if opt not in valid:
|
if opt and opt not in valid:
|
||||||
raise AnswerException(_(u'Invalid option!'))
|
raise AnswerException(_(u'Invalid option!'))
|
||||||
return dumps([opt])
|
return dumps([opt])
|
||||||
add_type('choice', 'Choice [radio]')
|
add_type('choice', 'Choice [radio]')
|
||||||
add_type('choice-freeform', 'Choice with a freeform option [radio]')
|
add_type('choice-freeform', 'Choice with a freeform option [radio]')
|
||||||
|
add_type('choice-optional', 'Optional choice [radio]')
|
||||||
|
add_type('choice-freeform-optional', 'Optional choice with a freeform option [radio]')
|
||||||
add_type('dropdown', 'Dropdown choice [select]')
|
add_type('dropdown', 'Dropdown choice [select]')
|
||||||
|
|
||||||
@question_proc('choice-multiple', 'choice-multiple-freeform', 'choice-multiple-values')
|
@question_proc('choice-multiple', 'choice-multiple-freeform', 'choice-multiple-values')
|
||||||
|
|
|
@ -8,7 +8,7 @@ from ..utils import get_runid_from_request
|
||||||
#true if either 'required' or if 'requiredif' is satisfied
|
#true if either 'required' or if 'requiredif' is satisfied
|
||||||
#def is_required
|
#def is_required
|
||||||
|
|
||||||
@question_proc('choice-yesno', 'choice-yesnocomment', 'choice-yesnodontknow')
|
@question_proc('choice-yesno', 'choice-yesnocomment', 'choice-yesnodontknow','choice-yesno-optional', 'choice-yesnocomment-optional', 'choice-yesnodontknow-optional')
|
||||||
def question_yesno(request, question):
|
def question_yesno(request, question):
|
||||||
key = "question_%s" % question.number
|
key = "question_%s" % question.number
|
||||||
key2 = "question_%s_comment" % question.number
|
key2 = "question_%s_comment" % question.number
|
||||||
|
@ -18,11 +18,11 @@ def question_yesno(request, question):
|
||||||
cd = question.getcheckdict()
|
cd = question.getcheckdict()
|
||||||
jstriggers = []
|
jstriggers = []
|
||||||
|
|
||||||
if qtype == 'choice-yesnocomment':
|
if qtype.startswith('choice-yesnocomment'):
|
||||||
hascomment = True
|
hascomment = True
|
||||||
else:
|
else:
|
||||||
hascomment = False
|
hascomment = False
|
||||||
if qtype == 'choice-yesnodontknow' or 'dontknow' in cd:
|
if qtype.startswith( 'choice-yesnodontknow') or 'dontknow' in cd:
|
||||||
hasdontknow = True
|
hasdontknow = True
|
||||||
else:
|
else:
|
||||||
hasdontknow = False
|
hasdontknow = False
|
||||||
|
@ -50,7 +50,7 @@ def question_yesno(request, question):
|
||||||
checks = ' checks="dep_check(\'%s,dontknow\')"' % question.number
|
checks = ' checks="dep_check(\'%s,dontknow\')"' % question.number
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'required': True,
|
'required': not qtype.endswith("-optional"),
|
||||||
'checks': checks,
|
'checks': checks,
|
||||||
'value': val,
|
'value': val,
|
||||||
'qvalue': val,
|
'qvalue': val,
|
||||||
|
@ -82,14 +82,14 @@ def question_open(request, question):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@answer_proc('open', 'open-textfield', 'choice-yesno', 'choice-yesnocomment', 'choice-yesnodontknow')
|
@answer_proc('open', 'open-textfield', 'choice-yesno', 'choice-yesnocomment', 'choice-yesnodontknow','choice-yesno-optional', 'choice-yesnocomment-optional', 'choice-yesnodontknow-optional')
|
||||||
def process_simple(question, ansdict):
|
def process_simple(question, ansdict):
|
||||||
# print 'process_simple has question, ansdict ', question, ',', ansdict
|
# print 'process_simple has question, ansdict ', question, ',', ansdict
|
||||||
checkdict = question.getcheckdict()
|
checkdict = question.getcheckdict()
|
||||||
ans = ansdict['ANSWER'] or ''
|
ans = ansdict['ANSWER'] or ''
|
||||||
qtype = question.get_type()
|
qtype = question.get_type()
|
||||||
if qtype.startswith('choice-yesno'):
|
if qtype.startswith('choice-yesno'):
|
||||||
if ans not in ('yes', 'no', 'dontknow'):
|
if ans not in ('yes', 'no', 'dontknow') and not qtype.endswith('-optional'):
|
||||||
raise AnswerException(_(u'You must select an option'))
|
raise AnswerException(_(u'You must select an option'))
|
||||||
if qtype == 'choice-yesnocomment' \
|
if qtype == 'choice-yesnocomment' \
|
||||||
and len(ansdict.get('comment', '').strip()) == 0:
|
and len(ansdict.get('comment', '').strip()) == 0:
|
||||||
|
@ -121,6 +121,9 @@ add_type('open-textfield', 'Open Answer, multi-line [textarea]')
|
||||||
add_type('choice-yesno', 'Yes/No Choice [radio]')
|
add_type('choice-yesno', 'Yes/No Choice [radio]')
|
||||||
add_type('choice-yesnocomment', 'Yes/No Choice with optional comment [radio, input]')
|
add_type('choice-yesnocomment', 'Yes/No Choice with optional comment [radio, input]')
|
||||||
add_type('choice-yesnodontknow', 'Yes/No/Don\'t know Choice [radio]')
|
add_type('choice-yesnodontknow', 'Yes/No/Don\'t know Choice [radio]')
|
||||||
|
add_type('choice-yesno-optional', 'Optional Yes/No Choice [radio]')
|
||||||
|
add_type('choice-yesnocomment-optional', 'Optional Yes/No Choice with optional comment [radio, input]')
|
||||||
|
add_type('choice-yesnodontknow-optional', 'Optional Yes/No/Don\'t know Choice [radio]')
|
||||||
|
|
||||||
|
|
||||||
@answer_proc('comment')
|
@answer_proc('comment')
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -22,14 +22,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.questionset-text p{
|
.questionset-text p{
|
||||||
font-size: 1.3em;
|
font-size: 1.2em;
|
||||||
line-height: 1.3em;
|
line-height: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.question-text {
|
.question-text {
|
||||||
font-size: 1.3em;
|
font-size: 1.2em;
|
||||||
line-height: 1.3em;
|
line-height: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.input {
|
div.input {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<title>{% block title %}Questionnaire{% endblock title %}</title>
|
<title>{% block title %}Questionnaire{% endblock title %}</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/static/bootstrap/bootstrap.min.css" type="text/css" />
|
<link rel="stylesheet" href="/static/bootstrap/bootstrap.min.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="/static/questionnaire.css"></script>
|
<link rel="stylesheet" href="/static/questionnaire.css" />
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
{% block styleextra %}
|
{% block styleextra %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<ul class="inputs-list">
|
<ul class="inputs-list list-unstyled">
|
||||||
{% for sel, choice in qdict.choices %}
|
{% for sel, choice in qdict.choices %}
|
||||||
<li>
|
<li>
|
||||||
<label>
|
<label>
|
||||||
|
@ -15,9 +15,11 @@
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<input onClick="valchanged('{{ question.number }}', '_entry_');" type="radio" id="{{ question.number }}_entry" name="question_{{ question.number }}" value="_entry_" {% if qdict.sel_entry %} checked {% endif %}>
|
<input onClick="valchanged('{{ question.number }}', '_entry_');" type="radio" id="{{ question.number }}_entry" name="question_{{ question.number }}" value="_entry_" {% if qdict.sel_entry %} checked {% endif %}>
|
||||||
{% if question.extra %}
|
{% if question.extra %}
|
||||||
<span class="extra-block">{{ question.extra }}</span>
|
<label for="{{ question.number }}_entry"><span class="extra-block">{{ question.extra }}</span></label>
|
||||||
|
{% else %}
|
||||||
|
<label for="{{ question.number }}_entry">{% trans "Other..." %}</label>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<input id="{{ question.number }}_comment" checks="dep_check('{{ question.number }},_entry_')" type="input" name="question_{{ question.number }}_comment" value="{{ qdict.comment }}">
|
<input id="{{ question.number }}_comment" checks="dep_check('{{ question.number }},_entry_')" type="text" name="question_{{ question.number }}_comment" id="{{ question.number }}_comment" value="{{ qdict.comment }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<ul class="inputs-list">
|
<ul class="inputs-list list-unstyled">
|
||||||
{% for choice, key, checked, prev_value in qdict.choices %}
|
{% for choice, key, checked, prev_value in qdict.choices %}
|
||||||
<li>
|
<li>
|
||||||
<!-- <label> -->
|
<label>
|
||||||
<span class="{{ qdict.type }}-text">
|
<span class="{{ qdict.type }}-text">
|
||||||
<input onClick="valchanged('{{ question.number }}_{{ choice.value }}', this.checked);" type="checkbox" id="{{ key }}" name="{{ key }}" value="{{ choice.value }}" {{ checked }}>
|
<input onClick="valchanged('{{ question.number }}_{{ choice.value }}', this.checked);" type="checkbox" id="{{ key }}" name="{{ key }}" value="{{ choice.value }}" {{ checked }}>
|
||||||
{{ choice.text }}
|
{{ choice.text }}
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
% <!-- percentage sign: all choice-multiple-values currently represent percentages and must add up to 100% -->
|
% <!-- percentage sign: all choice-multiple-values currently represent percentages and must add up to 100% -->
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!-- </label> -->
|
</label>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if qdict.type == 'choice-multiple-values' %}
|
{% if qdict.type == 'choice-multiple-values' %}
|
||||||
|
@ -29,7 +29,11 @@
|
||||||
|
|
||||||
{% if question.extra %}
|
{% if question.extra %}
|
||||||
<li>
|
<li>
|
||||||
<span class="extra-block">{{ question.extra }}</span>
|
<label for="{{ question.number }}extra"><span class="extra-block">{{ question.extra }}</span></label>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li>
|
||||||
|
<label for="{{ question.number }}extra">{% trans "Other..." %}</label>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if qdict.extras %}
|
{% if qdict.extras %}
|
||||||
|
@ -38,7 +42,7 @@
|
||||||
{% if not forloop.last or not forloop.first %}
|
{% if not forloop.last or not forloop.first %}
|
||||||
<b>{{ forloop.counter }}.</b>
|
<b>{{ forloop.counter }}.</b>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<input type="text" name="{{ key }}" size="50" value="{{ value }}">
|
<input type="text" id="{{ question.number }}extra{% if not forloop.first %}{{ forloop.counter }}{% endif %}" name="{{ key }}" size="50" value="{{ value }}">
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<ul class="inputs-list">
|
<ul class="inputs-list list-unstyled">
|
||||||
|
|
||||||
<!-- yes -->
|
<!-- yes -->
|
||||||
<li>
|
<li>
|
||||||
|
@ -31,12 +31,12 @@
|
||||||
|
|
||||||
<!-- comment -->
|
<!-- comment -->
|
||||||
{% if qdict.hascomment %}
|
{% if qdict.hascomment %}
|
||||||
<li>
|
<li><label>
|
||||||
{% if question.extra %}
|
{% if question.extra %}
|
||||||
<span class="extra-block">{{ question.extra }}</span><br />
|
<span class="extra-block">{{ question.extra }}</span><br />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<input type="text" id="{{ question.number }}_comment" name="question_{{ question.number }}_comment" value="{{ qdict.comment }}" size="50" {{ qdict.checks|safe }} placeholder="{% trans 'comment' %}">
|
<input type="text" id="{{ question.number }}_comment" name="question_{{ question.number }}_comment" value="{{ qdict.comment }}" size="50" {{ qdict.checks|safe }} placeholder="{% trans 'comment' %}">
|
||||||
</li>
|
</label></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<ul class="inputs-list">
|
<ul class="inputs-list list-unstyled">
|
||||||
{% for sel, choice in qdict.choices %}
|
{% for sel, choice in qdict.choices %}
|
||||||
<li>
|
<li>
|
||||||
<label>
|
<label>
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
{% extends "base-questionnaire.html" %}
|
{% extends "base-questionnaire.html" %}
|
||||||
{% block questionnaire %}
|
{% block questionnaire %}
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
Thanks for completing the survey!
|
Thanks for completing the survey!
|
||||||
</h2>
|
</h2>
|
||||||
<p>{{ landing_object.claim.all.0.rights_holder }}</p>
|
<div class="question-text">
|
||||||
|
{{ landing_object.claim.all.0.rights_holder }}
|
||||||
|
|
||||||
|
|
||||||
|
{% if request.COOKIES.next %}
|
||||||
|
<p>redirecting in 5 seconds...</p>
|
||||||
|
<script type="text/JavaScript">
|
||||||
|
setTimeout(function(){location.replace('/next/');}, 5000);
|
||||||
|
</script>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<div class="input">
|
<div class="input">
|
||||||
<textarea class="span8" name="question_{{ question.number }}" cols="60" rows="10">{{ qdict.value }}</textarea>
|
<textarea class="span8" name="question_{{ question.number }}" cols="60" rows="10" id={{ question.number }}>{{ qdict.value }}</textarea>
|
||||||
{% if question.extra %}
|
{% if question.extra %}
|
||||||
<span class="help-block">{{ question.extra }}</span>
|
<span class="help-block">{{ question.extra }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load dynamicStyleTags %}
|
{% load dynamicStyleTags %}
|
||||||
{% load landings %}
|
{% load landings %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Survey: {{ questionset.heading }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block headextra %}
|
{% block headextra %}
|
||||||
<script type="text/javascript" src="{% static 'jquery-1.7.1.min.js' %}"></script>
|
<script type="text/javascript" src="{% static 'jquery-1.7.1.min.js' %}"></script>
|
||||||
<script type="text/javascript" src="{% static 'questionset.js' %}"></script>
|
<script type="text/javascript" src="{% static 'questionset.js' %}"></script>
|
||||||
|
@ -12,7 +17,17 @@
|
||||||
{{ questionsetstylesheet|getAssociatedStylesheets|safe }}
|
{{ questionsetstylesheet|getAssociatedStylesheets|safe }}
|
||||||
</style>
|
</style>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if progress %}
|
||||||
|
{% if questionset.questionnaire.name|add:"Progress"|getAssociatedStylesheets %}
|
||||||
|
<style type="text/css">
|
||||||
|
{{ questionset.questionnaire.name|add:"Progress"|getAssociatedStylesheets|safe }}
|
||||||
|
</style>
|
||||||
|
{% else %}
|
||||||
|
<style type="text/css">
|
||||||
|
{{ "CommonProgressStyles"|getAssociatedStylesheets|safe }}
|
||||||
|
</style>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
{% for x in jsinclude %}
|
{% for x in jsinclude %}
|
||||||
<script type="text/javascript" src="{{ x }}"></script>
|
<script type="text/javascript" src="{{ x }}"></script>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -38,15 +53,6 @@
|
||||||
{% block questionnaire %}
|
{% block questionnaire %}
|
||||||
|
|
||||||
{% if progress %}
|
{% if progress %}
|
||||||
{% if questionset.questionnaire.name|add:"Progress"|getAssociatedStylesheets %}
|
|
||||||
<style type="text/css">
|
|
||||||
{{ questionset.questionnaire.name|add:"Progress"|getAssociatedStylesheets|safe }}
|
|
||||||
</style>
|
|
||||||
{% else %}
|
|
||||||
<style type="text/css">
|
|
||||||
{{ "CommonProgressStyles"|getAssociatedStylesheets|safe }}
|
|
||||||
</style>
|
|
||||||
{% endif %}
|
|
||||||
<div id="progress_bar" class="ui-progress-bar ui-container">
|
<div id="progress_bar" class="ui-progress-bar ui-container">
|
||||||
<div class="ui-progress" style="width: {{progress}}%;">
|
<div class="ui-progress" style="width: {{progress}}%;">
|
||||||
<span class="ui-label"><b class="value">{{progress}}%</b></span>
|
<span class="ui-label"><b class="value">{{progress}}%</b></span>
|
||||||
|
@ -108,12 +114,14 @@
|
||||||
{% include qdict.template %}
|
{% include qdict.template %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="question-text {% if qdict.required %}required{% endif %}">
|
<div class="question-text {% if qdict.required %}required{% endif %}">
|
||||||
|
<label for="{{ question.number }}">
|
||||||
<span class="qnumber">{{ question.display_number|safe }}.</span>
|
<span class="qnumber">{{ question.display_number|safe }}.</span>
|
||||||
{% if question.parse_html %}
|
{% if question.parse_html %}
|
||||||
{{ question.text|safe }}
|
{{ question.text|safe }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ question.text }}
|
{{ question.text }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="answer">
|
<div class="answer">
|
||||||
{% if error %}
|
{% if error %}
|
||||||
|
@ -139,7 +147,7 @@
|
||||||
|
|
||||||
|
|
||||||
<div style="text-align: center;" class="well questionset-submit">
|
<div style="text-align: center;" class="well questionset-submit">
|
||||||
<input class="btn large primary" name="submit" type="submit" value="{% trans "Continue" %}">
|
<input class="btn large primary" name="submit" type="submit" value="{% if questionset.next %}{% trans 'Continue' %}{% else %}{% trans 'Finish' %}{% endif %}" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -812,9 +812,9 @@ def _table_headers(questions):
|
||||||
ql.sort(lambda x, y: numal_sort(x.number, y.number))
|
ql.sort(lambda x, y: numal_sort(x.number, y.number))
|
||||||
columns = []
|
columns = []
|
||||||
for q in ql:
|
for q in ql:
|
||||||
if q.type == 'choice-yesnocomment':
|
if q.type.startswith('choice-yesnocomment'):
|
||||||
columns.extend([q.number, q.number + "-freeform"])
|
columns.extend([q.number, q.number + "-freeform"])
|
||||||
elif q.type == 'choice-freeform':
|
elif q.type.startswith('choice-freeform'):
|
||||||
columns.extend([q.number, q.number + "-freeform"])
|
columns.extend([q.number, q.number + "-freeform"])
|
||||||
elif q.type.startswith('choice-multiple'):
|
elif q.type.startswith('choice-multiple'):
|
||||||
cl = [c.value for c in q.choice_set.all()]
|
cl = [c.value for c in q.choice_set.all()]
|
||||||
|
@ -1063,7 +1063,9 @@ def generate_run(request, questionnaire_id, subject_id=None, context={}):
|
||||||
request.session['runcode'] = key
|
request.session['runcode'] = key
|
||||||
|
|
||||||
questionnaire_start.send(sender=None, runinfo=run, questionnaire=qu)
|
questionnaire_start.send(sender=None, runinfo=run, questionnaire=qu)
|
||||||
return HttpResponseRedirect(reverse('questionnaire', kwargs=kwargs))
|
response = HttpResponseRedirect(reverse('questionnaire', kwargs=kwargs))
|
||||||
|
response.set_cookie('next', context.get('next',''))
|
||||||
|
return response
|
||||||
|
|
||||||
def generate_error(request):
|
def generate_error(request):
|
||||||
return 400/0
|
return 400/0
|
||||||
|
@ -1077,6 +1079,8 @@ class SurveyView(TemplateView):
|
||||||
nonce = self.kwargs['nonce']
|
nonce = self.kwargs['nonce']
|
||||||
landing = get_object_or_404(Landing, nonce=nonce)
|
landing = get_object_or_404(Landing, nonce=nonce)
|
||||||
context["landing"] = landing
|
context["landing"] = landing
|
||||||
|
context["next"] = self.request.GET.get('next', '')
|
||||||
|
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ django-nose-selenium==0.7.3
|
||||||
#django-notification==0.2
|
#django-notification==0.2
|
||||||
git+git://github.com/eshellman/django-notification.git@8bb7afbbb07e8cad74bc1cf17e0ac6fc117c0497
|
git+git://github.com/eshellman/django-notification.git@8bb7afbbb07e8cad74bc1cf17e0ac6fc117c0497
|
||||||
django-registration==1.0
|
django-registration==1.0
|
||||||
django-selectable==0.7.0
|
django-selectable==0.9.0
|
||||||
django-smtp-ssl==1.0
|
django-smtp-ssl==1.0
|
||||||
django-storages==1.1.6
|
django-storages==1.1.6
|
||||||
django-tastypie==0.12.2
|
django-tastypie==0.12.2
|
||||||
|
|
|
@ -486,3 +486,7 @@ MOBIGEN_PASSWORD = "CXq5FSEQFgXtP_s"
|
||||||
|
|
||||||
QUESTIONNAIRE_USE_SESSION = False
|
QUESTIONNAIRE_USE_SESSION = False
|
||||||
QUESTIONNAIRE_DEBUG = True
|
QUESTIONNAIRE_DEBUG = True
|
||||||
|
|
||||||
|
# Selenium related -- set if Se tests run
|
||||||
|
FIREFOX_PATH = ''
|
||||||
|
CHROMEDRIVER_PATH = ''
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -42,6 +42,12 @@
|
||||||
color:@text-blue;
|
color:@text-blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h3.book-author span a, h3.book-year span a{
|
||||||
|
font-size: @font-size-default;
|
||||||
|
font-weight:normal;
|
||||||
|
color:@link-color;
|
||||||
|
}
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
width:100%;
|
width:100%;
|
||||||
clear:both;
|
clear:both;
|
||||||
|
|
|
@ -11,6 +11,7 @@ from urlparse import (urlparse, urlunparse)
|
||||||
from selenium import selenium, webdriver
|
from selenium import selenium, webdriver
|
||||||
from selenium.common.exceptions import NoSuchElementException
|
from selenium.common.exceptions import NoSuchElementException
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
|
||||||
|
|
||||||
"""
|
"""
|
||||||
django imports
|
django imports
|
||||||
|
@ -42,6 +43,21 @@ def set_test_logging():
|
||||||
sel.setLevel(logging.INFO)
|
sel.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
def selenium_driver(browser='firefox'):
|
||||||
|
|
||||||
|
if browser == 'firefox':
|
||||||
|
firefox_capabilities = DesiredCapabilities.FIREFOX
|
||||||
|
firefox_capabilities['marionette'] = True
|
||||||
|
firefox_capabilities['binary'] = settings.FIREFOX_PATH
|
||||||
|
driver = webdriver.Firefox(capabilities=firefox_capabilities)
|
||||||
|
elif browser == 'htmlunit':
|
||||||
|
# HTMLUNIT with JS -- not successful
|
||||||
|
driver = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabilities.HTMLUNITWITHJS)
|
||||||
|
else:
|
||||||
|
driver = webdriver.Chrome(executable_path=settings.CHROMEDRIVER_PATH)
|
||||||
|
|
||||||
|
return driver
|
||||||
|
|
||||||
|
|
||||||
class GoogleWebDriverTest(unittest.TestCase):
|
class GoogleWebDriverTest(unittest.TestCase):
|
||||||
|
|
||||||
|
@ -51,7 +67,7 @@ class GoogleWebDriverTest(unittest.TestCase):
|
||||||
# This is an empty array where we will store any verification errors
|
# This is an empty array where we will store any verification errors
|
||||||
# we find in our tests
|
# we find in our tests
|
||||||
|
|
||||||
self.selenium = webdriver.Firefox()
|
self.selenium = selenium_driver(browser='firefox')
|
||||||
set_test_logging()
|
set_test_logging()
|
||||||
|
|
||||||
def test_google_rc(self):
|
def test_google_rc(self):
|
||||||
|
@ -175,15 +191,7 @@ def test_relaunch(unglue_it_url = settings.LIVE_SERVER_TEST_URL, do_local=True,
|
||||||
# this assumes that we don't have donation functionality on
|
# this assumes that we don't have donation functionality on
|
||||||
assert settings.NONPROFIT.is_on == False
|
assert settings.NONPROFIT.is_on == False
|
||||||
|
|
||||||
if browser == 'firefox':
|
sel = selenium_driver(browser=browser)
|
||||||
sel = webdriver.Firefox()
|
|
||||||
elif browser == 'chrome':
|
|
||||||
sel = webdriver.Chrome(executable_path='/Users/raymondyee/C/src/Gluejar/regluit/test/chromedriver')
|
|
||||||
elif browser == 'htmlunit':
|
|
||||||
# HTMLUNIT with JS -- not successful
|
|
||||||
sel = webdriver.Remote("http://localhost:4444/wd/hub", webdriver.DesiredCapabilities.HTMLUNITWITHJS)
|
|
||||||
else:
|
|
||||||
sel = webdriver.Firefox()
|
|
||||||
|
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
|
@ -356,7 +364,7 @@ def successful_campaign_signal():
|
||||||
|
|
||||||
|
|
||||||
def berkeley_search():
|
def berkeley_search():
|
||||||
sel = webdriver.Firefox()
|
sel = selenium_driver(browser='firefox')
|
||||||
sel.get("http://berkeley.edu")
|
sel.get("http://berkeley.edu")
|
||||||
search = WebDriverWait(sel,5).until(lambda d: d.find_element_by_css_selector('input[id="search_text"]'))
|
search = WebDriverWait(sel,5).until(lambda d: d.find_element_by_css_selector('input[id="search_text"]'))
|
||||||
search.send_keys("quantum computing")
|
search.send_keys("quantum computing")
|
||||||
|
|
Loading…
Reference in New Issue