From 19d017a45712b0e59c5e7c3c0bd726cae0b7dda6 Mon Sep 17 00:00:00 2001 From: Philip Sargent Date: Thu, 17 Mar 2022 00:41:29 +0000 Subject: [PATCH] Edit contents.json online --- core/forms.py | 11 +- core/views/caves.py | 1 - core/views/uploads.py | 190 +++++++++++++++++++++++++++------- media/css/trog3.css | 4 + templates/scanuploadform.html | 96 +++++++++++++++-- 5 files changed, 246 insertions(+), 56 deletions(-) diff --git a/core/forms.py b/core/forms.py index a2727f8..08f7e6c 100644 --- a/core/forms.py +++ b/core/forms.py @@ -53,12 +53,6 @@ class CaveForm(ModelForm): self._errors["url"] = self.error_class(["This field cannot start with a /."]) return self.cleaned_data -# class VersionControlCommentForm(forms.Form): - # '''Was appended to all forms. Not used currently - # ''' - # description_of_change = forms.CharField(required = True, widget=forms.Textarea(attrs={'rows':2})) - - class EntranceForm(ModelForm): '''Only those fields for which we want to override defaults are listed here the other fields are present on the form, but use the default presentaiton style @@ -95,9 +89,10 @@ class EntranceForm(ModelForm): # This next line is called from the templates/edit_cave2.html template. -# This is sufficeint to create an entire entry for for the cave fields automatically +# This is sufficient to create an entire entry for for the cave fields automatically # http://localhost:8000/cave/new/ -# using django built-in Deep magic. https://docs.djangoproject.com/en/2.2/topics/forms/modelforms/ +# using django built-in Deep Magic. https://docs.djangoproject.com/en/3.2/topics/forms/modelforms/ +# for forms which map directly onto a Django Model CaveAndEntranceFormSet = modelformset_factory(CaveAndEntrance, exclude=('cave',)) class EntranceLetterForm(ModelForm): diff --git a/core/views/caves.py b/core/views/caves.py index 1e9c3c4..4956004 100644 --- a/core/views/caves.py +++ b/core/views/caves.py @@ -18,7 +18,6 @@ from troggle.core.views import expo from troggle.core.models.troggle import Expedition, DataIssue from troggle.core.models.caves import CaveSlug, Cave, CaveAndEntrance, QM, EntranceSlug, Entrance, Area, SurvexStation, GetCaveLookup from troggle.core.forms import CaveForm, CaveAndEntranceFormSet, EntranceForm, EntranceLetterForm -#from troggle.core.forms import VersionControlCommentForm from .auth import login_required_if_public '''Manages the complex procedures to assemble a cave description out of the compnoents diff --git a/core/views/uploads.py b/core/views/uploads.py index 0acd326..dfaa29d 100644 --- a/core/views/uploads.py +++ b/core/views/uploads.py @@ -31,15 +31,15 @@ from .auth import login_required_if_public ''' todo = ''' -- Write equivalent photo upload form system, similar to scanupload() but in expofiles/photos/ - Need to validate it as being a valid image file, not a dubious script or hack +- Need to validate uploaded file as being a valid image file, not a dubious script or hack - Write equivalent GPX upload form system, similar to scanupload() but in expofiles/gpslogs/ Need to validate it as being a valid GPX file using an XML parser, not a dubious script or hack - Validate Tunnel & Therion files using an XML parser in dwgupload() -- Validate image files using a magic recogniser in scanupload() +- Validate image files using a magic recogniser in scanupload() https://pypi.org/project/reportlab/ or + https://stackoverflow.com/questions/889333/how-to-check-if-a-file-is-a-valid-image-file - Enable folder creation in dwguploads or as a separate form @@ -52,14 +52,55 @@ class FilesForm(forms.Form): # not a model-form, just a form-form class TextForm(forms.Form): # not a model-form, just a form-form photographer = forms.CharField(strip=True) +class WalletForm(forms.Form): # not a model-form, just a form-form + descriptionw = forms.CharField(strip=True, required=False) + people = forms.CharField(strip=True, required=False) + survexnr = forms.CharField(strip=True, required=False) + qmsw = forms.CharField(strip=True, required=False) + date = forms.CharField(strip=True, required=True) # the only required field + websiteupt = forms.CharField(strip=True, required=False) + elevnr = forms.CharField(strip=True, required=False) + cave = forms.CharField(strip=True, required=False) + psg = forms.CharField(strip=True, required=False) + plannr = forms.CharField(strip=True, required=False) + electronic = forms.CharField(strip=True, required=False) + pland = forms.CharField(strip=True, required=False) + elevd = forms.CharField(strip=True, required=False) + url = forms.CharField(strip=True, required=False) + survex = forms.CharField(strip=True, required=False) + +xlate = {"url": "description url", + "descriptionw": "description written", + "people": "people", + "date": "date", + "cave": "cave", + "people": "people", + "plannr": "plan not required", + "survexnr": "survex not required", + "qmsw": "qms written", + "elevnr": "elev not required", + "websiteupt": "website updated", + "electronic": "electronic survey", + "pland": "plan drawn", + "elevd": "elev drawn", + "psg": "name", + "survex": "survex file", + } + @login_required_if_public def scanupload(request, wallet=None): '''Upload scanned image files into a wallet on /expofiles + Also display and edit the contents.json data in the wallet. + This does NOT use a Django model linked to a Django form. Just a simple Django form. You will find the Django documentation on forms very confusing, This is simpler. ''' filesaved = False actual_saved = [] + + checkboxes = ["description written", "survex not required", "qms written", "website updated", + "plan not required", "plan drawn", "elev not required", "elev drawn", "electronic survey" ] + # print(f'! - FORM scanupload - start {wallet}') if wallet is None: wallet = "2021#01" # improve this later @@ -90,33 +131,70 @@ def scanupload(request, wallet=None): form = FilesForm() if request.method == 'POST': - form = FilesForm(request.POST,request.FILES) - #print(f'! - FilesForm POSTED') - - if form.is_valid(): - f = request.FILES["uploadfiles"] - multiple = request.FILES.getlist('uploadfiles') - fs = FileSystemStorage(os.path.join(dirpath)) # creates wallet folder if necessary - - 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 - - # Wallet folder created, but index and contents.json need to be created. + if "psg" in request.POST: + formj = WalletForm(request.POST) + # Beware. All fields returned as strings. Must re-type them as lists etc. before using or re-saving + # Also lots of hassle with lists of strings interpreted as a single string + # Unset checkboxes do not return any value, checked ones return "True". So need initialising to False + if formj.is_valid(): + #print(f'--- JSON Update form is VALID, saving to {contents_path}') + posted = request.POST.copy() + posted.pop("csrfmiddlewaretoken") # discard this + wd = wallet_blank_json + for f in checkboxes: + wd[f] = False + #print(f'--- wd ${f}$ - {wd[f]}') + for f in posted: + wd[xlate[f]] = posted[f].replace("\'", "\"") - if not contents_path.is_file(): # double-check - with open(contents_path, "w") as json_file: - json.dump(wallet_blank_json, json_file, sort_keys=True, indent = 1) - index_path = dirpath / indexhtml - if not index_path.is_file(): # double-check - thishtml = wallet_blank_html.replace("YEAR", str(year)) - thishtml = thishtml.replace("WALLET", str(wallet)) - with open(index_path, "w") as html_file: - html_file.write(thishtml ) - + if posted[f] =="True": + wd[xlate[f]] = True + + wd["people"] = wd["people"][1:-1].replace("\"", "").split(",") + for i, elem in enumerate(wd["people"]): + wd["people"][i] = elem.strip() + + #print(f'--- ${wd["survex file"]}$ - {type(wd["survex file"])}') + if wd["survex file"][0] == '[': + wd["survex file"] = wd["survex file"][1:-1] + wd["survex file"] = wd["survex file"].replace("\"", "").split(",") + for i, elem in enumerate(wd["survex file"]): + wd["survex file"][i] = elem.strip() + #print(f'--- {wd["survex file"]} - {type(wd["survex file"])}') + + with open(contents_path, "w") as jfile: + json.dump(wd, jfile, indent = 1) + # print(f'--- FINISHED saving to JSON\n') + else: + print(f'--- INVALID JSON Update form submitted') + print(formj.errors) + return render(request,'errors/generic.html', {'message': formj.errors}) + + else: + form = FilesForm(request.POST,request.FILES) + + if form.is_valid(): + f = request.FILES["uploadfiles"] + multiple = request.FILES.getlist('uploadfiles') + fs = FileSystemStorage(os.path.join(dirpath)) # creates wallet folder if necessary + + 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 + + if not contents_path.is_file(): # double-check + with open(contents_path, "w") as json_file: + json.dump(wallet_blank_json, json_file, sort_keys=True, indent = 1) + index_path = dirpath / indexhtml + if not index_path.is_file(): # double-check + thishtml = wallet_blank_html.replace("YEAR", str(year)) + thishtml = thishtml.replace("WALLET", str(wallet)) + with open(index_path, "w") as html_file: + html_file.write(thishtml ) + files = [] dirs = [] # print(f'! - FORM scanupload - start {wallet} {dirpath}') @@ -150,35 +228,71 @@ def scanupload(request, wallet=None): print(message) DataIssue.objects.create(parser='scans', message=message, url=wurl) # set URL to this wallet folder raise - cave ="" psg = "" - + chkplannr = "" + chkpland = "" + svxfiles = [] + checked = {} if waldata: if not waldata["people"]: waldata["people"]=["NOBODY"] - + if not type(waldata["people"])==list: + if waldata["people"][0] == '"': + waldata["people"] = waldata["people"][1:-1] + waldata["people"] = list(waldata["people"]) + + if not waldata["description url"]: + waldata["description url"]="" if waldata["cave"]: cave = waldata["cave"] if waldata["name"]: psg = waldata["name"] + if waldata["survex file"]: - if not isinstance(waldata["survex file"], list): + #print(f'+++ ${waldata["survex file"]}$ {type(waldata["survex file"])}') + if not type(waldata["survex file"])==list: # a string also is a sequence type, so do it this way + #print(f'+++ NOT A LIST: {waldata["survex file"]} {type(waldata["survex file"])}') waldata["survex file"] = [waldata["survex file"]] for svx in waldata["survex file"]: - print(f'{svx}') + svxfiles.append(svx) if not (Path(settings.SURVEX_DATA) / svx).is_file(): message = f"! {wallet} Incorrect survex file in wallet data: {svx} not found in LOSER repo" print(message) DataIssue.objects.create(parser='scans', message=message, url=wurl) # set URL to this wallet folder - context = {'year': year, 'prev': prev, 'next': next, 'prevy': prevy, 'nexty': nexty, - 'files': files, 'dirs': dirs, 'waldata': waldata, 'create': create, + for f in checkboxes: + if waldata[f]: + checked[f] = "checked" + + context = {'year': year, 'prev': prev, 'next': next, 'prevy': prevy, 'nexty': nexty, + 'files': files, 'dirs': dirs, 'waldata': waldata, 'svxfiles': svxfiles, + 'checked': checked, + 'create': create, + 'people': waldata["people"], 'peoplesize': str(len(str(waldata["people"]))), 'filesaved': filesaved, 'actual_saved': actual_saved } - return render(request, 'scanuploadform.html', - {'form': form, 'wallet': wallet, **context, 'cave': cave, 'psg': psg}) + return render(request, 'scanuploadform.html', + {'form': form, 'wallet': wallet, **context, + 'date': waldata["date"], + 'url': waldata["description url"], 'urlsize': str(len(str(waldata["description url"]))), + 'survex': waldata["survex file"], 'survexsize': str(len(str(waldata["survex file"]))), + 'cave': cave, 'psg': psg, 'psgsize': str(max(12,len(str(psg))))}) + else: # no wallet here + context = {'year': year, 'prev': prev, 'next': next, 'prevy': prevy, 'nexty': nexty, + 'files': files, 'dirs': dirs, 'waldata': waldata, 'svxfiles': svxfiles, + 'checked': checked, + 'create': create, + 'people': "", 'peoplesize': 12, + 'filesaved': filesaved, 'actual_saved': actual_saved } + + return render(request, 'scanuploadform.html', + {'form': form, 'wallet': wallet, **context, + 'date': "", + 'url': "", 'urlsize': 12, + 'survex': "", 'survexsize': 12, + 'cave': cave, 'psg': psg, 'psgsize': 12}) @login_required_if_public def photoupload(request, folder=None): diff --git a/media/css/trog3.css b/media/css/trog3.css index 3da931a..54e6e84 100644 --- a/media/css/trog3.css +++ b/media/css/trog3.css @@ -427,6 +427,10 @@ div#difflistajax background-color: #dfffdf; border: thin green solid; } +/* FORMS */ +input:invalid { + border-color: red; +} /* Using in DrawingsUpload and ScanUpload*/ .fancybutton { color: #ffffff; diff --git a/templates/scanuploadform.html b/templates/scanuploadform.html index 095fad9..8f4e26e 100644 --- a/templates/scanuploadform.html +++ b/templates/scanuploadform.html @@ -60,26 +60,104 @@
{% if cave %}Cave ID: {{cave}}
{% endif %} -{% if psg %}Survey area: {{psg}}

{% endif %} +{% if psg %}Survey area: {{psg}}
{% endif %} +{% if svxfiles %}Survey files: + {% for svx in svxfiles%} + {{svx}} + {% endfor %} + +

+{% endif %}
+ + +
+
+ {% csrf_token %} + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +

+ +
+
{% endblock %}