Table filters
* adds table filtering for InterventionTable * adds default ordering * moves user-access filtering from view to InterventionTableFiler * adds generic render_icn method for BaseTable (for usage with fontawesome5) * adds translations * improves table.html template
This commit is contained in:
parent
117c740bad
commit
591bc739ec
113
intervention/filters.py
Normal file
113
intervention/filters.py
Normal file
@ -0,0 +1,113 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
||||
Created on: 22.07.21
|
||||
|
||||
"""
|
||||
import django_filters
|
||||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import QuerySet, Q
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from intervention.models import Intervention
|
||||
|
||||
|
||||
class InterventionTableFilter(django_filters.FilterSet):
|
||||
q = django_filters.Filter(
|
||||
method='_filter_by_keyword',
|
||||
widget=forms.HiddenInput(), # use search bar in template, we only need the filter logic in here!
|
||||
)
|
||||
sa = django_filters.BooleanFilter(
|
||||
method='_filter_show_all',
|
||||
label=_("Show all"),
|
||||
label_suffix=_(""),
|
||||
widget=forms.CheckboxInput()
|
||||
)
|
||||
sr = django_filters.BooleanFilter(
|
||||
method='_filter_show_recorded',
|
||||
label=_("Show recorded"),
|
||||
label_suffix=_(""),
|
||||
widget=forms.CheckboxInput()
|
||||
)
|
||||
# Gemarkung ##ToDo
|
||||
g = django_filters.CharFilter(
|
||||
field_name="name",
|
||||
lookup_expr="icontains",
|
||||
label=_(""),
|
||||
label_suffix=_(""),
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"placeholder": _("District"),
|
||||
"title": _("Search for district")
|
||||
}
|
||||
),
|
||||
)
|
||||
# Kreis
|
||||
## ToDo
|
||||
# Flur
|
||||
## ToDo
|
||||
# Zähler
|
||||
## ToDo
|
||||
# Nenner
|
||||
## ToDo
|
||||
|
||||
class Meta:
|
||||
model = Intervention
|
||||
fields = []
|
||||
|
||||
def __init__(self, user: User, *args, **kwargs):
|
||||
self.user = user
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _filter_by_keyword(self, queryset, name, value) -> QuerySet:
|
||||
""" Filters queryset depending on value of search bar input
|
||||
|
||||
Args:
|
||||
queryset ():
|
||||
name ():
|
||||
value ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# build filter expression
|
||||
q = Q(title__icontains=value) | Q(identifier__icontains=value)
|
||||
return queryset.filter(q)
|
||||
|
||||
def _filter_show_all(self, queryset, name, value) -> QuerySet:
|
||||
""" Filters queryset depending on value of 'show_all' setting
|
||||
|
||||
Args:
|
||||
queryset ():
|
||||
name ():
|
||||
value ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
if not value:
|
||||
return queryset.filter(
|
||||
users__in=[self.user], # requesting user has access
|
||||
)
|
||||
else:
|
||||
return queryset
|
||||
|
||||
def _filter_show_recorded(self, queryset, name, value) -> QuerySet:
|
||||
""" Filters queryset depending on value of 'show_recorded' setting
|
||||
|
||||
Args:
|
||||
queryset ():
|
||||
name ():
|
||||
value ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
if not value:
|
||||
return queryset.filter(
|
||||
recorded_on=None,
|
||||
)
|
||||
else:
|
||||
return queryset
|
@ -5,11 +5,13 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
||||
Created on: 01.12.20
|
||||
|
||||
"""
|
||||
from django.http import HttpRequest
|
||||
from django.urls import reverse
|
||||
from django.utils.html import format_html
|
||||
from django.utils.timezone import localtime
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from intervention.filters import InterventionTableFilter
|
||||
from intervention.models import Intervention
|
||||
from konova.sub_settings.django_settings import DEFAULT_DATE_TIME_FORMAT
|
||||
from konova.utils.tables import BaseTable
|
||||
@ -39,6 +41,12 @@ class InterventionTable(BaseTable):
|
||||
empty_values=[],
|
||||
accessor="recorded_on",
|
||||
)
|
||||
e = tables.Column(
|
||||
verbose_name=_("Editable"),
|
||||
orderable=True,
|
||||
empty_values=[],
|
||||
accessor="users",
|
||||
)
|
||||
lm = tables.Column(
|
||||
verbose_name=_("Last edit"),
|
||||
orderable=True,
|
||||
@ -58,10 +66,16 @@ class InterventionTable(BaseTable):
|
||||
class Meta(BaseTable.Meta):
|
||||
template_name = "django_tables2/bootstrap4.html"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
def __init__(self, request: HttpRequest, *args, **kwargs):
|
||||
self.title = _("Interventions")
|
||||
self.add_new_url = reverse("intervention:new")
|
||||
qs = kwargs.get("queryset", None)
|
||||
self.filter = InterventionTableFilter(
|
||||
user=request.user,
|
||||
data=request.GET,
|
||||
queryset=qs,
|
||||
)
|
||||
super().__init__(request, self.filter, *args, **kwargs)
|
||||
|
||||
def render_id(self, value, record: Intervention):
|
||||
""" Renders the id column for an intervention
|
||||
@ -128,6 +142,27 @@ class InterventionTable(BaseTable):
|
||||
)
|
||||
return format_html(html)
|
||||
|
||||
def render_e(self, value, record: Intervention):
|
||||
""" Renders the registered column for an intervention
|
||||
|
||||
Args:
|
||||
value (str): The identifier value
|
||||
record (Intervention): The intervention record
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
html = ""
|
||||
has_access = value.filter(
|
||||
username=self.user.username
|
||||
).exists()
|
||||
|
||||
html += self.render_icn(
|
||||
tooltip=_("Full access granted") if has_access else _("Access not granted"),
|
||||
icn_class="fas fa-edit rlp-r-inv" if has_access else "far fa-edit",
|
||||
)
|
||||
return format_html(html)
|
||||
|
||||
def render_ac(self, value, record):
|
||||
"""
|
||||
Renders possible actions for this record, such as delete.
|
||||
|
@ -24,11 +24,13 @@ def index_view(request: HttpRequest):
|
||||
A rendered view
|
||||
"""
|
||||
template = "generic_index.html"
|
||||
user = request.user
|
||||
|
||||
# Filtering by user access is performed in table filter inside of InterventionTableFilter class
|
||||
interventions = Intervention.objects.filter(
|
||||
deleted_on=None, # not deleted
|
||||
next_version=None, # only newest versions
|
||||
users__in=[user], # requesting user has access
|
||||
).order_by(
|
||||
"-created_on"
|
||||
)
|
||||
table = InterventionTable(
|
||||
request=request,
|
||||
|
@ -37,6 +37,10 @@ Declare some basic colours
|
||||
color:var(--rlp-red);
|
||||
}
|
||||
|
||||
.rlp-r-inv{
|
||||
color:var(--rlp-red);
|
||||
}
|
||||
|
||||
html {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
|
@ -126,6 +126,16 @@ class BaseTable(tables.tables.Table):
|
||||
icon
|
||||
)
|
||||
|
||||
def render_icn(self, tooltip: str = None, icn_class: str = None):
|
||||
"""
|
||||
Returns a rendered fontawesome icon
|
||||
"""
|
||||
return format_html(
|
||||
"<em title='{}' class='{}'></em>",
|
||||
tooltip,
|
||||
icn_class,
|
||||
)
|
||||
|
||||
|
||||
class ChoicesColumnForm(BaseForm):
|
||||
select = forms.ChoiceField(
|
||||
|
Binary file not shown.
@ -3,13 +3,15 @@
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#: konova/forms.py:69 user/forms.py:38
|
||||
#: intervention/filters.py:21 intervention/filters.py:27
|
||||
#: intervention/filters.py:34 intervention/filters.py:35 konova/forms.py:69
|
||||
#: user/forms.py:38
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-07-21 15:07+0200\n"
|
||||
"POT-Creation-Date: 2021-07-22 09:31+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -20,12 +22,12 @@ msgstr ""
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: compensation/tables.py:18 compensation/tables.py:71 intervention/forms.py:26
|
||||
#: intervention/tables.py:22
|
||||
#: intervention/tables.py:23
|
||||
msgid "Identifier"
|
||||
msgstr "Kennung"
|
||||
|
||||
#: compensation/tables.py:23 compensation/tables.py:76 intervention/forms.py:33
|
||||
#: intervention/tables.py:27
|
||||
#: intervention/tables.py:28
|
||||
msgid "Title"
|
||||
msgstr "Titel"
|
||||
|
||||
@ -47,17 +49,17 @@ msgid "Compensation"
|
||||
msgstr "Kompensation"
|
||||
|
||||
#: compensation/tables.py:54 compensation/tables.py:107
|
||||
#: intervention/tables.py:79 intervention/tables.py:139
|
||||
#: intervention/tables.py:92 intervention/tables.py:179
|
||||
msgid "Open {}"
|
||||
msgstr "Öffne {}"
|
||||
|
||||
#: compensation/tables.py:59 compensation/tables.py:112
|
||||
#: intervention/tables.py:143
|
||||
#: intervention/tables.py:183
|
||||
msgid "Edit {}"
|
||||
msgstr "Bearbeite {}"
|
||||
|
||||
#: compensation/tables.py:63 compensation/tables.py:116
|
||||
#: intervention/tables.py:147
|
||||
#: intervention/tables.py:187
|
||||
msgid "Delete {}"
|
||||
msgstr "Lösche {}"
|
||||
|
||||
@ -65,6 +67,22 @@ msgstr "Lösche {}"
|
||||
msgid "Eco Accounts"
|
||||
msgstr "Ökokonten"
|
||||
|
||||
#: intervention/filters.py:20
|
||||
msgid "Show all"
|
||||
msgstr "Alle anzeigen"
|
||||
|
||||
#: intervention/filters.py:26
|
||||
msgid "Show recorded"
|
||||
msgstr "Verzeichnete anzeigen"
|
||||
|
||||
#: intervention/filters.py:38
|
||||
msgid "District"
|
||||
msgstr "Gemarkung"
|
||||
|
||||
#: intervention/filters.py:39
|
||||
msgid "Search for district"
|
||||
msgstr "Nach Gemarkung suchen"
|
||||
|
||||
#: intervention/forms.py:29
|
||||
msgid "Generated automatically if none was given"
|
||||
msgstr "Wird automatisch erzeugt, falls nicht angegeben"
|
||||
@ -133,57 +151,69 @@ msgstr "Neuer Eingriff"
|
||||
msgid "Edit intervention"
|
||||
msgstr "Eingriff bearbeiten"
|
||||
|
||||
#: intervention/tables.py:32
|
||||
#: intervention/tables.py:33
|
||||
msgid "Checked"
|
||||
msgstr "Geprüft"
|
||||
|
||||
#: intervention/tables.py:38
|
||||
#: intervention/tables.py:39
|
||||
msgid "Registered"
|
||||
msgstr "Verzeichnet"
|
||||
|
||||
#: intervention/tables.py:44
|
||||
#: intervention/tables.py:45
|
||||
msgid "Editable"
|
||||
msgstr "Freigegeben"
|
||||
|
||||
#: intervention/tables.py:51
|
||||
msgid "Last edit"
|
||||
msgstr "Zuletzt bearbeitet"
|
||||
|
||||
#: intervention/tables.py:64
|
||||
#: intervention/tables.py:70
|
||||
msgid "Interventions"
|
||||
msgstr "Eingriffe"
|
||||
|
||||
#: intervention/tables.py:79 intervention/tables.py:136
|
||||
#: intervention/tables.py:92 intervention/tables.py:176
|
||||
#: intervention/templates/intervention/open.html:8
|
||||
#: konova/templates/konova/home.html:11 templates/navbar.html:22
|
||||
msgid "Intervention"
|
||||
msgstr "Eingriff"
|
||||
|
||||
#: intervention/tables.py:98
|
||||
#: intervention/tables.py:111
|
||||
msgid "Not checked yet"
|
||||
msgstr "Noch nicht geprüft"
|
||||
|
||||
#: intervention/tables.py:102
|
||||
#: intervention/tables.py:115
|
||||
msgid "Checked on {} by {}"
|
||||
msgstr "Am {} von {} geprüft worden"
|
||||
|
||||
#: intervention/tables.py:121
|
||||
#: intervention/tables.py:134
|
||||
msgid "Not registered yet"
|
||||
msgstr "Noch nicht verzeichnet"
|
||||
|
||||
#: intervention/tables.py:125
|
||||
#: intervention/tables.py:138
|
||||
msgid "Registered on {} by {}"
|
||||
msgstr "Am {} von {} verzeichnet worden"
|
||||
|
||||
#: intervention/tables.py:167
|
||||
msgid "Full access granted"
|
||||
msgstr "Für Sie freigegeben - Datensatz kann bearbeitet werden"
|
||||
|
||||
#: intervention/tables.py:167
|
||||
msgid "Access not granted"
|
||||
msgstr "Nicht freigegeben - Datensatz nur lesbar"
|
||||
|
||||
#: intervention/templates/intervention/open.html:12
|
||||
msgid "Edit"
|
||||
msgstr "Bearbeiten"
|
||||
|
||||
#: intervention/views.py:60
|
||||
#: intervention/views.py:63
|
||||
msgid "Intervention {} added"
|
||||
msgstr "Eingriff {} hinzugefügt"
|
||||
|
||||
#: intervention/views.py:63 intervention/views.py:116
|
||||
#: intervention/views.py:66 intervention/views.py:119
|
||||
msgid "Invalid input"
|
||||
msgstr "Eingabe fehlerhaft"
|
||||
|
||||
#: intervention/views.py:113
|
||||
#: intervention/views.py:116
|
||||
msgid "{} edited"
|
||||
msgstr "{} bearbeitet"
|
||||
|
||||
@ -371,10 +401,14 @@ msgstr "Starte Suche"
|
||||
msgid "Results per page"
|
||||
msgstr "Treffer pro Seite"
|
||||
|
||||
#: templates/table.html:70
|
||||
#: templates/table.html:70 templates/table.html:77
|
||||
msgid "Filter"
|
||||
msgstr ""
|
||||
|
||||
#: templates/table.html:79
|
||||
msgid "Apply filter"
|
||||
msgstr "Filter anwenden"
|
||||
|
||||
#: user/forms.py:23
|
||||
msgid "Notifications"
|
||||
msgstr "Benachrichtigungen"
|
||||
@ -1697,9 +1731,6 @@ msgstr ""
|
||||
#~ msgid "Process management"
|
||||
#~ msgstr "Vorgangsverwaltung"
|
||||
|
||||
#~ msgid "Show process"
|
||||
#~ msgstr "Zeige Vorgänge"
|
||||
|
||||
#~ msgid "New process"
|
||||
#~ msgstr "Neuer Vorgang"
|
||||
|
||||
|
@ -26,9 +26,9 @@
|
||||
{% endcomment %}
|
||||
<div class="row my-1">
|
||||
<div class="col-sm-12 col-md-8 col-lg-6">
|
||||
<form method="get" action="{{table.filter}}">
|
||||
<form method="get">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" aria-label="{% trans 'Search for keywords' %}" placeholder="{% trans 'Search' %}">
|
||||
<input id="id_q" name="q" type="text" class="form-control" aria-label="{% trans 'Search for keywords' %}" placeholder="{% trans 'Search' %}" value="{{ request.GET.q }}">
|
||||
<div class="input-group-append" title="{% trans 'Start search' %}">
|
||||
<button type="submit" class="btn btn-default input-group-text">
|
||||
<span class="">
|
||||
@ -72,6 +72,10 @@
|
||||
<div class="card-body">
|
||||
<form method="get">
|
||||
{{ table.filter.form.as_p }}
|
||||
<button class="btn btn-default" title="{% trans 'Filter' %}">
|
||||
{% fa5_icon 'filter' %}
|
||||
{% trans 'Apply filter' %}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user