From 381b3edb2674bc92f55b18d35b29c5e26b70dea8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Fri, 4 Nov 2022 18:10:30 +0100
Subject: [PATCH] workflows: use a simple file widget to set model document
 (#4281)

---
 tests/admin_pages/test_workflow.py | 12 +++++-----
 tests/workflow/test_all.py         |  4 ++--
 wcs/backoffice/deprecations.py     |  2 +-
 wcs/qommon/form.py                 | 35 ------------------------------
 wcs/wf/export_to_model.py          | 31 +++++++++++++++++++++++---
 5 files changed, 36 insertions(+), 48 deletions(-)

diff --git a/tests/admin_pages/test_workflow.py b/tests/admin_pages/test_workflow.py
index 9c8d4e0f4..cf1db96fb 100644
--- a/tests/admin_pages/test_workflow.py
+++ b/tests/admin_pages/test_workflow.py
@@ -534,7 +534,7 @@ def test_workflows_copy_status_item_create_document(pub):
     resp = resp.follow()
 
     resp = resp.click('Document Creation')
-    resp.form['model_file$file'] = Upload('test.rtf', b'Model content')
+    resp.form['model_file'] = Upload('test.rtf', b'Model content')
     resp = resp.form.submit('submit').follow().follow()
     resp = resp.click('Document Creation')
     resp_model_content = resp.click('test.rtf')
@@ -553,8 +553,7 @@ def test_workflows_copy_status_item_create_document(pub):
     # modify file in initial status
     resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st1.id))
     resp = resp.click('Document Creation')
-    resp.form['model_file$file'] = Upload('test2.rtf', b'Something else')
-    resp.form['model_file$orexisting'].checked = False
+    resp.form['model_file'] = Upload('test2.rtf', b'Something else')
     resp = resp.form.submit('submit').follow().follow()
 
     resp = resp.click('Document Creation')
@@ -1676,7 +1675,7 @@ def test_workflows_edit_export_to_model_action(pub):
     resp = resp.click('Document Creation')
     with open(os.path.join(os.path.dirname(__file__), '../template.odt'), 'rb') as fd:
         model_content = fd.read()
-    resp.form['model_file$file'] = Upload('test.odt', model_content)
+    resp.form['model_file'] = Upload('test.odt', model_content)
     resp = resp.form.submit('submit')
     resp = resp.follow()
     resp = resp.follow()
@@ -3654,7 +3653,7 @@ def test_workflows_duplicate_with_create_document_action(pub):
     resp = resp.follow()
 
     resp = resp.click('Document Creation')
-    resp.form['model_file$file'] = Upload('test.rtf', b'Model content')
+    resp.form['model_file'] = Upload('test.rtf', b'Model content')
     resp = resp.form.submit('submit').follow().follow()
     resp = resp.click('Document Creation')
     resp_model_content = resp.click('test.rtf')
@@ -3673,8 +3672,7 @@ def test_workflows_duplicate_with_create_document_action(pub):
     # modify file in initial action
     resp = app.get('/backoffice/workflows/1/status/1/')
     resp = resp.click('Document Creation')
-    resp.form['model_file$file'] = Upload('test2.rtf', b'Something else')
-    resp.form['model_file$orexisting'].checked = False
+    resp.form['model_file'] = Upload('test2.rtf', b'Something else')
     resp = resp.form.submit('submit').follow().follow()
 
     resp = resp.click('Document Creation')
diff --git a/tests/workflow/test_all.py b/tests/workflow/test_all.py
index 7e7aeaac5..5f6b0d57e 100644
--- a/tests/workflow/test_all.py
+++ b/tests/workflow/test_all.py
@@ -46,7 +46,7 @@ from wcs.fields import (
 from wcs.formdata import Evolution
 from wcs.formdef import FormDef
 from wcs.qommon.errors import ConnectionError
-from wcs.qommon.form import Form, UploadedFile, UploadValidationError
+from wcs.qommon.form import Form, UploadedFile
 from wcs.qommon.http_request import HTTPRequest
 from wcs.qommon.ident.password_accounts import PasswordAccount
 from wcs.qommon.upload_storage import PicklableUpload
@@ -57,7 +57,7 @@ from wcs.wf.create_formdata import Mapping
 from wcs.wf.criticality import MODE_DEC, MODE_INC, MODE_SET, ModifyCriticalityWorkflowStatusItem
 from wcs.wf.dispatch import DispatchWorkflowStatusItem
 from wcs.wf.display_message import DisplayMessageWorkflowStatusItem
-from wcs.wf.export_to_model import ExportToModel, transform_to_pdf
+from wcs.wf.export_to_model import ExportToModel, UploadValidationError, transform_to_pdf
 from wcs.wf.external_workflow import ManyExternalCallsPart
 from wcs.wf.form import WorkflowFormFieldsFormDef
 from wcs.wf.geolocate import GeolocateWorkflowStatusItem
diff --git a/wcs/backoffice/deprecations.py b/wcs/backoffice/deprecations.py
index e38df84e3..216177af6 100644
--- a/wcs/backoffice/deprecations.py
+++ b/wcs/backoffice/deprecations.py
@@ -27,7 +27,7 @@ from wcs.formdef import get_formdefs_of_all_kinds
 from wcs.qommon import _, ezt, template
 from wcs.qommon.afterjobs import AfterJob
 from wcs.qommon.backoffice.menu import html_top
-from wcs.qommon.form import UploadValidationError
+from wcs.wf.export_to_model import UploadValidationError
 from wcs.workflows import Workflow
 from wcs.wscalls import NamedWsCall
 
diff --git a/wcs/qommon/form.py b/wcs/qommon/form.py
index 6069d85ce..d61222419 100644
--- a/wcs/qommon/form.py
+++ b/wcs/qommon/form.py
@@ -752,41 +752,6 @@ class UploadedFile:
         return self.get_file().read()
 
 
-class UploadValidationError(Exception):
-    pass
-
-
-class UploadWidget(CompositeWidget):
-    def __init__(self, name, value=None, directory=None, filename=None, validation=None, **kwargs):
-        CompositeWidget.__init__(self, name, **kwargs)
-        del kwargs['title']
-        kwargs.pop('hint')
-        self.value = value
-        self.directory = directory or 'uploads'
-        self.filename = filename
-        self.validation = validation
-        if value:
-            self.add(CheckboxWidget, 'orexisting', title=_('Use previous file.'), value=True)
-            self.widgets[-1].render_br = False
-            self.add(FileWidget, 'file', title=_('Or upload a new one'), **kwargs)
-        else:
-            self.add(FileWidget, 'file', **kwargs)
-
-    def _parse(self, request):
-        if self.value and self.get('orexisting'):
-            pass
-        elif self.get('file'):
-            upload = self.get('file')
-            self.value = UploadedFile(self.directory, self.filename, upload)
-            if self.validation:
-                try:
-                    self.validation(upload)
-                except UploadValidationError as e:
-                    self.error = str(e)
-        else:
-            self.value = None
-
-
 class FileWithPreviewWidget(CompositeWidget):
     """Widget that proposes a File Upload widget but that stores the file
     ondisk so it has a "readonly" mode where the filename is shown."""
diff --git a/wcs/wf/export_to_model.py b/wcs/wf/export_to_model.py
index c08aebc76..b0176a799 100644
--- a/wcs/wf/export_to_model.py
+++ b/wcs/wf/export_to_model.py
@@ -50,12 +50,11 @@ from ..qommon import _, ezt, force_str, misc
 from ..qommon.form import (
     CheckboxWidget,
     ComputedExpressionWidget,
+    FileWidget,
     RadiobuttonsWidget,
     SingleSelectWidget,
     StringWidget,
     UploadedFile,
-    UploadValidationError,
-    UploadWidget,
     VarnameWidget,
     WidgetList,
     WysiwygTextWidget,
@@ -231,6 +230,32 @@ class ExportToModelDirectory(Directory):
         return self.wfstatusitem.apply_template_to_formdata(self.formdata).read()
 
 
+class UploadValidationError(Exception):
+    pass
+
+
+class ModelFileWidget(FileWidget):
+    def __init__(self, name, value=None, directory=None, filename=None, validation=None, **kwargs):
+        super().__init__(name, value=value, **kwargs)
+        self.existing_value = self.value = value
+        self.directory = directory or 'uploads'
+        self.filename = filename
+        self.validation = validation
+
+    def _parse(self, request):
+        super()._parse(request=request)
+        if self.value:
+            try:
+                self.validation(self.value)
+            except UploadValidationError as e:
+                self.error = str(e)
+            else:
+                self.value = UploadedFile(self.directory, self.filename, self.value)
+        else:
+            # keep existing value
+            self.value = self.existing_value
+
+
 class ExportToModel(WorkflowStatusItem):
     description = _('Document Creation')
     key = 'export_to_model'
@@ -381,7 +406,7 @@ class ExportToModel(WorkflowStatusItem):
                 )
                 hint = hint_prefix + force_text(hint)
             form.add(
-                UploadWidget,
+                ModelFileWidget,
                 widget_name,
                 directory='models',
                 filename=filename,
-- 
2.38.1

