Syntax Highliting and more
Moved template looking code in base.admin related to error messages, into an actual template file. New feature: Codearea widget Every JSONField will be highlighted in django-admin with json highlighter
This commit is contained in:
parent
f6ce4fc374
commit
07fe648b9c
|
|
@ -1,48 +1,44 @@
|
|||
from django.contrib import admin, messages
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.html import escape
|
||||
from django.template import loader
|
||||
from django.forms.fields import JSONField
|
||||
|
||||
from ..widgets import Codearea
|
||||
|
||||
import traceback
|
||||
|
||||
class BaseModelAdmin( admin.ModelAdmin ):
|
||||
|
||||
def formfield_for_dbfield( self, db_field, **kwargs ):
|
||||
formfield = super().formfield_for_dbfield(db_field, **kwargs)
|
||||
if isinstance( formfield, JSONField ):
|
||||
formfield.widget = Codearea( language = "json" )
|
||||
return formfield
|
||||
|
||||
def explain_gather_results( self, request, results, fails_to_show = 2 ):
|
||||
failed = 0
|
||||
for id, e in results.items():
|
||||
if isinstance(e, BaseException):
|
||||
failed += 1
|
||||
if failed <= fails_to_show:
|
||||
|
||||
traceback_message = None
|
||||
if request.user.is_superuser:
|
||||
traceback_message = ''.join(traceback.TracebackException.from_exception(e).format())
|
||||
self.message_user( request, mark_safe(f"""
|
||||
Error For <b>{id}</b>:
|
||||
<style>
|
||||
button.tb {{
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--link-fg);
|
||||
text-decoration: none;
|
||||
}}
|
||||
button.tb:hover {{ text-decoration: underline; }}
|
||||
pre.summary {{ white-space: pre-wrap; }}
|
||||
pre.tb {{
|
||||
display: none;
|
||||
background: #060d0a;
|
||||
white-space: pre-wrap;
|
||||
border-radius: 5px;
|
||||
font-size: 10px;
|
||||
line-height: 1.5em;
|
||||
padding: 10px;
|
||||
}}
|
||||
pre.tb.shown {{ display: block;}}
|
||||
</style>
|
||||
<pre class="summary">{escape(e)}</pre>
|
||||
<button class='tb' onclick="event.target.parentElement.querySelector('pre.tb').classList.toggle('shown')">[TraceBack]</button>
|
||||
<pre class='tb'>{escape(traceback_message)}</pre>
|
||||
"""), messages.ERROR
|
||||
)
|
||||
else: self.message_user( request, f"Error For {id}: {escape(e)}", messages.ERROR)
|
||||
|
||||
#NOT sure if there is a clean way to get the model
|
||||
#object_change_url = reverse(
|
||||
# f'admin:{self._meta.model_name}_{self._meta.app_label}_change',
|
||||
# kwargs={'object_id': self.pk}
|
||||
#)
|
||||
|
||||
self.message_user(
|
||||
request,
|
||||
loader.get_template("asyncron/admin-gather-error-message.html").render({
|
||||
"id": id, "e": e,
|
||||
"traceback_message": traceback_message
|
||||
}),
|
||||
messages.ERROR
|
||||
)
|
||||
|
||||
if failed == 0: self.message_user( request, f"All {len(results)} Succeeded!", messages.SUCCESS )
|
||||
elif failed <= fails_to_show:
|
||||
|
|
|
|||
31
asyncron/templates/asyncron/admin-gather-error-message.html
Normal file
31
asyncron/templates/asyncron/admin-gather-error-message.html
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{% autoescape on %}
|
||||
Error For Object {{ id }}:
|
||||
{% if traceback_message %}
|
||||
<style>
|
||||
button.tb {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--link-fg);
|
||||
text-decoration: none;
|
||||
}
|
||||
button.tb:hover { text-decoration: underline; }
|
||||
pre.summary { white-space: pre-wrap; }
|
||||
pre.tb {
|
||||
display: none;
|
||||
background: #060d0a;
|
||||
white-space: pre-wrap;
|
||||
border-radius: 5px;
|
||||
font-size: 10px;
|
||||
line-height: 1.5em;
|
||||
padding: 10px;
|
||||
}
|
||||
pre.tb.shown { display: block; }
|
||||
</style>
|
||||
<pre class="summary">{{ e }}</pre>
|
||||
<button class='tb' onclick="event.target.parentElement.querySelector('pre.tb').classList.toggle('shown')">
|
||||
[TraceBack]
|
||||
</button>
|
||||
<pre class='tb'>{{ traceback_message }}</pre>
|
||||
{% endif %}
|
||||
{% endautoescape %}
|
||||
56
asyncron/templates/asyncron/codearea-widget.html
Normal file
56
asyncron/templates/asyncron/codearea-widget.html
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
{% load static %}
|
||||
|
||||
<link rel="stylesheet" href="{% static 'highlight/styles/atom-one-dark.min.css' %}">
|
||||
<script src="{% static 'highlight/highlight.min.js' %}"></script>
|
||||
|
||||
<div id="codearea_{{ target }}">
|
||||
{{ textarea }}
|
||||
<pre>{{ value }}</pre>
|
||||
</div>
|
||||
<style media="screen">
|
||||
#codearea_{{ target }} {
|
||||
position: relative;
|
||||
}
|
||||
#codearea_{{ target }} textarea {
|
||||
background: #282c34;
|
||||
color: transparent;
|
||||
caret-color: white;
|
||||
outline: none;
|
||||
}
|
||||
#codearea_{{ target }} textarea::selection {
|
||||
background: hsl(221deg 13% 28%);
|
||||
color: transparent;
|
||||
text-shadow: none;
|
||||
}
|
||||
#codearea_{{ target }} > pre {
|
||||
position: absolute; pointer-events: none;
|
||||
left: 0; right: 0; top: 0; bottom: 0;
|
||||
white-space: wrap;
|
||||
opacity: 1;
|
||||
background: transparent;
|
||||
}
|
||||
#codearea_{{ target }} > * {
|
||||
font-family: var(--font-family-monospace);
|
||||
margin: 0;
|
||||
padding: 5px;
|
||||
font-size: 1em;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
|
||||
{{ hljs_config | json_script:"hlsj-config" }}
|
||||
<script>
|
||||
(function(){
|
||||
const codearea = document.getElementById("codearea_{{ target }}");
|
||||
const textarea = codearea.querySelector('textarea');
|
||||
const pre = codearea.querySelector('pre');
|
||||
const config = JSON.parse(document.getElementById('hlsj-config').textContent);
|
||||
|
||||
textarea.addEventListener('input', (e) => {
|
||||
pre.innerText = e.target.value;
|
||||
delete pre.dataset.highlighted;
|
||||
hljs.highlightElement( pre, config )
|
||||
});
|
||||
hljs.highlightElement( pre, config )
|
||||
})()
|
||||
</script>
|
||||
22
asyncron/widgets.py
Normal file
22
asyncron/widgets.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
from django.template import loader
|
||||
from django.forms import Textarea
|
||||
|
||||
|
||||
class Codearea( Textarea ):
|
||||
|
||||
def __init__( self, *args, language = "auto", **kwargs ):
|
||||
self.language = language
|
||||
super().__init__( *args, **kwargs )
|
||||
|
||||
def render( self, name, value, attrs = None, renderer = None ):
|
||||
print( self )
|
||||
print(f"RENDERING: {name=} {value=} {attrs=} {renderer=}")
|
||||
return loader.get_template("asyncron/codearea-widget.html").render({
|
||||
"textarea": super().render( name, value, attrs, renderer ),
|
||||
"value": value,
|
||||
"target": name,
|
||||
"hljs_config": {
|
||||
"language": self.language
|
||||
}
|
||||
})
|
||||
Loading…
Reference in New Issue
Block a user