feat(FORK): jeu -> outil/hackens

This commit is contained in:
sinavir 2024-07-03 00:52:16 +02:00
parent c29696a034
commit 8d58c55846
17 changed files with 978 additions and 151 deletions

View file

@ -24,7 +24,7 @@
</div> </div>
{% endif %} {% endif %}
{% empty %} {% empty %}
<p>(Aucun commentaire sur ce jeu)</p> <p>(Aucun commentaire sur cet outil)</p>
{% endfor %} {% endfor %}
{% if not edited_comment %} {% if not edited_comment %}
{% if request.user.is_authenticated %} {% if request.user.is_authenticated %}

View file

@ -37,46 +37,9 @@ class Tag(models.Model):
class Game(models.Model): class Game(models.Model):
title = models.CharField(verbose_name="titre du jeu", max_length=256, unique=True) title = models.CharField(verbose_name="Nom de l'outil", max_length=256, unique=True)
slug = AutoSlugField(populate_from="title", unique=True) slug = AutoSlugField(populate_from="title", unique=True)
nb_player_min = models.PositiveSmallIntegerField(
verbose_name="nombre de joueur·se·s minimum"
)
nb_player_max = models.PositiveSmallIntegerField(
verbose_name="nombre de joueur·se·s maximum"
)
player_range = models.CharField(
max_length=256,
blank=True,
help_text="Affichage personnalisé pour le nombre de joueur·se·s",
verbose_name="nombre de joueur·se·s",
)
duration_min = models.PositiveSmallIntegerField(
verbose_name="durée de partie minimale",
help_text="En minutes, telle qu'indiquée par l'éditeur",
)
duration_max = models.PositiveSmallIntegerField(
verbose_name="durée de partie maximale",
help_text="En minutes, telle qu'indiquée par l'éditeur, identique à la durée minimale si laissée vide",
blank=True,
)
duration = models.CharField(
max_length=256,
blank=True,
help_text="Affichage personnalisé pour la durée de la partie",
verbose_name="durée de partie",
)
game_designer = models.CharField(
max_length=256, blank=True, verbose_name="game designer"
)
illustrator = models.CharField(
max_length=256, blank=True, verbose_name="illustrateur·trice"
)
editor = models.CharField(max_length=256, blank=True, verbose_name="éditeur")
category = models.ForeignKey( category = models.ForeignKey(
Category, on_delete=models.RESTRICT, verbose_name="catégorie" Category, on_delete=models.RESTRICT, verbose_name="catégorie"
) )
@ -95,45 +58,18 @@ class Game(models.Model):
class Meta: class Meta:
ordering = ["title"] ordering = ["title"]
verbose_name = "jeu" verbose_name = "outil"
verbose_name_plural = "jeux" verbose_name_plural = "outils"
def __str__(self): def __str__(self):
return self.title return self.title
def clean(self):
if not self.nb_player_min or not self.nb_player_max or not self.duration_min:
return
if self.nb_player_min > self.nb_player_max:
raise ValidationError(
{
"nb_player_max": "Le nombre de joueur·se·s maximum doit être supérieur au nombre de joueur·se·s minimum"
}
)
if self.duration_max is None:
self.duration_max = self.duration_min
if self.duration_min > self.duration_max:
raise ValidationError(
{
"duration_max": "La durée maximale doit être supérieure à la durée minimale"
}
)
def get_player_range(self): def get_player_range(self):
if self.player_range: return ""
return self.player_range
elif self.nb_player_min != self.nb_player_max:
return "{} à {} joueur·se·s".format(self.nb_player_min, self.nb_player_max)
else:
return "{} joueur·se·s".format(self.nb_player_min)
def get_duration_range(self): def get_duration_range(self):
if self.duration: return ""
return self.duration
elif self.duration_min != self.duration_max:
return "{} à {} min".format(self.duration_min, self.duration_max)
else:
return "{} min".format(self.duration_min)
def get_absolute_url(self): def get_absolute_url(self):
return reverse("inventory:game", args=(self.slug,)) return reverse("inventory:game", args=(self.slug,))
@ -141,13 +77,13 @@ class Game(models.Model):
class GameComment(AbstractComment): class GameComment(AbstractComment):
commented_object = models.ForeignKey( commented_object = models.ForeignKey(
Game, on_delete=models.CASCADE, related_name="comments", verbose_name="jeu" Game, on_delete=models.CASCADE, related_name="comments", verbose_name="outil"
) )
class Meta: class Meta:
ordering = ["created_on"] ordering = ["created_on"]
verbose_name = "commentaire sur un jeu" verbose_name = "commentaire sur un outil"
verbose_name_plural = "commentaires sur des jeux" verbose_name_plural = "commentaires sur des outils"
def get_modification_url(self): def get_modification_url(self):
return reverse( return reverse(
@ -157,7 +93,7 @@ class GameComment(AbstractComment):
class GameLoan(AbstractLoan): class GameLoan(AbstractLoan):
lent_object = models.ForeignKey( lent_object = models.ForeignKey(
Game, on_delete=models.CASCADE, Game, on_delete=models.CASCADE,
verbose_name="jeu emprunté" verbose_name="outil emprunté"
) )
class Meta(AbstractLoan.Meta): class Meta(AbstractLoan.Meta):

View file

@ -1,8 +1,10 @@
import django_tables2 as tables import django_tables2 as tables
from django.utils.html import format_html
from django.urls import reverse from django.urls import reverse
from django.utils.html import format_html
from .models import GameLoan from .models import GameLoan
class LoanTable(tables.Table): class LoanTable(tables.Table):
next_pattern = "inventory:all_loans" next_pattern = "inventory:all_loans"
@ -10,24 +12,29 @@ class LoanTable(tables.Table):
model = GameLoan model = GameLoan
sequence = ("lent_object", "borrow_date", "return_date", "mail") sequence = ("lent_object", "borrow_date", "return_date", "mail")
exclude = ("id",) exclude = ("id",)
slug = tables.Column(verbose_name="Actions", orderable=False) slug = tables.Column(verbose_name="Actions", orderable=False)
def render_lent_object(self, value, record): def render_lent_object(self, value, record):
return format_html("<a href='{}'>{}</a>", return format_html(
reverse("inventory:game", args=[record.lent_object.slug]), value) "<a href='{}'>{}</a>",
reverse("inventory:game", args=[record.lent_object.slug]),
value,
)
def render_slug(self, value, record): def render_slug(self, value, record):
res = "" res = ""
if record.return_date == None: if record.return_date == None:
res = format_html("<a class='button' href='{}?next={}'>Rendre le jeu</a>", res = format_html(
"<a class='button' href='{}?next={}'>Rendre l'outil</a>",
reverse("inventory:return_game", args=[value]), reverse("inventory:return_game", args=[value]),
reverse(self.next_pattern)) reverse(self.next_pattern),
)
return res return res
class OngoingLoansTable(LoanTable): class OngoingLoansTable(LoanTable):
next_pattern = "inventory:ongoing_loans" next_pattern = "inventory:ongoing_loans"
class Meta(LoanTable.Meta): class Meta(LoanTable.Meta):
exclude = ("return_date", "mail", "id") exclude = ("return_date", "mail", "id")

View file

@ -4,7 +4,7 @@
<h1><i class="fa fa-bookmark" aria-hidden="true"></i> {{ category.name }}</h1> <h1><i class="fa fa-bookmark" aria-hidden="true"></i> {{ category.name }}</h1>
{% with game_list=category.game_set.all %} {% with game_list=category.game_set.all %}
<p>Il y a {{ game_list|length }} jeu{{ game_list|pluralize:"x" }} dans cette <p>Il y a {{ game_list|length }} outil{{ game_list|pluralize:"s" }} dans cette
étagère&nbsp;:</p> étagère&nbsp;:</p>
{% for game in game_list %} {% for game in game_list %}
{% include "./partials/game_item.html" %} {% include "./partials/game_item.html" %}

View file

@ -3,7 +3,7 @@
{% block "content" %} {% block "content" %}
<h1>Liste des étagères</h1> <h1>Liste des étagères</h1>
<p>Il y a {{ paginator.count }} étagère{{ paginator.count|pluralize }} de jeux&nbsp;:</p> <p>Il y a {{ paginator.count }} étagère{{ paginator.count|pluralize }} d'outils&nbsp;:</p>
{% include "partials/pagination.html" %} {% include "partials/pagination.html" %}
{% for category in category_list %} {% for category in category_list %}

View file

@ -12,9 +12,6 @@
<div id="details"> <div id="details">
<p><i class="fa fa-fw fa-bookmark"></i> <a href="{{ game.category.get_absolute_url }}">{{ game.category }}</a></p> <p><i class="fa fa-fw fa-bookmark"></i> <a href="{{ game.category.get_absolute_url }}">{{ game.category }}</a></p>
<hr/> <hr/>
<p><i class="fa fa-fw fa-users" aria-hidden="true"></i> {{ game.get_player_range }}</p>
<p><i class="fa fa-fw fa-clock-o" aria-hidden="true"></i> {{ game.get_duration_range }}</p>
<hr/>
<p><i class="fa fa-fw fa-tags" aria-hidden="true"></i> <p><i class="fa fa-fw fa-tags" aria-hidden="true"></i>
{% for tag in game.tags.all %} {% for tag in game.tags.all %}
<a href="{{ tag.get_absolute_url }}">{{ tag }}</a>{% if not forloop.last %},{% endif %} <a href="{{ tag.get_absolute_url }}">{{ tag }}</a>{% if not forloop.last %},{% endif %}
@ -23,14 +20,11 @@
{% endfor %} {% endfor %}
</p> </p>
<hr/> <hr/>
<p><i class="fa fa-fw fa-wrench" aria-hidden="true"></i> {{ game.game_designer|default:"(Game designer inconnu·e)" }}</p>
<p><i class="fa fa-fw fa-paint-brush" aria-hidden="true"></i> {{ game.illustrator|default:"(Illustrateur·trice inconnu·e)" }}</p>
<p><i class="fa fa-fw fa-cogs" aria-hidden="true"></i> {{ game.editor|default:"(Éditeur inconnu)" }}</p>
</div> </div>
</div> </div>
{% if is_borrowed %} {% if is_borrowed %}
<p class="warning">Ce jeu est emprunté depuis le {{ loan.borrow_date }}.</p> <p class="warning">Cet outil est emprunté depuis le {{ loan.borrow_date }}.</p>
{% endif %} {% endif %}
<a class="button" href="{% url "inventory:game_loan" game.slug %}"> <a class="button" href="{% url "inventory:game_loan" game.slug %}">
@ -45,7 +39,7 @@
<p class="warning">{{ game.missing_elements|linebreaksbr }}</p> <p class="warning">{{ game.missing_elements|linebreaksbr }}</p>
{% endif %} {% endif %}
<h2>Commentaires et propositions de variantes</h2> <h2>Commentaires</h2>
{% url "inventory:add_game_comment" game.slug as add_comment_url %} {% url "inventory:add_game_comment" game.slug as add_comment_url %}
{% include "comments.html" with comments=game.comments.all %} {% include "comments.html" with comments=game.comments.all %}
{% endblock %} {% endblock %}

View file

@ -1,9 +1,9 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block "content" %} {% block "content" %}
<h1>Liste des jeux</h1> <h1>Liste des outils</h1>
<p>Il y a {{ paginator.count }} jeu{{ paginator.count|pluralize:"x" }} en salle jeux&nbsp;:</p> <p>Il y a {{ paginator.count }} outil{{ paginator.count|pluralize:"s" }} en Hackens&nbsp;:</p>
{% include "partials/pagination.html" %} {% include "partials/pagination.html" %}
{% for game in game_list %} {% for game in game_list %}

View file

@ -1,9 +1,9 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block "content" %} {% block "content" %}
<h1>Inventaire du club Jeux</h1> <h1>Inventaire d'HackENS</h1>
Rechercher dans la ludothèque: Rechercher dans les outils:
<form class="search" method="get" action="{% url "inventory:search" %}"> <form class="search" method="get" action="{% url "inventory:search" %}">
<input type="search" name="q" /> <input type="search" name="q" />
<button type="submit"><i class="fa fa-fw fa-search" aria-hidden="true"></i></button> <button type="submit"><i class="fa fa-fw fa-search" aria-hidden="true"></i></button>
@ -17,19 +17,19 @@
<a class="button" href="{% url "inventory:category_list" %}"> <a class="button" href="{% url "inventory:category_list" %}">
Liste des étagères Liste des étagères
<p class="helptext"> <p class="helptext">
Chaque jeu est rangé dans une unique étagère comme en salle Jeux Chaque outils est rangé dans une étagère
</p> </p>
</a> </a>
<a class="button" href="{% url "inventory:tag_list" %}"> <a class="button" href="{% url "inventory:tag_list" %}">
Liste des tags Liste des tags
<p class="helptext"> <p class="helptext">
Chaque jeu est marqué par tous les tags qui lui correspondent Chaque outils est marqué par tous les tags qui lui correspondent
</p> </p>
</a> </a>
<a class="button" href="{% url "inventory:game_list" %}"> <a class="button" href="{% url "inventory:game_list" %}">
Liste alphabétique Liste alphabétique
<p class="helptext"> <p class="helptext">
La liste complète des jeux de la ludothèque La liste complète des outils
</p> </p>
</a> </a>
{% endblock %} {% endblock %}

View file

@ -7,7 +7,7 @@
{{ form.as_p }} {{ form.as_p }}
<button type="submit">Emprunter</button> <button type="submit">Emprunter</button>
<br/> <br/>
Vos données seront traitées pour les besoins de la gestion de la salle Jeux. Vos données seront traitées pour les besoins de la gestion du parc d'outils d'hackens.
Pour toute demande, contactez: <tt class="antispam">rf.sne@xuejopser</tt> Pour toute demande, contactez: <tt class="antispam">rf.sne@snekcah</tt>
</form> </form>
{% endblock %} {% endblock %}

View file

@ -30,7 +30,7 @@
<a class="button" href="{% url "inventory:borrow_game" game.slug %}"> <a class="button" href="{% url "inventory:borrow_game" game.slug %}">
Emprunter « {{ game.title }} » Emprunter « {{ game.title }} »
<p class="helptext"> <p class="helptext">
Si le jeu est emprunté par quelquun dautre, il sera rendu Si l'outil est emprunté par quelquun dautre, il sera rendu
automatiquement. automatiquement.
</p> </p>
</a> </a>
@ -39,12 +39,12 @@ automatiquement.
<a class="button" href="{% url "inventory:return_game" loan.slug %}"> <a class="button" href="{% url "inventory:return_game" loan.slug %}">
Rendre « {{ game.title }} » Rendre « {{ game.title }} »
<p class="helptext"> <p class="helptext">
Ce jeu est emprunté depuis le {{ loan.borrow_date }}. Ceit outil est emprunté depuis le {{ loan.borrow_date }}.
</p> </p>
</a> </a>
{% endif %} {% endif %}
<a class="button" href="/inventory/game/{{ game.slug }}/"> <a class="button" href="/inventory/game/{{ game.slug }}/">
Détails du jeu Détails de l'outil
</a> </a>
{% endblock %} {% endblock %}

View file

@ -4,7 +4,7 @@
<h1><i class="fa fa-tag" aria-hidden="true"></i> {{ tag.name }}</h1> <h1><i class="fa fa-tag" aria-hidden="true"></i> {{ tag.name }}</h1>
{% with game_list=tag.game_set.all %} {% with game_list=tag.game_set.all %}
<p>Il y a {{ game_list|length }} jeu{{ game_list|pluralize:"x" }} marqué{{ game_list|pluralize }} avec ce tag&nbsp;:</p> <p>Il y a {{ game_list|length }} outil{{ game_list|pluralize:"s" }} marqué{{ game_list|pluralize }} avec ce tag&nbsp;:</p>
{% for game in game_list %} {% for game in game_list %}
{% include "./partials/game_item.html" %} {% include "./partials/game_item.html" %}
{% endfor %} {% endfor %}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View file

@ -1,3 +1,3 @@
<footer> <footer>
Pour tout problème, contactez <tt class="antispam">rf.sne@xuejopser</tt>. Pour tout problème, contactez <tt class="antispam">rf.sne@snekcah</tt>.
</footer> </footer>

View file

@ -2,7 +2,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GestioJeux</title> <title>GestioHackens</title>
<link type="text/css" rel="stylesheet" href="{% static "css/style.css" %}" /> <link type="text/css" rel="stylesheet" href="{% static "css/style.css" %}" />
<link type="image/png" rel="shortcut icon" href="{% static "img/favicon.png" %}"/> <link type="image/png" rel="shortcut icon" href="{% static "img/favicon.png" %}"/>
<script src="{% static "js/jquery-3.4.1.min.js" %}"></script> <script src="{% static "js/jquery-3.4.1.min.js" %}"></script>

View file

@ -1,5 +1,5 @@
<header> <header>
<h1>GestioJeux</h1> <h1>GestioHackens</h1>
<div id="mobile_nav_trigger" onclick="toggle_mobile_nav()"> <div id="mobile_nav_trigger" onclick="toggle_mobile_nav()">
<i class="fa fa-fw fa-bars" aria-hidden="true"></i> Menu <i class="fa fa-fw fa-bars" aria-hidden="true"></i> Menu