forked from DGNum/gestiojeux
Add game comments and rework game models
Models are now more structured for number of players, and durations can be omitted.
This commit is contained in:
parent
497e83eca3
commit
ccd8ee9cc9
25 changed files with 547 additions and 162 deletions
|
@ -1,6 +1,7 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import Category, Tag, Game
|
from .models import Category, Tag, Game, GameComment
|
||||||
|
|
||||||
admin.site.register(Category)
|
admin.site.register(Category)
|
||||||
admin.site.register(Tag)
|
admin.site.register(Tag)
|
||||||
admin.site.register(Game)
|
admin.site.register(Game)
|
||||||
|
admin.site.register(GameComment)
|
||||||
|
|
76
inventory/migrations/0002_auto_20201212_2233.py
Normal file
76
inventory/migrations/0002_auto_20201212_2233.py
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
# Generated by Django 3.1.2 on 2020-12-12 21:33
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('inventory', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='category',
|
||||||
|
options={'ordering': ['name'], 'verbose_name': 'catégorie'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='game',
|
||||||
|
options={'ordering': ['title'], 'verbose_name': 'jeu', 'verbose_name_plural': 'jeux'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='tag',
|
||||||
|
options={'ordering': ['name']},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='game',
|
||||||
|
name='illustrator',
|
||||||
|
field=models.CharField(blank=True, max_length=256, verbose_name='illustrateur·trice'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='game',
|
||||||
|
name='missing_elements',
|
||||||
|
field=models.TextField(blank=True, verbose_name='pièces manquantes'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='game',
|
||||||
|
name='nb_player_max',
|
||||||
|
field=models.PositiveSmallIntegerField(default=20, verbose_name='nombre de joueur·se·s maximum'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='game',
|
||||||
|
name='nb_player_min',
|
||||||
|
field=models.PositiveSmallIntegerField(default=2, verbose_name='nombre de joueur·se·s minimum'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='game',
|
||||||
|
name='duration',
|
||||||
|
field=models.CharField(blank=True, max_length=256, verbose_name='durée de partie'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='game',
|
||||||
|
name='player_range',
|
||||||
|
field=models.CharField(blank=True, help_text='Affichage personnalisé pour le nombre de joueur·se·s', max_length=256, verbose_name='nombre de joueur·se·s'),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='GameComment',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('text', models.TextField(verbose_name='texte')),
|
||||||
|
('created_on', models.DateTimeField(auto_now_add=True, verbose_name='date de publication')),
|
||||||
|
('modified_on', models.DateTimeField(auto_now=True, verbose_name='date de modification')),
|
||||||
|
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='auteur·ice')),
|
||||||
|
('game', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='inventory.game', verbose_name='jeu')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'commentaire sur un jeu',
|
||||||
|
'verbose_name_plural': 'commentaires sur des jeux',
|
||||||
|
'ordering': ['created_on'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,5 +1,7 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from autoslug import AutoSlugField
|
from autoslug import AutoSlugField
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,6 +10,7 @@ class Category(models.Model):
|
||||||
slug = AutoSlugField(populate_from="name", unique=True)
|
slug = AutoSlugField(populate_from="name", unique=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
ordering = ["name"]
|
||||||
verbose_name = "catégorie"
|
verbose_name = "catégorie"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -21,6 +24,9 @@ class Tag(models.Model):
|
||||||
name = models.CharField(max_length=256, verbose_name="nom")
|
name = models.CharField(max_length=256, verbose_name="nom")
|
||||||
slug = AutoSlugField(populate_from="name", unique=True)
|
slug = AutoSlugField(populate_from="name", unique=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ["name"]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
@ -31,27 +37,83 @@ class Tag(models.Model):
|
||||||
class Game(models.Model):
|
class Game(models.Model):
|
||||||
title = models.CharField(verbose_name="titre", max_length=256)
|
title = models.CharField(verbose_name="titre", max_length=256)
|
||||||
slug = AutoSlugField(populate_from="title", unique=True)
|
slug = AutoSlugField(populate_from="title", unique=True)
|
||||||
player_range = models.CharField(
|
nb_player_min = models.PositiveSmallIntegerField(
|
||||||
max_length=256, verbose_name="nombre de joueur·se·s"
|
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 = models.CharField(
|
||||||
|
max_length=256, blank=True, verbose_name="durée de partie"
|
||||||
)
|
)
|
||||||
duration = models.CharField(max_length=256, verbose_name="durée de partie")
|
|
||||||
editor = models.CharField(max_length=256, blank=True, verbose_name="éditeur")
|
|
||||||
game_designer = models.CharField(
|
game_designer = models.CharField(
|
||||||
max_length=256, blank=True, verbose_name="game designer"
|
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")
|
||||||
description = models.TextField(blank=True, verbose_name="description")
|
description = models.TextField(blank=True, verbose_name="description")
|
||||||
category = models.ForeignKey(
|
category = models.ForeignKey(
|
||||||
Category, on_delete=models.RESTRICT, verbose_name="catégorie"
|
Category, on_delete=models.RESTRICT, verbose_name="catégorie"
|
||||||
)
|
)
|
||||||
tags = models.ManyToManyField(Tag, blank=True, verbose_name="tags")
|
tags = models.ManyToManyField(Tag, blank=True, verbose_name="tags")
|
||||||
image = models.ImageField(upload_to="game_img/", blank=True, verbose_name="image")
|
image = models.ImageField(upload_to="game_img/", blank=True, verbose_name="image")
|
||||||
|
missing_elements = models.TextField(blank=True, verbose_name="pièces manquantes")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
ordering = ["title"]
|
||||||
verbose_name = "jeu"
|
verbose_name = "jeu"
|
||||||
verbose_name_plural = "jeux"
|
verbose_name_plural = "jeux"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
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 joueurs minimum"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_player_range(self):
|
||||||
|
if self.player_range:
|
||||||
|
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_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("inventory:game", args=(self.slug,))
|
return reverse("inventory:game", args=(self.slug,))
|
||||||
|
|
||||||
|
|
||||||
|
class GameComment(models.Model):
|
||||||
|
game = models.ForeignKey(
|
||||||
|
Game, on_delete=models.CASCADE, related_name="comments", verbose_name="jeu"
|
||||||
|
)
|
||||||
|
author = models.ForeignKey(
|
||||||
|
User, on_delete=models.CASCADE, verbose_name="auteur·ice"
|
||||||
|
)
|
||||||
|
text = models.TextField(verbose_name="texte")
|
||||||
|
created_on = models.DateTimeField(
|
||||||
|
auto_now_add=True, verbose_name="date de publication"
|
||||||
|
)
|
||||||
|
modified_on = models.DateTimeField(
|
||||||
|
auto_now=True, verbose_name="date de modification"
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ["created_on"]
|
||||||
|
verbose_name = "commentaire sur un jeu"
|
||||||
|
verbose_name_plural = "commentaires sur des jeux"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "({}) {}: {}".format(self.game, self.author, self.text)
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
Il y a {{ category_list|length }} catégorie{{ category_list|pluralize }} de jeux :
|
Il y a {{ category_list|length }} catégorie{{ category_list|pluralize }} de jeux :
|
||||||
<ul>
|
<ul>
|
||||||
{% for category in category_list %}
|
{% for category in category_list %}
|
||||||
<li><a href="{{ category.get_absolute_url }}"><i class="fa fa-bookmark" aria-hidden="true"></i> {{ category.name }}</a></li>
|
{% include "./partials/category_item.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
<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.player_range }}</p>
|
<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.duration }}
|
<p><i class="fa fa-fw fa-clock-o" aria-hidden="true"></i> {{ game.duration|default:"(Durée de jeu inconnue)" }}
|
||||||
<hr/>
|
<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 %}
|
||||||
|
@ -23,10 +23,56 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
<hr/>
|
<hr/>
|
||||||
<p><i class="fa fa-fw fa-pencil" aria-hidden="true"></i> {{ game.game_designer|default:"(Game designer inconnu)" }}</li>
|
<p><i class="fa fa-fw fa-wrench" aria-hidden="true"></i> {{ game.game_designer|default:"(Game designer inconnu·e)" }}</li>
|
||||||
|
<p><i class="fa fa-fw fa-paint-brush" aria-hidden="true"></i> {{ game.illustrator|default:"(Illustrateur·trice inconnu·e)" }}</li>
|
||||||
<p><i class="fa fa-fw fa-cogs" aria-hidden="true"></i> {{ game.editor|default:"(Éditeur inconnu)" }}</p>
|
<p><i class="fa fa-fw fa-cogs" aria-hidden="true"></i> {{ game.editor|default:"(Éditeur inconnu)" }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p id="description">{{ object.description }}</p>
|
<h2 id="description">Description</h2>
|
||||||
|
{{ object.description|linebreaks }}
|
||||||
|
|
||||||
|
{% if game.missing_elements %}
|
||||||
|
<h2>Pièces manquantes</h2>
|
||||||
|
<p class="warning">{{ game.missing_elements|linebreaksbr }}</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<h2>Commentaires et propositions de variantes</h2>
|
||||||
|
<ul>
|
||||||
|
{% for comment in game.comments.all %}
|
||||||
|
{% if comment == edited_comment %}
|
||||||
|
<li id="edited_comment">
|
||||||
|
<form class="comment" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<textarea name="comment_text" required>{{ comment.text }}</textarea>
|
||||||
|
<button type="submit"><i class="fa fa-pencil" aria-hidden="true"></i> Modifier mon commentaire</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="comment">
|
||||||
|
<div class="meta">
|
||||||
|
<span class="author">{{ comment.author }}</span>
|
||||||
|
<span class="date">posté le {{ comment.created_on|date }} à {{ comment.created_on|time }}{% if comment.created_on|date:"YmdHi" != comment.modified_on|date:"YmdHi" %}, dernière modification le {{ comment.modified_on|date }} à {{ comment.modified_on|time }}{% endif %}</span>
|
||||||
|
{% if comment.author == request.user %}
|
||||||
|
<a href="{% url "inventory:modify_game_comment" game.slug comment.id %}#edited_comment"><i class="fa fa-pencil" aria-hidden="true"></i></a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{{ comment.text|linebreaks }}
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% empty %}
|
||||||
|
<li>(Aucun commentaire sur ce jeu)</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% if not edited_comment %}
|
||||||
|
{% if request.user.is_authenticated %}
|
||||||
|
<form class="comment" method="post" action="{% url "inventory:add_game_comment" game.slug %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<textarea name="comment_text" placeholder="Ajouter un commentaire à propos de {{ game.title }}" required></textarea>
|
||||||
|
<button type="submit"><i class="fa fa-paper-plane" aria-hidden="true"></i> Envoyer le commentaire</button>
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url "gestiojeux_auth:login" %}?next={{ request.get_full_path }}">Connectez-vous</a> pour ajouter un commentaire.
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<li>
|
||||||
|
<a href="{{ category.get_absolute_url }}"><i class="fa fa-bookmark" aria-hidden="true"></i> <span class="title">{{ category.name }}</span></a>
|
||||||
|
</li>
|
|
@ -1,15 +1,18 @@
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ game.get_absolute_url }}">
|
<a href="{{ game.get_absolute_url }}">
|
||||||
{{game.title}}
|
<span class="title">{{ game.title }}</span>
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<p><i class="fa fa-fw fa-users" aria-hidden="true"></i> {{ game.player_range }}</p>
|
<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.duration }}
|
<p><i class="fa fa-fw fa-clock-o" aria-hidden="true"></i> {{ game.duration }}
|
||||||
<p><i class="fa fa-fw fa-bookmark"></i> {{ game.category }}</p>
|
<p><i class="fa fa-fw fa-bookmark"></i> {{ game.category }}</p>
|
||||||
{% for tag in game.tags.all %}
|
{% for tag in game.tags.all %}
|
||||||
<p><i class="fa fa-fw fa-tag" aria-hidden="true"></i> {{ tag }}</p>
|
<p><i class="fa fa-fw fa-tag" aria-hidden="true"></i> {{ tag }}</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if game.game_designer %}
|
{% if game.game_designer %}
|
||||||
<p><i class="fa fa-fw fa-pencil" aria-hidden="true"></i> {{ game.game_designer }}
|
<p><i class="fa fa-fw fa-wrench" aria-hidden="true"></i> {{ game.game_designer }}</p>
|
||||||
|
{% endif %}
|
||||||
|
{% if game.illustrator %}
|
||||||
|
<p><i class="fa fa-fw fa-paint-brush" aria-hidden="true"></i> {{ game.illustrator }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if game.editor %}
|
{% if game.editor %}
|
||||||
<p><i class="fa fa-fw fa-cogs" aria-hidden="true"></i> {{ game.editor }}</p>
|
<p><i class="fa fa-fw fa-cogs" aria-hidden="true"></i> {{ game.editor }}</p>
|
||||||
|
|
8
inventory/templates/inventory/partials/pagination.html
Normal file
8
inventory/templates/inventory/partials/pagination.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{% if page_obj.has_other_pages %}
|
||||||
|
<div id="pagination">
|
||||||
|
{% if page_obj.has_previous %}<a href="?q={{ query }}&page={{ page_obj.previous_page_number }}">{% endif %}<i class="fa fa-arrow-left" aria-hidden="true"></i> Précédent{% if page_obj.has_previous %}</a>{% endif %}
|
||||||
|
| Page {{ page_obj.number }} sur {{ paginator.num_pages }} |
|
||||||
|
{% if page_obj.has_next %}<a href="?q={{ query }}&page={{ page_obj.next_page_number }}">{% endif %}Suivant <i class="fa fa-arrow-right" aria-hidden="true"></i>{% if page_obj.has_next %}</a>{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
3
inventory/templates/inventory/partials/tag_item.html
Normal file
3
inventory/templates/inventory/partials/tag_item.html
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<li>
|
||||||
|
<a href="{{ tag.get_absolute_url }}"><i class="fa fa-tag" aria-hidden="true"></i> <span class="title">{{ tag.name }}</span></a>
|
||||||
|
</li>
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
{% block "content" %}
|
{% block "content" %}
|
||||||
<h1>Recherche</h1>
|
<h1>Recherche</h1>
|
||||||
<form class="search" method="get" action=".">
|
<form class="search" method="get">
|
||||||
{{ form.q }}
|
{{ form.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>
|
||||||
</form>
|
</form>
|
||||||
|
@ -15,25 +15,15 @@
|
||||||
{% if result.model_name == "game" %}
|
{% if result.model_name == "game" %}
|
||||||
{% include "./partials/game_item.html" with game=result.object %}
|
{% include "./partials/game_item.html" with game=result.object %}
|
||||||
{% elif result.model_name == "category" %}
|
{% elif result.model_name == "category" %}
|
||||||
<li>
|
{% include "./partials/category_item.html" with category=result.object %}
|
||||||
<a href="{{ result.object.get_absolute_url }}"><i class="fa fa-bookmark" aria-hidden="true"></i> {{ result.object.name }}</a>
|
|
||||||
</li>
|
|
||||||
{% elif result.model_name == "tag" %}
|
{% elif result.model_name == "tag" %}
|
||||||
<li>
|
{% include "./partials/tag_item.html" with tag=result.object %}
|
||||||
<a href="{{ result.object.get_absolute_url }}"><i class="fa fa-tag" aria-hidden="true"></i> {{ result.object.name }}</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% empty %}
|
{% empty %}
|
||||||
<li>Aucun résultat trouvé</li>
|
<li>Aucun résultat trouvé</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{% if page_obj.has_previous or page_obj.has_next %}
|
{% include "./partials/pagination.html" %}
|
||||||
<div>
|
|
||||||
{% if page_obj.has_previous %}<a href="?q={{ query }}&page={{ page_obj.previous_page_number }}">{% endif %}« Précédent{% if page_obj.has_previous %}</a>{% endif %}
|
|
||||||
|
|
|
||||||
{% if page_obj.has_next %}<a href="?q={{ query }}&page={{ page_obj.next_page_number }}">{% endif %}Suivant »{% if page_obj.has_next %}</a>{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{{ object.title }}
|
{{ object.title }}
|
||||||
{{ object.editor }}
|
|
||||||
{{ object.game_designer }}
|
{{ object.game_designer }}
|
||||||
|
{{ object.illustrator }}
|
||||||
|
{{ object.editor }}
|
||||||
{{ object.description }}
|
{{ object.description }}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
Il y a {{ tag_list|length }} tag{{ tag_list|pluralize }} dans la ludothèque :
|
Il y a {{ tag_list|length }} tag{{ tag_list|pluralize }} dans la ludothèque :
|
||||||
<ul>
|
<ul>
|
||||||
{% for tag in tag_list %}
|
{% for tag in tag_list %}
|
||||||
<li><a href="{{ tag.get_absolute_url }}"><i class="fa fa-tag" aria-hidden="true"></i> {{ tag.name }}</a></li>
|
{% include "./partials/tag_item.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -7,6 +7,8 @@ from .views import (
|
||||||
TagView,
|
TagView,
|
||||||
GameListView,
|
GameListView,
|
||||||
GameView,
|
GameView,
|
||||||
|
AddGameCommentView,
|
||||||
|
ModifyGameCommentView,
|
||||||
InventorySearchView,
|
InventorySearchView,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,5 +22,13 @@ urlpatterns = [
|
||||||
path("tag/<slug>/", TagView.as_view(), name="tag"),
|
path("tag/<slug>/", TagView.as_view(), name="tag"),
|
||||||
path("game/", GameListView.as_view(), name="game_list"),
|
path("game/", GameListView.as_view(), name="game_list"),
|
||||||
path("game/<slug>/", GameView.as_view(), name="game"),
|
path("game/<slug>/", GameView.as_view(), name="game"),
|
||||||
|
path(
|
||||||
|
"game/<slug>/add_comment", AddGameCommentView.as_view(), name="add_game_comment"
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"game/<slug>/modify_comment/<int:comment_id>",
|
||||||
|
ModifyGameCommentView.as_view(),
|
||||||
|
name="modify_game_comment",
|
||||||
|
),
|
||||||
path("search/", InventorySearchView.as_view(), name="search"),
|
path("search/", InventorySearchView.as_view(), name="search"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,8 +1,20 @@
|
||||||
from django.views.generic import TemplateView, ListView, DetailView
|
from django.views.generic import (
|
||||||
|
TemplateView,
|
||||||
|
ListView,
|
||||||
|
DetailView,
|
||||||
|
RedirectView,
|
||||||
|
)
|
||||||
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.shortcuts import redirect, get_object_or_404
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.http import Http404
|
||||||
|
from django.core.exceptions import PermissionDenied
|
||||||
from haystack.generic_views import SearchView
|
from haystack.generic_views import SearchView
|
||||||
from haystack.forms import SearchForm
|
from haystack.forms import SearchForm
|
||||||
from haystack.query import SearchQuerySet
|
from haystack.query import SearchQuerySet
|
||||||
from .models import Category, Tag, Game
|
from .models import Category, Tag, Game, GameComment
|
||||||
|
|
||||||
|
|
||||||
class InventoryView(TemplateView):
|
class InventoryView(TemplateView):
|
||||||
|
@ -45,3 +57,55 @@ class InventorySearchView(SearchView):
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return SearchQuerySet().models(Category, Tag, Game)
|
return SearchQuerySet().models(Category, Tag, Game)
|
||||||
|
|
||||||
|
|
||||||
|
class AddGameCommentView(LoginRequiredMixin, SingleObjectMixin, RedirectView):
|
||||||
|
model = Game
|
||||||
|
permanent = False
|
||||||
|
|
||||||
|
def get_redirect_url(self, *args, **kwargs):
|
||||||
|
req_dict = self.request.POST
|
||||||
|
if "comment_text" in req_dict:
|
||||||
|
comment_text = req_dict["comment_text"]
|
||||||
|
|
||||||
|
game = self.get_object()
|
||||||
|
game.comments.create(author=self.request.user, text=comment_text)
|
||||||
|
messages.success(self.request, "Commentaire ajouté")
|
||||||
|
else:
|
||||||
|
messages.error(
|
||||||
|
self.request, "Pas de texte pour le commentaire dans la requête"
|
||||||
|
)
|
||||||
|
|
||||||
|
return reverse("inventory:game", kwargs=kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class ModifyGameCommentView(LoginRequiredMixin, SingleObjectMixin, TemplateView):
|
||||||
|
model = Game
|
||||||
|
template_name = "inventory/game.html"
|
||||||
|
|
||||||
|
def dispatch(self, *args, **kwargs):
|
||||||
|
comment_id = kwargs["comment_id"]
|
||||||
|
self.object = self.get_object()
|
||||||
|
self.comment = get_object_or_404(GameComment, id=comment_id)
|
||||||
|
if self.comment.game != self.object:
|
||||||
|
raise Http404()
|
||||||
|
if self.comment.author != self.request.user:
|
||||||
|
raise PermissionDenied()
|
||||||
|
return super().dispatch(*args, **kwargs)
|
||||||
|
|
||||||
|
def post(self, *args, **kwargs):
|
||||||
|
req_dict = self.request.POST
|
||||||
|
if "comment_text" in req_dict:
|
||||||
|
self.comment.text = req_dict["comment_text"]
|
||||||
|
self.comment.save()
|
||||||
|
messages.success(self.request, "Commentaire modifié")
|
||||||
|
else:
|
||||||
|
messages.error(
|
||||||
|
self.request, "Pas de texte pour le commentaire dans la requête"
|
||||||
|
)
|
||||||
|
return redirect("inventory:game", slug=kwargs["slug"])
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["edited_comment"] = self.comment
|
||||||
|
return context
|
||||||
|
|
|
@ -26,7 +26,7 @@ form {
|
||||||
color: $help_text_color;
|
color: $help_text_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input, textarea {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
|
@ -36,11 +36,13 @@ input {
|
||||||
|
|
||||||
input[type="text"],
|
input[type="text"],
|
||||||
input[type="email"],
|
input[type="email"],
|
||||||
input[type="password"], {
|
input[type="password"],
|
||||||
|
input[type="search"],
|
||||||
|
textarea {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border: solid 1px $help_text_color;
|
border: solid 1px $help_text_color;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
border-radius: 3px;
|
border-radius: 5px;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
|
||||||
&:optional {
|
&:optional {
|
||||||
|
@ -56,6 +58,13 @@ input[type="password"], {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
font-family: $font_family;
|
||||||
|
font-size: 1em;
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="checkbox"],
|
input[type="checkbox"],
|
||||||
input[type="radio"] {
|
input[type="radio"] {
|
||||||
width: auto;
|
width: auto;
|
||||||
|
@ -99,9 +108,26 @@ select {
|
||||||
|
|
||||||
form.search {
|
form.search {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 10px;
|
|
||||||
|
|
||||||
|
input[type="search"] {
|
||||||
|
border-radius: 5px 0 0 5px;
|
||||||
|
border-right: 0;
|
||||||
|
}
|
||||||
button {
|
button {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
border-radius: 0 10px 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
form.comment {
|
||||||
|
font-size: 0.7em;
|
||||||
|
textarea {
|
||||||
|
border-radius: 10px 10px 0 0;
|
||||||
|
border-bottom: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
border-radius: 0 0 10px 10px;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ header {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
color: $header_text_color;
|
color: $header_text_color;
|
||||||
font-size: $font_size;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav {
|
nav {
|
||||||
|
@ -31,12 +31,11 @@ header {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
|
||||||
color: $header_text_color;
|
color: $header_text_color;
|
||||||
font-size: $nav_font_size;
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: darken($header_bg_color, 10%);
|
background-color: darken($header_bg_color, 10%);
|
||||||
color: $page_link_hover_color;
|
color: $page_link_color;
|
||||||
}
|
}
|
||||||
&.current {
|
&.current {
|
||||||
background-color: $header_border_color;
|
background-color: $header_border_color;
|
||||||
|
@ -44,11 +43,11 @@ header {
|
||||||
&:focus {
|
&:focus {
|
||||||
background-color: darken($header_bg_color, 10%);
|
background-color: darken($header_bg_color, 10%);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
color: $page_link_hover_color;
|
color: $page_link_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
font-size: 12pt;
|
font-size: 0.7em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid $border_color;
|
border: 1px solid $border_color;
|
||||||
background-color: $bg_color;
|
background-color: $bg_color;
|
||||||
color: $page_text_color;
|
|
||||||
}
|
}
|
||||||
@mixin error_box {
|
@mixin error_box {
|
||||||
@include box($error_box_color, $error_box_border_color);
|
@include box($error_box_color, $error_box_border_color);
|
||||||
|
@ -23,6 +22,7 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
|
color: $page_text_color;
|
||||||
|
|
||||||
@include box(lighten($header_border_color, 40%), $header_border_color);
|
@include box(lighten($header_border_color, 40%), $header_border_color);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
$page_bg_color: #f6fbfd;
|
$page_bg_color: #f6fbfd;
|
||||||
$page_text_color: #250f2d;
|
$page_text_color: #250f2d;
|
||||||
$page_link_color: #2b153f;
|
$page_link_color: #1e464c;
|
||||||
$page_link_hover_color: #180c23;
|
|
||||||
$page_width: 800px;
|
$page_width: 800px;
|
||||||
$small_page_width: 500px;
|
$small_page_width: 500px;
|
||||||
|
|
||||||
|
@ -16,20 +15,18 @@ $header_bg_color: #6bb8c4;
|
||||||
$header_text_color: #f6fbfd;
|
$header_text_color: #f6fbfd;
|
||||||
$header_infos_font_family: "Kalam";
|
$header_infos_font_family: "Kalam";
|
||||||
$header_border_color: #51808c;
|
$header_border_color: #51808c;
|
||||||
$nav_font_size: 18pt;
|
|
||||||
|
|
||||||
$footer_bg_color: $header_bg_color;
|
$footer_bg_color: $header_bg_color;
|
||||||
$footer_font_size: 12pt;
|
|
||||||
|
|
||||||
$indexbar_bg_color_1: rgba($header_bg_color, 0.75);
|
$indexbar_bg_color_1: rgba($header_bg_color, 0.75);
|
||||||
$indexbar_bg_color_2: rgba($header_bg_color, 0.6);
|
$indexbar_bg_color_2: rgba($header_bg_color, 0.6);
|
||||||
$indexbar_text_color: darken($page_link_color, 15);
|
$indexbar_text_color: darken($page_link_color, 15);
|
||||||
|
|
||||||
$info_box_color: #c9c8ff;
|
$info_box_color: #e0dfff;
|
||||||
$info_box_border_color: darken($info_box_color, 20%);
|
$info_box_border_color: darken($info_box_color, 20%);
|
||||||
$error_box_color: #ffcddd;
|
$error_box_color: #ffdfe9;
|
||||||
$error_box_border_color: darken($error_box_color, 20%);
|
$error_box_border_color: darken($error_box_color, 20%);
|
||||||
$success_box_color: #a4ffc4;
|
$success_box_color: #ddffd8;
|
||||||
$success_box_border_color: darken($success_box_color, 40%);
|
$success_box_border_color: darken($success_box_color, 20%);
|
||||||
$warning_box_color: #ffd45d;
|
$warning_box_color: #ffedbb;
|
||||||
$warning_box_border_color: darken($warning_box_color, 20%);
|
$warning_box_border_color: darken($warning_box_color, 20%);
|
||||||
|
|
|
@ -50,7 +50,7 @@ main {
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
background-color: $footer_bg_color;
|
background-color: $footer_bg_color;
|
||||||
font-size: $footer_font_size;
|
font-size: 0.7em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
@ -69,13 +69,23 @@ h1 {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.25em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: underline;
|
text-decoration: underline lighten($header_border_color, 40%);
|
||||||
color: $page_link_color;
|
color: $page_link_color;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $page_link_hover_color;
|
text-decoration-color: $page_link_color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +116,7 @@ hr {
|
||||||
|
|
||||||
button, .btn_row a {
|
button, .btn_row a {
|
||||||
@include button;
|
@include button;
|
||||||
margin: 10px 5px;
|
margin: 10px 0;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -277,37 +287,62 @@ iframe {
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
padding: 0 20px;
|
padding: 0;
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
li>a {
|
li>a {
|
||||||
display: block;
|
display: block;
|
||||||
text-decoration: none;
|
padding: 15px;
|
||||||
padding: 15px;
|
margin: 10px 5px;
|
||||||
margin: 10px 5px;
|
border-radius: 10px;
|
||||||
border-radius: 10px;
|
border: 1px solid transparent;
|
||||||
border: 1px solid transparent;
|
text-decoration: none;
|
||||||
|
|
||||||
&:hover {
|
.title {
|
||||||
border-color: $header_border_color;
|
text-decoration: underline lighten($header_border_color, 40%);
|
||||||
background-color: lighten($header_border_color, 70%);
|
}
|
||||||
}
|
|
||||||
&:focus {
|
|
||||||
border-color: $header_border_color;
|
|
||||||
background-color: lighten($header_border_color, 70%);
|
|
||||||
box-shadow: 0 0 1.5px 1px $header_bg_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.details {
|
.details {
|
||||||
font-size: 0.7em;
|
font-size: 0.7em;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
gap: 5px 20px;
|
gap: 5px 20px;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: $header_border_color;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
text-decoration-color: currentColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
border-color: $header_border_color;
|
||||||
|
background-color: white;
|
||||||
|
box-shadow: 0 0 1.5px 1px $header_bg_color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li.comment {
|
||||||
|
@include box(white, $indexbar_bg_color_1);
|
||||||
|
margin: 1em 0;
|
||||||
|
font-size: 0.7em;
|
||||||
|
|
||||||
|
.author {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.date {
|
||||||
|
font-size: 0.7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ header {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
color: #f6fbfd;
|
color: #f6fbfd;
|
||||||
font-size: 16pt; }
|
font-size: 1em; }
|
||||||
header nav {
|
header nav {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
|
@ -24,19 +24,18 @@ header {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
color: #f6fbfd;
|
color: #f6fbfd;
|
||||||
font-size: 18pt;
|
|
||||||
text-decoration: none; }
|
text-decoration: none; }
|
||||||
header a:hover {
|
header a:hover {
|
||||||
background-color: #48a6b4;
|
background-color: #48a6b4;
|
||||||
color: #180c23; }
|
color: #1e464c; }
|
||||||
header a.current {
|
header a.current {
|
||||||
background-color: #51808c; }
|
background-color: #51808c; }
|
||||||
header a:focus {
|
header a:focus {
|
||||||
background-color: #48a6b4;
|
background-color: #48a6b4;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
color: #180c23; }
|
color: #1e464c; }
|
||||||
header .username {
|
header .username {
|
||||||
font-size: 12pt; }
|
font-size: 0.7em; }
|
||||||
|
|
||||||
form {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -50,9 +49,8 @@ form {
|
||||||
form .errorlist li {
|
form .errorlist li {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #ff6798;
|
border: 1px solid #ff79a3;
|
||||||
background-color: #ffcddd;
|
background-color: #ffdfe9;
|
||||||
color: #250f2d;
|
|
||||||
margin-bottom: 10px; }
|
margin-bottom: 10px; }
|
||||||
form p {
|
form p {
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
|
@ -62,7 +60,7 @@ form {
|
||||||
font-size: 0.7em;
|
font-size: 0.7em;
|
||||||
color: rgba(37, 15, 45, 0.65); }
|
color: rgba(37, 15, 45, 0.65); }
|
||||||
|
|
||||||
input {
|
input, textarea {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
|
@ -71,26 +69,40 @@ input {
|
||||||
|
|
||||||
input[type="text"],
|
input[type="text"],
|
||||||
input[type="email"],
|
input[type="email"],
|
||||||
input[type="password"] {
|
input[type="password"],
|
||||||
|
input[type="search"],
|
||||||
|
textarea {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border: solid 1px rgba(37, 15, 45, 0.65);
|
border: solid 1px rgba(37, 15, 45, 0.65);
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
border-radius: 3px;
|
border-radius: 5px;
|
||||||
box-shadow: none; }
|
box-shadow: none; }
|
||||||
input[type="text"]:optional,
|
input[type="text"]:optional,
|
||||||
input[type="email"]:optional,
|
input[type="email"]:optional,
|
||||||
input[type="password"]:optional {
|
input[type="password"]:optional,
|
||||||
|
input[type="search"]:optional,
|
||||||
|
textarea:optional {
|
||||||
border-color: rgba(37, 15, 45, 0.4); }
|
border-color: rgba(37, 15, 45, 0.4); }
|
||||||
input[type="text"]:focus,
|
input[type="text"]:focus,
|
||||||
input[type="email"]:focus,
|
input[type="email"]:focus,
|
||||||
input[type="password"]:focus {
|
input[type="password"]:focus,
|
||||||
|
input[type="search"]:focus,
|
||||||
|
textarea:focus {
|
||||||
border-color: #6bb8c4;
|
border-color: #6bb8c4;
|
||||||
box-shadow: 0 0 1.5px 1px #6bb8c4; }
|
box-shadow: 0 0 1.5px 1px #6bb8c4; }
|
||||||
input[type="text"]:-moz-ui-invalid,
|
input[type="text"]:-moz-ui-invalid,
|
||||||
input[type="email"]:-moz-ui-invalid,
|
input[type="email"]:-moz-ui-invalid,
|
||||||
input[type="password"]:-moz-ui-invalid {
|
input[type="password"]:-moz-ui-invalid,
|
||||||
border-color: #ff6798;
|
input[type="search"]:-moz-ui-invalid,
|
||||||
box-shadow: 0 0 1.5px 1px #ff6798; }
|
textarea:-moz-ui-invalid {
|
||||||
|
border-color: #ff79a3;
|
||||||
|
box-shadow: 0 0 1.5px 1px #ff79a3; }
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
font-family: "Open Sans";
|
||||||
|
font-size: 1em;
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 120px; }
|
||||||
|
|
||||||
input[type="checkbox"],
|
input[type="checkbox"],
|
||||||
input[type="radio"] {
|
input[type="radio"] {
|
||||||
|
@ -102,11 +114,11 @@ input[type="submit"] {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
|
color: #250f2d;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #51808c;
|
border: 1px solid #51808c;
|
||||||
background-color: #c9dbe0;
|
background-color: #c9dbe0; }
|
||||||
color: #250f2d; }
|
|
||||||
input[type="submit"]:hover {
|
input[type="submit"]:hover {
|
||||||
background-color: #a9c6cd; }
|
background-color: #a9c6cd; }
|
||||||
input[type="submit"]:focus {
|
input[type="submit"]:focus {
|
||||||
|
@ -120,11 +132,11 @@ select {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
|
color: #250f2d;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #51808c;
|
border: 1px solid #51808c;
|
||||||
background-color: #c9dbe0;
|
background-color: #c9dbe0;
|
||||||
color: #250f2d;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -149,12 +161,25 @@ select {
|
||||||
|
|
||||||
.error_field {
|
.error_field {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: rgba(255, 205, 221, 0.4); }
|
background-color: rgba(255, 223, 233, 0.4); }
|
||||||
|
|
||||||
form.search {
|
form.search {
|
||||||
flex-direction: row;
|
flex-direction: row; }
|
||||||
gap: 10px; }
|
form.search input[type="search"] {
|
||||||
|
border-radius: 5px 0 0 5px;
|
||||||
|
border-right: 0; }
|
||||||
form.search button {
|
form.search button {
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0 10px 10px 0; }
|
||||||
|
|
||||||
|
form.comment {
|
||||||
|
font-size: 0.7em; }
|
||||||
|
form.comment textarea {
|
||||||
|
border-radius: 10px 10px 0 0;
|
||||||
|
border-bottom: none;
|
||||||
|
margin: 0; }
|
||||||
|
form.comment button {
|
||||||
|
border-radius: 0 0 10px 10px;
|
||||||
margin: 0; }
|
margin: 0; }
|
||||||
|
|
||||||
html {
|
html {
|
||||||
|
@ -192,7 +217,7 @@ main {
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
background-color: #6bb8c4;
|
background-color: #6bb8c4;
|
||||||
font-size: 12pt;
|
font-size: 0.7em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 10px; }
|
padding: 10px; }
|
||||||
|
|
||||||
|
@ -207,16 +232,24 @@ h1 {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
font-weight: bold; }
|
font-weight: bold; }
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.25em;
|
||||||
|
font-weight: bold; }
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: bold; }
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: underline;
|
text-decoration: underline #c9dbe0;
|
||||||
color: #2b153f;
|
color: #1e464c;
|
||||||
border-radius: 3px; }
|
border-radius: 3px; }
|
||||||
a:hover {
|
a:hover {
|
||||||
color: #180c23; }
|
text-decoration-color: #1e464c; }
|
||||||
|
|
||||||
:focus {
|
:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: 0 0 1.5px 1px #2b153f; }
|
box-shadow: 0 0 1.5px 1px #1e464c; }
|
||||||
|
|
||||||
::-moz-focus-inner {
|
::-moz-focus-inner {
|
||||||
border: none; }
|
border: none; }
|
||||||
|
@ -240,12 +273,12 @@ button, .btn_row a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
|
color: #250f2d;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #51808c;
|
border: 1px solid #51808c;
|
||||||
background-color: #c9dbe0;
|
background-color: #c9dbe0;
|
||||||
color: #250f2d;
|
margin: 10px 0; }
|
||||||
margin: 10px 5px; }
|
|
||||||
button:hover, .btn_row a:hover {
|
button:hover, .btn_row a:hover {
|
||||||
background-color: #a9c6cd; }
|
background-color: #a9c6cd; }
|
||||||
button:focus, .btn_row a:focus {
|
button:focus, .btn_row a:focus {
|
||||||
|
@ -265,30 +298,26 @@ button, .btn_row a {
|
||||||
.error {
|
.error {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #ff6798;
|
border: 1px solid #ff79a3;
|
||||||
background-color: #ffcddd;
|
background-color: #ffdfe9; }
|
||||||
color: #250f2d; }
|
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #6562ff;
|
border: 1px solid #7d79ff;
|
||||||
background-color: #c9c8ff;
|
background-color: #e0dfff; }
|
||||||
color: #250f2d; }
|
|
||||||
|
|
||||||
.warning {
|
.warning {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #f6b500;
|
border: 1px solid #ffd255;
|
||||||
background-color: #ffd45d;
|
background-color: #ffedbb; }
|
||||||
color: #250f2d; }
|
|
||||||
|
|
||||||
.success {
|
.success {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #00d74c;
|
border: 1px solid #84ff72;
|
||||||
background-color: #a4ffc4;
|
background-color: #ddffd8; }
|
||||||
color: #250f2d; }
|
|
||||||
|
|
||||||
.tooltip {
|
.tooltip {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -408,27 +437,46 @@ iframe {
|
||||||
margin: 1ex; }
|
margin: 1ex; }
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
padding: 0 20px;
|
padding: 0;
|
||||||
list-style-type: none; }
|
list-style-type: none; }
|
||||||
ul li > a {
|
|
||||||
display: block;
|
li > a {
|
||||||
text-decoration: none;
|
display: block;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
margin: 10px 5px;
|
margin: 10px 5px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
border: 1px solid transparent; }
|
border: 1px solid transparent;
|
||||||
ul li > a:hover {
|
text-decoration: none; }
|
||||||
border-color: #51808c;
|
li > a .title {
|
||||||
background-color: white; }
|
text-decoration: underline #c9dbe0; }
|
||||||
ul li > a:focus {
|
li > a .details {
|
||||||
border-color: #51808c;
|
font-size: 0.7em;
|
||||||
background-color: white;
|
display: flex;
|
||||||
box-shadow: 0 0 1.5px 1px #6bb8c4; }
|
flex-wrap: wrap;
|
||||||
ul li > a .details {
|
margin: 5px;
|
||||||
font-size: 0.7em;
|
gap: 5px 20px; }
|
||||||
display: flex;
|
li > a .details p {
|
||||||
flex-wrap: wrap;
|
margin: 0; }
|
||||||
margin: 5px;
|
li > a:hover {
|
||||||
gap: 5px 20px; }
|
border-color: #51808c;
|
||||||
ul li > a .details p {
|
background-color: white; }
|
||||||
margin: 0; }
|
li > a:hover .title {
|
||||||
|
text-decoration-color: currentColor; }
|
||||||
|
li > a:focus {
|
||||||
|
border-color: #51808c;
|
||||||
|
background-color: white;
|
||||||
|
box-shadow: 0 0 1.5px 1px #6bb8c4; }
|
||||||
|
|
||||||
|
li.comment {
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid rgba(107, 184, 196, 0.75);
|
||||||
|
background-color: white;
|
||||||
|
margin: 1em 0;
|
||||||
|
font-size: 0.7em; }
|
||||||
|
li.comment .author {
|
||||||
|
font-weight: bold; }
|
||||||
|
li.comment .date {
|
||||||
|
font-size: 0.7em; }
|
||||||
|
li.comment p {
|
||||||
|
margin: 0.5em; }
|
||||||
|
|
25
mainsite/static/js/gestiojeux.js
Normal file
25
mainsite/static/js/gestiojeux.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
const MOBILE_NAV_PAGE_SIZE = 475; // px
|
||||||
|
const MOBILE_NAV_TOGGLE_TIME = 300; // msec
|
||||||
|
const TEXTAREA_MIN_SIZE = 120; // px
|
||||||
|
|
||||||
|
function mobile_nav_toggle() {
|
||||||
|
$("nav > a").slideToggle(MOBILE_NAV_TOGGLE_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(window).resize(function () {
|
||||||
|
if(window.innerWidth > MOBILE_NAV_PAGE_SIZE) {
|
||||||
|
$("nav > a").show(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$("nav > a").hide(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('textarea').each(function () {
|
||||||
|
this.style.height = Math.max(this.scrollHeight, TEXTAREA_MIN_SIZE) + 'px';
|
||||||
|
this.style.resize = 'none';
|
||||||
|
this.style.overflowY = 'hidden';
|
||||||
|
}).on('input', function () {
|
||||||
|
this.style.height = 'auto';
|
||||||
|
this.style.height = Math.max(this.scrollHeight, TEXTAREA_MIN_SIZE) + 'px';
|
||||||
|
});
|
|
@ -1,3 +1,5 @@
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="fr">
|
<html lang="fr">
|
||||||
<head>
|
<head>
|
||||||
|
@ -17,7 +19,7 @@
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{% include "partials/footer.html" %}
|
{% include "partials/footer.html" %}
|
||||||
{% include "partials/base_js.html" %}
|
<script src="{% static "js/gestiojeux.js" %}"></script>
|
||||||
{% block "extra_foot" %}{% endblock %}
|
{% block "extra_foot" %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
<script>
|
|
||||||
function mobile_nav_toggle() {
|
|
||||||
$("nav > a").slideToggle(300);
|
|
||||||
}
|
|
||||||
|
|
||||||
$(window).resize(function () {
|
|
||||||
if(window.innerWidth > 475) {
|
|
||||||
$("nav > a").show(0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$("nav > a").hide(0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -4,5 +4,5 @@
|
||||||
<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>GestioJeux</title>
|
||||||
<link type="text/css" rel="stylesheet" href="{% static "css/style.css" %}" />
|
<link type="text/css" rel="stylesheet" href="{% static "css/style.css" %}" />
|
||||||
<link rel="shortcut icon" type="image/png" 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>
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<div class="username">{{ request.user.username }}</div>
|
<div class="username">{{ request.user.username }}</div>
|
||||||
<a class="login" href="{% url "gestiojeux_auth:logout" %}?next={{ request.get_full_path }}"><i class="fa fa-sign-out" aria-hidden="true"></i></a>
|
<a class="login" href="{% url "gestiojeux_auth:logout" %}?next={{ request.get_full_path }}"><i class="fa fa-sign-out" aria-hidden="true"></i></a>
|
||||||
{% else %} <a class="login" href="{% url "gestiojeux_auth:login" %}?next={{ request.get_full_path }}">Connexion</a>
|
{% else %}
|
||||||
|
<a class="login{% if url_name == "login" %} current{% endif %}" href="{% url "gestiojeux_auth:login" %}?next={{ request.get_full_path }}">Connexion</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{# <a class="login" href="">Logout</a> #}
|
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</header>
|
</header>
|
||||||
|
|
Loading…
Reference in a new issue