infoscreen for empty

This commit is contained in:
Christoph J. Scherr 2023-10-07 17:55:53 +02:00
parent f76c18efaf
commit 21f3b19111
4 changed files with 168 additions and 61 deletions

View File

@ -32,11 +32,17 @@
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3">
<div class="container-fluid w-100 h-100 p-2"> <div class="container-fluid w-100 h-100 p-2">
<form class="w-100 h-100" role="search" action="" method="GET" novalidate> <form class="w-100 h-100"
role="search"
action=""
method="GET"
novalidate
id="filter-form">
<div class="py-2"> <div class="py-2">
<input type="search" <input type="search"
name="search" name="search"
class="form-control flex-fill py-2" class="form-control flex-fill py-2"
defaultValue=""
aria-label="Search" aria-label="Search"
placeholder="{% trans "Search" %}" placeholder="{% trans "Search" %}"
required="" required=""
@ -46,6 +52,7 @@
<div class="py-2"> <div class="py-2">
<select class="form-select py-2" <select class="form-select py-2"
aria-label="Large select example" aria-label="Large select example"
defaultValue=""
name="category"> name="category">
<option value="">{% trans "select category" %}</option> <option value="">{% trans "select category" %}</option>
{% for category in categories %} {% for category in categories %}
@ -57,6 +64,7 @@
<div class="py-2"> <div class="py-2">
<input class="tagify" <input class="tagify"
name="keywords" name="keywords"
defaultValue=""
placeholder="{% trans "Keywords" %}" placeholder="{% trans "Keywords" %}"
{% if filters.keywords %} value="{% for keyword in filters.keywords %}{{ keyword }} {% endfor %} {% if filters.keywords %} value="{% for keyword in filters.keywords %}{{ keyword }} {% endfor %}
" "
@ -65,9 +73,11 @@
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<div class="py-2"> <div class="py-2">
<input id="clear-button" <!-- will reset to the filters encoded in
type="reset" the url by GET attributes, not to the empty
class="btn bg-primary fw-bold py-2 float-end w-100"> form. -->
<input type="reset"
class="btn bg-primary fw-bold py-2 float-end w-100 reset-empty-button">
</div> </div>
</div> </div>
<div class="col"> <div class="col">
@ -91,8 +101,15 @@
<div class="row mb-5"> <div class="row mb-5">
<div class="container-fluid p-0 w-100 h-100"> <div class="container-fluid p-0 w-100 h-100">
<div class="row gap-3"> <div class="row gap-3">
{# TODO: display some info if the queryset is empty #} {% if is_empty %}
{# TODO: pagination #} <div class="text-center">
<img src="/media/img/http/404.svg"
class="img-fluid pb-5 pt-2 darkmode-invert"
style="max-height: 650px;"
alt="404" />
<h2 class="display-5">{% trans "No posts found for your filters." %}</h2>
</div>
{% else %}
{% for post in posts %} {% for post in posts %}
<div class="card col mx-auto my-2 py-2" style="min-width: 400px;"> <div class="card col mx-auto my-2 py-2" style="min-width: 400px;">
<a class="text-reset link-offset-2 link-underline link-underline-opacity-0" <a class="text-reset link-offset-2 link-underline link-underline-opacity-0"
@ -146,6 +163,7 @@
</a> </a>
</div> </div>
{% endfor %} {% endfor %}
{% endif %}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,4 +1,8 @@
from django.shortcuts import Http404, HttpResponse, get_object_or_404, render import json
import ast
from django.shortcuts import get_object_or_404, render
from django.http.response import Http404, HttpResponse
from django.http.request import HttpRequest
from django.utils.translation import get_language from django.utils.translation import get_language
from django.views.generic import TemplateView, DetailView, ListView, View from django.views.generic import TemplateView, DetailView, ListView, View
from django.db.models import Q from django.db.models import Q
@ -9,8 +13,6 @@ from start.views import SearchableView
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
import ast
import json
class Index(TemplateView, SearchableView): class Index(TemplateView, SearchableView):
""" """
@ -55,6 +57,7 @@ class Browse(ListView):
model = BlogPost model = BlogPost
template_name = "blog/browse.html" template_name = "blog/browse.html"
context_object_name = "posts" context_object_name = "posts"
allow_empty = False # but we have a special get method
def get_queryset(self): def get_queryset(self):
objects = BlogPost.objects.all() objects = BlogPost.objects.all()
@ -123,3 +126,27 @@ class Browse(ListView):
keywords = keywords.split('+') keywords = keywords.split('+')
context["filters"]["keywords"] = keywords context["filters"]["keywords"] = keywords
return context return context
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty:
# When pagination is enabled and object_list is a queryset,
# it's better to do a cheap query than to load the unpaginated
# queryset in memory.
if self.get_paginate_by(self.object_list) is not None and hasattr(
self.object_list, 'exists'):
is_empty = not self.object_list.exists()
else:
is_empty = not self.object_list
else:
is_empty = False
context = self.get_context_data()
context["is_empty"] = is_empty
response = self.render_to_response(context)
if is_empty:
response.status_code = 404
return response

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="557.15094"
height="210.8916"
viewBox="0 0 557.15094 210.8916"
version="1.1"
id="svg1"
inkscape:export-filename="404.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px" />
<defs
id="defs1">
<rect
x="292.2478"
y="154.0531"
width="462.1593"
height="240.14159"
id="rect1" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-239.50485,-280.19422)">
<text
xml:space="preserve"
id="text1"
style="font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:24.5524px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro, Bold Italic';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;white-space:pre;shape-inside:url(#rect1);fill:#3b3b3b;fill-opacity:1"
transform="matrix(13.034066,0,0,13.034066,-3571.9156,-1800.7033)"><tspan
x="292.24805"
y="175.53608"
id="tspan2">404</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -2,6 +2,18 @@
// dark theme stuff // dark theme stuff
const setTheme = (theme) => { const setTheme = (theme) => {
document.documentElement.setAttribute("data-bs-theme", theme); document.documentElement.setAttribute("data-bs-theme", theme);
if (theme === "dark") {
var to_invert = document.querySelectorAll('.darkmode-invert');
to_invert.forEach(element => {
element.style.filter = "invert(100%)";
});
}
if (theme === "light") {
var to_invert = document.querySelectorAll('.darkmode-invert');
to_invert.forEach(element => {
element.style.filter = "invert(0%)";
});
}
}; };
setTheme(localStorage.getItem("theme")); setTheme(localStorage.getItem("theme"));
document.getElementById("toggleThemeButton").onclick = function () { document.getElementById("toggleThemeButton").onclick = function () {