diff options
author | Madhusudan.C.S | 2010-04-01 11:59:35 +0530 |
---|---|---|
committer | Madhusudan.C.S | 2010-04-01 11:59:35 +0530 |
commit | f245bcffa2d4bd4efc6ab934db85eb76626ec599 (patch) | |
tree | 4c91dd755d542e7e0bc9e3154f93990410617e45 /project | |
parent | 93ab9caaffc346dfceb70648cd4bbaea7eb266ac (diff) | |
download | scipycon-f245bcffa2d4bd4efc6ab934db85eb76626ec599.tar.gz scipycon-f245bcffa2d4bd4efc6ab934db85eb76626ec599.tar.bz2 scipycon-f245bcffa2d4bd4efc6ab934db85eb76626ec599.zip |
Add admin interface and views for proceedings. Booklet is also setup to generate paper.
Diffstat (limited to 'project')
-rw-r--r-- | project/kiwipycon/proceedings/admin.py | 19 | ||||
-rw-r--r-- | project/kiwipycon/proceedings/booklet/__init__.py | 0 | ||||
-rw-r--r-- | project/kiwipycon/proceedings/booklet/mk_booklet.py | 94 | ||||
-rw-r--r-- | project/kiwipycon/proceedings/booklet/mk_scipy_paper.py | 463 | ||||
-rw-r--r-- | project/kiwipycon/proceedings/forms.py | 4 | ||||
-rw-r--r-- | project/kiwipycon/proceedings/views.py | 169 | ||||
-rw-r--r-- | project/kiwipycon/user/views.py | 40 | ||||
-rw-r--r-- | project/static/css/autosuggest_inquisitor.css | 208 | ||||
-rw-r--r-- | project/static/jquery/jquery.autosuggest.js | 17 | ||||
-rw-r--r-- | project/static/jquery/jquery.watermarkinput.js | 81 | ||||
-rw-r--r-- | project/templates/proceedings/submit.html | 51 | ||||
-rw-r--r-- | project/urls.py | 9 |
12 files changed, 1107 insertions, 48 deletions
diff --git a/project/kiwipycon/proceedings/admin.py b/project/kiwipycon/proceedings/admin.py new file mode 100644 index 0000000..830fcdb --- /dev/null +++ b/project/kiwipycon/proceedings/admin.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +from django.contrib import admin + +from project.kiwipycon.proceedings.models import Paper + + +class PaperAdmin(admin.ModelAdmin): + list_display = ('title', 'abstract') + list_filter = ('title', 'authors') + search_fields = ('title', 'abstract', 'authors') + fieldsets = ( + ('Details', { + 'fields': ('title', 'abstract', 'body', 'authors') + }), + ) + +admin.site.register(Paper, PaperAdmin) diff --git a/project/kiwipycon/proceedings/booklet/__init__.py b/project/kiwipycon/proceedings/booklet/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/project/kiwipycon/proceedings/booklet/__init__.py diff --git a/project/kiwipycon/proceedings/booklet/mk_booklet.py b/project/kiwipycon/proceedings/booklet/mk_booklet.py new file mode 100644 index 0000000..c27ddf7 --- /dev/null +++ b/project/kiwipycon/proceedings/booklet/mk_booklet.py @@ -0,0 +1,94 @@ +# encoding: utf-8 + +import os +import sys +import codecs +import re + +try: + from sanum import model +except: + root_dir = os.path.abspath(os.getcwd() + '/../../') + os.chdir(root_dir) + sys.path.append(root_dir) + from sanum import model + +import sanum + +import turbogears +turbogears.update_config(configfile="dev.cfg", + modulename="sanum.config") + + +from mk_scipy_paper import tex2pdf, current_dir , copy_files, preamble, \ + render_abstract, addfile, sourcedir, outdir, outfilename + + +def hack_include_graphics(latex_text, attach_dir): + """ Replaces all the \includegraphics call with call that impose the + width to be 0.9\linewidth. + """ + latex_text = re.sub(r'\\includegraphics(\[.*\])?\{', + r'\includegraphics\1{' + attach_dir, + latex_text) + return latex_text + + +class MyStringIO(object): + """ An unicode-friendly stringIO-like object. + """ + + def __init__(self): + self.lines = [] + + def write(self, line): + self.lines.append(line) + + def getvalue(self): + return u''.join(self.lines) + +def mk_booklet_tex(outfilename): + """ Generate the entire booklet latex file. + """ + outfile = codecs.open(outfilename, 'w', 'utf-8') + preamble(outfile) + copy_files() + #addfile(outfile, sourcedir + os.sep + 'title.tex') + addfile(outfile, sourcedir + os.sep + 'introduction.tex') + + #outfile.write(ur'\setcounter{page}{0}' + '\n') + + #from sanum.controllers import Root as Controller + abstracts = model.Abstract.select() + for abstract in abstracts: + if not abstract.approved: + continue + print abstract.title + # Hack: I don't use a stringIO, because it is not unicode-safe. + tmpout = MyStringIO() + # Hack: I don't wont to be bound to the controller, to be + # abstractle to run without cherrypy. + #attach_dir = Controller._paper_attach_dir(abstract.id) + attach_dir = os.path.abspath(os.sep.join( + (os.path.dirname(sanum.__file__), 'static', + 'papers', '%i' % abstract.id))) + os.sep + render_abstract(tmpout, abstract) + outstring = hack_include_graphics(tmpout.getvalue(), + attach_dir) + outfile.write(outstring) + #outfile.write(ur'\fillbreak' + '\n') + + outfile.write(ur'\end{document}' + '\n') + + + + +def mk_booklet(outfilename=outfilename): + """ Generate the entire booklet pdf file. + """ + name, ext = os.path.splitext(outfilename) + mk_booklet_tex(name + '.tex') + return tex2pdf(name, remove_tex=False, timeout=60) + +if __name__ == '__main__': + mk_booklet(outfilename) diff --git a/project/kiwipycon/proceedings/booklet/mk_scipy_paper.py b/project/kiwipycon/proceedings/booklet/mk_scipy_paper.py new file mode 100644 index 0000000..90e2fa4 --- /dev/null +++ b/project/kiwipycon/proceedings/booklet/mk_scipy_paper.py @@ -0,0 +1,463 @@ +# encoding: utf-8 + +import os +import re +import sys +import shutil +import codecs +from glob import glob + +from docutils import core as docCore + +conf_name = 'SciPy2009' + +current_dir = '/media/python/workspace/kiwipycon/project/kiwipycon/proceedings/booklet' + +outdir = current_dir + os.sep + 'output' + +sourcedir = current_dir + os.sep + 'sources' +try: + os.mkdir(outdir) +except: + pass + +outfilename = outdir + os.sep + 'booklet.tex' + +############################################################################## +# Routines for supervised execution +############################################################################## + +from threading import Thread +import os +import signal +from subprocess import Popen +from time import sleep + +def delayed_kill(pid, delay=10): + sleep(delay) + try: + os.kill(pid, signal.SIGTERM) + except OSError: + pass + +def supervise_popen(command, timeout=10): + process = Popen(command) + Thread(target=delayed_kill, args=(process.pid,timeout),).start() + + process.wait() + + + +############################################################################## +# LaTeX generation functions. +############################################################################## + +def protect(string): + r''' Protects all the "\" in a string by adding a second one before + + >>> protect(r'\foo \*') + '\\\\foo \\\\*' + ''' + return re.sub(r"\\", r"\\\\", string) + + +def safe_unlink(filename): + """ Remove a file from the disk only if it exists, if not r=fails silently + """ + if os.path.exists(filename): + os.unlink(filename) + +rxcountpages = re.compile(r"$\s*/Type\s*/Page[/\s]", re.MULTILINE|re.DOTALL) + +def count_pages(filename): + data = file(filename,"rb").read() + return len(rxcountpages.findall(data)) + + +def tex2pdf(filename, remove_tex=True, timeout=10, runs=2): + """ Compiles a TeX file with pdfLaTeX (or LaTeX, if or dvi ps requested) + and cleans up the mess afterwards + """ + current_dir = os.getcwd() + os.chdir(os.path.dirname(filename)) + print >> sys.stderr, "Compiling document to pdf" + basename = os.path.splitext(os.path.basename(filename))[0] + if os.path.exists(basename + '.pdf'): + os.unlink(basename + '.pdf') + for _ in range(runs): + supervise_popen(("pdflatex", "--interaction", "scrollmode", + os.path.basename(filename)), timeout=timeout) + error_file = None + errors = file(os.path.abspath(basename + '.log')).readlines()[-1] + if not os.path.exists(basename + '.pdf') or \ + "Fatal error" in errors: + error_file = os.path.abspath(basename + '.log') + if remove_tex: + safe_unlink(filename+".tex") + safe_unlink(filename+".log") + safe_unlink(filename+".aux") + safe_unlink(filename+".out") + os.chdir(current_dir) + return error_file + + +def rst2latex(rst_string, no_preamble=True, allow_latex=True): + """ Calls docutils' engine to convert a rst string to a LaTeX file. + """ + overrides = {'output_encoding': 'utf-8', 'initial_header_level': 3, + 'no_doc_title': True, 'use_latex_citations': True, + 'use_latex_footnotes':True} + if allow_latex: + rst_string = u'''.. role:: math(raw) + :format: latex + \n\n''' + rst_string + tex_string = docCore.publish_string( + source=rst_string, + writer_name='latex2e', + settings_overrides=overrides) + if no_preamble: + extract_document = \ + re.compile(r'.*\\begin\{document\}(.*)\\end\{document\}', + re.DOTALL) + matches = extract_document.match(tex_string) + tex_string = matches.groups()[0] + return tex_string + + +def get_latex_preamble(): + """ Retrieve the required preamble from docutils. + """ + full_document = rst2latex('\n', no_preamble=False) + preamble = re.split(r'\\begin\{document\}', full_document)[0] + ## Remove the documentclass. + preamble = r""" + %s + \makeatletter + \newcommand{\class@name}{gael} + \makeatother + \usepackage{ltxgrid} + %s + """ % ( + preamble.split('\n')[0], + '\n'.join(preamble.split('\n')[1:]), + ) + return preamble + + +############################################################################## +# Functions to generate part of the booklet +############################################################################## +def addfile(outfile, texfilename): + """ Includes the content of a tex file in our outfile. + """ + include = codecs.open(texfilename, 'r') + data = include.readlines() + outfile.write(ur'\thispagestyle{empty}' + u'\n') + outfile.writelines(data) + + +def preamble(outfile): + outfile.write(r''' + %s + \usepackage{abstracts} + \usepackage{ltxgrid} + \usepackage{amssymb,latexsym,amsmath,amsthm} + \usepackage{longtable} + \geometry{left=.8cm, textwidth=17cm, bindingoffset=0.6cm, + textheight=25.3cm, twoside} + \usepackage{hyperref} + \hypersetup{pdftitle={Proceedings of the 8th Annual Python in Science Conference}} + \begin{document} + + '''.encode('utf-8') % get_latex_preamble()) + + # XXX SciPy08 should not be hard coded, but to run out of the webapp + +def hack_include_graphics(latex_text): + """ Replaces all the \includegraphics call with call that impose the + width to be 0.9\linewidth. + """ + latex_text = re.sub(r'\\setlength\{\\rightmargin\}\{\\leftmargin\}', + r'\\setlength{\\leftmargin}{4ex}\\setlength{\\rightmargin}{0ex}', + latex_text) + latex_text = re.sub(r'\\begin\{quote\}\n\\begin\{itemize\}', + r'\\begin{itemize}', + latex_text) + latex_text = re.sub(r'\\end\{itemize\}\n\\end\{quote\}', + r'\\end{itemize}', + latex_text) + latex_text = re.sub(r'\\includegraphics(\[.*\])?\{', + r'\includegraphics[width=\linewidth]{', + latex_text) + latex_text = re.sub(r'\\href\{([^}]+)\}\{http://(([^{}]|(\{[^}]*\}))+)\}', + r'''% +% Break penalties to have URL break easily: +\mathchardef\UrlBreakPenalty=0 +\mathchardef\UrlBigBreakPenalty=0 +%\hskip 0pt plus 2em +\href{\1}{\url{\1}}''', + latex_text) + latex_text = re.sub(r'\\href\{([^}]+)\}\{https://(([^{}]|(\{[^}]*\}))+)\}', + r'''% +% Break penalties to have URL break easily: +\mathchardef\UrlBreakPenalty=0 +\mathchardef\UrlBigBreakPenalty=0 +\linebreak +\href{\1}{\url{\1}}''', + latex_text) + + return latex_text + + +def render_abstract(outfile, abstract, start_page=None): + """ Writes the LaTeX string corresponding to one abstract. + """ + if start_page is not None: + outfile.write(r""" +\setcounter{page}{%i} +""" % start_page) + else: + if hasattr(abstract, 'start_page'): + start_page = abstract.start_page + else: + start_page = 1 + if not abstract.authors: + author_list = abstract.owners + else: + author_list = abstract.authors + authors = [] + print dir(author_list[0]) + for author in author_list: + # If the author has no surname, he is not an author + if author.surname: + if author.email_address: + email = r'(\email{%s})' % author.email_address + else: + email = '' + authors.append(ur'''\otherauthors{ + %s %s + %s -- + \address{%s, %s} + }''' % (author.first_names, author.surname, + email, + author.institution, + author.city)) + if authors: + authors = u'\n'.join(authors) + authors += r'\addauthorstoc{%s}' % ', '.join( + '%s. %s' % (author.first_names[0], author.surname) + for author in author_list + ) + author_cite_list = ['%s. %s' % (a.first_names[0], a.surname) + for a in author_list] + if len(author_cite_list) > 4: + author_cite_list = author_cite_list[:3] + author_cite_list.append('et al.') + citation = ', '.join(author_cite_list) + \ + 'in Proc. SciPy 2009, G. Varoquaux, S. van der Walt, J. Millman (Eds), ' + copyright = '\\copyright 2009, %s' % ( ', '.join(author_cite_list)) + else: + authors = '' + citation = 'Citation' + copyright = 'Copyright' + if hasattr(abstract, 'num_pages'): + citation += 'pp. %i--%i' % (start_page, start_page + + abstract.num_pages) + else: + citation += 'p. %i'% start_page + if hasattr(abstract, 'number'): + abstract.url = 'http://conference.scipy.org/proceedings/%s/paper_%i' \ + % (conf_name, abstract.number) + url = r'\url{%s}' % abstract.url + else: + url = '' + paper_text = abstract.paper_text + if paper_text == '': + paper_text = abstract.summary + # XXX: It doesn't seem to be right to be doing this, but I get a + # nasty UnicodeDecodeError on some rare abstracts, elsewhere. + paper_text = codecs.utf_8_decode(hack_include_graphics( + rst2latex(paper_text)))[0] + paper_abstract = abstract.paper_abstract + if paper_abstract is None: + paper_abstract = '' + if not paper_abstract=='': + paper_abstract = ur'\begin{abstract}%s\end{abstract}' % \ + paper_abstract#.encode('utf-8') + abstract_dict = { + 'text': paper_text.encode('utf-8'), + 'abstract': paper_abstract.encode('utf-8'), + 'authors': authors.encode('utf-8'), + 'title': abstract.title.encode('utf-8'), + 'citation': citation.encode('utf-8'), + 'copyright': copyright.encode('utf-8'), + 'url': url.encode('utf-8'), + } + outfile.write(codecs.utf_8_decode(ur''' +\phantomsection +\hypertarget{chapter}{} +\vspace*{-2em} + +\resetheadings{%(title)s}{%(citation)s}{%(url)s}{%(copyright)s} +\title{%(title)s} + +\begin{minipage}{\linewidth} +%(authors)s +\end{minipage} + +\noindent\rule{\linewidth}{0.2ex} +\vspace*{-0.5ex} +\twocolumngrid +%(abstract)s + +\sloppy + +%(text)s + +\fussy +\onecolumngrid +\smallskip +\vfill +\filbreak +\clearpage + +'''.encode('utf-8') % abstract_dict )[0]) + +def copy_files(dest=outfilename): + """ Copy the required file from the source dir to the output dir. + """ + dirname = os.path.dirname(dest) + if dirname == '': + dirname = '.' + for filename in glob(sourcedir+os.sep+'*'): + destfile = os.path.abspath(dirname + os.sep + + os.path.basename(filename)) + shutil.copy2(filename, destfile) + + +def mk_abstract_preview(abstract, outfilename, attach_dir, start_page=None): + """ Generate a preview for an given paper. + """ + copy_files() + outdir = os.path.dirname(os.path.abspath(outfilename)) + for f in glob(os.path.join(attach_dir, '*')): + if os.path.isdir(f) and not os.path.exists(f): + os.makedirs(f) + else: + if not outdir == os.path.dirname(os.path.abspath(f)): + shutil.copy2(f, outdir) + for f in glob(os.path.join(sourcedir, '*')): + if os.path.isdir(f): + os.makedirs(f) + else: + destfile = os.path.abspath(os.path.join(outdir, f)) + shutil.copy2(f, outdir) + + outbasename = os.path.splitext(outfilename)[0] + outfilename = outbasename + '.tex' + + outfile = codecs.open(outfilename, 'w', 'utf-8') + preamble(outfile) + render_abstract(outfile, abstract, start_page=start_page) + outfile.write(ur'\end{document}' + u'\n') + outfile.close() + + tex2pdf(outbasename, remove_tex=False) + abstract.num_pages = count_pages(outbasename + '.pdf') + + # Generate the tex file again, now that we know the length. + outfile = codecs.open(outfilename, 'w', 'utf-8') + preamble(outfile) + render_abstract(outfile, abstract, start_page=start_page) + outfile.write(ur'\end{document}' + u'\n') + outfile.close() + + return tex2pdf(os.path.splitext(outfilename)[0], remove_tex=False) + + +############################################################################## +# Code for using outside of the webapp. +############################################################################## + +def mk_zipfile(): + """ Generates a zipfile with the required files to build an + abstract. + """ + from zipfile import ZipFile + zipfilename = os.path.join(os.path.dirname(__file__), + 'mk_scipy_paper.zip') + z = ZipFile(zipfilename, 'w') + for filename in glob(os.path.join(sourcedir, '*')): + if not os.path.isdir(filename): + z.write(filename, arcname='source/' + os.path.basename(filename)) + z.write(__file__, arcname='mk_scipy_paper.py') + return zipfilename + +class Bunch(dict): + def __init__(self, **kwargs): + dict.__init__(self, **kwargs) + self.__dict__ = self + + def __reprt(self): + return repr(self.__dict__) + +author_like = Bunch( + first_names='XX', + surname='XXX', + email_address='xxx@XXX', + institution='XXX', + address='XXX', + country='XXX' +) + + +abstract_like = Bunch( + paper_abstract='An abstract', + authors=[author_like, ], + title='', + ) + +if __name__ == '__main__': + from optparse import OptionParser + parser = OptionParser() + parser.add_option("-o", "--output", dest="outfilename", + default="./paper.pdf", + help="output to FILE", metavar="FILE") + parser.usage = """%prog [options] rst_file [data_file] + Compiles a given rest file and information file to pdf for the SciPy + proceedings. + """ + + (options, args) = parser.parse_args() + if not len(args) in (1, 2): + print "One or two arguments required: the input rest file and " \ + "the input data file" + print '' + parser.print_help() + sys.exit(1) + infile = args[0] + if len(args)==1: + data_file = 'data.py' + if os.path.exists('data.py'): + print "Using data file 'data.py'" + else: + print "Generating the data file and storing it in data.py" + print "You will need to edit this file to add title, author " \ + "information, and abstract." + abstract = abstract_like + file('data.py', 'w').write(repr(abstract)) + elif len(args)==2: + data_file = args[1] + + abstract = Bunch( **eval(file(data_file).read())) + abstract.authors = [Bunch(**a) for a in abstract.authors] + + abstract['summary'] = u'' + abstract['paper_text'] = file(infile).read().decode('utf-8') + + outfilename = options.outfilename + + mk_abstract_preview(abstract, options.outfilename, + os.path.dirname(options.outfilename)) + # Ugly, but I don't want to wait on the thread. + sys.exit() diff --git a/project/kiwipycon/proceedings/forms.py b/project/kiwipycon/proceedings/forms.py index df9d59b..ddff13c 100644 --- a/project/kiwipycon/proceedings/forms.py +++ b/project/kiwipycon/proceedings/forms.py @@ -26,5 +26,5 @@ class ProceedingsForm(forms.Form): "'Abstract' and other with a heading 'Body'.") authors = forms.CharField( - required=False, label=u'Author', - help_text=u'User ID of the author.') + required=False, label=u'Author(s)', + help_text=u'Comma separated list of User ID of the author(s).') diff --git a/project/kiwipycon/proceedings/views.py b/project/kiwipycon/proceedings/views.py index 3ebdd04..6a21691 100644 --- a/project/kiwipycon/proceedings/views.py +++ b/project/kiwipycon/proceedings/views.py @@ -1,20 +1,46 @@ -# -*- coding: utf-8 -*- + # -*- coding: utf-8 -*- + +import os from django.contrib.auth import login from django.contrib.auth.decorators import login_required from django.contrib.auth.forms import AuthenticationForm +from django.contrib.auth.models import User +from django.core.urlresolvers import reverse from django.shortcuts import render_to_response from django.template import RequestContext +from project.kiwipycon.proceedings.models import Paper from project.kiwipycon.user.forms import RegisterForm from project.kiwipycon.user.models import UserProfile +from project.kiwipycon.utils import set_message_cookie +from project.kiwipycon.proceedings.booklet import mk_scipy_paper from project.kiwipycon.proceedings.forms import ProceedingsForm +def handleUploadedFile(proceedings_form_data, rst_file): + """Handles the uploaded file content and process the form + """ + + title = proceedings_form_data.get('title') + abstract = proceedings_form_data.get('abstract') + body = proceedings_form_data.get('body') + authors = proceedings_form_data.get('authors') + + if rst_file: + destination = open('some/file/name.txt', 'wb+') + for chunk in rst_file.chunks(): + destination.write(chunk) + destination.close() + + return title, abstract, body, authors + + @login_required -def submit(request, template = 'proceedings/submit.html'): +def submit(request, id=None, template='proceedings/submit.html'): """View to submit the proceedings paper. """ + user = request.user if user.is_authenticated(): try: @@ -26,10 +52,7 @@ def submit(request, template = 'proceedings/submit.html'): message = None if request.method == 'POST': - proceedings_form = ProceedingsForm(data=request.POST) - - register_form = RegisterForm(data=request.POST, - files=request.FILES) + register_form = RegisterForm(data=request.POST) if request.POST.get('action', None) == 'login': login_form = AuthenticationForm(data=request.POST) @@ -47,28 +70,49 @@ def submit(request, template = 'proceedings/submit.html'): user = kiwipycon_createuser(request, register_form.data) + proceedings_form = ProceedingsForm(data=request.POST, + files=request.FILES) + if proceedings_form.is_valid(): if user.is_authenticated(): - title = proceedings_form.data.get('title') - - # Saved, ... redirect back to account - redirect_to = reverse('kiwipycon_account') - return set_message_cookie(redirect_to, - msg = u'Thanks, your paper has been submitted.') + # Data from reSt file is appended to the data in fields + title, abstract, body, authors = handleUploadedFile( + proceedings_form.cleaned_data, request.FILES.get('file')) + + paper = edit(id, title=title, + abstract=abstract, body=body, + authors=authors) if id else create(title=title, + abstract=abstract, body=body, + authors=authors) + + # Successfully saved. So get back to the edit page. + redirect_to = reverse('kiwipycon_submit_proceedings', + args=[paper.id]) + return set_message_cookie( + redirect_to, msg = u'Thanks, your paper has been submitted.') else: + # This is impossible. Something was wrong so return back + # to submit page redirect_to = reverse('kiwipycon_submit_proceedings') - return set_message_cookie(redirect_to, - msg = u'Something is wrong here.') - + return set_message_cookie( + redirect_to, msg = u'Something is wrong here.') else: - proceedings_form = ProceedingsForm() - register_form = RegisterForm() - login_form = AuthenticationForm() + if id: + # If id exists initialize the form with old values + paper = Paper.objects.get(id=id) + proceedings_form = ProceedingsForm( + initial={'title': paper.title, + 'abstract': paper.abstract, + 'body': paper.body, + 'authors': ', '.join([ + author.username for author in paper.authors.all()]) + }) + else: + # Otherwise create a new form + proceedings_form = ProceedingsForm() - - proceedings_form = ProceedingsForm() - register_form = RegisterForm() - login_form = AuthenticationForm() + register_form = RegisterForm() + login_form = AuthenticationForm() context = RequestContext(request, { 'proceedings_form': proceedings_form, @@ -77,18 +121,83 @@ def submit(request, template = 'proceedings/submit.html'): 'login_form' : login_form }) + context['id'] = id if id else None + return render_to_response(template, context) -def edit(request, id, template = 'proceedings/edit.html'): +def create(**kwargs): + """View to create a new proceedings. + """ + + title = kwargs.get('title') + abstract = kwargs.get('abstract') + body = kwargs.get('body') + authors = kwargs.get('authors') + + paper = Paper(title=title, abstract=abstract, body=body) + paper.save() + + if authors: + authors = authors.split(',') + for author in authors: + user = User.objects.get(username=author.strip()) + paper.authors.add(user) + + return paper + + +def edit(id, **kwargs): """View to edit the proceedings paper. """ - context = RequestContext(request, { - 'proceedings_form': proceedings_form, - 'register_form' : register_form, - 'message' : message, - 'login_form' : login_form - }) + paper = Paper.objects.get(id=id) - return render_to_response(template, context) + paper.title = kwargs.get('title') + paper.abstract = kwargs.get('abstract') + paper.body = kwargs.get('body') + authors = kwargs.get('authors') + + if authors: + authors = authors.split(',') + for author in authors: + user = User.objects.get(username=author.strip()) + paper.authors.add(user) + + paper.save() + + return paper + + +def show_paper(request, id): + """Display the thumbnail of the rendered paper for download + """ + + paper = Paper.objects.get(id=id) + + paper_data = { + 'paper_abstract': paper.abstract, + 'authors': [ + {'first_names': author.first_name, + 'surname': author.last_name, + 'address': 'XXX', + 'country': 'XXX', + 'email_address': 'XXX@xx.com', + 'institution': 'XXX' + } for author in paper.authors.all()], + 'title': paper.title + } + + abstract = mk_scipy_paper.Bunch(**paper_data) + abstract.authors = [mk_scipy_paper.Bunch(**a) for a in abstract.authors] + + abstract['paper_text'] = paper.body + + outfilename = '/media/python/workspace/kiwipycon/project/kiwipycon/proceedings/booklet/output/paper.pdf' + attach_dir = os.path.dirname('/media/python/workspace/kiwipycon/project/kiwipycon/proceedings/booklet/output/') + mk_scipy_paper.mk_abstract_preview(abstract, outfilename, attach_dir) + + from django.http import HttpResponse + return HttpResponse('Machi') + +
\ No newline at end of file diff --git a/project/kiwipycon/user/views.py b/project/kiwipycon/user/views.py index e9a0454..8b890c1 100644 --- a/project/kiwipycon/user/views.py +++ b/project/kiwipycon/user/views.py @@ -1,12 +1,16 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import + #python from urlparse import urlparse +import json import urllib import os #django from django.conf import settings +from django.db.models import Q +from django.http import HttpResponse from django.shortcuts import render_to_response from django.template import RequestContext from django.core.urlresolvers import reverse @@ -16,6 +20,7 @@ from django.db.models.signals import post_save from django.contrib.auth.decorators import login_required from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import PasswordChangeForm +from django.contrib.auth.models import User from django.core.exceptions import ObjectDoesNotExist #PIL @@ -236,3 +241,38 @@ def username(request, template_name="user/username.html"): "form": username_form })) + +def get_usernames(request): + """Returns in json the list of ten possible usernames + starting with the last pattern in the comma separated string + """ + + get_params = request.GET + authors_str = get_params.get('input') + + if not authors_str: + return HttpResponse(json.dumps('')) + + authors = authors_str.split(',') + search_author = authors[-1].strip() + + users = User.objects.filter( + Q(username__istartswith=search_author) | Q( + first_name__istartswith=search_author) | Q( + last_name__istartswith=search_author)) + + results = [{'id': '', + 'info': 'plugin_header', + 'value': 'User Names' + }] + + for user in users: + results.append( + {'id': 'author_name', + 'info': str(user.get_full_name()), + 'value': str(user.username) + }) + + json_response = {'results': results} + + return HttpResponse(json.dumps(json_response))
\ No newline at end of file diff --git a/project/static/css/autosuggest_inquisitor.css b/project/static/css/autosuggest_inquisitor.css new file mode 100644 index 0000000..ae9d6e1 --- /dev/null +++ b/project/static/css/autosuggest_inquisitor.css @@ -0,0 +1,208 @@ +/*
+================================================
+autosuggest, inquisitor style
+================================================
+*/
+
+div.autosuggest
+{
+ position: absolute;
+ background-position: top;
+ background-repeat: no-repeat;
+ padding: 0px 0 0 0;
+}
+
+/* IEXX compatinility */
+* html div.autosuggest {
+ padding-top:1px;
+}
+
+/* Only IE7 compatibility */
+*+html div.autosuggest {
+ margin-top:12px;
+ padding:0px;
+}
+
+div.autosuggest div.as_header
+{
+ margin-top:5px;
+ position: relative;
+ height: 3px;
+ padding: 1px 0 0 0 ;
+ border-top:1px solid #95a5c6;
+ border-left:1px solid #95a5c6;
+ border-right:1px solid #95a5c6;
+ background-color:#ffffff;
+ background-position: top right;
+ background-repeat: no-repeat;
+ overflow: hidden;
+}
+div.autosuggest div.as_footer
+{
+ position: relative;
+ height: 3px;
+ padding: 1px 0 0 0 ;
+ border-bottom:1px solid #95a5c6;
+ border-left:1px solid #95a5c6;
+ border-right:1px solid #95a5c6;
+ background-color:#ffffff;
+ background-position: top right;
+ background-repeat: no-repeat;
+ overflow: hidden;
+}
+/* Only IE7 compatibility */
+*+html div.autosuggest div.as_header { margin-top:0px; }
+* html div.autosuggest div.as_header { margin-top:5px; }
+
+div.autosuggest div.as_footer
+{
+ /* border-bottom:1px solid #95a5c6; */
+}
+
+div.autosuggest div.as_header div.as_corner,
+div.autosuggest div.as_footer div.as_corner
+{
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+div.autosuggest div.as_footer div.as_corner
+{
+
+}
+div.autosuggest div.as_header div.as_bar,
+div.autosuggest div.as_footer div.as_bar
+{
+ height: 0px;
+ overflow: hidden;
+ background-color: #ffffff;
+}
+
+
+div.autosuggest ul
+{
+ list-style: none;
+ margin: 0 0 -4px 0;
+ padding: 0;
+ overflow: hidden;
+ background-color: #ffffff;
+ border-left:1px solid #95a5c6;
+ border-right:1px solid #95a5c6;
+}
+
+div.autosuggest ul li
+{
+ color: #5776ae;
+ padding: 0;
+ margin: 0 4px 4px;
+ text-align: left;
+}
+
+div.autosuggest ul li a
+{
+ color: #000000;
+ display: block;
+ text-decoration: none;
+ background-color: transparent;
+ text-shadow: #000 0px 0px 5px;
+ position: relative;
+ padding: 0;
+ width: 100%;
+}
+div.autosuggest ul li a:hover
+{
+ background-color: #3b5998;
+ text-decoration:none;
+}
+div.autosuggest ul li.as_highlight a:hover
+{
+ background-color: #3b5998;
+ text-decoration:none;
+}
+
+div.autosuggest ul li a span
+{
+ display: block;
+ padding: 3px 6px;
+ font-weight: normal;
+}
+
+div.autosuggest ul li a span small
+{
+ font-weight: normal;
+ color: #999;
+}
+
+div.autosuggest ul li.as_highlight a span small
+{
+ color: #ccc;
+}
+
+div.autosuggest ul li.as_highlight a
+{
+ color: #fff;
+ background-color: #3b5998;
+ background-position: bottom right;
+ background-repeat: no-repeat;
+ text-decoration:none;
+}
+
+div.autosuggest ul li.as_highlight a span
+{
+ background-position: bottom left;
+ background-repeat: no-repeat;
+}
+
+div.autosuggest ul li a .tl,
+div.autosuggest ul li a .tr
+{
+ background-image: transparent;
+ background-repeat: no-repeat;
+ width: 6px;
+ height: 6px;
+ position: absolute;
+ top: 0;
+ padding: 0;
+ margin: 0;
+}
+div.autosuggest ul li a .tr
+{
+ right: 0;
+}
+
+div.autosuggest ul li.as_highlight a .tl
+{
+ left: 0;
+ background-position: bottom left;
+}
+
+div.autosuggest ul li.as_highlight a .tr
+{
+ right: 0;
+ background-position: bottom right;
+}
+
+div.autosuggest ul li.as_warning
+{
+ font-weight: bold;
+ text-align: center;
+}
+
+div.autosuggest ul li.as_header
+{
+ font-weight: bold;
+ font-size:14px;
+ color:#FFFFFF;
+ background:#999;
+ padding-left:6px;
+ padding-top:2px;
+ padding-bottom:2px;
+}
+
+div.autosuggest ul em
+{
+ font-style: normal;
+ font-weight:bold;
+ color: #000000;
+ background-color:#d8dfea;
+}
\ No newline at end of file diff --git a/project/static/jquery/jquery.autosuggest.js b/project/static/jquery/jquery.autosuggest.js new file mode 100644 index 0000000..a96cffe --- /dev/null +++ b/project/static/jquery/jquery.autosuggest.js @@ -0,0 +1,17 @@ +<!-- Init AutoSuggest -->
+/** AutoSuggest Packed JS **/
+if(typeof(bsn)=="undefined")_b=bsn={};if(typeof(_b.Autosuggest)=="undefined")_b.Autosuggest={};else alert("Autosuggest is already set!");_b.AutoSuggest=function(id,param){if(!document.getElementById)return 0;this.fld=_b.DOM.gE(id);if(!this.fld)return 0;this.sInp="";this.nInpC=0;this.aSug=[];this.iHigh=0;this.oP=param?param:{};var k,def={minchars:1,meth:"get",varname:"input",className:"autosuggest",timeout:2500,delay:500,offsety:-5,shownoresults:true,noresults:"No results!",maxheight:250,cache:true,maxentries:25};for(k in def){if(typeof(this.oP[k])!=typeof(def[k]))this.oP[k]=def[k]}var p=this;this.fld.onkeypress=function(ev){return p.onKeyPress(ev)};this.fld.onkeyup=function(ev){return p.onKeyUp(ev)};this.fld.setAttribute("autocomplete","off")};_b.AutoSuggest.prototype.onKeyPress=function(ev){var key=(window.event)?window.event.keyCode:ev.keyCode;var RETURN=13;var TAB=9;var ESC=27;var bubble=1;switch(key){case RETURN:this.setHighlightedValue();bubble=0;break;case ESC:this.clearSuggestions();break}return bubble};_b.AutoSuggest.prototype.onKeyUp=function(ev){var key=(window.event)?window.event.keyCode:ev.keyCode;var ARRUP=38;var ARRDN=40;var bubble=1;switch(key){case ARRUP:this.changeHighlight(key);bubble=0;break;case ARRDN:this.changeHighlight(key);bubble=0;break;default:this.getSuggestions(this.fld.value)}return bubble};_b.AutoSuggest.prototype.getSuggestions=function(val){if(val==this.sInp)return 0;_b.DOM.remE(this.idAs);this.sInp=val;if(val.length<this.oP.minchars){this.aSug=[];this.nInpC=val.length;return 0}var ol=this.nInpC;this.nInpC=val.length?val.length:0;var l=this.aSug.length;if(this.nInpC>ol&&l&&l<this.oP.maxentries&&this.oP.cache){var arr=[];for(var i=0;i<l;i++){if(this.aSug[i].value.substr(0,val.length).toLowerCase()==val.toLowerCase()||this.aSug[i].info=='as_header')arr.push(this.aSug[i])}this.aSug=arr;this.createList(this.aSug);return false}else{var pointer=this;var input=this.sInp;clearTimeout(this.ajID);this.ajID=setTimeout(function(){pointer.doAjaxRequest(input)},this.oP.delay)}return false};_b.AutoSuggest.prototype.doAjaxRequest=function(input){if(input!=this.fld.value)return false;var pointer=this;if(typeof(this.oP.script)=="function")var url=this.oP.script(encodeURIComponent(this.sInp));else var url=this.oP.script+this.oP.varname+"="+encodeURIComponent(this.sInp);if(!url)return false;var meth=this.oP.meth;var input=this.sInp;var onSuccessFunc=function(req){pointer.setSuggestions(req,input)};var onErrorFunc=function(status){alert("AJAX error: "+status)};var myAjax=new _b.Ajax();myAjax.makeRequest(url,meth,onSuccessFunc,onErrorFunc)};_b.AutoSuggest.prototype.setSuggestions=function(req,input){if(input!=this.fld.value)return false;this.aSug=[];if(this.oP.json){var jsondata=eval('('+req.responseText+')');for(var i=0;i<jsondata.results.length;i++){this.aSug.push({'id':jsondata.results[i].id,'value':jsondata.results[i].value,'info':jsondata.results[i].info})}}else{var xml=req.responseXML;var results=xml.getElementsByTagName('results')[0].childNodes;for(var i=0;i<results.length;i++){if(results[i].hasChildNodes())this.aSug.push({'id':results[i].getAttribute('id'),'value':results[i].childNodes[0].nodeValue,'info':results[i].getAttribute('info')})}}this.idAs="as_"+this.fld.id;this.createList(this.aSug)};_b.AutoSuggest.prototype.createList=function(arr){var pointer=this;_b.DOM.remE(this.idAs);this.killTimeout();if(arr.length==0&&!this.oP.shownoresults)return false;var div=_b.DOM.cE("div",{id:this.idAs,className:this.oP.className});var hcorner=_b.DOM.cE("div",{className:"as_corner"});var hbar=_b.DOM.cE("div",{className:"as_bar"});var header=_b.DOM.cE("div",{className:"as_header"});header.appendChild(hcorner);header.appendChild(hbar);div.appendChild(header);var ul=_b.DOM.cE("ul",{id:"as_ul"});for(var i=0;i<arr.length;i++){if(arr[i].info=="plugin_header"){var li=_b.DOM.cE("li",{className:"as_header"},arr[i].value);ul.appendChild(li);i++}var val=arr[i].value;var st=val.toLowerCase().indexOf(this.sInp.toLowerCase());var output=val.substring(0,st)+"<em>"+val.substring(st,st+this.sInp.length)+"</em>"+val.substring(st+this.sInp.length);var span=_b.DOM.cE("span",{},output,true);if(arr[i].info!=""){var br=_b.DOM.cE("br",{});span.appendChild(br);var small=_b.DOM.cE("small",{},arr[i].info);span.appendChild(small)}var a=_b.DOM.cE("a",{href:"#"});var tl=_b.DOM.cE("span",{className:"tl"}," ");var tr=_b.DOM.cE("span",{className:"tr"}," ");a.appendChild(tl);a.appendChild(tr);a.appendChild(span);a.name=i+1;a.onclick=function(){pointer.setHighlightedValue();return false};a.onmouseover=function(){pointer.setHighlight(this.name)};var li=_b.DOM.cE("li",{},a);ul.appendChild(li)}if(arr.length==0&&this.oP.shownoresults){var li=_b.DOM.cE("li",{className:"as_warning"},this.oP.noresults);ul.appendChild(li)}div.appendChild(ul);var fcorner=_b.DOM.cE("div",{className:"as_corner"});var fbar=_b.DOM.cE("div",{className:"as_bar"});var footer=_b.DOM.cE("div",{className:"as_footer"});footer.appendChild(fcorner);footer.appendChild(fbar);div.appendChild(footer);var pos=_b.DOM.getPos(this.fld);div.style.left=pos.x+"px";div.style.top=(pos.y+this.fld.offsetHeight+this.oP.offsety)+"px";div.style.width=this.fld.offsetWidth+"px";div.onmouseover=function(){pointer.killTimeout()};div.onmouseout=function(){pointer.resetTimeout()};document.getElementsByTagName("body")[0].appendChild(div);this.iHigh=0;var pointer=this;this.toID=setTimeout(function(){pointer.clearSuggestions()},this.oP.timeout)};_b.AutoSuggest.prototype.changeHighlight=function(key){var list=_b.DOM.gE("as_ul");if(!list)return false;var n;if(key==40)n=this.iHigh+1;else if(key==38)n=this.iHigh-1;if(n>list.childNodes.length)n=list.childNodes.length;if(n<1)n=1;this.setHighlight(n)};_b.AutoSuggest.prototype.setHighlight=function(n){var list=_b.DOM.gE("as_ul");if(!list)return false;if(this.iHigh>0)this.clearHighlight();this.iHigh=Number(n);if(list.childNodes[this.iHigh-1].className!="as_header")list.childNodes[this.iHigh-1].className="as_highlight";this.killTimeout()};_b.AutoSuggest.prototype.clearHighlight=function(){var list=_b.DOM.gE("as_ul");if(!list)return false;if(this.iHigh>0){if(list.childNodes[this.iHigh-1].className!="as_header")list.childNodes[this.iHigh-1].className="";this.iHigh=0}};
+_b.AutoSuggest.prototype.setHighlightedValue=function(){
+ var value = this.fld.value;
+ var new_val = value.split(', ');
+ if(this.iHigh){
+ this.sInp=this.fld.value=this.aSug[this.iHigh-1].value;
+ this.fld.focus();
+ if(this.fld.selectionStart)
+ this.fld.setSelectionRange(this.sInp.length,this.sInp.length);
+ this.clearSuggestions();
+ if(typeof(this.oP.callback)=="function")
+ this.oP.callback(this.aSug[this.iHigh-1])
+ }
+ };
+_b.AutoSuggest.prototype.killTimeout=function(){clearTimeout(this.toID)};_b.AutoSuggest.prototype.resetTimeout=function(){clearTimeout(this.toID);var pointer=this;this.toID=setTimeout(function(){pointer.clearSuggestions()},1000)};_b.AutoSuggest.prototype.clearSuggestions=function(){this.killTimeout();var ele=_b.DOM.gE(this.idAs);var pointer=this;if(ele){var fade=new _b.Fader(ele,1,0,250,function(){_b.DOM.remE(pointer.idAs)})}};if(typeof(_b.Ajax)=="undefined")_b.Ajax={};_b.Ajax=function(){this.req={};this.isIE=false};_b.Ajax.prototype.makeRequest=function(url,meth,onComp,onErr){if(meth!="POST")meth="GET";this.onComplete=onComp;this.onError=onErr;var pointer=this;if(window.XMLHttpRequest){this.req=new XMLHttpRequest();this.req.onreadystatechange=function(){pointer.processReqChange()};this.req.open("GET",url,true);this.req.send(null)}else if(window.ActiveXObject){this.req=new ActiveXObject("Microsoft.XMLHTTP");if(this.req){this.req.onreadystatechange=function(){pointer.processReqChange()};this.req.open(meth,url,true);this.req.send()}}};_b.Ajax.prototype.processReqChange=function(){if(this.req.readyState==4){if(this.req.status==200){this.onComplete(this.req)}else{this.onError(this.req.status)}}};if(typeof(_b.DOM)=="undefined")_b.DOM={};_b.DOM.cE=function(type,attr,cont,html){var ne=document.createElement(type);if(!ne)return 0;for(var a in attr)ne[a]=attr[a];var t=typeof(cont);if(t=="string"&&!html)ne.appendChild(document.createTextNode(cont));else if(t=="string"&&html)ne.innerHTML=cont;else if(t=="object")ne.appendChild(cont);return ne};_b.DOM.gE=function(e){var t=typeof(e);if(t=="undefined")return 0;else if(t=="string"){var re=document.getElementById(e);if(!re)return 0;else if(typeof(re.appendChild)!="undefined")return re;else return 0}else if(typeof(e.appendChild)!="undefined")return e;else return 0};_b.DOM.remE=function(ele){var e=this.gE(ele);if(!e)return 0;else if(e.parentNode.removeChild(e))return true;else return 0};_b.DOM.getPos=function(e){var e=this.gE(e);var obj=e;var curleft=0;if(obj.offsetParent){while(obj.offsetParent){curleft+=obj.offsetLeft;obj=obj.offsetParent}}else if(obj.x)curleft+=obj.x;var obj=e;var curtop=0;if(obj.offsetParent){while(obj.offsetParent){curtop+=obj.offsetTop;obj=obj.offsetParent}}else if(obj.y)curtop+=obj.y;return{x:curleft,y:curtop}};if(typeof(_b.Fader)=="undefined")_b.Fader={};_b.Fader=function(ele,from,to,fadetime,callback){if(!ele)return 0;this.e=ele;this.from=from;this.to=to;this.cb=callback;this.nDur=fadetime;this.nInt=50;this.nTime=0;var p=this;this.nID=setInterval(function(){p._fade()},this.nInt)};_b.Fader.prototype._fade=function(){this.nTime+=this.nInt;var ieop=Math.round(this._tween(this.nTime,this.from,this.to,this.nDur)*100);var op=ieop/100;if(this.e.filters){try{this.e.filters.item("DXImageTransform.Microsoft.Alpha").opacity=ieop}catch(e){this.e.style.filter='progid:DXImageTransform.Microsoft.Alpha(opacity='+ieop+')'}}else{this.e.style.opacity=op}if(this.nTime==this.nDur){clearInterval(this.nID);if(this.cb!=undefined)this.cb()}};_b.Fader.prototype._tween=function(t,b,c,d){return b+((c-b)*(t/d))};
diff --git a/project/static/jquery/jquery.watermarkinput.js b/project/static/jquery/jquery.watermarkinput.js new file mode 100644 index 0000000..f14ec24 --- /dev/null +++ b/project/static/jquery/jquery.watermarkinput.js @@ -0,0 +1,81 @@ +/*
+ * Copyright (c) 2007 Josh Bush (digitalbush.com)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Version: Beta 1
+ * Release: 2007-06-01
+ */
+(function($) {
+ var map=new Array();
+ $.Watermark = {
+ ShowAll:function(){
+ for (var i=0;i<map.length;i++){
+ if(map[i].obj.val()==""){
+ map[i].obj.val(map[i].text);
+ map[i].obj.css("color",map[i].WatermarkColor);
+ }else{
+ map[i].obj.css("color",map[i].DefaultColor);
+ }
+ }
+ },
+ HideAll:function(){
+ for (var i=0;i<map.length;i++){
+ if(map[i].obj.val()==map[i].text)
+ map[i].obj.val("");
+ }
+ }
+ };
+
+ $.fn.Watermark = function(text,color) {
+ if(!color)
+ color="#cccccc";
+ return this.each(
+ function(){
+ var input=$(this);
+ var defaultColor=input.css("color");
+ map[map.length]={text:text,obj:input,DefaultColor:defaultColor,WatermarkColor:color};
+ function clearMessage(){
+ if(input.val()==text)
+ input.val("");
+ input.css("color",defaultColor);
+ }
+
+ function insertMessage(){
+ if(input.val().length==0 || input.val()==text){
+ input.val(text);
+ input.css("color",color);
+ }else
+ input.css("color",defaultColor);
+ }
+
+ input.focus(clearMessage);
+ input.blur(insertMessage);
+ input.change(insertMessage);
+
+ insertMessage();
+ }
+ );
+ };
+})(jQuery);
\ No newline at end of file diff --git a/project/templates/proceedings/submit.html b/project/templates/proceedings/submit.html index 28a8bfb..de6b516 100644 --- a/project/templates/proceedings/submit.html +++ b/project/templates/proceedings/submit.html @@ -2,12 +2,37 @@ {% block title %}Submit Paper for Proceedings{% endblock %} {% block addscripts %} - <script type="text/javascript" src="/static/jquery/jquery-ui-1.7.2.custom.min.js"></script> - <script type="text/javascript" src="/static/jquery/jquery-dynamic-form.js"></script> + <script type="text/javascript" src="/static/jquery/jquery.watermarkinput.js"></script> + <link rel="stylesheet" href="/static/css/autosuggest_inquisitor.css" type="text/css" media="screen" charset="utf-8"> + <script type="text/javascript" src="/static/jquery/jquery.autosuggest.js"></script> <script type="text/javascript"> - $(document).ready(function(){ - $("#author").dynamicForm("#plus", "#minus", {createColor: 'yellow',removeColor: 'red'}); - }); + /** Init autosuggest on Search Input **/ + jQuery(function() { + + // Set autosuggest options with all plugins activated + var options = { + script:"{% url kiwipycon_get_usernames %}?limit=10&", + varname:"input", + json:true, // Returned response type + shownoresults:true, // If disable, display nothing if no results + noresults:"No Results", // String displayed when no results + maxresults:8, // Max num results displayed + cache:false, // To enable cache + minchars:2, // Start AJAX request with at leat 2 chars + timeout:100000, // AutoHide in XX ms + callback: function (obj) { // Callback after click or selection + // => TO submit form (general use) + //$('#id_authors').val('sucks'); + //$('#form_search_country').submit(); + } + }; + + // Init autosuggest + var as_json = new bsn.AutoSuggest('id_authors', options); + + // Display a little watermak + $("#id_authors").Watermark("Ex : alex, guido, travis"); + }); </script> {% endblock %} @@ -16,7 +41,7 @@ {% include '_errors.html' %} - <form action="{% url kiwipycon_submit_proceedings %}" method="post"> + <form action="{% if id %}{% url kiwipycon_submit_proceedings id %}{% else %}{% url kiwipycon_submit_proceedings %}{% endif %}" method="post"> {% if not user.is_authenticated %} <fieldset> <legend>Are you a member of this site?</legend> @@ -26,7 +51,8 @@ </fieldset> </form> <br /> - <form action="{% url kiwipycon_submit_talk %}" enctype="multipart/form-data" method="post"> + <form action="{% url kiwipycon_submit_proceedings id %}" + enctype="multipart/form-data" method="post"> <fieldset> <legend>User Registration</legend> <table class="kiwipycon-default required">{{ register_form }}</table> @@ -53,16 +79,13 @@ </tr> <tr> <th>{{ proceedings_form.rst_file.label }}</th> - <td>{{ proceedings_form.rst_file.errors }}{{ proceedings_form.rst_file }}</td> + <td>{{ proceedings_form.rst_file.errors }} + {{ proceedings_form.rst_file }}</td> </tr> <tr> <th>{{ proceedings_form.authors.label }}</th> - <td id="author"> - {{ proceedings_form.authors.errors }} - {{ proceedings_form.authors }} - <span><a id="minus" href="">[Remove]</a><a id="plus" href="">[Add]</a></span> - <br /> - </td> + <td>{{ proceedings_form.authors.errors }} + {{ proceedings_form.authors }}</td> </tr> </table> <button class="button left" type="submit">Submit Paper</button> diff --git a/project/urls.py b/project/urls.py index 652b75d..9f3d998 100644 --- a/project/urls.py +++ b/project/urls.py @@ -54,12 +54,17 @@ urlpatterns += patterns('project.kiwipycon.user.views', url(r'^password/$', 'password', name='kiwipycon_password'), # change pwd url(r'^username/$', 'username', name='kiwipycon_username'), # change uname url(r'^edit-profile/$', 'edit_profile', name='kiwipycon_edit_profile'), + url(r'^get-usernames/$', 'get_usernames', name='kiwipycon_get_usernames'), ) # Proceedings urlpatterns += patterns('project.kiwipycon.proceedings.views', - url(r'^proceedings/submit/$', 'submit', name='kiwipycon_submit_proceedings'), - url(r'^proceedings/edit/$', 'edit', name='kiwipycon_edit_proceedings'), + url(r'^proceedings/submit/$', 'submit', + name='kiwipycon_submit_proceedings'), + url(r'^proceedings/submit/(?P<id>\d+)/$', 'submit', + name='kiwipycon_submit_proceedings'), + url(r'^proceedings/show_paper/(?P<id>\d+)/$', 'show_paper', + name='kiwipycon_show_paper'), ) # About pages and all other static html pages |