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

Added some test pages showing different ways pages could be edited. This probably wants removing soon

This commit is contained in:
Martin Green 2022-06-28 00:18:24 +01:00
parent 82fe350493
commit 2af88353f3
6 changed files with 192 additions and 3 deletions

View File

@ -6,7 +6,7 @@ from django.forms import ModelForm
from django.forms.models import modelformset_factory from django.forms.models import modelformset_factory
from django.contrib.admin.widgets import AdminDateWidget from django.contrib.admin.widgets import AdminDateWidget
#from tinymce.widgets import TinyMCE from tinymce.widgets import TinyMCE
from troggle.core.models.troggle import Person, PersonExpedition, Expedition from troggle.core.models.troggle import Person, PersonExpedition, Expedition
from troggle.core.models.caves import Cave, LogbookEntry, QM, Entrance, CaveAndEntrance from troggle.core.models.caves import Cave, LogbookEntry, QM, Entrance, CaveAndEntrance
@ -25,6 +25,7 @@ class CaveForm(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 presentation style the other fields are present on the form, but use the default presentation style
''' '''
official_name = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'})) official_name = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
underground_description = forms.CharField(required = False, widget=HTMLarea( underground_description = forms.CharField(required = False, widget=HTMLarea(
attrs={"height":"80%", "rows":20, 'placeholder': "Enter page content (using HTML)"})) attrs={"height":"80%", "rows":20, 'placeholder': "Enter page content (using HTML)"}))
@ -63,6 +64,123 @@ 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 CaveFormTextArea(ModelForm):
'''Only those fields for which we want to override defaults are listed here
the other fields are present on the form, but use the default presentation style
'''
official_name = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
underground_description = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':9}))
explorers = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':9}))
equipment = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':9}))
survey = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':9}))
#survey = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10}))
kataster_status = forms.CharField(required = False)
underground_centre_line = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':9}))
notes = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':9}))
references = forms.CharField(required = False, widget=forms.Textarea(attrs={'rows':9}))
description_file = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
survex_file = forms.CharField(required = False, label="Survex file [caves-1623/000/000.svx]", widget=forms.TextInput(attrs={'size': '45'}))
url = forms.CharField(required = True, label="URL [1623/000/000]", widget=forms.TextInput(attrs={'size': '45'}))
length = forms.CharField(required = False, label="Length (m)")
depth = forms.CharField(required = False, label="Depth (m)")
extent = forms.CharField(required = False, label="Extent (m)")
class Meta:
model = Cave
exclude = ("filename",)
def clean(self):
if self.cleaned_data.get("kataster_number") == "" and self.cleaned_data.get("unofficial_number") == "":
self._errors["unofficial_number"] = self.error_class(["Either the kataster or unoffical number is required."])
# if self.cleaned_data.get("kataster_number") != "" and self.cleaned_data.get("official_name") == "":
# self._errors["official_name"] = self.error_class(["This field is required when there is a kataster number."])
if self.cleaned_data.get("area") == []:
self._errors["area"] = self.error_class(["This field is required."])
if self.cleaned_data.get("url") and self.cleaned_data.get("url").startswith("/"):
self._errors["url"] = self.error_class(["This field cannot start with a /."])
return self.cleaned_data
class CaveFormCodeMirrorPreview(ModelForm):
'''Only those fields for which we want to override defaults are listed here
the other fields are present on the form, but use the default presentation style
'''
official_name = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
underground_description = forms.CharField(required = False, widget=HTMLarea(preview = True,
attrs={"height":"80%", "rows":20, 'placeholder': "Enter page content (using HTML)"}))
explorers = forms.CharField(required = False, widget=HTMLarea(preview = True,
attrs={"height":"80%", "rows":20, 'placeholder': "Enter page content (using HTML)"}))
equipment = forms.CharField(required = False, widget=HTMLarea(preview = True,
attrs={"height":"80%", "rows":20, 'placeholder': "Enter page content (using HTML)"}))
survey = forms.CharField(required = False, widget=HTMLarea(preview = True,
attrs={"height":"80%", "rows":20, 'placeholder': "Enter page content (using HTML)"}))
#survey = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10}))
kataster_status = forms.CharField(required = False)
underground_centre_line = forms.CharField(required = False, widget=HTMLarea(preview = True,
attrs={"height":"80%", "rows":20, 'placeholder': "Enter page content (using HTML)"}))
notes = forms.CharField(required = False, widget=HTMLarea(preview = True,
attrs={"height":"80%", "rows":20, 'placeholder': "Enter page content (using HTML)"}))
references = forms.CharField(required = False, widget=HTMLarea(preview = True,
attrs={"height":"80%", "rows":20, 'placeholder': "Enter page content (using HTML)"}))
description_file = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
survex_file = forms.CharField(required = False, label="Survex file [caves-1623/000/000.svx]", widget=forms.TextInput(attrs={'size': '45'}))
url = forms.CharField(required = True, label="URL [1623/000/000]", widget=forms.TextInput(attrs={'size': '45'}))
length = forms.CharField(required = False, label="Length (m)")
depth = forms.CharField(required = False, label="Depth (m)")
extent = forms.CharField(required = False, label="Extent (m)")
class Meta:
model = Cave
exclude = ("filename",)
def clean(self):
if self.cleaned_data.get("kataster_number") == "" and self.cleaned_data.get("unofficial_number") == "":
self._errors["unofficial_number"] = self.error_class(["Either the kataster or unoffical number is required."])
# if self.cleaned_data.get("kataster_number") != "" and self.cleaned_data.get("official_name") == "":
# self._errors["official_name"] = self.error_class(["This field is required when there is a kataster number."])
if self.cleaned_data.get("area") == []:
self._errors["area"] = self.error_class(["This field is required."])
if self.cleaned_data.get("url") and self.cleaned_data.get("url").startswith("/"):
self._errors["url"] = self.error_class(["This field cannot start with a /."])
return self.cleaned_data
class CaveFormTinyMCE(ModelForm):
'''Only those fields for which we want to override defaults are listed here
the other fields are present on the form, but use the default presentation style
'''
official_name = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
underground_description = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
explorers = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
equipment = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
survey = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
#survey = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 10}))
kataster_status = forms.CharField(required = False)
underground_centre_line = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
notes = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
references = forms.CharField(required = False, widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
description_file = forms.CharField(required = False, widget=forms.TextInput(attrs={'size': '45'}))
survex_file = forms.CharField(required = False, label="Survex file [caves-1623/000/000.svx]", widget=forms.TextInput(attrs={'size': '45'}))
url = forms.CharField(required = True, label="URL [1623/000/000]", widget=forms.TextInput(attrs={'size': '45'}))
length = forms.CharField(required = False, label="Length (m)")
depth = forms.CharField(required = False, label="Depth (m)")
extent = forms.CharField(required = False, label="Extent (m)")
class Meta:
model = Cave
exclude = ("filename",)
def clean(self):
if self.cleaned_data.get("kataster_number") == "" and self.cleaned_data.get("unofficial_number") == "":
self._errors["unofficial_number"] = self.error_class(["Either the kataster or unoffical number is required."])
# if self.cleaned_data.get("kataster_number") != "" and self.cleaned_data.get("official_name") == "":
# self._errors["official_name"] = self.error_class(["This field is required when there is a kataster number."])
if self.cleaned_data.get("area") == []:
self._errors["area"] = self.error_class(["This field is required."])
if self.cleaned_data.get("url") and self.cleaned_data.get("url").startswith("/"):
self._errors["url"] = self.error_class(["This field cannot start with a /."])
return self.cleaned_data
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

View File

@ -18,7 +18,7 @@ import troggle.settings as settings
from troggle.core.views import expo 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, CaveFormCodeMirrorPreview, CaveFormTextArea, CaveFormTinyMCE
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
@ -297,6 +297,42 @@ def caveEntrance(request, slug):
else: else:
return render(request,'cave_entrances.html', {'cave': cave}) return render(request,'cave_entrances.html', {'cave': cave})
def test_edit_cave(request, editor = "codemirror"):
'''This is the form that edits all the cave data and writes out an XML file in the :expoweb: repo folder
The format for the file being saved is in templates/dataformat/cave.xml
It does save the data into into the database directly, not by parsing the file.
It does NOT yet commit to the git repoSaving is not allowed
'''
form_type = {"codemirror": CaveForm, "codemirrorpreview": CaveFormCodeMirrorPreview, "textarea": CaveFormTextArea, "tinymce": CaveFormTinyMCE}[editor]
message = ""
try:
cave = Cave.objects.get(caveslug__slug = "1623-264")
except:
return render(request,'errors/badslug.html')
if request.POST:
form = form_type(request.POST, instance=cave)
ceFormSet = CaveAndEntranceFormSet(request.POST)
#versionControlForm = VersionControlCommentForm(request.POST)
if form.is_valid() and ceFormSet.is_valid():
pass
else:
message = f'! POST data is INVALID {cave}'
print(message)
else:
form = form_type(instance=cave)
ceFormSet = CaveAndEntranceFormSet(queryset=cave.caveandentrance_set.all())
#versionControlForm = VersionControlCommentForm()
return render(request,
'editcave.html',
{'form': form, 'cave': cave, 'message': message,
'caveAndEntranceFormSet': ceFormSet,
'editor': editor,
#'versionControlForm': versionControlForm
})
@login_required_if_public @login_required_if_public
def edit_cave(request, slug=None): def edit_cave(request, slug=None):
'''This is the form that edits all the cave data and writes out an XML file in the :expoweb: repo folder '''This is the form that edits all the cave data and writes out an XML file in the :expoweb: repo folder
@ -305,6 +341,7 @@ def edit_cave(request, slug=None):
It does save the data into into the database directly, not by parsing the file. It does save the data into into the database directly, not by parsing the file.
It does NOT yet commit to the git repo It does NOT yet commit to the git repo
''' '''
message = "" message = ""
if slug is not None: if slug is not None:
try: try:

View File

@ -14,3 +14,4 @@ reportlab==3.6.0
sqlparse==0.4.0 sqlparse==0.4.0
typing_extensions==4.2.0 typing_extensions==4.2.0
Unidecode==1.3.0 Unidecode==1.3.0
django-tinymce

View File

@ -127,7 +127,26 @@ X_FRAME_OPTIONS = 'DENY' # changed to "DENY" after I eliminated all the iframes
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # from Django 3.2 DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # from Django 3.2
TINYMCE_JS_URL = 'https://cloud.tinymce.com/stable/tinymce.min.js'
TINYMCE_DEFAULT_CONFIG = {
"height": "320px",
"width": "960px",
"menubar": "file edit view insert format tools table help",
"plugins": "advlist autolink lists link image charmap print preview anchor searchreplace visualblocks code "
"fullscreen insertdatetime media table paste code help wordcount spellchecker",
"toolbar": "undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft "
"aligncenter alignright alignjustify | outdent indent | numlist bullist checklist | forecolor "
"backcolor casechange permanentpen formatpainter removeformat | pagebreak | charmap emoticons | "
"fullscreen preview save print | insertfile image media pageembed template link anchor codesample | "
"a11ycheck ltr rtl | showcomments addcomment code",
"custom_undo_redo_levels": 10,
"language": "es_ES", # To force a specific language instead of the Django current language.
}
TINYMCE_SPELLCHECKER = True
TINYMCE_COMPRESSOR = True
INSTALLED_APPS = ( INSTALLED_APPS = (
'tinymce',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', # includes the url redirections for login, logout 'django.contrib.auth', # includes the url redirections for login, logout
'django.contrib.contenttypes', 'django.contrib.contenttypes',

View File

@ -2,6 +2,17 @@
{% block title %}Edit Cave - {{cave.official_name|safe}} - {{cave.kataster_number}}{% endblock %} {% block title %}Edit Cave - {{cave.official_name|safe}} - {{cave.kataster_number}}{% endblock %}
{% block extraheaders %} {% block extraheaders %}
{% include 'html_editor_scripts_css.html' %} {% include 'html_editor_scripts_css.html' %}
<script src="https://cdn.tiny.cloud/1/ib8fvyuhkhhdyt25zh35cbdo1gwvocm8w89e9vu3wf2107t4/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script>
<script>
tinyMCE.init({
mode: "textareas",
plugins: "spellchecker,directionality,paste,searchreplace",
language: "{{ language }}",
directionality: "{{ directionality }}",
spellchecker_languages : "{{ spellchecker_languages }}",
spellchecker_rpc_url : "{{ spellchecker_rpc_url }}"
});
</script>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<h1>Edit Cave - {{cave.official_name|safe}} - {{cave.kataster_number}}</h1> <h1>Edit Cave - {{cave.official_name|safe}} - {{cave.kataster_number}}</h1>

View File

@ -13,7 +13,7 @@ from troggle.core.views.drawings import dwgallfiles, dwgfilesingle
from troggle.core.views.uploads import dwgupload, scanupload, photoupload from troggle.core.views.uploads import dwgupload, scanupload, photoupload
from troggle.core.views.other import troggle404, frontpage, todos, controlpanel, frontpage from troggle.core.views.other import troggle404, frontpage, todos, controlpanel, frontpage
from troggle.core.views.other import exportlogbook from troggle.core.views.other import exportlogbook
from troggle.core.views.caves import ent, cavepage, caveindex, get_entrances, get_qms, edit_cave, cave3d, caveEntrance, edit_entrance, caveQMs, qm from troggle.core.views.caves import ent, cavepage, caveindex, get_entrances, get_qms, edit_cave, cave3d, caveEntrance, edit_entrance, caveQMs, qm, test_edit_cave
from troggle.core.views.logbooks import get_logbook_entries, logbookentry, logbookSearch from troggle.core.views.logbooks import get_logbook_entries, logbookentry, logbookSearch
from troggle.core.views.logbooks import notablepersons, person, get_people from troggle.core.views.logbooks import notablepersons, person, get_people
from troggle.core.views.logbooks import expedition, personexpedition, Expeditions_tsvListView, Expeditions_jsonListView from troggle.core.views.logbooks import expedition, personexpedition, Expeditions_tsvListView, Expeditions_jsonListView
@ -76,6 +76,8 @@ else:
# Some overlap with 'admin.site.urls' needs to be investigated. # Some overlap with 'admin.site.urls' needs to be investigated.
trogglepatterns = [ trogglepatterns = [
path('tinymce/', include('tinymce.urls')),
path('expofiles/', include(expofilesurls)), # intercepted by Apache, if it is running. path('expofiles/', include(expofilesurls)), # intercepted by Apache, if it is running.
path('expofiles', include(expofilesurls)), # curious interaction with the include() here, not just a slash problem. path('expofiles', include(expofilesurls)), # curious interaction with the include() here, not just a slash problem.
@ -135,6 +137,7 @@ trogglepatterns = [
re_path(r'^(?P<karea>\d\d\d\d)(?P<subpath>.*)$', cavepage, name="cavepage"), # shorthand /1623/264 or 1623/161/top.htm re_path(r'^(?P<karea>\d\d\d\d)(?P<subpath>.*)$', cavepage, name="cavepage"), # shorthand /1623/264 or 1623/161/top.htm
# Note that urls eg '/1623/161/l/rl89a.htm' are handled by cavepage which redirects them to 'expopage' # Note that urls eg '/1623/161/l/rl89a.htm' are handled by cavepage which redirects them to 'expopage'
# Note that _edit$ for a cave description page in a subfolder e.g. /1623/204/204.html_edit gets caught here and breaks with 404 # Note that _edit$ for a cave description page in a subfolder e.g. /1623/204/204.html_edit gets caught here and breaks with 404
re_path(r'^test_cave_edit/(?P<editor>.*)$', test_edit_cave, name="test_edit_cave"), # edit_cave needed by cave.html template for url matching
# Entrances # Entrances
re_path(r'^cave/entrance/([^/]+)/?$', caveEntrance), # lists all entrances !!!BAD, local links fail re_path(r'^cave/entrance/([^/]+)/?$', caveEntrance), # lists all entrances !!!BAD, local links fail