mirror of
https://expo.survex.com/repositories/troggle/.git
synced 2024-11-29 21:31:54 +00:00
279 lines
11 KiB
Python
279 lines
11 KiB
Python
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
|
|
from django.http import HttpResponse, HttpResponseRedirect
|
|
from django.shortcuts import render
|
|
from django.template import Context, loader
|
|
from django.core.files.storage import FileSystemStorage, default_storage
|
|
|
|
from troggle.parsers.imports import import_caves, import_people, import_surveyscans
|
|
from troggle.parsers.imports import import_logbooks, import_QMs, import_drawingsfiles, import_survex
|
|
# from databaseReset import reinit_db # don't do this. databaseRest runs code *at import time*
|
|
from troggle.core.models.troggle import Expedition, Person, PersonExpedition
|
|
from troggle.core.models.caves import LogbookEntry, QM, Cave, PersonTrip
|
|
from .auth import login_required_if_public
|
|
|
|
'''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).
|
|
|
|
Also has code to download a logbook in a choice of formats (why?!)
|
|
'''
|
|
|
|
todo = '''
|
|
- Check that the logbookdownloader works by testing with a round trip.
|
|
|
|
- Use it to convert all older logbooks into the 2005-variant of HTML then we can
|
|
get rid of the parsers for older formats. There are no images stored in the database,
|
|
so this is only a tool for a first pass, to be followed by extensive hand-editing!
|
|
When we have done all the old logbooks, delete this function and the two templates.
|
|
|
|
- But how does this interact with troggle/logbooksdump.py ?
|
|
'''
|
|
|
|
def todos(request, module):
|
|
'''produces todo text from module
|
|
We should automate this to find all those strings automatically
|
|
'''
|
|
from troggle.core.TESTS.tests import todo as tests
|
|
from troggle.core.views.logbooks import todo as viewlogbooks
|
|
from troggle.core.views.survex import todo as viewsurvex
|
|
from troggle.parsers.caves import todo as parserscaves
|
|
from troggle.parsers.logbooks import todo as parserslogbooks
|
|
from troggle.parsers.survex import todo as parserssurvex
|
|
from troggle.core.models.caves import todo as modelcaves
|
|
from troggle.core.middleware import todo as middleware
|
|
from troggle.core.forms import todo as forms
|
|
tododict = {'views/other': todo,
|
|
'tests': tests,
|
|
'views/logbooks': viewlogbooks,
|
|
'views/survex': viewsurvex,
|
|
'parsers/caves': parserscaves,
|
|
'parsers/logbooks': parserslogbooks,
|
|
'parsers/survex': parserssurvex,
|
|
'core/models/caves': modelcaves,
|
|
'core/middleware': middleware,
|
|
'core/forms': forms}
|
|
return render(request,'core/todos.html', {'tododict': tododict})
|
|
|
|
def troggle404(request): # cannot get this to work. Handler404 in urls.py not right syntax
|
|
'''Custom 404 page to be used even when Debug=True
|
|
https://blog.juanwolf.fr/posts/programming/how-to-create-404-page-django/
|
|
'''
|
|
context = RequestContext(request)
|
|
#context['caves'] = Cave.objects.all()
|
|
return render(request, ('404.html', context.flatten()))
|
|
|
|
def frontpage(request):
|
|
'''never seen in common practice. Logon should redirect here when this is more useful'''
|
|
# the messages system does a popup on this page if there is a recent message, e.g. from the admin site actions.
|
|
# via django.contrib.messages.middleware.MessageMiddleware
|
|
# this is set in the templates.
|
|
if request.user.is_authenticated:
|
|
return render(request,'tasks.html')
|
|
|
|
expeditions = Expedition.objects.order_by("-year")
|
|
logbookentry = LogbookEntry
|
|
cave = Cave
|
|
#from django.contrib.admin.templatetags import log
|
|
return render(request,'frontpage.html', locals())
|
|
|
|
|
|
@login_required_if_public
|
|
def controlpanel(request):
|
|
'''This should be re-written to use ajax so that the user can see the progress
|
|
of the actions.
|
|
|
|
Also need to add reinit_db option
|
|
'''
|
|
jobs_completed=[]
|
|
|
|
def process_imports():
|
|
'''databaseReset.py
|
|
jq.enq("reinit",reinit_db)
|
|
jq.enq("caves",import_caves)
|
|
jq.enq("people",import_people)
|
|
jq.enq("scans",import_surveyscans)
|
|
jq.enq("logbooks",import_logbooks)
|
|
jq.enq("QMs",import_QMs)
|
|
jq.enq("drawings",import_drawingsfiles)
|
|
jq.enq("survex",import_survex)
|
|
'''
|
|
if request.POST.get("import_caves", False):
|
|
import_caves()
|
|
jobs_completed.append('Caves')
|
|
if request.POST.get("import_people", False):
|
|
import_people()
|
|
jobs_completed.append('People')
|
|
if request.POST.get("import_surveyscans", False):
|
|
import_surveyscans()
|
|
jobs_completed.append('Scans')
|
|
if request.POST.get("import_logbooks", False):
|
|
import_logbooks()
|
|
jobs_completed.append('Logbooks')
|
|
if request.POST.get("import_QMs", False):
|
|
import_QMs()
|
|
jobs_completed.append('QMs')
|
|
if request.POST.get("import_drawingsfiles", False):
|
|
import_drawingsfiles()
|
|
jobs_completed.append('Drawings')
|
|
if request.POST.get("import_survex", False):
|
|
import_survex()
|
|
jobs_completed.append('Survex')
|
|
|
|
print("", flush=True)
|
|
|
|
if not request.user.is_superuser: # expoadmin is both .is_staff and ._is_superuser
|
|
return render(request,'controlPanel.html', {'error': 'You are logged in, but not logged in as "expoadmin". \nLogout and login again to contnue.'})
|
|
else:
|
|
if request.method=='POST':
|
|
#reinit_db()
|
|
process_imports()
|
|
return render(request,'controlPanel.html', {'expeditions':Expedition.objects.all(),'jobs_completed':jobs_completed})
|
|
else:
|
|
return render(request,'controlPanel.html', {'expeditions':Expedition.objects.all(),'jobs_completed':jobs_completed})
|
|
|
|
|
|
|
|
def exportlogbook(request,year=None,extension=None):
|
|
'''Constructs, from the database, a complete HTML (or TXT) formatted logbook - but TEXT ONLY
|
|
for the current year. Formats available are HTML2005 or 2008text
|
|
|
|
There are no images stored in the database, so this is only a tool for a first pass, to be followed by
|
|
extensive hand-editing.
|
|
|
|
NEED TO ADD IN THE MATERIAL WHIHC IS NOT IN ANY LBE ! e.g. front matter.
|
|
|
|
This is the recipient of the POST action os the export form in the control panel
|
|
'''
|
|
def lbeKey(lbe):
|
|
"""This function goes into a lexicogrpahic sort function
|
|
"""
|
|
return str(lbe.date)
|
|
|
|
if not request.method=='POST':
|
|
return render(request,'controlPanel.html', {'expeditions':Expedition.objects.all(),'jobs_completed':""})
|
|
else:
|
|
print(f'Logbook export {request.POST}')
|
|
|
|
if request.POST.get("year", '2016'):
|
|
year = request.POST['year']
|
|
if request.POST.get("extension", 'html'):
|
|
extension = request.POST['extension'] # e.g. html
|
|
|
|
current_expedition=Expedition.objects.get(year=year)
|
|
logbook_entries=LogbookEntry.objects.filter(expedition=current_expedition).order_by('date') # need to be sorted by date!
|
|
|
|
#print(f'Logbook has {len(logbook_entries)} entries in it.')
|
|
|
|
if extension =='txt':
|
|
response = HttpResponse(content_type='text/plain')
|
|
style='2008'
|
|
else :
|
|
extension == 'html'
|
|
response = HttpResponse(content_type='text/html')
|
|
style='2005'
|
|
|
|
filename='newlogbook.' + extension
|
|
template='logbook'+style+'style.'+extension
|
|
response['Content-Disposition'] = 'attachment; filename='+filename
|
|
t=loader.get_template(template)
|
|
logbookfile = (t.render({'logbook_entries':logbook_entries}))
|
|
|
|
dir = Path(settings.EXPOWEB) / "years" / year
|
|
filepath = Path(dir, filename)
|
|
with(open(filepath, 'w')) as lb:
|
|
lb.writelines(logbookfile)
|
|
|
|
#print(f'Logbook exported to {filepath}')
|
|
completed = f'Logbook exported to <a href="/years/{filename}">{filename}</a>'
|
|
|
|
return render(request,'controlPanel.html', {'expeditions':Expedition.objects.all(),'jobs_completed':[completed]})
|
|
|
|
|
|
# def ajax_test(request):
|
|
# post_text = request.POST['post_data']
|
|
# return HttpResponse("{'response_text': '"+post_text+" recieved.'}",
|
|
# content_type="application/json")
|
|
|
|
|
|
|
|
class FilesForm(forms.Form): # not a model-form, just a form-form
|
|
scanfiles = forms.FileField()
|
|
|
|
@login_required_if_public
|
|
def scanupload(request, wallet=None):
|
|
'''Upload one scanned image file into a wallet on /expofiles
|
|
This does NOT use a Django model linked to a Django form. Just a simple Django form.
|
|
'''
|
|
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]
|
|
if int(year) < 1977:
|
|
year = "1977"
|
|
if int(year) > 2050:
|
|
year = "2050"
|
|
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}'
|
|
|
|
context = {'year': year, 'prev': prev, 'next': next, 'prevy': prevy, 'nexty': nexty}
|
|
|
|
wallet = wallet.replace(':','#')
|
|
dirpath = Path(settings.SURVEY_SCANS, year, wallet)
|
|
|
|
form = FilesForm()
|
|
|
|
if request.method == 'POST':
|
|
form = FilesForm(request.POST,request.FILES)
|
|
if form.is_valid():
|
|
f = request.FILES["scanfiles"]
|
|
multiple = request.FILES.getlist('scanfiles')
|
|
fs = FileSystemStorage(os.path.join(settings.SURVEY_SCANS, year, wallet))
|
|
|
|
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)')
|
|
else:
|
|
files = sorted(files)
|
|
|
|
if dirs:
|
|
dirs = sorted(dirs)
|
|
|
|
return render(request, 'scanuploadform.html',
|
|
{'form': form, 'wallet': wallet, **context, 'files': files, 'dirs': dirs, 'filesaved': filesaved, 'actual_saved': actual_saved})
|