Add user-configurable pagination and enhance case view filters
This commit is contained in:
@@ -7,7 +7,9 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<h2>My Cases</h2>
|
<h2>Cases</h2>
|
||||||
|
Quick filters:<br/>
|
||||||
|
Show <a href='{% url "atlas:case_view" %}?author={{request.user.id}}'>my cases only</a>, <a href='{% url "atlas:case_view" %}'>all cases</a>
|
||||||
<details>
|
<details>
|
||||||
<summary>
|
<summary>
|
||||||
<h4>Filter</h4>
|
<h4>Filter</h4>
|
||||||
@@ -20,7 +22,6 @@
|
|||||||
</div>
|
</div>
|
||||||
View my <a href='{% url "atlas:case_view" %}?author={{request.user.id}}'>cases</a>.
|
View my <a href='{% url "atlas:case_view" %}?author={{request.user.id}}'>cases</a>.
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<details id="actions-detail" class="mt-3">
|
<details id="actions-detail" class="mt-3">
|
||||||
<summary>
|
<summary>
|
||||||
@@ -78,7 +79,8 @@
|
|||||||
</details>
|
</details>
|
||||||
{% render_table table %}
|
{% render_table table %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
|
{% include "generic/partials/page_size_form.html" %}
|
||||||
|
|
||||||
<div id="exam-options"></div>
|
<div id="exam-options"></div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
+10
-10
@@ -27,7 +27,7 @@ from django.views.generic import View
|
|||||||
from django.views.generic.detail import DetailView
|
from django.views.generic.detail import DetailView
|
||||||
import pydicom
|
import pydicom
|
||||||
from pydicom.uid import generate_uid
|
from pydicom.uid import generate_uid
|
||||||
from generic.mixins import SuperuserRequiredMixin
|
from generic.mixins import SuperuserRequiredMixin, UserConfigurablePaginationMixin
|
||||||
|
|
||||||
from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView
|
from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
@@ -1580,7 +1580,7 @@ def get_examination_id(request):
|
|||||||
return HttpResponse("/")
|
return HttpResponse("/")
|
||||||
|
|
||||||
|
|
||||||
class CaseView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
class CaseView(LoginRequiredMixin, UserConfigurablePaginationMixin, SingleTableMixin, FilterView):
|
||||||
model = Case
|
model = Case
|
||||||
table_class = CaseTable
|
table_class = CaseTable
|
||||||
template_name = "atlas/case_view.html"
|
template_name = "atlas/case_view.html"
|
||||||
@@ -1588,7 +1588,7 @@ class CaseView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
filterset_class = CaseFilter
|
filterset_class = CaseFilter
|
||||||
|
|
||||||
|
|
||||||
class SeriesView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
class SeriesView(LoginRequiredMixin, UserConfigurablePaginationMixin, SingleTableMixin, FilterView):
|
||||||
model = Series
|
model = Series
|
||||||
table_class = SeriesTable
|
table_class = SeriesTable
|
||||||
template_name = "atlas/series_view.html"
|
template_name = "atlas/series_view.html"
|
||||||
@@ -1596,7 +1596,7 @@ class SeriesView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
filterset_class = SeriesFilter
|
filterset_class = SeriesFilter
|
||||||
|
|
||||||
|
|
||||||
class ConditionView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
class ConditionView(LoginRequiredMixin, UserConfigurablePaginationMixin, SingleTableMixin, FilterView):
|
||||||
model = Condition
|
model = Condition
|
||||||
table_class = ConditionTable
|
table_class = ConditionTable
|
||||||
template_name = "atlas/view.html"
|
template_name = "atlas/view.html"
|
||||||
@@ -1604,7 +1604,7 @@ class ConditionView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
filterset_class = ConditionFilter
|
filterset_class = ConditionFilter
|
||||||
|
|
||||||
|
|
||||||
class QuestionSchemaView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
class QuestionSchemaView(LoginRequiredMixin, UserConfigurablePaginationMixin, SingleTableMixin, FilterView):
|
||||||
model = QuestionSchema
|
model = QuestionSchema
|
||||||
table_class = QuestionSchemaTable
|
table_class = QuestionSchemaTable
|
||||||
template_name = "atlas/schema_table_view.html"
|
template_name = "atlas/schema_table_view.html"
|
||||||
@@ -1612,7 +1612,7 @@ class QuestionSchemaView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
filterset_class = QuestionSchemaFilter
|
filterset_class = QuestionSchemaFilter
|
||||||
|
|
||||||
|
|
||||||
class SubspecialtyView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
class SubspecialtyView(LoginRequiredMixin, UserConfigurablePaginationMixin, SingleTableMixin, FilterView):
|
||||||
model = Subspecialty
|
model = Subspecialty
|
||||||
table_class = SubspecialtyTable
|
table_class = SubspecialtyTable
|
||||||
template_name = "atlas/view.html"
|
template_name = "atlas/view.html"
|
||||||
@@ -1620,7 +1620,7 @@ class SubspecialtyView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
filterset_class = SubspecialtyFilter
|
filterset_class = SubspecialtyFilter
|
||||||
|
|
||||||
|
|
||||||
class PresentationView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
class PresentationView(LoginRequiredMixin, UserConfigurablePaginationMixin, SingleTableMixin, FilterView):
|
||||||
model = Presentation
|
model = Presentation
|
||||||
table_class = PresentationTable
|
table_class = PresentationTable
|
||||||
template_name = "atlas/view.html"
|
template_name = "atlas/view.html"
|
||||||
@@ -1628,7 +1628,7 @@ class PresentationView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
filterset_class = PresentationFilter
|
filterset_class = PresentationFilter
|
||||||
|
|
||||||
|
|
||||||
class PathologicalProcessView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
class PathologicalProcessView(LoginRequiredMixin, UserConfigurablePaginationMixin, SingleTableMixin, FilterView):
|
||||||
model = PathologicalProcess
|
model = PathologicalProcess
|
||||||
table_class = PathologicalProcessTable
|
table_class = PathologicalProcessTable
|
||||||
template_name = "atlas/view.html"
|
template_name = "atlas/view.html"
|
||||||
@@ -1636,7 +1636,7 @@ class PathologicalProcessView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
filterset_class = PathologicalProcessFilter
|
filterset_class = PathologicalProcessFilter
|
||||||
|
|
||||||
|
|
||||||
class StructureView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
class StructureView(LoginRequiredMixin, UserConfigurablePaginationMixin, SingleTableMixin, FilterView):
|
||||||
model = Structure
|
model = Structure
|
||||||
table_class = StructureTable
|
table_class = StructureTable
|
||||||
template_name = "atlas/view.html"
|
template_name = "atlas/view.html"
|
||||||
@@ -1644,7 +1644,7 @@ class StructureView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
|||||||
filterset_class = StructureFilter
|
filterset_class = StructureFilter
|
||||||
|
|
||||||
|
|
||||||
class FindingView(LoginRequiredMixin, SingleTableMixin, FilterView):
|
class FindingView(LoginRequiredMixin, UserConfigurablePaginationMixin, SingleTableMixin, FilterView):
|
||||||
model = Finding
|
model = Finding
|
||||||
table_class = FindingTable
|
table_class = FindingTable
|
||||||
template_name = "atlas/view.html"
|
template_name = "atlas/view.html"
|
||||||
|
|||||||
@@ -62,3 +62,22 @@ class AuthorMixin():
|
|||||||
def remove_author(self, user: User):
|
def remove_author(self, user: User):
|
||||||
"""Remove an author from the object"""
|
"""Remove an author from the object"""
|
||||||
self.author.remove(user)
|
self.author.remove(user)
|
||||||
|
|
||||||
|
|
||||||
|
class UserConfigurablePaginationMixin:
|
||||||
|
default_per_page = 25
|
||||||
|
allowed_per_page = [25, 50, 100, 250, 500]
|
||||||
|
|
||||||
|
def get_table_pagination(self, table):
|
||||||
|
try:
|
||||||
|
per_page = int(self.request.GET.get("per_page", self.default_per_page))
|
||||||
|
if per_page not in self.allowed_per_page:
|
||||||
|
per_page = self.default_per_page
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
per_page = self.default_per_page
|
||||||
|
return {"per_page": per_page}
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["page_sizes"] = [25, 50, 100, 250, 500]
|
||||||
|
return context
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<form method="get" class="row align-items-center mb-3">
|
||||||
|
{# Keep existing filters/searches #}
|
||||||
|
{% for key, value in request.GET.items %}
|
||||||
|
{% if key != 'per_page' %}
|
||||||
|
<input type="hidden" name="{{ key }}" value="{{ value }}">
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<div class="col-auto">
|
||||||
|
<label for="per_page" class="form-label mb-0 ">Rows per page:</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<select name="per_page" id="per_page" class="form-select form-select-sm" onchange="this.form.submit()">
|
||||||
|
{% for size in page_sizes %}
|
||||||
|
<option value="{{ size }}" {% if request.GET.per_page|stringformat:"s" == size|stringformat:"s" %}selected{% endif %}>{{ size }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
Reference in New Issue
Block a user