forms: autosave existing drafts (#4858)
This commit is contained in:
parent
64c16c1a5a
commit
0f17fa2172
|
@ -167,7 +167,7 @@ class FormData(StorableObject):
|
|||
|
||||
def migrate(self):
|
||||
changed = False
|
||||
if self.status and not self.status.startswith('wf-'):
|
||||
if self.status and not self.status.startswith('wf-') and self.status != 'draft':
|
||||
self.status = 'wf-%s' % self.status
|
||||
changed = True
|
||||
if self.evolution:
|
||||
|
|
|
@ -120,7 +120,7 @@ class TokensDirectory(Directory):
|
|||
|
||||
class FormPage(Directory):
|
||||
_q_exports = ['', 'listing', 'tempfile', 'tokens', 'schema', 'tryauth',
|
||||
'auth', 'qrcode']
|
||||
'auth', 'qrcode', 'autosave']
|
||||
|
||||
steps = [N_("Filling"), N_("Validating"), N_("Receipt")]
|
||||
|
||||
|
@ -223,6 +223,14 @@ class FormPage(Directory):
|
|||
self.feed_current_data(magictoken)
|
||||
|
||||
form = self.formdef.create_form(page_no, displayed_fields)
|
||||
# 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')
|
||||
if magictoken:
|
||||
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'])
|
||||
|
||||
if page_no == 0 and not get_request().form.has_key('magictoken'):
|
||||
magictoken = randbytes(8)
|
||||
|
@ -440,6 +448,11 @@ 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 page_no == self.page_number:
|
||||
# last page has been submitted
|
||||
req = get_request()
|
||||
|
@ -543,6 +556,64 @@ class FormPage(Directory):
|
|||
if form_data.get('draft_formdata_id'):
|
||||
self.formdef.data_class().remove_object(form_data.get('draft_formdata_id'))
|
||||
|
||||
def autosave_draft(self, draft_id, page_no, form_data):
|
||||
try:
|
||||
formdata = self.formdef.data_class().get(draft_id)
|
||||
except KeyError:
|
||||
return
|
||||
|
||||
if not formdata.status == 'draft':
|
||||
return
|
||||
|
||||
formdata.page_no = page_no
|
||||
formdata.data = form_data
|
||||
formdata.receipt_time = time.localtime()
|
||||
session = get_session()
|
||||
if session and session.user and not str(session.user).startswith('anonymous-'):
|
||||
formdata.user_id = session.user
|
||||
formdata.store()
|
||||
|
||||
def autosave(self):
|
||||
get_response().set_content_type('application/json')
|
||||
def result_error(reason):
|
||||
return json.dumps({'result': 'error', 'reason': reason})
|
||||
|
||||
try:
|
||||
page_no = int(get_request().form.get('page'))
|
||||
except TypeError:
|
||||
return result_error('missing page_no')
|
||||
|
||||
magictoken = get_request().form.get('magictoken')
|
||||
if not magictoken:
|
||||
return result_error('missing magictoken')
|
||||
|
||||
session = get_session()
|
||||
if not session:
|
||||
return result_error('missing session')
|
||||
|
||||
draft_id = session.get_by_magictoken(magictoken, {}).get('draft_formdata_id')
|
||||
if not draft_id:
|
||||
return result_error('missing draft id')
|
||||
|
||||
try:
|
||||
formdata = self.formdef.data_class().get(draft_id)
|
||||
except KeyError:
|
||||
return result_error('missing formdata')
|
||||
|
||||
if not formdata.is_draft():
|
||||
return result_error('formdata has already been saved')
|
||||
|
||||
formdata.page_no = page_no
|
||||
form = self.formdef.create_form(page_no)
|
||||
formdata.data.update(self.formdef.get_data(form))
|
||||
formdata.receipt_time = time.localtime()
|
||||
session = get_session()
|
||||
if session and session.user and not str(session.user).startswith('anonymous-'):
|
||||
formdata.user_id = session.user
|
||||
formdata.store()
|
||||
|
||||
return json.dumps({'result': 'success'})
|
||||
|
||||
def save_draft(self, data, page_no):
|
||||
filled = self.formdef.data_class()()
|
||||
filled.data = data
|
||||
|
|
|
@ -3,4 +3,22 @@ $(function() {
|
|||
$('fieldset.form-plus legend').on('click', function() {
|
||||
$(this).parent().toggleClass('closed');
|
||||
});
|
||||
if ($('form[data-has-draft]').length == 1) {
|
||||
var last_auto_save = $('form[data-has-draft]').serialize();
|
||||
var timeout_id = window.setInterval(function() {
|
||||
var new_auto_save = $('form[data-has-draft]').serialize();
|
||||
if (last_auto_save == new_auto_save) return;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: window.location.pathname + 'autosave',
|
||||
data: new_auto_save,
|
||||
success: function(json) {
|
||||
if (json.result == 'success') {
|
||||
last_auto_save = new_auto_save;
|
||||
}
|
||||
last_auto_save = new_auto_save;
|
||||
}
|
||||
});
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue