diff --git a/help/fr/api-cards.page b/help/fr/api-cards.page index e80a7a64b..bece02065 100644 --- a/help/fr/api-cards.page +++ b/help/fr/api-cards.page @@ -386,6 +386,7 @@ Une API existe pour récupérer le schéma de données d’un modèle de fiches. "disabled_redirection" : null, "discussion" : false, "drafts_lifespan" : null, + "drafts_max_per_user" : null, "enable_tracking_codes" : false, "expiration_date" : null, "fields" : [ diff --git a/tests/admin_pages/test_form.py b/tests/admin_pages/test_form.py index fd0713334..81938d5e9 100644 --- a/tests/admin_pages/test_form.py +++ b/tests/admin_pages/test_form.py @@ -284,6 +284,7 @@ def test_forms_edit_tracking_code(pub, formdef): resp = resp.click('Form Tracking') assert resp.forms[0]['drafts_lifespan'].value == '' + assert resp.forms[0]['drafts_max_per_user'].value == '' resp = resp.forms[0].submit().follow() # check empty value is ok resp = resp.click('Form Tracking') @@ -297,6 +298,20 @@ def test_forms_edit_tracking_code(pub, formdef): resp = resp.forms[0].submit().follow() assert FormDef.get(1).drafts_lifespan == '5' + resp = resp.click('Form Tracking') + resp.forms[0]['drafts_max_per_user'].value = 'xxx' + resp = resp.forms[0].submit() + assert 'Maximum must be between 2 and 100 drafts.' in resp + resp.forms[0]['drafts_max_per_user'].value = '120' + resp = resp.forms[0].submit() + assert 'Maximum must be between 2 and 100 drafts.' in resp + resp.forms[0]['drafts_max_per_user'].value = '1' + resp = resp.forms[0].submit() + assert 'Maximum must be between 2 and 100 drafts.' in resp + resp.forms[0]['drafts_max_per_user'].value = '3' + resp = resp.forms[0].submit().follow() + assert FormDef.get(1).drafts_max_per_user == '3' + formdef.fields = [ fields.StringField(id='1', label='VerifyString'), fields.DateField(id='2', label='VerifyDate'), diff --git a/tests/form_pages/test_draft.py b/tests/form_pages/test_draft.py index b008d7da9..7f351cc6b 100644 --- a/tests/form_pages/test_draft.py +++ b/tests/form_pages/test_draft.py @@ -414,6 +414,14 @@ def test_form_max_drafts(pub): assert not formdef.data_class().has_key(drafts[0].id) # oldest draft was removed + formdef.drafts_max_per_user = '3' + formdef.store() + + resp = app.get('/test/') + resp.form['f0'] = 'hello2' + resp = resp.form.submit('submit') + assert formdef.data_class().count([Equal('status', 'draft')]) == 4 + def test_form_draft_temporary_access_url(pub): FormDef.wipe() diff --git a/wcs/admin/forms.py b/wcs/admin/forms.py index e3ff8239f..b17b56bfb 100644 --- a/wcs/admin/forms.py +++ b/wcs/admin/forms.py @@ -30,6 +30,7 @@ from wcs.carddef import CardDef from wcs.categories import Category from wcs.formdef import ( DRAFTS_DEFAULT_LIFESPAN, + DRAFTS_DEFAULT_MAX_PER_USER, FormDef, FormdefImportError, FormdefImportRecoverableError, @@ -290,6 +291,23 @@ class OptionsDirectory(Directory): widget.validation_function = check_lifespan widget.validation_function_error_message = _('Lifespan must be between 2 and 100 days.') + widget = form.add( + WcsExtraStringWidget, + 'drafts_max_per_user', + title=_('Maximum number of drafts per user (between 2 and 100)'), + value=self.formdef.drafts_max_per_user, + hint=_('%s drafts per user by default') % DRAFTS_DEFAULT_MAX_PER_USER, + ) + + def check_max_per_user(value): + try: + return bool(int(value) >= 2 and int(value) <= 100) + except (ValueError, TypeError): + return False + + widget.validation_function = check_max_per_user + widget.validation_function_error_message = _('Maximum must be between 2 and 100 drafts.') + form.widgets.append(HtmlWidget(htmltext('