Add admin interface and views for proceedings. Booklet is also setup to generate paper.
--- a/buildout.cfg Thu Jan 14 21:07:03 2010 +0530
+++ b/buildout.cfg Thu Apr 01 11:59:35 2010 +0530
@@ -51,9 +51,8 @@
${registration:location}
[basic-apps]
-recipe = infrae.subversion
-urls =
- http://django-basic-apps.googlecode.com/svn/trunk/ basic
+recipe = zerokspot.recipe.git
+repository = http://github.com/nathanborror/django-basic-apps.git
[tagging]
recipe = infrae.subversion
--- a/development.cfg Thu Jan 14 21:07:03 2010 +0530
+++ b/development.cfg Thu Apr 01 11:59:35 2010 +0530
@@ -2,8 +2,8 @@
extends =
buildout.cfg
-#eggs +=
-# pysqlite
+eggs +=
+ pysqlite
[django]
settings = development
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project/kiwipycon/proceedings/admin.py Thu Apr 01 11:59:35 2010 +0530
@@ -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)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project/kiwipycon/proceedings/booklet/mk_booklet.py Thu Apr 01 11:59:35 2010 +0530
@@ -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)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project/kiwipycon/proceedings/booklet/mk_scipy_paper.py Thu Apr 01 11:59:35 2010 +0530
@@ -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()
--- a/project/kiwipycon/proceedings/forms.py Thu Jan 14 21:07:03 2010 +0530
+++ b/project/kiwipycon/proceedings/forms.py Thu Apr 01 11:59:35 2010 +0530
@@ -26,5 +26,5 @@
"'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).')
--- a/project/kiwipycon/proceedings/views.py Thu Jan 14 21:07:03 2010 +0530
+++ b/project/kiwipycon/proceedings/views.py Thu Apr 01 11:59:35 2010 +0530
@@ -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 @@
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 @@
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')
+ # Data from reSt file is appended to the data in fields
+ title, abstract, body, authors = handleUploadedFile(
+ proceedings_form.cleaned_data, request.FILES.get('file'))
- # Saved, ... redirect back to account
- redirect_to = reverse('kiwipycon_account')
- return set_message_cookie(redirect_to,
- msg = u'Thanks, your paper has been submitted.')
+ 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:
+ 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()
- else:
- proceedings_form = ProceedingsForm()
register_form = RegisterForm()
- login_form = AuthenticationForm()
-
-
- proceedings_form = ProceedingsForm()
- register_form = RegisterForm()
- login_form = AuthenticationForm()
+ login_form = AuthenticationForm()
context = RequestContext(request, {
'proceedings_form': proceedings_form,
@@ -77,18 +121,83 @@
'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)
+
+ 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)
- return render_to_response(template, context)
+ 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
--- a/project/kiwipycon/user/views.py Thu Jan 14 21:07:03 2010 +0530
+++ b/project/kiwipycon/user/views.py Thu Apr 01 11:59:35 2010 +0530
@@ -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.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 @@
"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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project/static/css/autosuggest_inquisitor.css Thu Apr 01 11:59:35 2010 +0530
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project/static/jquery/jquery.autosuggest.js Thu Apr 01 11:59:35 2010 +0530
@@ -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))};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project/static/jquery/jquery.watermarkinput.js Thu Apr 01 11:59:35 2010 +0530
@@ -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
--- a/project/templates/proceedings/submit.html Thu Jan 14 21:07:03 2010 +0530
+++ b/project/templates/proceedings/submit.html Thu Apr 01 11:59:35 2010 +0530
@@ -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>
--- a/project/urls.py Thu Jan 14 21:07:03 2010 +0530
+++ b/project/urls.py Thu Apr 01 11:59:35 2010 +0530
@@ -54,12 +54,17 @@
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