2
0
mirror of https://expo.survex.com/repositories/troggle/.git synced 2024-11-21 23:01:52 +00:00

Revert "update oddity with VS Code and WSL2"

This reverts commit 41b2bcee4f.

CR LF != LF issue
This commit is contained in:
Philip Sargent 2022-04-05 10:37:31 +03:00
parent 41b2bcee4f
commit 71ed0815cc
6 changed files with 711 additions and 711 deletions

View File

@ -1,3 +1,3 @@
The copy in this /_deploy/ folder may not be the latest if active development The copy in this /_deploy/ folder may not be the latest if active development
has been going on in the parent folder. Check there for a later copy of has been going on in the parent folder. Check there for a later copy of
the localsettingsWSL file. the localsettingsWSL file.

View File

@ -1,368 +1,368 @@
import os import os
import re import re
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from urllib.parse import urljoin, unquote as urlunquote from urllib.parse import urljoin, unquote as urlunquote
from urllib.request import urlopen from urllib.request import urlopen
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect, Http404 from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.urls import reverse, resolve from django.urls import reverse, resolve
from django.template import Context, loader from django.template import Context, loader
from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import ensure_csrf_cookie
from django.contrib import admin from django.contrib import admin
import django.forms as forms import django.forms as forms
from .auth import login_required_if_public from .auth import login_required_if_public
from troggle.core.models.caves import Cave from troggle.core.models.caves import Cave
import troggle.core.views.caves import troggle.core.views.caves
import troggle.settings as settings import troggle.settings as settings
'''Formerly a separate package called 'flatpages' written by Martin Green 2011. '''Formerly a separate package called 'flatpages' written by Martin Green 2011.
This was NOT django.contrib.flatpages which stores HTML in the database, so the name was changed to expopages. This was NOT django.contrib.flatpages which stores HTML in the database, so the name was changed to expopages.
Then it was incorporated into troggle directly, rather than being an unnecessary external package. Then it was incorporated into troggle directly, rather than being an unnecessary external package.
''' '''
default_head = '''<head> default_head = '''<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>CUCC Expedition - index</title> <title>CUCC Expedition - index</title>
<link rel="stylesheet" type="text/css" href="../css/main2.css" /> <link rel="stylesheet" type="text/css" href="../css/main2.css" />
<link rel="stylesheet" type="text/css" href="../../css/main2.css" /> <link rel="stylesheet" type="text/css" href="../../css/main2.css" />
<link rel="stylesheet" type="text/css" href="../../../css/main2.css" /> <link rel="stylesheet" type="text/css" href="../../../css/main2.css" />
</head> </head>
<body> <body>
<h1>Expo</h1> <h1>Expo</h1>
<h2 id="tophead">CUCC Expedition</h2> <h2 id="tophead">CUCC Expedition</h2>
<ul id="links"> <ul id="links">
<li><a href="/index.htm">Home</a></li> <li><a href="/index.htm">Home</a></li>
<li><a href="/infodx.htm">Main Index</a></li> <li><a href="/infodx.htm">Main Index</a></li>
<li><a href="/handbook/index.htm">Handbook</a></li> <li><a href="/handbook/index.htm">Handbook</a></li>
<li><a href="/handbook/computing/onlinesystems.html">Online systems</a></li> <li><a href="/handbook/computing/onlinesystems.html">Online systems</a></li>
<li><a href="/pubs.htm">Reports</a></li> <li><a href="/pubs.htm">Reports</a></li>
<li><a href="/areas.htm">Areas</a></li> <li><a href="/areas.htm">Areas</a></li>
<li><a href="/caves">Caves</a></li> <li><a href="/caves">Caves</a></li>
<li><a href="/expedition/2019">Troggle</a></li> <li><a href="/expedition/2019">Troggle</a></li>
<li><form name=P method=get action="/search" target="_top"> <li><form name=P method=get action="/search" target="_top">
<input id="omega-autofocus" type=search name=P size=8 autofocus> <input id="omega-autofocus" type=search name=P size=8 autofocus>
<input type=submit value="Search"></li> <input type=submit value="Search"></li>
</ul>''' # this gets overwritten by templates/menu.html by django for most normal pages </ul>''' # this gets overwritten by templates/menu.html by django for most normal pages
def expofiles_redirect(request, filepath): def expofiles_redirect(request, filepath):
'''This is used only when running as a test system without a local copy of /expofiles/ '''This is used only when running as a test system without a local copy of /expofiles/
when settings.EXPOFILESREMOTE is True when settings.EXPOFILESREMOTE is True
''' '''
return redirect(urljoin('http://expo.survex.com/expofiles/', filepath)) return redirect(urljoin('http://expo.survex.com/expofiles/', filepath))
def map(request): def map(request):
'''Serves unadorned the expoweb/map/map.html file '''Serves unadorned the expoweb/map/map.html file
''' '''
fn = Path(settings.EXPOWEB, 'map', 'map.html') fn = Path(settings.EXPOWEB, 'map', 'map.html')
return HttpResponse(content=open(fn, "r"),content_type='text/html') return HttpResponse(content=open(fn, "r"),content_type='text/html')
def mapfile(request, path): def mapfile(request, path):
'''Serves unadorned file '''Serves unadorned file
''' '''
fn = Path(settings.EXPOWEB, 'map', path) fn = Path(settings.EXPOWEB, 'map', path)
return HttpResponse(content=open(fn, "r"),content_type=getmimetype(fn)) return HttpResponse(content=open(fn, "r"),content_type=getmimetype(fn))
def expofilessingle(request, filepath): def expofilessingle(request, filepath):
'''sends a single binary file to the user, if not found, show the parent directory '''sends a single binary file to the user, if not found, show the parent directory
If the path actually is a directory, then show that. If the path actually is a directory, then show that.
''' '''
#print(f' - expofilessingle {filepath}') #print(f' - expofilessingle {filepath}')
if filepath =="" or filepath =="/": if filepath =="" or filepath =="/":
return expofilesdir(request, settings.EXPOFILES, "") return expofilesdir(request, settings.EXPOFILES, "")
fn=urlunquote(filepath) fn=urlunquote(filepath)
fn = Path(settings.EXPOFILES,filepath) fn = Path(settings.EXPOFILES,filepath)
if fn.is_dir(): if fn.is_dir():
return expofilesdir(request, Path(fn), Path(filepath)) return expofilesdir(request, Path(fn), Path(filepath))
if fn.is_file(): if fn.is_file():
return HttpResponse(content=open(fn, "rb"),content_type=getmimetype(filepath)) # any file return HttpResponse(content=open(fn, "rb"),content_type=getmimetype(filepath)) # any file
else: else:
# not a file, so show parent directory - DANGER need to check this is limited to below expofiles # not a file, so show parent directory - DANGER need to check this is limited to below expofiles
if Path(fn).parent == Path(settings.EXPOFILES).parent: if Path(fn).parent == Path(settings.EXPOFILES).parent:
return expofilesdir(request, Path(settings.EXPOFILES), Path(filepath).parent) return expofilesdir(request, Path(settings.EXPOFILES), Path(filepath).parent)
else: else:
return expofilesdir(request, Path(fn).parent, Path(filepath).parent) return expofilesdir(request, Path(fn).parent, Path(filepath).parent)
def expofilesdir(request, dirpath, filepath): def expofilesdir(request, dirpath, filepath):
'''does a directory display. If there is an index.html file we should display that. '''does a directory display. If there is an index.html file we should display that.
- dirpath is a full Path() resolved including local machine /expofiles/ - dirpath is a full Path() resolved including local machine /expofiles/
- filepath is a Path() and it does not have /expofiles/ in it - filepath is a Path() and it does not have /expofiles/ in it
''' '''
#print(f' - expofilesdir {dirpath} settings.EXPOFILESREMOTE: {settings.EXPOFILESREMOTE}') #print(f' - expofilesdir {dirpath} settings.EXPOFILESREMOTE: {settings.EXPOFILESREMOTE}')
if filepath: if filepath:
urlpath = 'expofiles' / Path(filepath) urlpath = 'expofiles' / Path(filepath)
else: else:
urlpath = Path('expofiles') urlpath = Path('expofiles')
try: try:
for f in dirpath.iterdir(): for f in dirpath.iterdir():
pass pass
except FileNotFoundError: except FileNotFoundError:
#print(f' - expofilesdir error {dirpath}') #print(f' - expofilesdir error {dirpath}')
return expofilesdir(request, dirpath.parent, filepath.parent) return expofilesdir(request, dirpath.parent, filepath.parent)
fileitems = [] fileitems = []
diritems = [] diritems = []
for f in dirpath.iterdir(): for f in dirpath.iterdir():
if f.is_dir(): if f.is_dir():
diritems.append((urlpath / f.parts[-1], str(f.parts[-1]))) diritems.append((urlpath / f.parts[-1], str(f.parts[-1])))
else: else:
# if f.parts[-1].lower() == 'index.htm' or f.parts[-1].lower() == 'index.html': # css cwd problem # if f.parts[-1].lower() == 'index.htm' or f.parts[-1].lower() == 'index.html': # css cwd problem
# return HttpResponse(content=open(f, "rb"),content_type=getmimetype(filepath)) # any file # return HttpResponse(content=open(f, "rb"),content_type=getmimetype(filepath)) # any file
# return expofilessingle(request, str(Path(filepath / f.parts[-1]))) # return expofilessingle(request, str(Path(filepath / f.parts[-1])))
fileitems.append((Path(urlpath) / f.parts[-1], str(f.parts[-1]), getmimetype(f))) fileitems.append((Path(urlpath) / f.parts[-1], str(f.parts[-1]), getmimetype(f)))
return render(request, 'dirdisplay.html', { 'filepath': urlpath, 'fileitems':fileitems, 'diritems': diritems,'settings': settings }) return render(request, 'dirdisplay.html', { 'filepath': urlpath, 'fileitems':fileitems, 'diritems': diritems,'settings': settings })
def expowebpage(request, expowebpath, path): def expowebpage(request, expowebpath, path):
'''Adds menus and serves an HTML page '''Adds menus and serves an HTML page
''' '''
if not Path(expowebpath / path).is_file(): if not Path(expowebpath / path).is_file():
# Should not get here if the path has suffix "_edit" # Should not get here if the path has suffix "_edit"
print(f' - 404 error in expowebpage() {path}') print(f' - 404 error in expowebpage() {path}')
return render(request, 'pagenotfound.html', {'path': path}, status="404") return render(request, 'pagenotfound.html', {'path': path}, status="404")
try: try:
with open(os.path.normpath(expowebpath / path), "r") as o: with open(os.path.normpath(expowebpath / path), "r") as o:
html = o.read() html = o.read()
except: except:
try: try:
with open(os.path.normpath(expowebpath / path), "rb") as o: with open(os.path.normpath(expowebpath / path), "rb") as o:
html = str(o.read()).replace("<h1>","<h1>BAD NON-UTF-8 characters here - ") html = str(o.read()).replace("<h1>","<h1>BAD NON-UTF-8 characters here - ")
except: except:
return HttpResponse(default_head + '<h3>UTF-8 Parsing Failure:<br>Page could not be parsed using UTF-8:<br>failure detected in expowebpage in views.expo.py</h3> Please edit this <var>:expoweb:</var> page to replace dubious umlauts and &pound; symbols with correct HTML entities e.g. <em>&amp;pound;;</em>. </body' ) return HttpResponse(default_head + '<h3>UTF-8 Parsing Failure:<br>Page could not be parsed using UTF-8:<br>failure detected in expowebpage in views.expo.py</h3> Please edit this <var>:expoweb:</var> page to replace dubious umlauts and &pound; symbols with correct HTML entities e.g. <em>&amp;pound;;</em>. </body' )
m = re.search(r'(.*)<\s*head([^>]*)>(.*)<\s*/head\s*>(.*)<\s*body([^>]*)>(.*)<\s*/body\s*>(.*)', html, re.DOTALL + re.IGNORECASE) m = re.search(r'(.*)<\s*head([^>]*)>(.*)<\s*/head\s*>(.*)<\s*body([^>]*)>(.*)<\s*/body\s*>(.*)', html, re.DOTALL + re.IGNORECASE)
if m: if m:
preheader, headerattrs, head, postheader, bodyattrs, body, postbody = m.groups() preheader, headerattrs, head, postheader, bodyattrs, body, postbody = m.groups()
else: else:
return HttpResponse(default_head + html + '<h3>HTML Parsing failure:<br>Page could not be parsed into header and body:<br>failure detected in expowebpage in views.expo.py</h3> Please edit this <var>:expoweb:</var> page to be in the expected full HTML format </body' ) return HttpResponse(default_head + html + '<h3>HTML Parsing failure:<br>Page could not be parsed into header and body:<br>failure detected in expowebpage in views.expo.py</h3> Please edit this <var>:expoweb:</var> page to be in the expected full HTML format </body' )
m = re.search(r"<title>(.*)</title>", head, re.DOTALL + re.IGNORECASE) m = re.search(r"<title>(.*)</title>", head, re.DOTALL + re.IGNORECASE)
if m: if m:
title, = m.groups() title, = m.groups()
else: else:
title = "" title = ""
m = re.search(r"^<meta([^>]*)noedit", head, re.DOTALL + re.IGNORECASE) m = re.search(r"^<meta([^>]*)noedit", head, re.DOTALL + re.IGNORECASE)
if m: if m:
editable = False editable = False
else: else:
editable = os.access(Path(expowebpath / path), os.W_OK) # are file permissions writeable? editable = os.access(Path(expowebpath / path), os.W_OK) # are file permissions writeable?
has_menu = False has_menu = False
menumatch = re.match(r'(.*)<div id="menu">', body, re.DOTALL + re.IGNORECASE) menumatch = re.match(r'(.*)<div id="menu">', body, re.DOTALL + re.IGNORECASE)
if menumatch: if menumatch:
has_menu = True has_menu = True
menumatch = re.match(r'(.*)<ul id="links">', body, re.DOTALL + re.IGNORECASE) menumatch = re.match(r'(.*)<ul id="links">', body, re.DOTALL + re.IGNORECASE)
if menumatch: if menumatch:
has_menu = True has_menu = True
return render(request, 'expopage.html', {'editable': editable, 'path': path, 'title': title, return render(request, 'expopage.html', {'editable': editable, 'path': path, 'title': title,
'body': body, 'homepage': (path == "index.htm"), 'has_menu': has_menu}) 'body': body, 'homepage': (path == "index.htm"), 'has_menu': has_menu})
def mediapage(request, subpath=None, doc_root=None): def mediapage(request, subpath=None, doc_root=None):
'''This is for special prefix paths /photos/ /site_media/, /static/ etc. '''This is for special prefix paths /photos/ /site_media/, /static/ etc.
as defined in urls.py . If given a directory, gives a failure page. as defined in urls.py . If given a directory, gives a failure page.
''' '''
#print(" - XXXXX_ROOT: {} ...{}".format(doc_root, subpath)) #print(" - XXXXX_ROOT: {} ...{}".format(doc_root, subpath))
if doc_root is not None: if doc_root is not None:
filetobeopened = Path(doc_root, subpath) filetobeopened = Path(doc_root, subpath)
if filetobeopened.is_dir(): if filetobeopened.is_dir():
return render(request, 'nodirlist.html', {'path': subpath}) return render(request, 'nodirlist.html', {'path': subpath})
try: try:
return HttpResponse(content=open(filetobeopened, "rb"), content_type=getmimetype(subpath)) return HttpResponse(content=open(filetobeopened, "rb"), content_type=getmimetype(subpath))
except IOError: except IOError:
return render(request, 'pagenotfound.html', {'path': subpath}, status="404") return render(request, 'pagenotfound.html', {'path': subpath}, status="404")
else: else:
return render(request, 'pagenotfound.html', {'path': subpath}, status="404") return render(request, 'pagenotfound.html', {'path': subpath}, status="404")
def expopage(request, path): def expopage(request, path):
'''Either renders an HTML page from expoweb with all the menus, '''Either renders an HTML page from expoweb with all the menus,
or serves an unadorned binary file with mime type or serves an unadorned binary file with mime type
''' '''
#print(" - EXPOPAGES delivering the file: '{}':{} as MIME type: {}".format(request.path, path,getmimetype(path)),flush=True) #print(" - EXPOPAGES delivering the file: '{}':{} as MIME type: {}".format(request.path, path,getmimetype(path)),flush=True)
if path.startswith("noinfo") and settings.PUBLIC_SITE and not request.user.is_authenticated: if path.startswith("noinfo") and settings.PUBLIC_SITE and not request.user.is_authenticated:
return HttpResponseRedirect(urljoin(reverse("auth_login"),'?next={}'.format(request.path))) return HttpResponseRedirect(urljoin(reverse("auth_login"),'?next={}'.format(request.path)))
if path.startswith("admin/"): if path.startswith("admin/"):
# don't even attempt to handle these sorts of mistakes # don't even attempt to handle these sorts of mistakes
return HttpResponseRedirect("/admin/") return HttpResponseRedirect("/admin/")
expowebpath = Path(settings.EXPOWEB) expowebpath = Path(settings.EXPOWEB)
if path == "": if path == "":
return expowebpage(request, expowebpath, "index.htm") return expowebpage(request, expowebpath, "index.htm")
if path.endswith(".htm") or path.endswith(".html"): if path.endswith(".htm") or path.endswith(".html"):
return expowebpage(request, expowebpath, path) return expowebpage(request, expowebpath, path)
if Path(expowebpath / path ).is_dir(): if Path(expowebpath / path ).is_dir():
for p in ["index.html", "index.htm"]: for p in ["index.html", "index.htm"]:
if (expowebpath / path / p).is_file(): if (expowebpath / path / p).is_file():
# This needs to reset the path to the new subdirectory # This needs to reset the path to the new subdirectory
return HttpResponseRedirect('/'+str(Path(path) / p)) return HttpResponseRedirect('/'+str(Path(path) / p))
return render(request, 'pagenotfound.html', {'path': Path(path) / "index.html"}, status="404") return render(request, 'pagenotfound.html', {'path': Path(path) / "index.html"}, status="404")
if path.endswith("/"): if path.endswith("/"):
# we already know it is not a directory. # we already know it is not a directory.
# the final / may have been appended by middleware if there was no page without it # the final / may have been appended by middleware if there was no page without it
# do not redirect to a file path without the slash as we may get in a loop. Let the user fix it: # do not redirect to a file path without the slash as we may get in a loop. Let the user fix it:
return render(request, 'dirnotfound.html', {'path': path, 'subpath': path[0:-1]}) return render(request, 'dirnotfound.html', {'path': path, 'subpath': path[0:-1]})
# So it must be a file in /expoweb/ but not .htm or .html probably an image # So it must be a file in /expoweb/ but not .htm or .html probably an image
filetobeopened = os.path.normpath(expowebpath / path) filetobeopened = os.path.normpath(expowebpath / path)
try: try:
return HttpResponse(content=open(filetobeopened, "rb"), content_type=getmimetype(path)) return HttpResponse(content=open(filetobeopened, "rb"), content_type=getmimetype(path))
except IOError: except IOError:
return render(request, 'pagenotfound.html', {'path': path}, status="404") return render(request, 'pagenotfound.html', {'path': path}, status="404")
def getmimetype(path): def getmimetype(path):
'''Our own version rather than relying on what is provided by the python library. Note that when '''Our own version rather than relying on what is provided by the python library. Note that when
Apache or nginx is used to deliver /expofiles/ it will use it's own idea of mimetypes and Apache or nginx is used to deliver /expofiles/ it will use it's own idea of mimetypes and
not these. not these.
''' '''
path = str(path) path = str(path)
if path.lower().endswith(".css"): return "text/css" if path.lower().endswith(".css"): return "text/css"
if path.lower().endswith(".txt"): return "text/css" if path.lower().endswith(".txt"): return "text/css"
if path.lower().endswith(".js"): return "application/javascript" if path.lower().endswith(".js"): return "application/javascript"
if path.lower().endswith(".json"): return "application/javascript" if path.lower().endswith(".json"): return "application/javascript"
if path.lower().endswith(".ico"): return "image/vnd.microsoft.icon" if path.lower().endswith(".ico"): return "image/vnd.microsoft.icon"
if path.lower().endswith(".png"): return "image/png" if path.lower().endswith(".png"): return "image/png"
if path.lower().endswith(".tif"): return "image/tif" if path.lower().endswith(".tif"): return "image/tif"
if path.lower().endswith(".gif"): return "image/gif" if path.lower().endswith(".gif"): return "image/gif"
if path.lower().endswith(".jpeg"): return "image/jpeg" if path.lower().endswith(".jpeg"): return "image/jpeg"
if path.lower().endswith(".jpg"): return "image/jpeg" if path.lower().endswith(".jpg"): return "image/jpeg"
if path.lower().endswith("svg"): return "image/svg+xml" if path.lower().endswith("svg"): return "image/svg+xml"
if path.lower().endswith("xml"): return "application/xml" # we use "text/xhtml" for tunnel files if path.lower().endswith("xml"): return "application/xml" # we use "text/xhtml" for tunnel files
if path.lower().endswith(".pdf"): return "application/pdf" if path.lower().endswith(".pdf"): return "application/pdf"
if path.lower().endswith(".ps"): return "application/postscript" if path.lower().endswith(".ps"): return "application/postscript"
if path.lower().endswith(".svx"): return "application/x-survex-svx" if path.lower().endswith(".svx"): return "application/x-survex-svx"
if path.lower().endswith(".3d"): return "application/x-survex-3d" if path.lower().endswith(".3d"): return "application/x-survex-3d"
if path.lower().endswith(".pos"): return "application/x-survex-pos" if path.lower().endswith(".pos"): return "application/x-survex-pos"
if path.lower().endswith(".err"): return "application/x-survex-err" if path.lower().endswith(".err"): return "application/x-survex-err"
if path.lower().endswith(".odt"): return "application/vnd.oasis.opendocument.text" if path.lower().endswith(".odt"): return "application/vnd.oasis.opendocument.text"
if path.lower().endswith(".ods"): return "application/vnd.oasis.opendocument.spreadsheet" if path.lower().endswith(".ods"): return "application/vnd.oasis.opendocument.spreadsheet"
if path.lower().endswith(".docx"): return "application/vnd.openxmlformats-officedocument.wordprocessingml.document" if path.lower().endswith(".docx"): return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
if path.lower().endswith(".xslx"): return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" if path.lower().endswith(".xslx"): return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
if path.lower().endswith(".gz"): return "application/x-7z-compressed" if path.lower().endswith(".gz"): return "application/x-7z-compressed"
if path.lower().endswith(".7z"): return "application/x-7z-compressed" if path.lower().endswith(".7z"): return "application/x-7z-compressed"
if path.lower().endswith(".zip"): return "application/zip" if path.lower().endswith(".zip"): return "application/zip"
return "" return ""
@login_required_if_public @login_required_if_public
@ensure_csrf_cookie @ensure_csrf_cookie
def editexpopage(request, path): def editexpopage(request, path):
'''Manages the 'Edit this Page' capability for expo handbook and other html pages. '''Manages the 'Edit this Page' capability for expo handbook and other html pages.
Relies on HTML5 or javascript to provide the in-browser editing environment. Relies on HTML5 or javascript to provide the in-browser editing environment.
''' '''
try: try:
# if a cave not a webpage at all. # if a cave not a webpage at all.
r = Cave.objects.get(url = path) r = Cave.objects.get(url = path)
return troggle.core.views.caves.editCave(request, r.cave.slug) return troggle.core.views.caves.editCave(request, r.cave.slug)
except Cave.DoesNotExist: except Cave.DoesNotExist:
pass pass
try: try:
filepath = Path(settings.EXPOWEB) / path filepath = Path(settings.EXPOWEB) / path
o = open(filepath, "r") o = open(filepath, "r")
html = o.read() html = o.read()
autogeneratedmatch = re.search(r"\<\!--\s*(.*?(Do not edit|It is auto-generated).*?)\s*--\>", html, re.DOTALL + re.IGNORECASE) autogeneratedmatch = re.search(r"\<\!--\s*(.*?(Do not edit|It is auto-generated).*?)\s*--\>", html, re.DOTALL + re.IGNORECASE)
if autogeneratedmatch: if autogeneratedmatch:
return HttpResponse(autogeneratedmatch.group(1)) return HttpResponse(autogeneratedmatch.group(1))
m = re.search(r"(.*)<head([^>]*)>(.*)</head>(.*)<body([^>]*)>(.*)</body>(.*)", html, re.DOTALL + re.IGNORECASE) m = re.search(r"(.*)<head([^>]*)>(.*)</head>(.*)<body([^>]*)>(.*)</body>(.*)", html, re.DOTALL + re.IGNORECASE)
if m: if m:
filefound = True filefound = True
preheader, headerargs, head, postheader, bodyargs, body, postbody = m.groups() preheader, headerargs, head, postheader, bodyargs, body, postbody = m.groups()
linksmatch = re.match(r'(.*)(<ul\s+id="links">.*)', body, re.DOTALL + re.IGNORECASE) linksmatch = re.match(r'(.*)(<ul\s+id="links">.*)', body, re.DOTALL + re.IGNORECASE)
if linksmatch: if linksmatch:
body, links = linksmatch.groups() body, links = linksmatch.groups()
# if re.search(r"iso-8859-1", html): # if re.search(r"iso-8859-1", html):
# body = str(body, "iso-8859-1") # body = str(body, "iso-8859-1")
else: else:
return HttpResponse(default_head + html + '<h3>HTML Parsing failure:<br>Page could not be parsed into header and body:<br>failure detected in expowebpage in views.expo.py</h3> Please edit this <var>:expoweb:</var> page to be in the expected full HTML format .</body' ) return HttpResponse(default_head + html + '<h3>HTML Parsing failure:<br>Page could not be parsed into header and body:<br>failure detected in expowebpage in views.expo.py</h3> Please edit this <var>:expoweb:</var> page to be in the expected full HTML format .</body' )
except IOError: except IOError:
print("### File not found ### ", filepath) print("### File not found ### ", filepath)
filefound = False filefound = False
if request.method == 'POST': # If the form has been submitted... if request.method == 'POST': # If the form has been submitted...
pageform = ExpoPageForm(request.POST) # A form bound to the POST data pageform = ExpoPageForm(request.POST) # A form bound to the POST data
if pageform.is_valid():# Form valid therefore write file if pageform.is_valid():# Form valid therefore write file
print("### \n", str(pageform)[0:300]) print("### \n", str(pageform)[0:300])
print("### \n csrfmiddlewaretoken: ",request.POST['csrfmiddlewaretoken']) print("### \n csrfmiddlewaretoken: ",request.POST['csrfmiddlewaretoken'])
if filefound: if filefound:
headmatch = re.match(r"(.*)<title>.*</title>(.*)", head, re.DOTALL + re.IGNORECASE) headmatch = re.match(r"(.*)<title>.*</title>(.*)", head, re.DOTALL + re.IGNORECASE)
if headmatch: if headmatch:
head = headmatch.group(1) + "<title>" + pageform.cleaned_data["title"] + "</title>" + headmatch.group(2) head = headmatch.group(1) + "<title>" + pageform.cleaned_data["title"] + "</title>" + headmatch.group(2)
else: else:
head = "<title>" + pageform.cleaned_data["title"] + "</title>" head = "<title>" + pageform.cleaned_data["title"] + "</title>"
else: else:
head = "<title>" + pageform.cleaned_data["title"] + "</title>" head = "<title>" + pageform.cleaned_data["title"] + "</title>"
preheader = "<html>" preheader = "<html>"
headerargs = "" headerargs = ""
postheader = "" postheader = ""
bodyargs = "" bodyargs = ""
postbody = "</html>\n" postbody = "</html>\n"
body = pageform.cleaned_data["html"] body = pageform.cleaned_data["html"]
body = body.replace("\r", "") body = body.replace("\r", "")
result = "%s<head%s>%s</head>%s<body%s>\n%s</body>%s" % (preheader, headerargs, head, postheader, bodyargs, body, postbody) result = "%s<head%s>%s</head>%s<body%s>\n%s</body>%s" % (preheader, headerargs, head, postheader, bodyargs, body, postbody)
cwd = filepath.parent cwd = filepath.parent
filename = filepath.name filename = filepath.name
git = settings.GIT git = settings.GIT
# GIT see also core/models/cave.py writetrogglefile() # GIT see also core/models/cave.py writetrogglefile()
# GIT see also core/views/uploads.py dwgupload() # GIT see also core/views/uploads.py dwgupload()
try: try:
with open(filepath, "w") as f: with open(filepath, "w") as f:
print(f'WRITING{cwd}---{filename} ') print(f'WRITING{cwd}---{filename} ')
# as the wsgi process www-data, we have group write-access but are not owner, so cannot chmod. # as the wsgi process www-data, we have group write-access but are not owner, so cannot chmod.
# os.chmod(filepath, 0o664) # set file permissions to rw-rw-r-- # os.chmod(filepath, 0o664) # set file permissions to rw-rw-r--
f.write(result) f.write(result)
except PermissionError: except PermissionError:
message = f'CANNOT save this file.\nPERMISSIONS incorrectly set on server for this file {filename}. Ask a nerd to fix this.' message = f'CANNOT save this file.\nPERMISSIONS incorrectly set on server for this file {filename}. Ask a nerd to fix this.'
return render(request,'errors/generic.html', {'message': message}) return render(request,'errors/generic.html', {'message': message})
try: try:
cp_add = subprocess.run([git, "add", filename], cwd=cwd, capture_output=True, text=True) cp_add = subprocess.run([git, "add", filename], cwd=cwd, capture_output=True, text=True)
if cp_add.returncode != 0: if cp_add.returncode != 0:
msgdata = 'Ask a nerd to fix this.\n\n' + cp_add.stderr + '\n\n' + cp_add.stdout + '\n\nreturn code: ' + str(cp_add.returncode) msgdata = 'Ask a nerd to fix this.\n\n' + cp_add.stderr + '\n\n' + cp_add.stdout + '\n\nreturn code: ' + str(cp_add.returncode)
message = f'CANNOT git on server for this file {filename}. Edits saved but not added to git.\n\n' + msgdata message = f'CANNOT git on server for this file {filename}. Edits saved but not added to git.\n\n' + msgdata
return render(request,'errors/generic.html', {'message': message}) return render(request,'errors/generic.html', {'message': message})
cp_commit = subprocess.run([git, "commit", "-m", f'Troggle online: Edit this page - {filename}'], cwd=cwd, capture_output=True, text=True) cp_commit = subprocess.run([git, "commit", "-m", f'Troggle online: Edit this page - {filename}'], cwd=cwd, capture_output=True, text=True)
# This produces return code = 1 if it commits OK, but when the repo still needs to be pushed to origin/expoweb # This produces return code = 1 if it commits OK, but when the repo still needs to be pushed to origin/expoweb
if cp_commit.returncode != 0 and cp_commit.stdout != 'nothing to commit, working tree clean': if cp_commit.returncode != 0 and cp_commit.stdout != 'nothing to commit, working tree clean':
msgdata = 'Ask a nerd to fix this.\n\n' + cp_commit.stderr + '\n\n' + cp_commit.stdout + '\n\nreturn code: ' + str(cp_commit.returncode) msgdata = 'Ask a nerd to fix this.\n\n' + cp_commit.stderr + '\n\n' + cp_commit.stdout + '\n\nreturn code: ' + str(cp_commit.returncode)
message = f'Error code with git on server for this file {filename}. Edits saved, added to git, but NOT committed.\n\n' + msgdata message = f'Error code with git on server for this file {filename}. Edits saved, added to git, but NOT committed.\n\n' + msgdata
return render(request,'errors/generic.html', {'message': message}) return render(request,'errors/generic.html', {'message': message})
except subprocess.SubprocessError: except subprocess.SubprocessError:
message = f'CANNOT git on server for this file {filename}. Subprocess error. Edits not saved.\nAsk a nerd to fix this.' message = f'CANNOT git on server for this file {filename}. Subprocess error. Edits not saved.\nAsk a nerd to fix this.'
return render(request,'errors/generic.html', {'message': message}) return render(request,'errors/generic.html', {'message': message})
return HttpResponseRedirect(reverse('expopage', args=[path])) # Redirect after POST return HttpResponseRedirect(reverse('expopage', args=[path])) # Redirect after POST
else: else:
if filefound: if filefound:
m = re.search(r"<title>(.*)</title>", head, re.DOTALL + re.IGNORECASE) m = re.search(r"<title>(.*)</title>", head, re.DOTALL + re.IGNORECASE)
if m: if m:
title, = m.groups() title, = m.groups()
else: else:
title = "" title = ""
pageform = ExpoPageForm({"html": body, "title": title}) pageform = ExpoPageForm({"html": body, "title": title})
else: else:
body = "### File not found ###\n" + str(filepath) body = "### File not found ###\n" + str(filepath)
pageform = ExpoPageForm({"html": body, "title": "Missing"}) pageform = ExpoPageForm({"html": body, "title": "Missing"})
return render(request, 'editexpopage.html', {'path': path, 'form': pageform, }) return render(request, 'editexpopage.html', {'path': path, 'form': pageform, })
class ExpoPageForm(forms.Form): class ExpoPageForm(forms.Form):
'''The form used by the editexpopage function '''The form used by the editexpopage function
''' '''
title = forms.CharField(widget=forms.TextInput(attrs={'size':'60'})) title = forms.CharField(widget=forms.TextInput(attrs={'size':'60'}))
html = forms.CharField(widget=forms.Textarea(attrs={"cols":80, "rows":20})) html = forms.CharField(widget=forms.Textarea(attrs={"cols":80, "rows":20}))

View File

@ -1,173 +1,173 @@
import datetime import datetime
import os.path import os.path
import re import re
from collections import OrderedDict from collections import OrderedDict
import django.db.models import django.db.models
from django.db.models import Min, Max from django.db.models import Min, Max
from django.shortcuts import render from django.shortcuts import render
from django.template import Context, loader from django.template import Context, loader
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from django.utils import timezone from django.utils import timezone
#from django.views.generic.list import ListView #from django.views.generic.list import ListView
from troggle.core.models.troggle import Expedition, Person, PersonExpedition, DataIssue from troggle.core.models.troggle import Expedition, Person, PersonExpedition, DataIssue
from troggle.core.models.caves import Cave, LogbookEntry, Entrance from troggle.core.models.caves import Cave, LogbookEntry, Entrance
from troggle.core.models.survex import SurvexBlock, SurvexStation from troggle.core.models.survex import SurvexBlock, SurvexStation
import troggle.settings as settings import troggle.settings as settings
'''Very simple report pages summarizing data about the whole set of expeditions and of '''Very simple report pages summarizing data about the whole set of expeditions and of
the status of data inconsistencies the status of data inconsistencies
''' '''
def pathsreport(request): def pathsreport(request):
pathsdict = OrderedDict() pathsdict = OrderedDict()
try: try:
pathsdict = { pathsdict = {
# "BOGUS" : str( settings.BOGUS), # "BOGUS" : str( settings.BOGUS),
"JSLIB_URL" : str( settings.JSLIB_URL), "JSLIB_URL" : str( settings.JSLIB_URL),
"JSLIB_ROOT" : str( settings.JSLIB_ROOT), "JSLIB_ROOT" : str( settings.JSLIB_ROOT),
# "CSSLIB_URL" : str( settings.CSSLIB_URL), # "CSSLIB_URL" : str( settings.CSSLIB_URL),
"CAVEDESCRIPTIONS" : str( settings.CAVEDESCRIPTIONS), "CAVEDESCRIPTIONS" : str( settings.CAVEDESCRIPTIONS),
"DIR_ROOT" : str( settings.DIR_ROOT), "DIR_ROOT" : str( settings.DIR_ROOT),
"ENTRANCEDESCRIPTIONS" : str( settings.ENTRANCEDESCRIPTIONS), "ENTRANCEDESCRIPTIONS" : str( settings.ENTRANCEDESCRIPTIONS),
"EXPOUSER_EMAIL" : str( settings.EXPOUSER_EMAIL), "EXPOUSER_EMAIL" : str( settings.EXPOUSER_EMAIL),
"EXPOUSERPASS" : str("<redacted>"), "EXPOUSERPASS" : str("<redacted>"),
"EXPOUSER" : str( settings.EXPOUSER), "EXPOUSER" : str( settings.EXPOUSER),
"EXPOWEB" : str( settings.EXPOWEB), "EXPOWEB" : str( settings.EXPOWEB),
"EXPOWEB_URL" : str( settings.EXPOWEB_URL), "EXPOWEB_URL" : str( settings.EXPOWEB_URL),
"FILES" : str( settings.FILES), "FILES" : str( settings.FILES),
"LIBDIR" : str( settings.LIBDIR), "LIBDIR" : str( settings.LIBDIR),
"LOGFILE" : str( settings.LOGFILE), "LOGFILE" : str( settings.LOGFILE),
"LOGIN_REDIRECT_URL" : str( settings.LOGIN_REDIRECT_URL), "LOGIN_REDIRECT_URL" : str( settings.LOGIN_REDIRECT_URL),
"MEDIA_ROOT" : str( settings.MEDIA_ROOT), "MEDIA_ROOT" : str( settings.MEDIA_ROOT),
"MEDIA_URL" : str( settings.MEDIA_URL), "MEDIA_URL" : str( settings.MEDIA_URL),
"PHOTOS_URL" : str( settings.PHOTOS_URL), "PHOTOS_URL" : str( settings.PHOTOS_URL),
"PYTHON_PATH" : str( settings.PYTHON_PATH), "PYTHON_PATH" : str( settings.PYTHON_PATH),
"REPOS_ROOT_PATH" : str( settings.REPOS_ROOT_PATH), "REPOS_ROOT_PATH" : str( settings.REPOS_ROOT_PATH),
"ROOT_URLCONF" : str( settings.ROOT_URLCONF), "ROOT_URLCONF" : str( settings.ROOT_URLCONF),
"STATIC_URL" : str( settings.STATIC_URL), "STATIC_URL" : str( settings.STATIC_URL),
"SURVEX_DATA" : str( settings.SURVEX_DATA), "SURVEX_DATA" : str( settings.SURVEX_DATA),
"SURVEY_SCANS" : str( settings.SURVEY_SCANS), "SURVEY_SCANS" : str( settings.SURVEY_SCANS),
"SURVEYS" : str( settings.SURVEYS), "SURVEYS" : str( settings.SURVEYS),
"SURVEYS_URL" : str( settings.SURVEYS_URL), "SURVEYS_URL" : str( settings.SURVEYS_URL),
"SURVEXPORT" : str( settings.SURVEXPORT), "SURVEXPORT" : str( settings.SURVEXPORT),
"DRAWINGS_DATA" : str( settings.DRAWINGS_DATA), "DRAWINGS_DATA" : str( settings.DRAWINGS_DATA),
"URL_ROOT" : str( settings.URL_ROOT) "URL_ROOT" : str( settings.URL_ROOT)
} }
except: except:
pathsdict["! EXCEPTION !"] = "missing or exta string constant in troggle/settings" pathsdict["! EXCEPTION !"] = "missing or exta string constant in troggle/settings"
pathstype = OrderedDict() pathstype = OrderedDict()
try: try:
pathstype = { pathstype = {
# "BOGUS" : type(settings.BOGUS), # "BOGUS" : type(settings.BOGUS),
"JSLIB_URL" : type(settings.JSLIB_URL), "JSLIB_URL" : type(settings.JSLIB_URL),
"JSLIB_ROOT" : type( settings.JSLIB_ROOT), "JSLIB_ROOT" : type( settings.JSLIB_ROOT),
# "CSSLIB_URL" : type(settings.CSSLIB_URL), # "CSSLIB_URL" : type(settings.CSSLIB_URL),
"CAVEDESCRIPTIONS" : type(settings.CAVEDESCRIPTIONS), "CAVEDESCRIPTIONS" : type(settings.CAVEDESCRIPTIONS),
"DIR_ROOT" : type(settings.DIR_ROOT), "DIR_ROOT" : type(settings.DIR_ROOT),
"ENTRANCEDESCRIPTIONS" : type(settings.ENTRANCEDESCRIPTIONS), "ENTRANCEDESCRIPTIONS" : type(settings.ENTRANCEDESCRIPTIONS),
"EXPOUSER_EMAIL" : type(settings.EXPOUSER_EMAIL), "EXPOUSER_EMAIL" : type(settings.EXPOUSER_EMAIL),
"EXPOUSERPASS" : type(settings.EXPOUSERPASS), "EXPOUSERPASS" : type(settings.EXPOUSERPASS),
"EXPOUSER" : type(settings.EXPOUSER), "EXPOUSER" : type(settings.EXPOUSER),
"EXPOWEB" : type(settings.EXPOWEB), "EXPOWEB" : type(settings.EXPOWEB),
"EXPOWEB_URL" : type(settings.EXPOWEB_URL), "EXPOWEB_URL" : type(settings.EXPOWEB_URL),
"FILES" : type(settings.FILES), "FILES" : type(settings.FILES),
"LIBDIR" : type( settings.LIBDIR), "LIBDIR" : type( settings.LIBDIR),
"LOGFILE" : type(settings.LOGFILE), "LOGFILE" : type(settings.LOGFILE),
"LOGIN_REDIRECT_URL" : type(settings.LOGIN_REDIRECT_URL), "LOGIN_REDIRECT_URL" : type(settings.LOGIN_REDIRECT_URL),
"MEDIA_ROOT" : type(settings.MEDIA_ROOT), "MEDIA_ROOT" : type(settings.MEDIA_ROOT),
"MEDIA_URL" : type(settings.MEDIA_URL), "MEDIA_URL" : type(settings.MEDIA_URL),
"PHOTOS_URL" : type(settings.PHOTOS_URL), "PHOTOS_URL" : type(settings.PHOTOS_URL),
"PYTHON_PATH" : type(settings.PYTHON_PATH), "PYTHON_PATH" : type(settings.PYTHON_PATH),
"REPOS_ROOT_PATH" : type(settings.REPOS_ROOT_PATH), "REPOS_ROOT_PATH" : type(settings.REPOS_ROOT_PATH),
"ROOT_URLCONF" : type(settings.ROOT_URLCONF), "ROOT_URLCONF" : type(settings.ROOT_URLCONF),
"STATIC_URL" : type(settings.STATIC_URL), "STATIC_URL" : type(settings.STATIC_URL),
"SURVEX_DATA" : type(settings.SURVEX_DATA), "SURVEX_DATA" : type(settings.SURVEX_DATA),
"SURVEY_SCANS" : type(settings.SURVEY_SCANS), "SURVEY_SCANS" : type(settings.SURVEY_SCANS),
"SURVEYS" : type(settings.SURVEYS), "SURVEYS" : type(settings.SURVEYS),
"SURVEYS_URL" : type(settings.SURVEYS_URL), "SURVEYS_URL" : type(settings.SURVEYS_URL),
"SURVEXPORT" : type(settings.SURVEXPORT), "SURVEXPORT" : type(settings.SURVEXPORT),
"DRAWINGS_DATA" : type(settings.DRAWINGS_DATA), "DRAWINGS_DATA" : type(settings.DRAWINGS_DATA),
"URL_ROOT" : type(settings.URL_ROOT) "URL_ROOT" : type(settings.URL_ROOT)
} }
except: except:
pathstype["! EXCEPTION !"] = "missing or exta string constant in troggle/settings" pathstype["! EXCEPTION !"] = "missing or exta string constant in troggle/settings"
raise raise
# settings are unique by paths are not # settings are unique by paths are not
ncodes = len(pathsdict) ncodes = len(pathsdict)
bycodeslist = sorted(pathsdict.items()) # a list of tuples bycodeslist = sorted(pathsdict.items()) # a list of tuples
bycodeslist2 = [] bycodeslist2 = []
for k, p in bycodeslist: for k, p in bycodeslist:
bycodeslist2.append((k, p, str(pathstype[k]))) bycodeslist2.append((k, p, str(pathstype[k])))
bypaths = sorted(pathsdict.values()) # a list bypaths = sorted(pathsdict.values()) # a list
bypathslist = [] bypathslist = []
for p in bypaths: for p in bypaths:
for k in pathsdict.keys(): for k in pathsdict.keys():
if pathsdict[k] == p: if pathsdict[k] == p:
bypathslist.append((p, k, str(pathstype[k]))) bypathslist.append((p, k, str(pathstype[k])))
del pathsdict[k] del pathsdict[k]
break break
return render(request, 'pathsreport.html', { return render(request, 'pathsreport.html', {
"pathsdict":pathsdict, "pathsdict":pathsdict,
"bycodeslist":bycodeslist2, "bycodeslist":bycodeslist2,
"bypathslist":bypathslist, "bypathslist":bypathslist,
"ncodes":ncodes}) "ncodes":ncodes})
def stats(request): def stats(request):
statsDict={} statsDict={}
statsDict['expoCount'] = "{:,}".format(Expedition.objects.count()) statsDict['expoCount'] = "{:,}".format(Expedition.objects.count())
statsDict['caveCount'] = "{:,}".format(Cave.objects.count()) statsDict['caveCount'] = "{:,}".format(Cave.objects.count())
statsDict['personCount'] = "{:,}".format(Person.objects.count()) statsDict['personCount'] = "{:,}".format(Person.objects.count())
statsDict['logbookEntryCount'] = "{:,}".format(LogbookEntry.objects.count()) statsDict['logbookEntryCount'] = "{:,}".format(LogbookEntry.objects.count())
legsbyexpo = [ ] legsbyexpo = [ ]
addupsurvexlength = 0 addupsurvexlength = 0
for expedition in Expedition.objects.all(): for expedition in Expedition.objects.all():
survexblocks = expedition.survexblock_set.all() survexblocks = expedition.survexblock_set.all()
legsyear=0 legsyear=0
survexleglength = 0.0 survexleglength = 0.0
for survexblock in survexblocks: for survexblock in survexblocks:
survexleglength += survexblock.legslength survexleglength += survexblock.legslength
try: try:
legsyear += int(survexblock.legsall) legsyear += int(survexblock.legsall)
except: except:
pass pass
addupsurvexlength += survexleglength addupsurvexlength += survexleglength
legsbyexpo.append((expedition, {"nsurvexlegs": "{:,}".format(legsyear), legsbyexpo.append((expedition, {"nsurvexlegs": "{:,}".format(legsyear),
"survexleglength":"{:,.0f}".format(survexleglength)})) "survexleglength":"{:,.0f}".format(survexleglength)}))
legsbyexpo.reverse() legsbyexpo.reverse()
renderDict = {**statsDict, **{ "addupsurvexlength":addupsurvexlength/1000, "legsbyexpo":legsbyexpo }} # new syntax renderDict = {**statsDict, **{ "addupsurvexlength":addupsurvexlength/1000, "legsbyexpo":legsbyexpo }} # new syntax
return render(request,'statistics.html', renderDict) return render(request,'statistics.html', renderDict)
def dataissues(request): def dataissues(request):
'''Each issue has a parser, a message and a url linking to the offending object after loading '''Each issue has a parser, a message and a url linking to the offending object after loading
''' '''
def myFunc(di): def myFunc(di):
return di.parser.lower() + di.message.lower() return di.parser.lower() + di.message.lower()
dilist = list(DataIssue.objects.all()) dilist = list(DataIssue.objects.all())
dilist.sort(key = myFunc) dilist.sort(key = myFunc)
return render(request,'dataissues.html', {'didict': dilist}) return render(request,'dataissues.html', {'didict': dilist})
def eastings(request): def eastings(request):
'''report each Northing/Easting pair wherever recorded '''report each Northing/Easting pair wherever recorded
''' '''
ents = [] ents = []
entrances = Entrance.objects.all() entrances = Entrance.objects.all()
for e in entrances: for e in entrances:
if e.easting or e.northing: if e.easting or e.northing:
ents.append(e) ents.append(e)
stations = SurvexStation.objects.all() stations = SurvexStation.objects.all()
return render(request,'eastings.html', {'ents': ents, 'stations': stations}) return render(request,'eastings.html', {'ents': ents, 'stations': stations})

View File

@ -1,164 +1,164 @@
From: <Saved by Blink> From: <Saved by Blink>
Snapshot-Content-Location: https://aardgoose.github.io/CaveView.js/installation.html Snapshot-Content-Location: https://aardgoose.github.io/CaveView.js/installation.html
Subject: CaveView installation Subject: CaveView installation
Date: Sun, 24 Oct 2021 15:46:19 -0000 Date: Sun, 24 Oct 2021 15:46:19 -0000
MIME-Version: 1.0 MIME-Version: 1.0
Content-Type: multipart/related; Content-Type: multipart/related;
type="text/html"; type="text/html";
boundary="----MultipartBoundary--eCFBXfFmJiPIUIDdJDuaiHRJfZ59xqA99QxmIcmsBZ----" boundary="----MultipartBoundary--eCFBXfFmJiPIUIDdJDuaiHRJfZ59xqA99QxmIcmsBZ----"
------MultipartBoundary--eCFBXfFmJiPIUIDdJDuaiHRJfZ59xqA99QxmIcmsBZ---- ------MultipartBoundary--eCFBXfFmJiPIUIDdJDuaiHRJfZ59xqA99QxmIcmsBZ----
Content-Type: text/html Content-Type: text/html
Content-ID: <frame-F25506009C17180F1D15EDA63865EFC8@mhtml.blink> Content-ID: <frame-F25506009C17180F1D15EDA63865EFC8@mhtml.blink>
Content-Transfer-Encoding: quoted-printable Content-Transfer-Encoding: quoted-printable
Content-Location: https://aardgoose.github.io/CaveView.js/installation.html Content-Location: https://aardgoose.github.io/CaveView.js/installation.html
<!DOCTYPE html><html xmlns=3D"http://www.w3.org/1999/xhtml" xml:lang=3D"en-= <!DOCTYPE html><html xmlns=3D"http://www.w3.org/1999/xhtml" xml:lang=3D"en-=
gb" lang=3D"en-gb" dir=3D"ltr"><head><meta http-equiv=3D"Content-Type" cont= gb" lang=3D"en-gb" dir=3D"ltr"><head><meta http-equiv=3D"Content-Type" cont=
ent=3D"text/html; charset=3DUTF-8"> ent=3D"text/html; charset=3DUTF-8">
<title>CaveView installation</title> <title>CaveView installation</title>
=09 =09
<link type=3D"text/css" href=3D"https://aardgoose.github.io/CaveView.js/do= <link type=3D"text/css" href=3D"https://aardgoose.github.io/CaveView.js/do=
c.css" rel=3D"stylesheet"> c.css" rel=3D"stylesheet">
</head> </head>
<body> <body>
<h1>Cave View - installation instructions - V2 API</h1> <h1>Cave View - installation instructions - V2 API</h1>
<h2>Install CaveView files</h2> <h2>Install CaveView files</h2>
<p>A zip archive containing the required files for the latest release are = <p>A zip archive containing the required files for the latest release are =
<a href=3D"https://github.com/aardgoose/CaveView.js/releases">here</a>.</p> <a href=3D"https://github.com/aardgoose/CaveView.js/releases">here</a>.</p>
<p>There is no need to build the JavaScript application from source files = <p>There is no need to build the JavaScript application from source files =
unless you would like to modify the application.</p> unless you would like to modify the application.</p>
<p>Unzip the archive in a convenient location on your web server </p> <p>Unzip the archive in a convenient location on your web server </p>
<h2>Using in a web page</h2> <h2>Using in a web page</h2>
<p>CaveView requires two files to be included in the page. Replace the plac= <p>CaveView requires two files to be included in the page. Replace the plac=
eholder %path% with the path to the unzipped files on the server in the fol= eholder %path% with the path to the unzipped files on the server in the fol=
lowing examples.</p><p> lowing examples.</p><p>
</p><h3>caveview.css</h3> </p><h3>caveview.css</h3>
<p>The side panel interface and on screen indicators are styled with cavevi= <p>The side panel interface and on screen indicators are styled with cavevi=
ew.css. Include this in the <strong>head</strong> section of the page.</p> ew.css. Include this in the <strong>head</strong> section of the page.</p>
<pre> &lt;link type=3D"text/css" href=3D"%path%/CaveView/css/caveview.css" = <pre> &lt;link type=3D"text/css" href=3D"%path%/CaveView/css/caveview.css" =
rel=3D"stylesheet" /&gt;</pre> rel=3D"stylesheet" /&gt;</pre>
<h3>CaveView.js</h3> <h3>CaveView.js</h3>
<p>The CaveView application is provided in one javascript file. Include thi= <p>The CaveView application is provided in one javascript file. Include thi=
s in the <strong>body</strong> section of the page. <strong>NOTE: The filen= s in the <strong>body</strong> section of the page. <strong>NOTE: The filen=
ame has changed for the V2 API.</strong></p> ame has changed for the V2 API.</strong></p>
<pre> &lt;script type=3D"text/javascript" src=3D"%path%/CaveView/js/CaveVie= <pre> &lt;script type=3D"text/javascript" src=3D"%path%/CaveView/js/CaveVie=
w2.js" &gt;&lt;/script&gt;</pre> w2.js" &gt;&lt;/script&gt;</pre>
<h3>Add a container element</h3> <h3>Add a container element</h3>
<p>Add an empty block element to the page, with a suitable <strong>id</stro= <p>Add an empty block element to the page, with a suitable <strong>id</stro=
ng> attribute. This contains the application, and be sized as required. For= ng> attribute. This contains the application, and be sized as required. For=
example a <strong>div</strong> element:</p> example a <strong>div</strong> element:</p>
<pre>&lt;div id=3D'% element-id %' &gt;&lt;/div&gt;</pre> <pre>&lt;div id=3D'% element-id %' &gt;&lt;/div&gt;</pre>
<h3>Create a script to run the application</h3> <h3>Create a script to run the application</h3>
<p>The application can be loaded using javascript, typically using an load = <p>The application can be loaded using javascript, typically using an load =
event handler. Replace the placeholder %...% elements with values appropria= event handler. Replace the placeholder %...% elements with values appropria=
te for your site.</p> te for your site.</p>
<pre>&lt;script type=3D"text/javascript" &gt; <pre>&lt;script type=3D"text/javascript" &gt;
function onLoad () { function onLoad () {
// display the user interface - and a blank canvas // display the user interface - and a blank canvas
// the configuration object specifies the location of CaveView, surveys a= // the configuration object specifies the location of CaveView, surveys a=
nd terrain files nd terrain files
var viewer =3D new CV2.CaveViewer( '% element-id %', { var viewer =3D new CV2.CaveViewer( '% element-id %', {
home: '% location of the unzipped CaveView directory on the survey %', home: '% location of the unzipped CaveView directory on the survey %',
surveyDirectory: '% location of the survey files on the server %', surveyDirectory: '% location of the survey files on the server %',
terrainDirectory: '% location of the terrain files on the server %' terrainDirectory: '% location of the terrain files on the server %'
} ); } );
// if using the full user interface (UI) // if using the full user interface (UI)
var ui =3D new CV2.CaveViewUI( viewer ); var ui =3D new CV2.CaveViewUI( viewer );
// load a single survey to display // load a single survey to display
ui.loadCave( '% survey filename %' ); ui.loadCave( '% survey filename %' );
// or without the user interface // or without the user interface
viewer.loadCave( '% survey filename %' ); viewer.loadCave( '% survey filename %' );
} }
&lt;/script&gt; &lt;/script&gt;
</pre> </pre>
<p>alternatively provide a list of surveys to display, by replacing the loa= <p>alternatively provide a list of surveys to display, by replacing the loa=
dCave() function call with loadCaveList() :</p> dCave() function call with loadCaveList() :</p>
<pre> ui.loadCaveList( [ '% survey filename 1 %', '% survey filename 2 %', = <pre> ui.loadCaveList( [ '% survey filename 1 %', '% survey filename 2 %', =
'% survey filename 3 %' ] ); '% survey filename 3 %' ] );
</pre> </pre>
<p>This can be automatically executed on page load by including a page load= <p>This can be automatically executed on page load by including a page load=
handler in the page <strong>body</strong> tag:</p> handler in the page <strong>body</strong> tag:</p>
<pre>&lt;body onload=3D"onload();" &gt;</pre> <pre>&lt;body onload=3D"onload();" &gt;</pre>
<p>CaveView should now display when the page is viewed.</p> <p>CaveView should now display when the page is viewed.</p>
<p>The example files included demonstrate using multiple viewers on a page, <p>The example files included demonstrate using multiple viewers on a page,
changing the default view settings and altering the appearance of the viewe= changing the default view settings and altering the appearance of the viewe=
r.</p> r.</p>
<h3>Removal</h3> <h3>Removal</h3>
<p>To remove the viewer from a page and reclaim memory used promptly:</p> <p>To remove the viewer from a page and reclaim memory used promptly:</p>
<pre> ui.dispose(); <pre> ui.dispose();
ui =3D null; ui =3D null;
viewer =3D null; viewer =3D null;
</pre> </pre>
<p>Or if not using the UI, just the viewer:</p> <p>Or if not using the UI, just the viewer:</p>
<pre> viewer.dispose(); <pre> viewer.dispose();
viewer =3D null; viewer =3D null;
</pre> </pre>
</body></html> </body></html>
------MultipartBoundary--eCFBXfFmJiPIUIDdJDuaiHRJfZ59xqA99QxmIcmsBZ---- ------MultipartBoundary--eCFBXfFmJiPIUIDdJDuaiHRJfZ59xqA99QxmIcmsBZ----
Content-Type: text/css Content-Type: text/css
Content-Transfer-Encoding: quoted-printable Content-Transfer-Encoding: quoted-printable
Content-Location: https://aardgoose.github.io/CaveView.js/doc.css Content-Location: https://aardgoose.github.io/CaveView.js/doc.css
@charset "utf-8"; @charset "utf-8";
h1, h2 { margin: 0px 16px 1em; } h1, h2 { margin: 0px 16px 1em; }
h3, h4, h5, p, pre, dl { margin-left: 32px; margin-right: 32px; } h3, h4, h5, p, pre, dl { margin-left: 32px; margin-right: 32px; }
h2 { border-bottom: 2px solid gray; } h2 { border-bottom: 2px solid gray; }
h3 { color: navy; } h3 { color: navy; }
h4 { margin-top: 2em; background-color: rgb(238, 238, 238); padding: 3px 2p= h4 { margin-top: 2em; background-color: rgb(238, 238, 238); padding: 3px 2p=
x 1px; } x 1px; }
* { font-family: sans-serif; } * { font-family: sans-serif; }
pre { font-family: monospace; font-weight: bold; background-color: rgb(238,= pre { font-family: monospace; font-weight: bold; background-color: rgb(238,=
238, 238); padding: 8px; } 238, 238); padding: 8px; }
dd > span { display: inline-block; padding: 0px 2px; margin-right: 5px; bac= dd > span { display: inline-block; padding: 0px 2px; margin-right: 5px; bac=
kground: rgb(238, 238, 238); } kground: rgb(238, 238, 238); }
dd > span::before { content: "["; } dd > span::before { content: "["; }
dd > span::after { content: "]"; } dd > span::after { content: "]"; }
dt { margin-bottom: 0.5em; font-weight: bold; color: rgb(102, 102, 102); pa= dt { margin-bottom: 0.5em; font-weight: bold; color: rgb(102, 102, 102); pa=
dding-left: 16px; } dding-left: 16px; }
dd { margin-bottom: 1em; } dd { margin-bottom: 1em; }
------MultipartBoundary--eCFBXfFmJiPIUIDdJDuaiHRJfZ59xqA99QxmIcmsBZ------ ------MultipartBoundary--eCFBXfFmJiPIUIDdJDuaiHRJfZ59xqA99QxmIcmsBZ------

View File

@ -1,2 +1,2 @@
[InternetShortcut] [InternetShortcut]
URL=https://github.com/aardgoose/CaveView.js/releases URL=https://github.com/aardgoose/CaveView.js/releases

View File

@ -1,2 +1,2 @@
[InternetShortcut] [InternetShortcut]
URL=https://aardgoose.github.io/CaveView.js/ URL=https://aardgoose.github.io/CaveView.js/