From 00148cd5ca4487aa2afdf6ecfb424901cf8a8442 Mon Sep 17 00:00:00 2001 From: Sylvain Gay Date: Mon, 6 May 2024 16:24:16 +0200 Subject: [PATCH] Add loan tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two views for loans : - inventory:ongoing_loans - inventory:all_loans (permission inventory.can_see_loan_details required) --- gestiojeux/settings_base.py | 1 + ...options_alter_gameloan_options_and_more.py | 31 +++++++++++++++++ inventory/models.py | 2 ++ inventory/tables.py | 33 +++++++++++++++++++ inventory/templates/inventory/inventory.html | 3 ++ .../inventory/loans/loans_table.html | 9 +++++ .../templates/inventory/loans/ongoing.html | 7 ++++ inventory/urls.py | 6 +++- inventory/views.py | 19 +++++++++++ loans/models.py | 5 +-- loans/views.py | 2 ++ requirements.txt | 1 + website/scss/style.scss | 23 ++++++++++++- website/static/css/style.css | 17 ++++++++-- website/templates/partials/header.html | 3 ++ 15 files changed, 156 insertions(+), 6 deletions(-) create mode 100644 inventory/migrations/0004_alter_category_options_alter_gameloan_options_and_more.py create mode 100644 inventory/tables.py create mode 100644 inventory/templates/inventory/loans/loans_table.html create mode 100644 inventory/templates/inventory/loans/ongoing.html diff --git a/gestiojeux/settings_base.py b/gestiojeux/settings_base.py index 78c4d5d..dad2919 100644 --- a/gestiojeux/settings_base.py +++ b/gestiojeux/settings_base.py @@ -26,6 +26,7 @@ INSTALLED_APPS = [ "django.contrib.messages", "django.contrib.staticfiles", "django_cas_ng", + "django_tables2", "markdownx", "haystack", "website", diff --git a/inventory/migrations/0004_alter_category_options_alter_gameloan_options_and_more.py b/inventory/migrations/0004_alter_category_options_alter_gameloan_options_and_more.py new file mode 100644 index 0000000..282fb06 --- /dev/null +++ b/inventory/migrations/0004_alter_category_options_alter_gameloan_options_and_more.py @@ -0,0 +1,31 @@ +# Generated by Django 4.2.8 on 2024-05-06 14:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0003_gameloan'), + ] + + operations = [ + migrations.AlterModelOptions( + name='category', + options={'ordering': ['name'], 'verbose_name': 'étagère'}, + ), + migrations.AlterModelOptions( + name='gameloan', + options={'ordering': ['borrow_date'], 'permissions': [('can_see_loan_details', 'Can see loan details')], 'verbose_name': 'emprunt', 'verbose_name_plural': 'emprunts'}, + ), + migrations.AlterField( + model_name='gameloan', + name='borrow_date', + field=models.DateTimeField(auto_now_add=True, verbose_name='Date d’emprunt'), + ), + migrations.AlterField( + model_name='gameloan', + name='return_date', + field=models.DateTimeField(null=True, verbose_name='Date de retour'), + ), + ] diff --git a/inventory/models.py b/inventory/models.py index f7aa776..bd05a03 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -162,3 +162,5 @@ class GameLoan(AbstractLoan): class Meta(AbstractLoan.Meta): abstract = False + permissions = [("can_see_loan_details", "Can see loan details")] + diff --git a/inventory/tables.py b/inventory/tables.py new file mode 100644 index 0000000..d66e231 --- /dev/null +++ b/inventory/tables.py @@ -0,0 +1,33 @@ +import django_tables2 as tables +from django.utils.html import format_html +from django.urls import reverse +from .models import GameLoan + +class LoanTable(tables.Table): + next_pattern = "inventory:all_loans" + + class Meta: + model = GameLoan + sequence = ("lent_object", "borrow_date", "return_date", "mail") + exclude = ("id",) + slug = tables.Column(verbose_name="Actions", orderable=False) + + def render_lent_object(self, value, record): + return format_html("{}", + reverse("inventory:game", args=[record.lent_object.slug]), value) + + def render_slug(self, value, record): + res = "" + if record.return_date == None: + res = format_html("Rendre le jeu", + reverse("inventory:return_game", args=[value]), + reverse(self.next_pattern)) + return res + + +class OngoingLoansTable(LoanTable): + next_pattern = "inventory:ongoing_loans" + + class Meta(LoanTable.Meta): + exclude = ("return_date", "mail", "id") + diff --git a/inventory/templates/inventory/inventory.html b/inventory/templates/inventory/inventory.html index a9d0219..aecadbf 100644 --- a/inventory/templates/inventory/inventory.html +++ b/inventory/templates/inventory/inventory.html @@ -11,6 +11,9 @@
+ + Emprunts en cours + Liste des étagères

diff --git a/inventory/templates/inventory/loans/loans_table.html b/inventory/templates/inventory/loans/loans_table.html new file mode 100644 index 0000000..c1ffe38 --- /dev/null +++ b/inventory/templates/inventory/loans/loans_table.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} +{% load render_table from django_tables2 %} + +{% block "content" %} +

Liste des emprunts

+ {% render_table table %} +{% endblock %} + +{% block "main_attributes" %}class="wide-main"{% endblock %} diff --git a/inventory/templates/inventory/loans/ongoing.html b/inventory/templates/inventory/loans/ongoing.html new file mode 100644 index 0000000..32d4967 --- /dev/null +++ b/inventory/templates/inventory/loans/ongoing.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% load render_table from django_tables2 %} + +{% block "content" %} +

Emprunts en cours

+ {% render_table table %} +{% endblock %} diff --git a/inventory/urls.py b/inventory/urls.py index 65cca0c..29d3813 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -13,6 +13,8 @@ from .views import ( GameLoanView, BorrowGameView, ReturnGameView, + OngoingLoansView, + DetailLoanView, ) app_name = "inventory" @@ -34,7 +36,9 @@ urlpatterns = [ name="modify_game_comment", ), path("search/", InventorySearchView.as_view(), name="search"), - path("loans//", GameLoanView.as_view(), name="game_loan"), + path("loans/game//", GameLoanView.as_view(), name="game_loan"), path("loans/return//", ReturnGameView.as_view(), name="return_game"), path("loans/borrow//", BorrowGameView.as_view(), name="borrow_game"), + path("loans/ongoing/", OngoingLoansView.as_view(), name="ongoing_loans"), + path("loans/all/", DetailLoanView.as_view(), name="all_loans"), ] diff --git a/inventory/views.py b/inventory/views.py index cd9ccf2..52d9dfa 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -1,11 +1,14 @@ from django.views.generic import TemplateView, ListView, DetailView +from django.contrib.auth.mixins import PermissionRequiredMixin from haystack.generic_views import SearchView from haystack.forms import SearchForm from haystack.query import SearchQuerySet +from django_tables2.views import SingleTableView from comments.views import AddCommentView, ModifyCommentView from loans.views import BorrowView, ReturnView, DetailLoanView from .models import Category, Tag, Game, GameComment, GameLoan from .forms import BorrowGameForm +from .tables import LoanTable, OngoingLoansTable class InventoryView(TemplateView): @@ -67,6 +70,7 @@ class ModifyGameCommentView(ModifyCommentView): template_name = "inventory/game.html" success_pattern_name = "inventory:game" + class BorrowGameView(BorrowView): model = Game loan_model = GameLoan @@ -74,12 +78,27 @@ class BorrowGameView(BorrowView): form_class = BorrowGameForm success_pattern_name = "inventory:game_loan" + class ReturnGameView(ReturnView): model = GameLoan pattern_name = "inventory:game_loan" + class GameLoanView(DetailLoanView): model = Game loan_model = GameLoan template_name = "inventory/loans/game_loan.html" + +class OngoingLoansView(SingleTableView): + queryset = GameLoan.ongoing_loans() + table_class = OngoingLoansTable + template_name = "inventory/loans/ongoing.html" + + +class DetailLoanView(PermissionRequiredMixin, SingleTableView): + permission_required = "inventory.can_see_loan_details" + model = GameLoan + table_class = LoanTable + template_name = "inventory/loans/loans_table.html" + diff --git a/loans/models.py b/loans/models.py index ac52a77..ba8b23f 100644 --- a/loans/models.py +++ b/loans/models.py @@ -5,8 +5,9 @@ from django.utils.timezone import now class AbstractLoan(models.Model): lent_object = None # Fill this with a foreign key in subclasses slug = AutoSlugField(unique=True, populate_from="lent_object") - borrow_date = models.DateTimeField(auto_now_add=True) - return_date = models.DateTimeField(null=True) + borrow_date = models.DateTimeField( + auto_now_add=True, verbose_name="Date d’emprunt") + return_date = models.DateTimeField(null=True, verbose_name="Date de retour") mail = models.EmailField() lent_object_slug_field = "slug" diff --git a/loans/views.py b/loans/views.py index 9903472..ab061bf 100644 --- a/loans/views.py +++ b/loans/views.py @@ -21,6 +21,8 @@ class ReturnView(SingleObjectMixin, RedirectView): kwargs[self.redirect_slug_field] = getattr(loan.lent_object, loan.lent_object_slug_field) messages.success(self.request, "Rendu effectué.") + if "next" in self.request.GET: + return self.request.GET["next"] return super().get_redirect_url(*args, **kwargs) diff --git a/requirements.txt b/requirements.txt index 6a50ce2..8dbcd9e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,4 @@ Pillow django-cas-ng django-haystack Whoosh +django-tables2 diff --git a/website/scss/style.scss b/website/scss/style.scss index e9be175..9f2e684 100644 --- a/website/scss/style.scss +++ b/website/scss/style.scss @@ -31,7 +31,6 @@ body { } main { - max-width: $page_width; width: 100%; padding: 20px 40px; margin: 0 auto 50px; @@ -48,6 +47,10 @@ main { } } +main:not(.wide-main){ + max-width: $page_width; +} + footer { background-color: $footer_bg_color; font-size: 0.7em; @@ -153,6 +156,24 @@ table { th { border-bottom-width: 2px; } + + th.asc::before { + display: inline; + font-family: FontAwesome; + content: '\f0de'; // Sort up symbol + } + + th.desc::before { + display: inline; + font-family: FontAwesome; + content: '\f0dd'; // Sort down symbol + } + + th.orderable:not(.asc, .desc)::before { + display: inline; + font-family: FontAwesome; + content: '\f0dc'; // Sort up/down symbol + } } iframe { diff --git a/website/static/css/style.css b/website/static/css/style.css index 551630d..d17859f 100644 --- a/website/static/css/style.css +++ b/website/static/css/style.css @@ -277,9 +277,7 @@ body { @media (max-width: 700px) { body { font-size: 12pt; } } - main { - max-width: 850px; width: 100%; padding: 20px 40px; margin: 0 auto 50px; @@ -291,6 +289,9 @@ main { main.small_page { max-width: 550px; } +main:not(.wide-main) { + max-width: 850px; } + footer { background-color: #6bb8c4; font-size: 0.7em; @@ -403,6 +404,18 @@ table { text-align: left; } table th { border-bottom-width: 2px; } + table th.asc::before { + display: inline; + font-family: FontAwesome; + content: '\f0de'; } + table th.desc::before { + display: inline; + font-family: FontAwesome; + content: '\f0dd'; } + table th.orderable:not(.asc, .desc)::before { + display: inline; + font-family: FontAwesome; + content: '\f0dc'; } iframe { width: 100%; diff --git a/website/templates/partials/header.html b/website/templates/partials/header.html index 8064ce8..fd1d171 100644 --- a/website/templates/partials/header.html +++ b/website/templates/partials/header.html @@ -11,6 +11,9 @@
Inventaire Suggestions + {% if perms.inventory.can_see_loan_details %} + Gestion des emprunts + {% endif %} {% if request.user.is_staff %} Admin {% endif %}