forms: add tracking code UI elements
This commit is contained in:
parent
402e6f65fb
commit
ebe4bc6137
|
@ -71,11 +71,47 @@ a:visited {
|
|||
padding-top: 70px;
|
||||
}
|
||||
|
||||
#steps {
|
||||
#side {
|
||||
float: right;
|
||||
width: 204px;
|
||||
padding: 0;
|
||||
margin: 0 -20px 0 20px;
|
||||
}
|
||||
|
||||
#side #tracking-code {
|
||||
margin-bottom: 1em;
|
||||
border: 1px solid #bfbfbf;
|
||||
color: #333333;
|
||||
background: #e6e6e6;
|
||||
padding: 1ex;
|
||||
}
|
||||
|
||||
#side #tracking-code h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#side #tracking-code button,
|
||||
#side #tracking-code a {
|
||||
margin: 1ex auto;
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 120%;
|
||||
background: white;
|
||||
border: 1px solid black;
|
||||
padding: 0.5ex 0;
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
#side #tracking-code button {
|
||||
background: #0273B9;
|
||||
color: white;
|
||||
}
|
||||
|
||||
input[name=savedraft] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#steps {
|
||||
background: white;
|
||||
border: 1px solid #bfbfbf;
|
||||
color: #333333;
|
||||
|
|
|
@ -4,6 +4,7 @@ from quixote import cleanup
|
|||
from wcs.qommon.ident.password_accounts import PasswordAccount
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.categories import Category
|
||||
from wcs.tracking_code import TrackingCode
|
||||
from wcs import fields
|
||||
|
||||
from utilities import get_app, login, create_temporary_pub, emails
|
||||
|
@ -232,3 +233,111 @@ def test_form_tryauth():
|
|||
|
||||
pub.cfg['identification'] = {'methods': ['password']}
|
||||
pub.write_cfg()
|
||||
|
||||
def test_form_tracking_code():
|
||||
formdef = create_formdef()
|
||||
formdef.data_class().wipe()
|
||||
formdef.fields = [fields.StringField(id='0', label='string')]
|
||||
formdef.allow_drafts = True
|
||||
formdef.store()
|
||||
resp = get_app(pub).get('/test/')
|
||||
assert '<h3>Tracking code</h3>' in resp.body
|
||||
resp.forms[0]['f0'] = 'foobar'
|
||||
resp = resp.forms[0].submit('submit')
|
||||
tracking_code = None
|
||||
for a_tag in resp.html.findAll('a'):
|
||||
if 'code/' in a_tag['href']:
|
||||
tracking_code = a_tag.text
|
||||
break
|
||||
assert tracking_code is not None
|
||||
|
||||
assert formdef.data_class().count() == 1
|
||||
assert formdef.data_class().select()[0].is_draft()
|
||||
assert formdef.data_class().select()[0].tracking_code == tracking_code
|
||||
assert formdef.data_class().select()[0].data['0'] == 'foobar'
|
||||
|
||||
# check we can load the formdata as a draft
|
||||
resp = get_app(pub).get('/')
|
||||
resp.forms[0]['code'] = tracking_code
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.location == 'http://example.net/code/%s/load' % tracking_code
|
||||
resp = resp.follow()
|
||||
assert resp.location == 'http://example.net/test/1'
|
||||
resp = resp.follow()
|
||||
assert resp.location.startswith('http://example.net/test/?mt=')
|
||||
resp = resp.follow()
|
||||
resp = resp.forms[0].submit('previous')
|
||||
assert resp.forms[0]['f0'].value == 'foobar'
|
||||
|
||||
# check submitted form keeps the tracking code
|
||||
resp.forms[0]['f0'] = 'barfoo'
|
||||
resp = resp.forms[0].submit('submit') # -> confirmation page
|
||||
resp = resp.forms[0].submit('submit') # -> done
|
||||
resp = resp.follow()
|
||||
assert 'barfoo' in resp.body
|
||||
assert formdef.data_class().count() == 1 # check the draft one has been removed
|
||||
assert formdef.data_class().select()[0].tracking_code == tracking_code
|
||||
assert formdef.data_class().select()[0].status == 'wf-new'
|
||||
assert formdef.data_class().select()[0].data['0'] == 'barfoo'
|
||||
formdata_id = formdef.data_class().select()[0].id
|
||||
|
||||
# check we can still go back to it
|
||||
resp = get_app(pub).get('/')
|
||||
resp.forms[0]['code'] = tracking_code
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.location == 'http://example.net/code/%s/load' % tracking_code
|
||||
resp = resp.follow()
|
||||
assert resp.location == 'http://example.net/test/%s' % formdata_id
|
||||
resp = resp.follow()
|
||||
|
||||
def test_form_tracking_code_email():
|
||||
formdef = create_formdef()
|
||||
formdef.data_class().wipe()
|
||||
formdef.fields = [fields.StringField(id='0', label='string')]
|
||||
formdef.allow_drafts = True
|
||||
formdef.store()
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {'0': 'foobar'}
|
||||
formdata.tracking_code = 'ABCDEF'
|
||||
formdata.store()
|
||||
|
||||
resp = get_app(pub).get('/test/code/ABCDEF/')
|
||||
assert '<h2>Keep your tracking code</h2>' in resp.body
|
||||
resp.forms[0]['email'] = 'foo@localhost'
|
||||
resp = resp.forms[0].submit()
|
||||
assert emails.emails.get('Tracking Code reminder')
|
||||
assert 'ABCDEF' in emails.emails.values()[0]['args'][0]
|
||||
assert resp.location == 'http://example.net/test/code/ABCDEF/load'
|
||||
|
||||
def test_form_invalid_tracking_code():
|
||||
formdef = create_formdef()
|
||||
formdef.data_class().wipe()
|
||||
formdef.fields = [fields.StringField(id='0', label='string')]
|
||||
formdef.allow_drafts = True
|
||||
formdef.store()
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
formdata.data = {'0': 'foobar'}
|
||||
formdata.store()
|
||||
|
||||
code = TrackingCode()
|
||||
code.formdata = formdata
|
||||
code.store()
|
||||
|
||||
# check we can go back to it
|
||||
resp = get_app(pub).get('/')
|
||||
resp.forms[0]['code'] = code.id
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.location == 'http://example.net/code/%s/load' % code.id
|
||||
resp = resp.follow()
|
||||
assert resp.location == 'http://example.net/test/%s' % formdata.id
|
||||
resp = resp.follow()
|
||||
|
||||
# check we get a not found error message on non-existent code
|
||||
fake_code = TrackingCode().get_new_id()
|
||||
resp = get_app(pub).get('/')
|
||||
resp.forms[0]['code'] = fake_code
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.location == 'http://example.net/code/%s/load' % fake_code
|
||||
resp = resp.follow(status=404)
|
||||
|
|
|
@ -31,17 +31,20 @@ from quixote.util import randbytes
|
|||
from quixote.form.widget import *
|
||||
from quixote.html import TemplateIO, htmltext
|
||||
|
||||
from qommon.admin.emails import EmailsDirectory
|
||||
from qommon import errors, get_cfg
|
||||
from qommon import misc, get_logger
|
||||
from qommon import template
|
||||
from qommon.form import *
|
||||
from qommon import tokens
|
||||
from qommon import emails
|
||||
|
||||
from wcs.anonylink import AnonymityLink
|
||||
from wcs.categories import Category
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.formdata import FormData
|
||||
from wcs.roles import logged_users_role
|
||||
from wcs.tracking_code import TrackingCode
|
||||
from wcs.workflows import Workflow, EditableWorkflowStatusItem
|
||||
from wcs.api import get_user_from_api_query_string
|
||||
|
||||
|
@ -118,9 +121,73 @@ class TokensDirectory(Directory):
|
|||
return TokenDirectory(self.formdef, token)
|
||||
|
||||
|
||||
class TrackingCodeDirectory(Directory):
|
||||
_q_exports = ['', 'load']
|
||||
|
||||
def __init__(self, code, formdef):
|
||||
self.code = code
|
||||
self.formdef = formdef
|
||||
|
||||
def _q_index(self):
|
||||
if self.formdef is None:
|
||||
raise errors.TraversalError()
|
||||
form = Form()
|
||||
if get_request().user and get_request().user.email:
|
||||
email = get_request().user.email
|
||||
else:
|
||||
email = None
|
||||
form.add(EmailWidget, 'email', value=email, title=_('Email'), size=25, required=True)
|
||||
form.add_submit('submit', _('Send email'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
|
||||
if form.get_submit() == 'cancel':
|
||||
return redirect('./load')
|
||||
|
||||
if form.is_submitted() and not form.has_errors():
|
||||
email = form.get_widget('email').parse()
|
||||
data = {
|
||||
'tracking_code': self.code,
|
||||
'email': email
|
||||
}
|
||||
data.update(self.formdef.get_substitution_variables(minimal=True))
|
||||
emails.custom_ezt_email('tracking-code-reminder', data,
|
||||
email, fire_and_forget=True)
|
||||
return redirect('./load')
|
||||
|
||||
html_top()
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<h2>%s</h2>') % _('Keep your tracking code')
|
||||
r += TextsDirectory.get_html_text('tracking-code-email-dialog')
|
||||
r += form.render()
|
||||
return r.getvalue()
|
||||
|
||||
def load(self):
|
||||
try:
|
||||
tracking_code = TrackingCode.get(self.code)
|
||||
except KeyError:
|
||||
raise errors.TraversalError()
|
||||
formdata = tracking_code.formdata
|
||||
if not get_session().user:
|
||||
get_session().mark_anonymous_formdata(formdata)
|
||||
return redirect(formdata.get_url().rstrip('/'))
|
||||
|
||||
|
||||
class TrackingCodesDirectory(Directory):
|
||||
_q_exports = ['load']
|
||||
|
||||
def __init__(self, formdef=None):
|
||||
self.formdef = formdef
|
||||
|
||||
def load(self):
|
||||
code = get_request().form.get('code')
|
||||
return redirect('./%s/load' % code)
|
||||
|
||||
def _q_lookup(self, component):
|
||||
return TrackingCodeDirectory(component, self.formdef)
|
||||
|
||||
class FormPage(Directory):
|
||||
_q_exports = ['', 'listing', 'tempfile', 'tokens', 'schema', 'tryauth',
|
||||
'auth', 'qrcode', 'autosave']
|
||||
'auth', 'qrcode', 'autosave', 'code']
|
||||
|
||||
steps = [N_("Filling"), N_("Validating"), N_("Receipt")]
|
||||
|
||||
|
@ -135,6 +202,7 @@ class FormPage(Directory):
|
|||
get_publisher().substitutions.feed(self.formdef)
|
||||
|
||||
self.tokens = TokensDirectory(self.formdef)
|
||||
self.code = TrackingCodesDirectory(self.formdef)
|
||||
|
||||
self.page_number = len([
|
||||
x for x in self.formdef.fields[1:] if x.type == 'page']) + 1
|
||||
|
@ -223,6 +291,7 @@ class FormPage(Directory):
|
|||
self.feed_current_data(magictoken)
|
||||
|
||||
form = self.formdef.create_form(page_no, displayed_fields)
|
||||
form.action = '.'
|
||||
# include a data-has-draft attribute on the <form> element when a draft
|
||||
# already exists for the form; this will activate the autosave.
|
||||
magictoken = get_request().form.get('magictoken')
|
||||
|
@ -230,7 +299,8 @@ class FormPage(Directory):
|
|||
form_data = session.get_by_magictoken(magictoken, {})
|
||||
if form_data.get('draft_formdata_id'):
|
||||
form.attrs['data-has-draft'] = 'yes'
|
||||
get_response().add_javascript(['jquery.js', 'qommon.forms.js'])
|
||||
else:
|
||||
form_data = {}
|
||||
|
||||
if page_no == 0 and not get_request().form.has_key('magictoken'):
|
||||
magictoken = randbytes(8)
|
||||
|
@ -289,19 +359,50 @@ class FormPage(Directory):
|
|||
req.form = {}
|
||||
|
||||
html_top(self.formdef.name)
|
||||
r += self.step(0, page_no, log_detail, data = data, editing = editing)
|
||||
r += self.form_side(0, page_no, log_detail=log_detail, data=data, editing=editing)
|
||||
|
||||
form.add_hidden('step', '0')
|
||||
form.add_hidden('page', page_no)
|
||||
|
||||
form.add_submit('cancel', _('Cancel'), css_class = 'cancel')
|
||||
if session.user and self.formdef.allow_drafts and not editing:
|
||||
if get_request().form.has_key('mt'):
|
||||
form.add_submit('removedraft', _('Remove Draft'), css_class = 'remove-draft')
|
||||
form.add_submit('savedraft', _('Save As Draft'), css_class = 'save-draft')
|
||||
if self.formdef.allow_drafts and not editing:
|
||||
form.add_submit('savedraft', _('Save As Draft'), css_class = 'save-draft',
|
||||
attrs={'style': 'display: none'})
|
||||
|
||||
r += form.render()
|
||||
return r.getvalue()
|
||||
|
||||
def form_side(self, step_no, page_no=0, log_detail=None, data=None, editing=None):
|
||||
'''Create the elements that typically appear aside the main form
|
||||
(tracking code and steps).'''
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<div id="side">')
|
||||
if self.formdef.allow_drafts:
|
||||
r += self.tracking_code_box(data)
|
||||
r += self.step(step_no, page_no, log_detail, data=data, editing=editing)
|
||||
r += htmltext('</div> <!-- #side -->')
|
||||
return r.getvalue()
|
||||
|
||||
def tracking_code_box(self, data):
|
||||
'''Create the tracking code box, it displays the current tracking code
|
||||
or a 'save' button if it has not yet been created.'''
|
||||
r = TemplateIO(html=True)
|
||||
draft_formdata_id = data.get('draft_formdata_id')
|
||||
r += htmltext('<div id="tracking-code">')
|
||||
r += htmltext('<h3>%s</h3>') % _('Tracking code')
|
||||
if draft_formdata_id:
|
||||
formdata = self.formdef.data_class().get(draft_formdata_id)
|
||||
if formdata.tracking_code:
|
||||
get_response().add_javascript(['jquery.js', 'jquery-ui.js', 'popup.js'])
|
||||
r += htmltext('<a rel="popup" href="%s">%s</a>') % (
|
||||
'code/%s/' % formdata.tracking_code,
|
||||
formdata.tracking_code)
|
||||
else:
|
||||
r += htmltext('<button>%s</button>') % _('Save')
|
||||
r += TextsDirectory.get_html_text('tracking-code-short-text')
|
||||
r += htmltext('</div>') # <!-- #tracking-code -->
|
||||
return r.getvalue()
|
||||
|
||||
def feed_current_data(self, magictoken):
|
||||
# create a fake FormData to feed variables
|
||||
formdata = FormData()
|
||||
|
@ -339,6 +440,7 @@ class FormPage(Directory):
|
|||
if [x for x in user_forms if not x.is_draft()]:
|
||||
return redirect('%s/' % user_forms[0].id)
|
||||
|
||||
get_response().add_javascript(['jquery.js', 'qommon.forms.js'])
|
||||
form = Form()
|
||||
form.add_hidden('step', '-1')
|
||||
form.add_hidden('page', '-1')
|
||||
|
@ -353,6 +455,7 @@ class FormPage(Directory):
|
|||
if get_request().form.has_key('mt'):
|
||||
magictoken = get_request().form['mt']
|
||||
data = session.get_by_magictoken(magictoken, {})
|
||||
session.remove_magictoken(magictoken)
|
||||
if data:
|
||||
# create a new one since the other has been exposed in a url
|
||||
magictoken = randbytes(8)
|
||||
|
@ -418,8 +521,8 @@ class FormPage(Directory):
|
|||
form_data = session.get_by_magictoken(magictoken, {})
|
||||
data = self.formdef.get_data(form)
|
||||
form_data.update(data)
|
||||
self.save_draft(form_data, page_no)
|
||||
return redirect(get_publisher().get_root_url())
|
||||
filled = self.save_draft(form_data, page_no)
|
||||
return redirect(filled.get_url().rstrip('/'))
|
||||
|
||||
# form.get_submit() returns the name of the clicked button, and
|
||||
# it will return True if the form has been submitted, but not
|
||||
|
@ -448,10 +551,14 @@ class FormPage(Directory):
|
|||
if next_page.is_visible(form_data, self.formdef):
|
||||
break
|
||||
|
||||
# if there's a draft, update it with current data
|
||||
draft_id = session.get_by_magictoken(magictoken, {}).get('draft_formdata_id')
|
||||
if draft_id:
|
||||
self.autosave_draft(draft_id, page_no, form_data)
|
||||
if self.formdef.allow_drafts:
|
||||
draft_id = session.get_by_magictoken(magictoken, {}).get('draft_formdata_id')
|
||||
if draft_id:
|
||||
# if there's a draft, update it with current data
|
||||
self.autosave_draft(draft_id, page_no, form_data)
|
||||
else:
|
||||
# if there's no draft yet, create one
|
||||
filled = self.save_draft(form_data, page_no)
|
||||
|
||||
if page_no == self.page_number:
|
||||
# last page has been submitted
|
||||
|
@ -516,8 +623,8 @@ class FormPage(Directory):
|
|||
return redirect(get_publisher().get_root_url())
|
||||
|
||||
if self.formdef.allow_drafts and form.get_submit() == 'savedraft':
|
||||
self.save_draft(form_data, page_no = -1)
|
||||
return redirect(get_publisher().get_root_url())
|
||||
filled = self.save_draft(form_data, page_no = -1)
|
||||
return redirect(filled.get_url().rstrip('/'))
|
||||
|
||||
# so it gets FakeFileWidget in preview mode
|
||||
form = self.formdef.create_view_form(form_data,
|
||||
|
@ -625,14 +732,14 @@ class FormPage(Directory):
|
|||
filled.user_id = session.user
|
||||
filled.store()
|
||||
|
||||
magictoken = get_request().form.get('magictoken')
|
||||
if magictoken:
|
||||
form_data = session.get_by_magictoken(magictoken, {})
|
||||
if form_data.get('draft_formdata_id'):
|
||||
filled.remove_object(form_data.get('draft_formdata_id'))
|
||||
if not filled.user_id:
|
||||
get_session().mark_anonymous_formdata(filled)
|
||||
|
||||
self.keep_tracking_code(filled)
|
||||
|
||||
get_logger().info('form %s - saving draft (id: %s)' % (self.formdef.name, filled.id))
|
||||
|
||||
return filled
|
||||
|
||||
def submitted(self, form, existing_formdata = None):
|
||||
if existing_formdata: # modifying
|
||||
|
@ -657,13 +764,10 @@ class FormPage(Directory):
|
|||
user_forms = get_user_forms(self.formdef)
|
||||
if [x for x in user_forms if not x.is_draft()]:
|
||||
return redirect('%s/' % user_forms[0].id)
|
||||
filled.store()
|
||||
|
||||
magictoken = get_request().form.get('magictoken')
|
||||
if magictoken:
|
||||
form_data = session.get_by_magictoken(magictoken, {})
|
||||
if form_data.get('draft_formdata_id'):
|
||||
filled.remove_object(form_data.get('draft_formdata_id'))
|
||||
self.keep_tracking_code(filled)
|
||||
session.remove_magictoken(get_request().form.get('magictoken'))
|
||||
filled.store()
|
||||
|
||||
if not filled.user_id and existing_formdata is None:
|
||||
a = AnonymityLink()
|
||||
|
@ -686,6 +790,26 @@ class FormPage(Directory):
|
|||
url = filled.get_url()
|
||||
return redirect(url)
|
||||
|
||||
def keep_tracking_code(self, formdata):
|
||||
'''Remove current draft in favour of formdata, conserving the same
|
||||
tracking code.'''
|
||||
code = None
|
||||
magictoken = get_request().form.get('magictoken')
|
||||
if magictoken:
|
||||
session = get_session()
|
||||
form_data = session.get_by_magictoken(magictoken, {})
|
||||
draft_formdata_id = form_data.get('draft_formdata_id')
|
||||
if draft_formdata_id:
|
||||
old_draft_formdata = self.formdef.data_class().get(draft_formdata_id)
|
||||
old_draft_formdata.remove_self()
|
||||
if old_draft_formdata.tracking_code:
|
||||
code = TrackingCode.get(old_draft_formdata.tracking_code)
|
||||
form_data['draft_formdata_id'] = formdata.id
|
||||
|
||||
if code is None:
|
||||
code = TrackingCode()
|
||||
code.formdata = formdata # this will .store() the code
|
||||
|
||||
def submitted_existing(self, form, editing):
|
||||
old_data = editing.data
|
||||
editing.data = self.formdef.get_data(form)
|
||||
|
@ -716,7 +840,7 @@ class FormPage(Directory):
|
|||
html_top(self.formdef.name)
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<div class="form-validation">')
|
||||
r += self.step(1, data = data)
|
||||
r += self.form_side(step_no=1, data=data)
|
||||
r += TextsDirectory.get_html_text('check-before-submit')
|
||||
form = self.formdef.create_view_form(data)
|
||||
token_widget = form.get_widget(form.TOKEN_NAME)
|
||||
|
@ -725,10 +849,9 @@ class FormPage(Directory):
|
|||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'), css_class = 'cancel')
|
||||
session = get_session()
|
||||
if session.user and self.formdef.allow_drafts:
|
||||
if get_request().form.has_key('mt'):
|
||||
form.add_submit('removedraft', _('Remove Draft'), css_class = 'remove-draft')
|
||||
form.add_submit('savedraft', _('Save As Draft'), css_class = 'save-draft')
|
||||
if self.formdef.allow_drafts:
|
||||
form.add_submit('savedraft', _('Save As Draft'), css_class = 'save-draft',
|
||||
attrs={'style': 'display: none'})
|
||||
form.add_hidden('step', '2')
|
||||
magictoken = get_request().form['magictoken']
|
||||
form.add_hidden('magictoken', magictoken)
|
||||
|
@ -803,12 +926,17 @@ class FormPage(Directory):
|
|||
if not filled.is_draft():
|
||||
return PublicFormStatusPage(self.formdef, filled)
|
||||
|
||||
if get_request().user is None:
|
||||
raise errors.AccessUnauthorizedError()
|
||||
|
||||
session = get_session()
|
||||
if str(session.user) != str(filled.user_id):
|
||||
raise errors.AccessForbiddenError()
|
||||
if session.user:
|
||||
if str(session.user) != str(filled.user_id):
|
||||
raise errors.AccessForbiddenError()
|
||||
else:
|
||||
if not session.is_anonymous_submitter(filled):
|
||||
raise errors.AccessUnauthorizedError()
|
||||
|
||||
if get_request().get_query() == 'remove-draft':
|
||||
filled.remove_self()
|
||||
return redirect(get_publisher().get_root_url())
|
||||
|
||||
magictoken = randbytes(8)
|
||||
filled.feed_session()
|
||||
|
@ -817,13 +945,14 @@ class FormPage(Directory):
|
|||
form_data['page_no'] = filled.page_no
|
||||
session.add_magictoken(magictoken, form_data)
|
||||
|
||||
return redirect('./?mt=%s' % magictoken)
|
||||
return redirect('%s?mt=%s' % (filled.formdef.get_url(), magictoken))
|
||||
|
||||
|
||||
class RootDirectory(AccessControlled, Directory):
|
||||
_q_exports = ['', 'json', 'categories']
|
||||
_q_exports = ['', 'json', 'categories', 'code']
|
||||
|
||||
category = None
|
||||
code = TrackingCodesDirectory()
|
||||
|
||||
def __init__(self, category = None):
|
||||
self.category = category
|
||||
|
@ -879,6 +1008,17 @@ class RootDirectory(AccessControlled, Directory):
|
|||
r += message
|
||||
r += htmltext('</div>')
|
||||
|
||||
if FormDef.count():
|
||||
r += htmltext('<div id="side">')
|
||||
r += htmltext('<div id="tracking-code">')
|
||||
r += htmltext('<h3>%s</h3>') % _('Tracking code')
|
||||
r += htmltext('<form action="/code/load">')
|
||||
r += htmltext('<input size="12" name="code" placeholder="%s"/>') % _('ex: RPQDFVCD')
|
||||
r += htmltext('<input type="submit" value="load"/>')
|
||||
r += htmltext('</form>')
|
||||
r += htmltext('</div>')
|
||||
r += htmltext('</div> <!-- #side -->')
|
||||
|
||||
if self.category:
|
||||
formdefs = FormDef.select(lambda x: (
|
||||
x.category_id == self.category.id and (not x.is_disabled() or x.disabled_redirection)),
|
||||
|
@ -1211,3 +1351,23 @@ TextsDirectory.register('check-before-submit',
|
|||
category = N_('Forms'),
|
||||
default = N_('Check values then click submit.'))
|
||||
|
||||
TextsDirectory.register('tracking-code-email-dialog',
|
||||
N_('Message in tracking code popup dialog'),
|
||||
category = N_('Forms'),
|
||||
default = N_('You can get a reminder of the tracking code by email.'))
|
||||
|
||||
TextsDirectory.register('tracking-code-short-text',
|
||||
N_('Short text in the tracking code box'),
|
||||
category=N_('Forms'))
|
||||
|
||||
EmailsDirectory.register('tracking-code-reminder',
|
||||
N_('Tracking Code'),
|
||||
N_('Available variables: email, form, tracking_code'),
|
||||
category = N_('Miscellaneous'),
|
||||
default_subject = N_('Tracking Code reminder'),
|
||||
default_body = N_('''\
|
||||
Hello,
|
||||
|
||||
As a reminder your tracking code for [form_name] is [tracking_code].
|
||||
|
||||
'''))
|
||||
|
|
|
@ -21,4 +21,7 @@ $(function() {
|
|||
});
|
||||
}, 5000);
|
||||
}
|
||||
$('#tracking-code button').click(function() {
|
||||
$('input[name=savedraft]').click();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -46,6 +46,12 @@ class BasicSession(Session):
|
|||
return default
|
||||
return self.magictokens.get(token, default)
|
||||
|
||||
def remove_magictoken(self, token):
|
||||
if not self.magictokens:
|
||||
return
|
||||
if token in self.magictokens:
|
||||
del self.magictokens[token]
|
||||
|
||||
def mark_anonymous_formdata(self, formdata):
|
||||
if not self.anonymous_formdata_keys:
|
||||
self.anonymous_formdata_keys = {}
|
||||
|
|
Loading…
Reference in New Issue