From f35fb64efed6ae6d1eac0039af65dd682f5231bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Tue, 30 Jun 2020 11:32:39 +0200
Subject: [PATCH] backoffice: delete page fields (#41770)

---
 tests/test_admin_pages.py | 50 +++++++++++++++++++++++++++++++++++++++
 wcs/admin/fields.py       | 27 +++++++++++++++++----
 2 files changed, 73 insertions(+), 4 deletions(-)

diff --git a/tests/test_admin_pages.py b/tests/test_admin_pages.py
index c199a2b3..88c7afcb 100644
--- a/tests/test_admin_pages.py
+++ b/tests/test_admin_pages.py
@@ -1196,6 +1196,7 @@ def test_form_delete_field(pub):
     resp = resp.click(href='fields/')
     assert '1st field' in resp.text
     assert 'Use drag and drop' in resp.text
+    assert 'Also remove all fields from the page' not in resp.text
 
     resp = resp.click(href='1/delete')
     assert 'You are about to remove the "1st field" field.' in resp.text
@@ -1246,6 +1247,55 @@ def test_form_delete_field_existing_data(pub):
     resp = resp.follow()
     assert len(FormDef.get(1).fields) == 0
 
+
+def test_form_delete_page_field(pub):
+    create_superuser(pub)
+    create_role()
+
+    FormDef.wipe()
+    formdef = FormDef()
+    formdef.name = 'form title'
+    formdef.fields = [
+        fields.PageField(id='1', label='page 1', type='page'),
+        fields.StringField(id='2', label='field 1 1', type='string'),
+        fields.StringField(id='3', label='field 1 2', type='string'),
+        fields.PageField(id='4', label='page 2', type='page'),
+        fields.PageField(id='5', label='page 3', type='page'),
+        fields.StringField(id='6', label='field 3 1', type='string'),
+        fields.StringField(id='7', label='field 3 2', type='string'),
+    ]
+    formdef.store()
+    formdef.data_class().wipe()
+
+    app = login(get_app(pub))
+
+    # delete fields from the page
+    resp = app.get('/backoffice/forms/1/fields/1/delete')
+    assert 'You are about to remove the "page 1" field.' in resp.text
+    assert 'Also remove all fields from the page' in resp.text
+    resp.forms[0]['delete_fields'] = True
+    resp = resp.forms[0].submit()
+    resp = resp.follow()
+    assert len(FormDef.get(1).fields) == 4
+
+    # empty page
+    resp = app.get('/backoffice/forms/1/fields/4/delete')
+    assert 'You are about to remove the "page 2" field.' in resp.text
+    assert 'Also remove all fields from the page' not in resp.text
+    resp = resp.forms[0].submit()
+    resp = resp.follow()
+    assert len(FormDef.get(1).fields) == 3
+
+    # keep fields
+    resp = app.get('/backoffice/forms/1/fields/5/delete')
+    assert 'You are about to remove the "page 3" field.' in resp.text
+    assert 'Also remove all fields from the page' in resp.text
+    resp.forms[0]['delete_fields'] = False
+    resp = resp.forms[0].submit()
+    resp = resp.follow()
+    assert len(FormDef.get(1).fields) == 2
+
+
 def test_form_duplicate_field(pub):
     user = create_superuser(pub)
     create_role()
diff --git a/wcs/admin/fields.py b/wcs/admin/fields.py
index de3eafe1..a050f02f 100644
--- a/wcs/admin/fields.py
+++ b/wcs/admin/fields.py
@@ -118,6 +118,20 @@ class FieldDefPage(Directory):
             warning = self.get_deletion_extra_warning()
             if warning:
                 form.widgets.append(HtmlWidget('<div class="warningnotice">%s</div>' % warning))
+        current_field_index = self.objectdef.fields.index(self.field)
+        to_be_deleted = []
+        if self.field.type == 'page':
+            # get fields of the page and store indexes for deletion
+            for index in range(current_field_index + 1, len(self.objectdef.fields)):
+                field = self.objectdef.fields[index]
+                if field.type == 'page':
+                    # next page found; break
+                    break
+                to_be_deleted.append(index)
+            to_be_deleted.reverse()
+            # add delete_fields checkbox only if the page has fields
+            if to_be_deleted:
+                form.add(CheckboxWidget, 'delete_fields', title=_('Also remove all fields from the page'))
         form.add_submit('delete', _('Submit'))
         form.add_submit("cancel", _("Cancel"))
         if form.get_widget('cancel').parse():
@@ -130,15 +144,20 @@ class FieldDefPage(Directory):
             r += form.render()
             return r.getvalue()
         else:
-            field_index = self.objectdef.fields.index(self.field)
-            del self.objectdef.fields[field_index]
+            # delete page fields if requested
+            delete_fields = form.get_widget('delete_fields')
+            if delete_fields and delete_fields.parse():
+                for index in to_be_deleted:
+                    del self.objectdef.fields[index]
+            # delete current field
+            del self.objectdef.fields[current_field_index]
             self.objectdef.store()
             # redirect to the field that was above this one
             if self.objectdef.fields:
-                if field_index == 0:
+                if current_field_index == 0:
                     above_field = self.objectdef.fields[0]
                 else:
-                    above_field = self.objectdef.fields[field_index-1]
+                    above_field = self.objectdef.fields[current_field_index-1]
             else:
                 above_field = None
             return self.redirect_field_anchor(above_field)
-- 
2.20.1

