From 8f1d6e2cc22563bd4fca94f5e7e08085154e8262 Mon Sep 17 00:00:00 2001
From: Philip Sargent <philip.sargent@klebos.com>
Date: Fri, 30 Apr 2021 18:02:05 +0100
Subject: [PATCH] file upload integration test working

---
 core/TESTS/tests.py           |  3 +-
 core/TESTS/tests_logins.py    | 37 ++++++++++++++++
 core/forms.py                 | 52 +----------------------
 core/models/troggle.py        |  9 ----
 core/views/other.py           | 80 ++++++++++++++++++++++++++++++++---
 templates/_fileupload.html    | 18 --------
 templates/scanuploadform.html | 29 ++++++-------
 urls.py                       |  2 +-
 8 files changed, 128 insertions(+), 102 deletions(-)
 delete mode 100644 templates/_fileupload.html

diff --git a/core/TESTS/tests.py b/core/TESTS/tests.py
index 77cd998..7a12637 100644
--- a/core/TESTS/tests.py
+++ b/core/TESTS/tests.py
@@ -25,6 +25,7 @@ todo = '''ADD TESTS when we are redirecting /expofiles/ to a remote file-deliver
 
 import unittest
 import re
+from http import HTTPStatus
 from django.test import TestCase, SimpleTestCase, Client
 
 
@@ -170,8 +171,6 @@ class PageTests(TestCase):
         ph = r'All Survey scans folders '
         content = response.content.decode()
         phmatch    = re.search(ph, content)
-        # with open('ss-op.html', 'w') as f: 
-            # f.write(content) 
         self.assertIsNotNone(phmatch, "Failed to find expected text: '" + ph +"'") 
 
 
diff --git a/core/TESTS/tests_logins.py b/core/TESTS/tests_logins.py
index 45bd33e..66e69c6 100644
--- a/core/TESTS/tests_logins.py
+++ b/core/TESTS/tests_logins.py
@@ -7,6 +7,8 @@ Modified for Expo April 2021.
 
 import unittest
 import re
+from http import HTTPStatus
+
 from django.test import TestCase, SimpleTestCase, TransactionTestCase, Client
 
              
@@ -61,6 +63,41 @@ class FixturePageTests(TestCase):
         t    = re.search(r'Troggle administration', content)
         self.assertIsNone(t, 'Logged in as \'' + u.username + '\' (not staff) but still managed to get the Admin page' )
 
+class PostTests(TestCase):
+    '''
+    '''
+    fixtures = ['auth_users']
+
+    @classmethod
+    def setUpTestData(cls):
+        pass
+        
+    def setUp(self):
+        from django.contrib.auth.models import User
+        self.user = User.objects.get(username='expotest')
+        self.client = Client()
+
+    def test_scan_upload(self):
+        '''Test file upload. Need to login first.
+        '''
+        c = self.client
+        from django.contrib.auth.models import User
+        u = User.objects.get(username='expotest')
+         
+        self.assertTrue(u.is_active, 'User \'' + u.username + '\' is INACTIVE')
+        logged_in = c.login(username=u.username, password='secretword') 
+
+        with open('README.txt','r') as testf:
+            response = self.client.post('/scanupload/2021:02', data={'title': '2021#00', 'name': 'README.txt', 'scanfiles': testf })
+            content = response.content.decode()
+            self.assertEqual(response.status_code, 200)
+            self.assertEqual(response.status_code, HTTPStatus.OK)
+            with open('test_up.html', 'w') as f: 
+                f.write(content) 
+            t    = re.search(r'README.txt', content)
+            self.assertIsNone(t, 'Logged in as \'' + u.username + '\' (not staff) but failed to upload file' )
+
+
 
 class ComplexLoginTests(TestCase):
     '''These test the login and capabilities of logged-in users, they do not use fixtures'''
diff --git a/core/forms.py b/core/forms.py
index a7b44db..2781c67 100644
--- a/core/forms.py
+++ b/core/forms.py
@@ -8,7 +8,7 @@ from django.contrib.admin.widgets import AdminDateWidget
 
 #from tinymce.widgets import TinyMCE
 
-from troggle.core.models.troggle import Person, PersonExpedition, Expedition, SimpleFileModel
+from troggle.core.models.troggle import Person, PersonExpedition, Expedition
 from troggle.core.models.caves import Cave, LogbookEntry, QM, Entrance, CaveAndEntrance
 
 '''These are all the Forms used by troggle
@@ -107,55 +107,5 @@ class EntranceLetterForm(ModelForm):
         model = CaveAndEntrance
         exclude = ('cave', 'entrance')
 
-def get_name(pe):
-            if pe.nickname:
-                return pe.nickname
-            else:
-                return pe.person.first_name
-
-class UploadFileForm(forms.Form):
-    """Only called by views.others.newFile() which seems to be only about logbook files.
-    """
-    title = forms.CharField(max_length=50)
-    file  = forms.FileField()
-    #html = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
-    html = forms.CharField(widget=forms.Textarea(attrs={"cols":80, "rows":20}))
-    lon_utm = forms.FloatField(required=False)
-    lat_utm = forms.FloatField(required=False)
-    slug = forms.CharField(max_length=50)
-    date = forms.DateField(required=False)
-    survey_point = forms.CharField()
-
-    # Because this has EXECUTABLE statements in its signature (the fields) they get
-    # executed when this module is LOADED. Which barfs horribly.
-    # so all put in an __init__ method instead pending deletion or rewriting
-    def __init__(self):
-        #This next line is the one that causes django.setup() to BARF LOUDLY
-        caves = [cave.slug for cave in Cave.objects.all()]
-        #caves.sort() # sort needs rewriting for python3
-        caves = ["-----"] + caves
-        cave = forms.ChoiceField([(c, c) for c in caves], required=False)
-        
-        entrance = forms.ChoiceField([("-----", "Please select a cave"), ], required=False) 
-
-        expeditions = [e.year for e in Expedition.objects.all()]
-        expeditions.sort()
-        expeditions = ["-----"] + expeditions
-        expedition = forms.ChoiceField([(e, e) for e in expeditions], required=False)  
-
-        qm = forms.ChoiceField([("-----", "Please select a cave"), ], required=False) 
-        logbookentry = forms.ChoiceField([("-----", "Please select an expedition"), ], required=False) 
-        person = forms.ChoiceField([("-----", "Please select an expedition"), ], required=False) 
-
-
-        
-class SimpleUploadFileForm(forms.ModelForm):
-    """New in April 2021
-    """
-    class Meta:
-        model = SimpleFileModel
-        fields = ('title', 'simplefile',)   
-
-
 
 
diff --git a/core/models/troggle.py b/core/models/troggle.py
index f9558ff..32a5064 100644
--- a/core/models/troggle.py
+++ b/core/models/troggle.py
@@ -229,12 +229,3 @@ class PersonExpedition(TroggleModel):
     def day_max(self):
         res = self.persontrip_set.all().aggregate(day_max=models.Max("expeditionday__date"))
         return res["day_max"]
-
-class SimpleFileModel(models.Model):
-    simplefile = models.FileField(upload_to='fileuploads/') # in MEDIA_FILES
-    title = models.CharField(max_length = 80)
-    class Meta:
-        ordering = ['title']
-     
-    def __str__(self):
-        return f"{self.title}"
diff --git a/core/views/other.py b/core/views/other.py
index d9eba3f..c721a61 100644
--- a/core/views/other.py
+++ b/core/views/other.py
@@ -2,6 +2,7 @@ import re, os
 from pathlib import Path
 
 from django import forms
+
 from django.conf import settings
 from django.urls import reverse
 from django.db.models import Q
@@ -16,7 +17,6 @@ from troggle.parsers.imports import import_logbooks, import_QMs, import_drawings
 from troggle.core.models.troggle import Expedition, Person, PersonExpedition
 from troggle.core.models.caves import LogbookEntry, QM, Cave, PersonTrip
 from .login import login_required_if_public
-from troggle.core.forms import UploadFileForm, SimpleUploadFileForm
 
 '''Utility functions and code to serve the control panel and individual user's 
 progress and task list (deprecated as we do not have individual user login).
@@ -203,6 +203,11 @@ def ajax_test(request):
                                    content_type="application/json")
                                    
 
+
+class MyForm(forms.Form):  # not a model-form
+    title = forms.CharField(max_length=20)
+    scanfiles = forms.FileField() # in MEDIA_FILES
+
 @login_required_if_public
 def scanupload(request, wallet=None):
     '''Upload one scanned image file into a wallet on /expofiles
@@ -228,13 +233,15 @@ def scanupload(request, wallet=None):
     wallet = wallet.replace(':','#')
     dirpath = Path(settings.SURVEY_SCANS, year, wallet)
     
+    form = MyForm()
+    
     if request.method == 'POST':
-        form = SimpleUploadFileForm(request.POST,request.FILES)
+        form = MyForm(request.POST,request.FILES)
         if form.is_valid():
             #form.save() # comment out so nothing saved in MEDIA_ROOT/fileuploads
-            f = request.FILES["simplefile"]
+            f = request.FILES["scanfiles"]
             w = request.POST["title"]
-            multiple = request.FILES.getlist('simplefile')
+            multiple = request.FILES.getlist('scanfiles')
             fs = FileSystemStorage(os.path.join(settings.SURVEY_SCANS, year, w))
            
             actual_saved = []
@@ -260,7 +267,70 @@ def scanupload(request, wallet=None):
         files.append('(no image files in wallet)')
         
 
-    form = SimpleUploadFileForm()
     return render(request, 'scanuploadform.html', 
         {'form': form, 'wallet': wallet, 'year': year, 'prev': prev, 'next': next, 'prevy': prevy, 'nexty': nexty, 'files': files, 'dirs': dirs, 'filesaved': filesaved, 'actual_saved': actual_saved})
 
+
+# @login_required_if_public
+# def verysimplescanupload(request, wallet=None):
+    # '''Upload one scanned image file into a wallet on /expofiles
+    # '''
+    # print(f'VERY SIMPLE')
+    # filesaved = False
+    # actual_saved = []
+    # print(f'! - FORM scanupload - start {wallet}')
+    # if wallet is None:
+        # wallet = "2021#01" # improve this later
+    # if not re.match('(19|20)\d\d:\d\d', wallet):
+        # wallet = "2021:01" # improve this later
+    
+    # year = wallet[:4]
+    # nexty = f'{int(year)+1}'
+    # prevy = f'{int(year)-1}'
+    # wnumber = wallet[5:]
+    # next = f'{int(wnumber)+1:02d}'
+    # prev = f'{int(wnumber)-1:02d}'
+    
+    # if int(wnumber) == 0:
+        # prev = f'{int(wnumber):02d}'
+    
+    # wallet = wallet.replace(':','#')
+    # dirpath = Path(settings.SURVEY_SCANS, year, wallet)
+    
+    # form = MyForm()
+
+    # if request.method == 'POST':
+        # form = MyForm(request.POST,request.FILES) 
+        # if form.is_valid():
+            # #form.save() # comment out so nothing saved in MEDIA_ROOT/fileuploads
+            # f = request.FILES["simplefile"]
+            # w = request.POST["title"]
+            # multiple = request.FILES.getlist('simplefile')
+            # fs = FileSystemStorage(os.path.join(settings.SURVEY_SCANS, year, w))
+           
+            # actual_saved = []
+            # if multiple:
+                # for f in multiple:
+                    # actual_saved.append( fs.save(f.name, content=f) )
+                    # #print(f'! - FORM scanupload multiple {actual_saved}')
+            # filesaved = True
+    
+    # files = []
+    # dirs = []
+    # #print(f'! - FORM scanupload - start {wallet} {dirpath}')
+    # try:
+        # for f in dirpath.iterdir():
+            # if f.is_dir():
+                # dirs.append(f.name)
+            # if f.is_file():
+                # if f.name != 'contents.json' and f.name != 'walletindex.html':
+                    # files.append(f.name)
+    # except FileNotFoundError:
+        # files.append('(no wallet yet - would be created)')
+    # if len(files) ==0 :
+        # files.append('(no image files in wallet)')
+        
+
+    # return render(request, 'scanuploadform.html', 
+        # {'form': form, 'wallet': wallet, 'year': year, 'prev': prev, 'next': next, 'prevy': prevy, 'nexty': nexty, 'files': files, 'dirs': dirs, 'filesaved': filesaved, 'actual_saved': actual_saved})
+
diff --git a/templates/_fileupload.html b/templates/_fileupload.html
deleted file mode 100644
index f71760d..0000000
--- a/templates/_fileupload.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<h2>Fileupload</h2>
-
-<ul>
-{% for fileuploaded in filesuploaded %}
-<li>UPLOADEDFILE: {{fileuploaded}}
-</li>
-{% endfor %}
-</ul>
-<p>MESSAGE: {{message}}
-</p>
-
-{% if not filesuploaded %}
-<form action="" method="POST">
-    <p>file to upload</p>
-    <p><input type="file" name="file1"/></p>
-    <p><input type="submit" name="submit" value="Submit" /></p>
-</form>
-{% endif %}
diff --git a/templates/scanuploadform.html b/templates/scanuploadform.html
index ed16301..4beae89 100644
--- a/templates/scanuploadform.html
+++ b/templates/scanuploadform.html
@@ -16,25 +16,12 @@
 </p>
 
 
-    <div style = "max-width:40%;">
-
-    {% if filesaved %}
-        <p style="margin-left:20%;">
-        <b>File(s) saved as 
-        {% for f in actual_saved %}
-        <em>'{{f}}'</em> 
-        {% endfor %}
-        <br><br>Upload more?</b>
-        </p>
-        <br>
-    {% endif %}
-
-
+<div style = "max-width:40%;">
     <form method ='post' enctype ="multipart/form-data">
         {% csrf_token %}              
             <br>         
                    <input type = "file" multiple="multiple"  style = "margin-left:20%;" 
-                   placeholder = "Simplefile" name = "simplefile" id="files">
+                   placeholder = "Scanfiles" name = "scanfiles" id="scanfiles">
             <br>  <br>    
                    <input type = "text" size = "8" style = "margin-left:20%;" 
                    placeholder = "Wallet id e.g. 2021#23" name = "title" value='{{wallet}}'id="wallet"><label for="wallet"> Wallet id</label>
@@ -46,7 +33,17 @@
                    </button>
                 </center>
     </form>
-    </div>
+    {% if filesaved %}
+        <p style="margin-left:20%;">
+        <b>File(s) saved as 
+        {% for f in actual_saved %}
+        <em>'{{f}}'</em> 
+        {% endfor %}
+        <br><br>Upload more?</b>
+        </p>
+        <br>
+    {% endif %}
+</div>
 
         <p style="margin-left:20%;">
 {% for f in files %}
diff --git a/urls.py b/urls.py
index 4b4ccf8..85a9759 100644
--- a/urls.py
+++ b/urls.py
@@ -10,7 +10,7 @@ from django.urls import reverse, resolve
 
 from troggle.core.views import caves, statistics, survex
 from troggle.core.views.surveys import scansingle, singlewallet, allwallets, dwgdata, dwgfilesingle, dwgfileupload
-from troggle.core.views.other import troggle404, frontpage, todos, controlpanel, frontpage, scanupload
+from troggle.core.views.other import troggle404, frontpage, todos, controlpanel, frontpage, scanupload 
 from troggle.core.views.other import exportlogbook
 from troggle.core.views.caves import ent, cavepage
 from troggle.core.views.logbooks import get_logbook_entries, logbookentry, logbookSearch