From f59a2e84f00b1b33eef8c3ed48e06a8548364998 Mon Sep 17 00:00:00 2001
From: Todd Dembrey <todd.dembrey@torchbox.com>
Date: Tue, 25 Sep 2018 11:36:07 +0100
Subject: [PATCH] Totally rework how the multifile upload works

---
 opentech/apply/stream_forms/fields.py         | 55 ++++++++++++++++---
 .../stream_forms/fields/multi_file_field.html | 13 +++++
 2 files changed, 60 insertions(+), 8 deletions(-)
 create mode 100644 opentech/apply/stream_forms/templates/stream_forms/fields/multi_file_field.html

diff --git a/opentech/apply/stream_forms/fields.py b/opentech/apply/stream_forms/fields.py
index 7517213d0..b2b0f44fa 100644
--- a/opentech/apply/stream_forms/fields.py
+++ b/opentech/apply/stream_forms/fields.py
@@ -1,25 +1,64 @@
-from django.forms import FileInput, FileField
+from django.forms import ClearableFileInput, FileField, CheckboxInput
 
 
-class MultiFileInput(FileInput):
+class MultiFileInput(ClearableFileInput):
     """
     File Input only returns one file from its clean method.
 
     This passes all files through the clean method and means we have a list of
     files available for post processing
     """
-    def __init__(self, *args, attrs={}, **kwargs):
-        attrs['multiple'] = True
-        super().__init__(*args, attrs=attrs, **kwargs)
+    template_name = 'stream_forms/fields/multi_file_field.html'
+
+    input_text = ''
+
+    def __init__(self, *args, **kwargs):
+        self.multiple = kwargs.pop('multiple', True)
+        super().__init__(*args, **kwargs)
+
+    def is_initial(self, value):
+        is_initial = super().is_initial
+        return all(
+            is_initial(file) for file in value
+        )
+
+    def render(self, name, value, attrs=None):
+        if self.multiple:
+            attrs['multiple'] = 'multiple'
+
+        return super().render(name, value, attrs)
 
     def value_from_datadict(self, data, files, name):
-        return files.getlist(name)
+        if hasattr(files, 'getlist'):
+            upload = files.getlist(name)
+        else:
+            upload = files.get(name)
+            if not isinstance(upload, list):
+                upload = [upload]
+
+        checkbox_name = self.clear_checkbox_name(name)
+        checkboxes = {k for k in data if checkbox_name in k}
+        cleared = {
+            i for i, checkbox in enumerate(checkboxes)
+            if CheckboxInput().value_from_datadict(data, files, checkbox)
+        }
+
+        return {
+            'files': upload,
+            'cleared': cleared,
+        }
 
 
 class MultiFileField(FileField):
     widget = MultiFileInput
 
     def clean(self, value, initial):
-        if not value:
+        files = value['files']
+        cleared = value['cleared']
+        if not files and not cleared:
             return initial
-        return [FileField().clean(file, initial) for file in value]
+        new = [FileField().clean(file, initial) for file in files]
+
+        old = [file for i, file in enumerate(initial) if i not in cleared]
+
+        return old + new
diff --git a/opentech/apply/stream_forms/templates/stream_forms/fields/multi_file_field.html b/opentech/apply/stream_forms/templates/stream_forms/fields/multi_file_field.html
new file mode 100644
index 000000000..de6bbcfaf
--- /dev/null
+++ b/opentech/apply/stream_forms/templates/stream_forms/fields/multi_file_field.html
@@ -0,0 +1,13 @@
+{% if widget.is_initial %}{{ widget.initial_text }}:
+<p>
+{{ widget.clear_checkbox_label }}
+</p>
+{% for file in widget.value %}
+<p>
+<input type="checkbox" name="{{ widget.checkbox_name }}-{{ forloop.counter }}" id="{{ widget.checkbox_id }}-{{ forloop.counter }}">
+<label for="{{ widget.checkbox_id }}-{{ forloop.counter }}"></label>
+<a href="{{ file.url }}">{{ file.filename }}</a>
+</p>
+{% endfor %}
+{{ widget.input_text }}{% endif %}
+<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
-- 
GitLab