2
0
mirror of https://expo.survex.com/repositories/troggle/.git synced 2024-11-25 08:41:51 +00:00

Edit contents.json online

This commit is contained in:
Philip Sargent 2022-03-17 00:41:29 +00:00
parent e34f162688
commit 19d017a457
5 changed files with 246 additions and 56 deletions

View File

@ -53,12 +53,6 @@ class CaveForm(ModelForm):
self._errors["url"] = self.error_class(["This field cannot start with a /."]) self._errors["url"] = self.error_class(["This field cannot start with a /."])
return self.cleaned_data 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): class EntranceForm(ModelForm):
'''Only those fields for which we want to override defaults are listed here '''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 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 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/ # 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',)) CaveAndEntranceFormSet = modelformset_factory(CaveAndEntrance, exclude=('cave',))
class EntranceLetterForm(ModelForm): class EntranceLetterForm(ModelForm):

View File

@ -18,7 +18,6 @@ from troggle.core.views import expo
from troggle.core.models.troggle import Expedition, DataIssue 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.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 CaveForm, CaveAndEntranceFormSet, EntranceForm, EntranceLetterForm
#from troggle.core.forms import VersionControlCommentForm
from .auth import login_required_if_public from .auth import login_required_if_public
'''Manages the complex procedures to assemble a cave description out of the compnoents '''Manages the complex procedures to assemble a cave description out of the compnoents

View File

@ -31,15 +31,15 @@ from .auth import login_required_if_public
''' '''
todo = ''' todo = '''
- Write equivalent photo upload form system, similar to scanupload() but in expofiles/photos/ - Need to validate uploaded file as being a valid image file, not a dubious script or hack
Need to validate it 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/ - 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 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 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 - 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 class TextForm(forms.Form): # not a model-form, just a form-form
photographer = forms.CharField(strip=True) 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 @login_required_if_public
def scanupload(request, wallet=None): def scanupload(request, wallet=None):
'''Upload scanned image files into a wallet on /expofiles '''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. 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. You will find the Django documentation on forms very confusing, This is simpler.
''' '''
filesaved = False filesaved = False
actual_saved = [] 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}') # print(f'! - FORM scanupload - start {wallet}')
if wallet is None: if wallet is None:
wallet = "2021#01" # improve this later wallet = "2021#01" # improve this later
@ -90,33 +131,70 @@ def scanupload(request, wallet=None):
form = FilesForm() form = FilesForm()
if request.method == 'POST': if request.method == 'POST':
form = FilesForm(request.POST,request.FILES) if "psg" in request.POST:
#print(f'! - FilesForm POSTED') formj = WalletForm(request.POST)
# Beware. All fields returned as strings. Must re-type them as lists etc. before using or re-saving
if form.is_valid(): # Also lots of hassle with lists of strings interpreted as a single string
f = request.FILES["uploadfiles"] # Unset checkboxes do not return any value, checked ones return "True". So need initialising to False
multiple = request.FILES.getlist('uploadfiles') if formj.is_valid():
fs = FileSystemStorage(os.path.join(dirpath)) # creates wallet folder if necessary #print(f'--- JSON Update form is VALID, saving to {contents_path}')
posted = request.POST.copy()
actual_saved = [] posted.pop("csrfmiddlewaretoken") # discard this
if multiple: wd = wallet_blank_json
for f in multiple: for f in checkboxes:
actual_saved.append( fs.save(f.name, content=f) ) wd[f] = False
# print(f'! - FORM scanupload multiple {actual_saved}') #print(f'--- wd ${f}$ - {wd[f]}')
filesaved = True for f in posted:
wd[xlate[f]] = posted[f].replace("\'", "\"")
# Wallet folder created, but index and contents.json need to be created.
if not contents_path.is_file(): # double-check if posted[f] =="True":
with open(contents_path, "w") as json_file: wd[xlate[f]] = True
json.dump(wallet_blank_json, json_file, sort_keys=True, indent = 1)
index_path = dirpath / indexhtml wd["people"] = wd["people"][1:-1].replace("\"", "").split(",")
if not index_path.is_file(): # double-check for i, elem in enumerate(wd["people"]):
thishtml = wallet_blank_html.replace("YEAR", str(year)) wd["people"][i] = elem.strip()
thishtml = thishtml.replace("WALLET", str(wallet))
with open(index_path, "w") as html_file: #print(f'--- ${wd["survex file"]}$ - {type(wd["survex file"])}')
html_file.write(thishtml ) 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 = [] files = []
dirs = [] dirs = []
# print(f'! - FORM scanupload - start {wallet} {dirpath}') # print(f'! - FORM scanupload - start {wallet} {dirpath}')
@ -150,35 +228,71 @@ def scanupload(request, wallet=None):
print(message) print(message)
DataIssue.objects.create(parser='scans', message=message, url=wurl) # set URL to this wallet folder DataIssue.objects.create(parser='scans', message=message, url=wurl) # set URL to this wallet folder
raise raise
cave ="" cave =""
psg = "" psg = ""
chkplannr = ""
chkpland = ""
svxfiles = []
checked = {}
if waldata: if waldata:
if not waldata["people"]: if not waldata["people"]:
waldata["people"]=["NOBODY"] 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"]: if waldata["cave"]:
cave = waldata["cave"] cave = waldata["cave"]
if waldata["name"]: if waldata["name"]:
psg = waldata["name"] psg = waldata["name"]
if waldata["survex file"]: 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"]] waldata["survex file"] = [waldata["survex file"]]
for svx in waldata["survex file"]: for svx in waldata["survex file"]:
print(f'{svx}') svxfiles.append(svx)
if not (Path(settings.SURVEX_DATA) / svx).is_file(): if not (Path(settings.SURVEX_DATA) / svx).is_file():
message = f"! {wallet} Incorrect survex file in wallet data: {svx} not found in LOSER repo" message = f"! {wallet} Incorrect survex file in wallet data: {svx} not found in LOSER repo"
print(message) print(message)
DataIssue.objects.create(parser='scans', message=message, url=wurl) # set URL to this wallet folder 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, for f in checkboxes:
'files': files, 'dirs': dirs, 'waldata': waldata, 'create': create, 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 } 'filesaved': filesaved, 'actual_saved': actual_saved }
return render(request, 'scanuploadform.html', return render(request, 'scanuploadform.html',
{'form': form, 'wallet': wallet, **context, 'cave': cave, 'psg': psg}) {'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 @login_required_if_public
def photoupload(request, folder=None): def photoupload(request, folder=None):

View File

@ -427,6 +427,10 @@ div#difflistajax
background-color: #dfffdf; background-color: #dfffdf;
border: thin green solid; border: thin green solid;
} }
/* FORMS */
input:invalid {
border-color: red;
}
/* Using in DrawingsUpload and ScanUpload*/ /* Using in DrawingsUpload and ScanUpload*/
.fancybutton { .fancybutton {
color: #ffffff; color: #ffffff;

View File

@ -60,26 +60,104 @@
<br> <br>
<span style="font-family: monospace; font-size: 150%; "> <span style="font-family: monospace; font-size: 150%; ">
{% if cave %}<u>Cave ID</u>: <b>{{cave}}</b><br> {% endif %} {% 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>
<span style="font-family: monospace; font-size: 130%; "> <span style="font-family: monospace; font-size: 130%; ">
<!--
<table style="border: 1px; border-style: hidden;> <table style="border: 1px; border-style: hidden;>
{% for d, value in waldata.items %} {% for d, value in waldata.items %}
<tr style="border-style: hidden;"> <tr style="border-style: hidden;">
<td style="border-style: hidden; padding-right: 3em;">{{d}}</td> <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> <td> <b>{{value}}</b></td>
{% endif %}
</tr> </tr>
{% empty %} {% empty %}
<p>&lt;No JSON data here&gt; <p>&lt;No JSON data here&gt;
{% endfor %} {% endfor %}
</table> </table>
-->
</span> </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 %} {% endblock %}