diff options
author | Philip Sargent <philip.sargent@klebos.com> | 2022-03-17 00:41:29 +0000 |
---|---|---|
committer | Philip Sargent <philip.sargent@klebos.com> | 2022-03-17 00:41:29 +0000 |
commit | 19d017a45712b0e59c5e7c3c0bd726cae0b7dda6 (patch) | |
tree | 79cc1771d2f95eaf72637c6a69e78c918e2535f8 | |
parent | e34f162688cf7e06c030e25e67865a17337bdeb8 (diff) | |
download | troggle-19d017a45712b0e59c5e7c3c0bd726cae0b7dda6.tar.gz troggle-19d017a45712b0e59c5e7c3c0bd726cae0b7dda6.tar.bz2 troggle-19d017a45712b0e59c5e7c3c0bd726cae0b7dda6.zip |
Edit contents.json online
-rw-r--r-- | core/forms.py | 11 | ||||
-rw-r--r-- | core/views/caves.py | 1 | ||||
-rw-r--r-- | core/views/uploads.py | 192 | ||||
-rw-r--r-- | media/css/trog3.css | 4 | ||||
-rw-r--r-- | templates/scanuploadform.html | 96 |
5 files changed, 247 insertions, 57 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 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 "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 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 @@ <br> <span style="font-family: monospace; font-size: 150%; "> {% if cave %}<u>Cave ID</u>: <b>{{cave}}</b><br> {% endif %} -{% if psg %}<u>Survey area</u>: <b>{{psg}}</b><br><br> {% endif %} +{% if psg %}<u>Survey area</u>: <b>{{psg}}</b><br>{% endif %} +{% if svxfiles %}<u>Survey files</u>: + {% for svx in svxfiles%} + <a href="/survexfile/{{svx}}">{{svx}}</a> + {% endfor %} + +<br><br> +{% endif %} </span> <span style="font-family: monospace; font-size: 130%; "> +<!-- <table style="border: 1px; border-style: hidden;> {% for d, value in waldata.items %} <tr style="border-style: hidden;"> <td style="border-style: hidden; padding-right: 3em;">{{d}}</td> - {% if d == "survex file" %} - <td> - {% for svx in value %} - <a href="/survexfile/{{svx}}">{{svx}}</a> - {% endfor %} - </td> - {% else %} + <td> <b>{{value}}</b></td> - {% endif %} + </tr> {% empty %} <p><No JSON data here> {% endfor %} </table> +--> </span> +<style> +input {font-family: monospace; font-weight: bold; font-size: 100%; padding: 0.5em; } +</style> +<div style = "max-width:100%; margin-left:15%; font-family: monospace; font-weight: bold; font-size: 150%; text-align: right; " > + <form method ='post'> + {% csrf_token %} + <label for="date">Date of the survey trip</label> + <input + label = "Date" name = "date" size="12" + title="Date of the trip in ISO format: 2020-08-17" + placeholder="{{date}}" value="{{date}}" required /> +<br> + <label for="cave">Cave ID</label> + <input + label = "Cave" name = "cave" size="12" + title="Cave id e.g. 2017-DM-01 or 1623/256" + placeholder="{{cave}}" value="{{cave}}" /> +<br> + <label for="psg">Survey area</label> + <input + label = "Survey area" name = "psg" size ="{{psgsize}}" + title="Survey area, e.g. White Elephant or Nieder Augst Eck" + placeholder="{{psg}}" value="{{psg}}" /> +<br> + <label for="plannr">Plan not required ?</label> + <input type="checkbox" name="plannr" id="plannr" value=" True" {% if "plan not required" in checked %}checked{% endif %}> +<br> + <label for="elevnr">Elevation not required ?</label> + <input type="checkbox" name="elevnr" id="elevnr" value="True" {% if "elev not required" in checked %}checked{% endif %}> +<br> + <label for="survexvnr">Survex file not required ?</label> + <input type="checkbox" name="survexvnr" id="survexvnr" value="True" {% if "survex not required" in checked %}checked{% endif %}> +<br> + <label for="pland">Plan drawn ?</label> + <input type="checkbox" name="pland" id="pland" value="True" {{chkpland}} {% if "plan drawn" in checked %}checked{% endif %}> +<br> + <label for="elevd">Elevation drawn ?</label> + <input type="checkbox" name="elevd" id="elevd" value="True" {% if "elev drawn" in checked %}checked{% endif %}> +<br> + <label for="descriptionw">Cave description written ?</label> + <input type="checkbox" name="descriptionw" id="descriptionw" value="True" {% if "description written" in checked %}checked{% endif %}> +<br> + <label for="qmsw">QMs written ?</label> + <input type="checkbox" name="qmsw" id="qmsw" value="True" {% if "qms written" in checked %}checked{% endif %}> +<br> + <label for="websiteupt">Website updated ?</label> + <input type="checkbox" name="websiteupt" id="websiteupt" value="True" {% if "website updated" in checked %}checked{% endif %}> +<br> + <label for="electronic">Electronic survey ?</label> + <input type="checkbox" name="electronic" id="electronic" value="True" {% if "electronic survey" in checked %}checked{% endif %}> +<br> + <label for="people">List of people on the survey trip</label> + <input + label = "People" name = "people" size ="{{peoplesize}}" + title="List of people on the survey trip" + placeholder="{{people}}" value="{{people}}" /> +<br> + <label for="url">URL of cave description</label> + <input + label = "URL" name = "url" size ="{{urlsize}}" + title="URL of cave description, e.g. /1623/264/264.html" + placeholder="{{url}}" value="{{url}}" /> +<br> + <label for="survex">List of survex files</label> + <input + label = "survex" name = "survex" size ="{{survexsize}}" + title="List of survex files using this data" + placeholder="{{survex}}" value="{{survex}}" /> +<br><br> + <button class="fancybutton" style="padding: 0.5em 25px; margin-left: 155px; font-size: 90%; " + type = "submit" value = "Edit" > + Submit changes + </button> + </form> +</div> {% endblock %} |