diff --git a/core/views/caves.py b/core/views/caves.py
index 993519c4..6d2d32a3 100644
--- a/core/views/caves.py
+++ b/core/views/caves.py
@@ -639,6 +639,7 @@ def edit_cave(request, path="", slug=None):
if not cave.url:
cave.url = cave.areacode + "/" + cave.number()
cave.save()
+ # save_m2m is Django https://docs.djangoproject.com/en/6.0/topics/forms/modelforms/
form.save_m2m() # this does the many-to-many relationship saving between caves and entrances
if slug is None:
# it is not visible on the form so it always will be None
diff --git a/core/views/new_hole.py b/core/views/new_hole.py
index b368421b..fad910db 100644
--- a/core/views/new_hole.py
+++ b/core/views/new_hole.py
@@ -1,11 +1,13 @@
import re
import subprocess
+from pathlib import Path
from django import forms
from django.core.exceptions import ValidationError
from django.utils.safestring import mark_safe
from django.conf import settings
+from troggle.core.models.caves import Cave, CaveAndEntrance, Entrance, GetCaveLookup
from troggle.parsers.people import who_is_this
from troggle.core.utils import (
get_cookie_max_age,
@@ -19,6 +21,8 @@ from troggle.core.utils import (
is_identified_user,
write_and_commit,
)
+# TO DO check if wallet already exists and if so put a blue label against it & check names are same people
+# assuming this is a new wallet for now - so add a check for this?
from troggle.core.position_utils import which_area # file-type import, not module type.
@@ -196,14 +200,19 @@ class NewHoleForm(forms.Form):
# cleaned_data['cameramen_ids'] = cameramen
gps_lat = cleaned_data.get("gps_lat")
- gps_lang = cleaned_data.get("gps_long")
- valid_area, area = which_area(lat, long)
+ gps_long = cleaned_data.get("gps_long")
+ valid_area, area = which_area(gps_lat, gps_long)
if not valid_area:
self.add_error('gps_lat', "Not in Area 1626 or 1623")
self.add_error('gps_long', "Not in Area 1626 or 1623")
else:
- if Cave.objects.filter(unofficial_number=cave_id, areacode=areacode).exists():
- self.add_error('cave_id', "This Cave already exists, pick another identifier.")
+ if Cave.objects.filter(unofficial_number=cave_id, areacode=area).exists():
+ slug = f"{area}-{cave_id}"
+ error_html = mark_safe(
+ f"This Cave already exists, pick another identifier, or edit it here: "
+ f"{slug}"
+ )
+ self.add_error('cave_id', error_html)
# Entrance Photo Logic
photo_ent_on_camera = cleaned_data.get("photo_ent_on_camera")
@@ -334,7 +343,7 @@ def new_hole(request):
lat = float(form.data['gps_lat'])
long = float(form.data['gps_long'])
valid_area, area = which_area(lat, long)
- if valid:
+ if valid_area:
areatext = f"in {area}"
else:
areatext = "Not in 1623 or 1626"
@@ -397,9 +406,9 @@ def process_new_hole(form, area):
✅ Create a fixed point *fix record by inserting into :loser:/fixedpts/gps/auto.svx
✅ Do a git commit (loser) of the new GPS position
- ⚡Create a new Cave description file
+ ✅Create a new Cave description file
⚡Create an associated new Entrance description file with GPS location using *fix
- ⚡Update the database with this new Cave
+ ✅Update the database with this new Cave
⚡Update the database with this new Entrance
⚡Do a git commit (expoweb) of the new Cave and Entrance description files
⚡+ Link page to go to
@@ -423,8 +432,8 @@ def process_new_hole(form, area):
editor = git_string(form.cleaned_data["who_are_you"])
_newfix(form, area, editor)
+ _newent(form, area, editor) # yes, make the Entrance first
_newcave(form, area, editor)
- _newent(form, area, editor)
return
def _newfix(form, area, editor):
@@ -453,12 +462,102 @@ def _newfix(form, area, editor):
except:
raise
return
+
+def _newent(form, areacode, editor):
+ """All a bit over-complicated by the existance of teh combined Entrance & Letter Form and the
+ CaveAndEntrance class
+
+ Ideally we want to use the validity checks defined on the Form objects to check that this data is valid.
+ But really this should be done within the form we have just processed which the user has just filled in.
+ So we won't use the EntranceForm or the EntranceLetterForm, but just duplicate the checks above instead.
+
+ In the parser, the Entrance is created first, then the Cave. But when doing NewCave, the Cave is created
+ first, then the Entrance. So this code is derived from a bit of both.
+ """
+ slug = f"{areacode}-{form.cleaned_data.get("cave_id")}" # no letter suffix a,b, or c..
+ imgpath = Path(areacode) / form.cleaned_data.get("cave_id")
+
+ ent = Entrance.objects.create( # creates object and saves into db
+ slug=slug,
+ filename = slug + ".html",
+ entrance_description="Created when registering a new cave. "
+ + "Click on 'Edit' to enter the updated data, then 'Submit'.",
+ marking="?",
+ )
+
+ #ce = CaveAndEntrance(cave=cave, entrance=Entrance()) # creates a new Entrance object as well as a new CE object
+ #
+ # Add in default text for various fields here, and links to the two Wallets.
+ #
+
+
+ #
+ # Add in saving Entrance to database and then .html file to filesystem and git
+ #
+
-def _newcave(form, area, editor):
- # unofficial_number
- slug = f"{area}-{form.cleaned_data.get("cave_id")}"
- #cave = make_cave(slug)
return
-def _newent(form, area, editor):
- return
\ No newline at end of file
+def _guess_survex_file(areacode, id):
+ survex_file = f"caves-{areacode}/{id}/{id}.svx"
+ if Path(settings.SURVEX_DATA, survex_file).is_file():
+ return survex_file
+ else:
+ survex_file = f"caves-{areacode}/{id}.svx"
+ if Path(settings.SURVEX_DATA, survex_file).is_file():
+ return survex_file
+ return ""
+
+def _newcave(form, areacode, editor):
+ cave_id = form.cleaned_data.get("cave_id")
+ slug = f"{areacode}-{cave_id}"
+ cave = make_cave(slug)
+
+ # Add in default text for various fields here, and links to the two Wallets.
+ description = f"Created from New Cave Datasheet on {form.cleaned_data.get("discovery_date")} "
+ f"details in wallet: {form.cleaned_data.get("survey_wallet")} "
+ if form.cleaned_data.get("surface_wallet"):
+ description += f" discovered using old wallet: {form.cleaned_data.get("surface_wallet")} "
+ default_note = "Created from New Cave Datasheet. "
+
+ wallet = form.cleaned_data.get("survey_wallet")
+ wallet_url = "/walletedit/{wallet.replace("#",":")}"
+ references = f"Wallet {wallet}"
+
+ # TO-DO Need to detect if the existence of the survex was ticked but the file was not found,
+ # but that is probably normal: people will mostly record the Cave first and then do the survex data.
+
+ cave = Cave(
+ official_name=form.cleaned_data.get("proposed_name"),
+ underground_description=description,
+ unofficial_number=cave_id,
+ survex_file=_guess_survex_file(areacode, cave_id), # possible that they did the survex file already?
+ url=f"{areacode}/{cave_id}/{cave_id}.html",
+ notes=default_note,
+ areacode=areacode,
+ fully_explored=form.cleaned_data.get("is_explored"),
+ unexplored= not form.cleaned_data.get("is_explored"),
+ references=references,
+ )
+ cave.save()
+ # need a CaveForm f we do it this way, which is a ModelForm.
+ # form.save_m2m() # this does the many-to-many relationship saving between caves and entrances
+ # can we do this manually?
+ try:
+ cave_file = cave.file_output()
+ write_and_commit([cave_file], f"Creating new cave {cave}", editor)
+ # leave other exceptions unhandled so that they bubble up to user interface
+ except PermissionError:
+ message = f"CANNOT save this file.\nPERMISSIONS incorrectly set on server for this file {cave.filename}. Ask a nerd to fix this."
+ return render(request, "errors/generic.html", {"message": message})
+ except WriteAndCommitError as e:
+ message = f"CANNOT git on server for this file {cave.filename}.\n{e}\nEdits may not be committed.\nAsk a nerd to fix this."
+ return render(request, "errors/generic.html", {"message": e.message})
+ except subprocess.SubprocessError as e:
+ message = f"CANNOT update server for this file {cave.filename}.\n{e}\nEdits may not be committed.\nAsk a nerd to fix this."
+ return render(request, "errors/generic.html", {"message": message})
+ except:
+ raise
+
+ return
+
diff --git a/templates/new_hole.html b/templates/new_hole.html
index 0a1fcf6c..67aecea2 100644
--- a/templates/new_hole.html
+++ b/templates/new_hole.html
@@ -126,7 +126,7 @@