forms: add option to control max number of drafts per user (#88237)
gitea/wcs/pipeline/head There was a failure building this commit Details

This commit is contained in:
Thomas NOËL 2024-03-15 16:47:02 +01:00 committed by Thomas NOËL
parent 0ed9d5d0a0
commit 955f012b3d
7 changed files with 52 additions and 2 deletions

View File

@ -386,6 +386,7 @@ Une API existe pour récupérer le schéma de données dun 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" : [

View File

@ -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'),

View File

@ -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()

View File

@ -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('<h3>%s</h3>') % _('Tracking Code')))
form.add(
CheckboxWidget,
@ -495,6 +513,7 @@ class OptionsDirectory(Directory):
'id_template',
'submission_lateral_template',
'drafts_lifespan',
'drafts_max_per_user',
'user_support',
'management_sidebar_items',
]

View File

@ -61,6 +61,7 @@ from .qommon.upload_storage import PicklableUpload
from .roles import logged_users_role
DRAFTS_DEFAULT_LIFESPAN = 100 # days
DRAFTS_DEFAULT_MAX_PER_USER = 5
if not hasattr(types, 'ClassType'):
types.ClassType = type
@ -190,6 +191,7 @@ class FormDef(StorableObject):
submission_lateral_template = None
id_template = None
drafts_lifespan = None
drafts_max_per_user = None
user_support = None
geolocations = None
@ -220,6 +222,7 @@ class FormDef(StorableObject):
'submission_lateral_template',
'id_template',
'drafts_lifespan',
'drafts_max_per_user',
'user_support',
]
BOOLEAN_ATTRIBUTES = [
@ -634,6 +637,9 @@ class FormDef(StorableObject):
def get_drafts_lifespan(self):
return int(self.drafts_lifespan or DRAFTS_DEFAULT_LIFESPAN)
def get_drafts_max_per_user(self):
return int(self.drafts_max_per_user or DRAFTS_DEFAULT_MAX_PER_USER)
_workflow = None
def get_workflow(self):

View File

@ -1778,11 +1778,11 @@ class FormPage(Directory, TempfileDirectoryMixin, FormTemplateMixin):
if get_session().mark_anonymous_formdata(filled):
get_session().store()
elif new_draft:
# keep at most 5 drafts per user
# keep at most "max_per_user" drafts per user
data_class = self.formdef.data_class()
for id in data_class.get_sorted_ids(
'-last_update_time', [Equal('status', 'draft'), Equal('user_id', str(filled.user_id))]
)[5:]:
)[self.formdef.get_drafts_max_per_user() :]:
data_class.remove_object(id)
if new_draft:

View File

@ -67,6 +67,7 @@
<li><span class="parameter">{% trans "Fields to check after entering the tracking code" %}{% trans ":" %}</span> {{ tracking_code_verify_fields_labels|default:"-" }}</li>
{% endif %}
<li><span class="parameter">{% trans "Lifespan of drafts (in days)" %}{% trans ":" %}</span> {{ formdef.get_drafts_lifespan }}</li>
<li><span class="parameter">{% trans "Maximum number of drafts per user" %}{% trans ":" %}</span> {{ formdef.get_drafts_max_per_user }}</li>
<li><span class="parameter">{% trans "Templates" %}</span>
<ul>
<li><span class="parameter">{% trans "Digest" %}{% trans ":" %}</span> {{ formdef.default_digest_template|default:"-" }}</li>