From cedf9a91085af9648f51881c8e579641b3a1973c Mon Sep 17 00:00:00 2001
From: Oliver Walters <oliver.henry.walters@gmail.com>
Date: Wed, 13 May 2020 10:16:26 +1000
Subject: [PATCH 1/4] Attachment comment field is optional

---
 InvenTree/InvenTree/models.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/InvenTree/InvenTree/models.py b/InvenTree/InvenTree/models.py
index e192e34a0f..5ec2e2945d 100644
--- a/InvenTree/InvenTree/models.py
+++ b/InvenTree/InvenTree/models.py
@@ -56,7 +56,7 @@ class InvenTreeAttachment(models.Model):
     attachment = models.FileField(upload_to=rename_attachment,
                                   help_text=_('Select file to attach'))
 
-    comment = models.CharField(max_length=100, help_text=_('File comment'))
+    comment = models.CharField(blank=True, max_length=100, help_text=_('File comment'))
 
     user = models.ForeignKey(
         User,

From db01f3646ae2e3ab3fb527a8361a52e4f8aae095 Mon Sep 17 00:00:00 2001
From: Oliver Walters <oliver.henry.walters@gmail.com>
Date: Wed, 13 May 2020 11:13:26 +1000
Subject: [PATCH 2/4] Enable drag-and-drop attachment upload for Part

---
 .../InvenTree/static/script/inventree/inventree.js |  8 ++++++++
 InvenTree/part/templates/part/attachments.html     | 14 ++++++++++++++
 InvenTree/templates/attachment_table.html          |  4 +++-
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/InvenTree/InvenTree/static/script/inventree/inventree.js b/InvenTree/InvenTree/static/script/inventree/inventree.js
index 5995034241..45565f1d6a 100644
--- a/InvenTree/InvenTree/static/script/inventree/inventree.js
+++ b/InvenTree/InvenTree/static/script/inventree/inventree.js
@@ -140,10 +140,13 @@ function enableDragAndDrop(element, url, options) {
         url - URL to POST the file to
         options - object with following possible values:
             label - Label of the file to upload (default='file')
+            data - Other form data to upload
             success - Callback function in case of success
             error - Callback function in case of error
     */
 
+    data = options.data || {};
+
     $(element).on('drop', function(event) {
 
         var transfer = event.originalEvent.dataTransfer;
@@ -152,6 +155,11 @@ function enableDragAndDrop(element, url, options) {
 
         var formData = new FormData();
 
+        // Add the extra data
+        for (var key in data) {
+            formData.append(key, data[key]);
+        }
+
         if (isFileTransfer(transfer)) {
             formData.append(label, transfer.files[0]);
             
diff --git a/InvenTree/part/templates/part/attachments.html b/InvenTree/part/templates/part/attachments.html
index 965645b748..049ef0cd7a 100644
--- a/InvenTree/part/templates/part/attachments.html
+++ b/InvenTree/part/templates/part/attachments.html
@@ -16,6 +16,20 @@
 {% block js_ready %}
 {{ block.super }}
 
+    enableDragAndDrop(
+        '#attachment-dropzone',
+        "{% url 'part-attachment-create' %}",
+        {
+            data: {
+                part: {{ part.id }},
+            },
+            label: 'attachment',
+            success: function(data, status, xhr) {
+                location.reload();
+            }
+        }
+    );
+
     $("#new-attachment").click(function() {
         launchModalForm("{% url 'part-attachment-create' %}?part={{ part.id }}",
             {
diff --git a/InvenTree/templates/attachment_table.html b/InvenTree/templates/attachment_table.html
index 090ae566f6..71664a3ccc 100644
--- a/InvenTree/templates/attachment_table.html
+++ b/InvenTree/templates/attachment_table.html
@@ -6,6 +6,7 @@
     </div>
 </div>
 
+<div class='dropzone' id='attachment-dropzone'>
 <table class='table table-striped table-condensed' data-toolbar='#attachment-buttons' id='attachment-table'>
     <thead>
         <tr>
@@ -37,4 +38,5 @@
         </tr>
         {% endfor %}
     </tbody>
-</table>
\ No newline at end of file
+</table>
+</div>
\ No newline at end of file

From 7143c32fc95b6521dc92f41c3682424f56023fb1 Mon Sep 17 00:00:00 2001
From: Oliver Walters <oliver.henry.walters@gmail.com>
Date: Wed, 13 May 2020 11:22:57 +1000
Subject: [PATCH 3/4] Drag-and-drop attachments for stock item

---
 InvenTree/InvenTree/static/css/inventree.css       |  2 ++
 .../stock/templates/stock/item_attachments.html    | 14 ++++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/InvenTree/InvenTree/static/css/inventree.css b/InvenTree/InvenTree/static/css/inventree.css
index a1358341cc..7861be295a 100644
--- a/InvenTree/InvenTree/static/css/inventree.css
+++ b/InvenTree/InvenTree/static/css/inventree.css
@@ -346,9 +346,11 @@
     z-index: 2;
 }
 
+/*
 .dropzone * {
     pointer-events: none;
 }
+*/
 
 .dragover {
     background-color: #55A;
diff --git a/InvenTree/stock/templates/stock/item_attachments.html b/InvenTree/stock/templates/stock/item_attachments.html
index 2d056afbcf..453ab7f09b 100644
--- a/InvenTree/stock/templates/stock/item_attachments.html
+++ b/InvenTree/stock/templates/stock/item_attachments.html
@@ -17,6 +17,20 @@
 {% block js_ready %}
 {{ block.super }}
 
+enableDragAndDrop(
+        '#attachment-dropzone',
+        "{% url 'stock-item-attachment-create' %}",
+        {
+            data: {
+                stock_item: {{ item.id }},
+            },
+            label: 'attachment',
+            success: function(data, status, xhr) {
+                location.reload();
+            }
+        }
+    );
+
 $("#new-attachment").click(function() {
     launchModalForm("{% url 'stock-item-attachment-create' %}?item={{ item.id }}",
         {

From 30b5f7d507961b370716740d3a9fcac475470515 Mon Sep 17 00:00:00 2001
From: Oliver Walters <oliver.henry.walters@gmail.com>
Date: Wed, 13 May 2020 11:28:45 +1000
Subject: [PATCH 4/4] Drag and drop for order attachments

---
 .../migrations/0035_auto_20200513_0016.py     | 23 +++++++++++++++++++
 .../order/templates/order/po_attachments.html | 14 +++++++++++
 .../order/templates/order/so_attachments.html | 14 +++++++++++
 InvenTree/order/views.py                      | 10 ++++++--
 .../migrations/0038_auto_20200513_0016.py     | 18 +++++++++++++++
 .../migrations/0039_auto_20200513_0016.py     | 18 +++++++++++++++
 6 files changed, 95 insertions(+), 2 deletions(-)
 create mode 100644 InvenTree/order/migrations/0035_auto_20200513_0016.py
 create mode 100644 InvenTree/part/migrations/0038_auto_20200513_0016.py
 create mode 100644 InvenTree/stock/migrations/0039_auto_20200513_0016.py

diff --git a/InvenTree/order/migrations/0035_auto_20200513_0016.py b/InvenTree/order/migrations/0035_auto_20200513_0016.py
new file mode 100644
index 0000000000..101a55764e
--- /dev/null
+++ b/InvenTree/order/migrations/0035_auto_20200513_0016.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.0.5 on 2020-05-13 00:16
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('order', '0034_auto_20200512_1054'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='purchaseorderattachment',
+            name='comment',
+            field=models.CharField(blank=True, help_text='File comment', max_length=100),
+        ),
+        migrations.AlterField(
+            model_name='salesorderattachment',
+            name='comment',
+            field=models.CharField(blank=True, help_text='File comment', max_length=100),
+        ),
+    ]
diff --git a/InvenTree/order/templates/order/po_attachments.html b/InvenTree/order/templates/order/po_attachments.html
index a08b618fca..f5421e8760 100644
--- a/InvenTree/order/templates/order/po_attachments.html
+++ b/InvenTree/order/templates/order/po_attachments.html
@@ -20,6 +20,20 @@
 {% block js_ready %}
 {{ block.super }}
 
+enableDragAndDrop(
+    '#attachment-dropzone',
+    "{% url 'po-attachment-create' %}",
+    {
+        data: {
+            order: {{ order.id }},
+        },
+        label: 'attachment',
+        success: function(data, status, xhr) {
+            location.reload();
+        }
+    }
+);
+
 $("#new-attachment").click(function() {
     launchModalForm("{% url 'po-attachment-create' %}?order={{ order.id }}",
         {
diff --git a/InvenTree/order/templates/order/so_attachments.html b/InvenTree/order/templates/order/so_attachments.html
index aff62213e5..672d9af952 100644
--- a/InvenTree/order/templates/order/so_attachments.html
+++ b/InvenTree/order/templates/order/so_attachments.html
@@ -19,6 +19,20 @@
 {% block js_ready %}
 {{ block.super }}
 
+enableDragAndDrop(
+    '#attachment-dropzone',
+    "{% url 'so-attachment-create' %}",
+    {
+        data: {
+            order: {{ order.id }},
+        },
+        label: 'attachment',
+        success: function(data, status, xhr) {
+            location.reload();
+        }
+    }
+);
+
 $("#new-attachment").click(function() {
     launchModalForm("{% url 'so-attachment-create' %}?order={{ order.id }}",
         {
diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py
index 370c629cac..41a5b231a7 100644
--- a/InvenTree/order/views.py
+++ b/InvenTree/order/views.py
@@ -112,7 +112,10 @@ class PurchaseOrderAttachmentCreate(AjaxCreateView):
 
         initials = super(AjaxCreateView, self).get_initial()
 
-        initials["order"] = PurchaseOrder.objects.get(id=self.request.GET.get('order', -1))
+        try:
+            initials["order"] = PurchaseOrder.objects.get(id=self.request.GET.get('order', -1))
+        except (ValueError, PurchaseOrder.DoesNotExist):
+            pass
 
         return initials
 
@@ -149,7 +152,10 @@ class SalesOrderAttachmentCreate(AjaxCreateView):
     def get_initial(self):
         initials = super().get_initial().copy()
 
-        initials['order'] = SalesOrder.objects.get(id=self.request.GET.get('order', None))
+        try:
+            initials['order'] = SalesOrder.objects.get(id=self.request.GET.get('order', None))
+        except (ValueError, SalesOrder.DoesNotExist):
+            pass
 
         return initials
 
diff --git a/InvenTree/part/migrations/0038_auto_20200513_0016.py b/InvenTree/part/migrations/0038_auto_20200513_0016.py
new file mode 100644
index 0000000000..a472480186
--- /dev/null
+++ b/InvenTree/part/migrations/0038_auto_20200513_0016.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.5 on 2020-05-13 00:16
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('part', '0037_partattachment_upload_date'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='partattachment',
+            name='comment',
+            field=models.CharField(blank=True, help_text='File comment', max_length=100),
+        ),
+    ]
diff --git a/InvenTree/stock/migrations/0039_auto_20200513_0016.py b/InvenTree/stock/migrations/0039_auto_20200513_0016.py
new file mode 100644
index 0000000000..dacf666779
--- /dev/null
+++ b/InvenTree/stock/migrations/0039_auto_20200513_0016.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.5 on 2020-05-13 00:16
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('stock', '0038_stockitemattachment_upload_date'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='stockitemattachment',
+            name='comment',
+            field=models.CharField(blank=True, help_text='File comment', max_length=100),
+        ),
+    ]