Début d'implémentation de la partie "connecté" du site

This commit is contained in:
Jean-Marie Favreau 2023-11-01 22:49:39 +01:00
parent 4bb91184ef
commit 9f6b0dc5f0
12 changed files with 220 additions and 30 deletions

View File

@ -40,6 +40,7 @@ INSTALLED_APPS = [
"colorfield",
'django_extensions',
'django_better_admin_arrayfield',
'django_filters',
]
MIDDLEWARE = [
@ -124,6 +125,10 @@ LANGUAGES = (
)
# Auth
LOGIN_REDIRECT_URL = "/"
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/

View File

@ -6,6 +6,11 @@ body {
padding-bottom: 1em;
}
h1 a, h1 a:visited {
text-decoration: none;
color: #000;
}
[role="doc-subtitle"] {
font-size: 140%;
margin-top: -1em;
@ -16,6 +21,12 @@ body {
font-weight: bold;
}
.button {
box-shadow: 0 0 0.2em rgba(0, 0, 0, 0.3);
}
.button:hover {
box-shadow: 0 0 0.2em rgba(0, 0, 0, 0.2);
}
.cat, .mode {
line-height: 2.4em;
@ -34,16 +45,16 @@ span.cat, span.mode {
}
.mode {
background-color: #CCC;
background-color: rgb(230, 235, 235);
}
a.mode:hover {
background-color: #666;
background-color: rgb(133, 136, 136);
color: #FFF;
}
.mode.selected {
background-color: #444;
background-color: rgb(65, 67, 67);
color: #fff;
}
@ -71,7 +82,7 @@ a.mode:hover {
font-size: 80%;
display: inline-block;
padding: 0.1em 0.8em;
border-radius: .4em;
border-radius: .8em;
}
.warning-simple {
@ -79,7 +90,53 @@ a.mode:hover {
}
.warning {
background: #EEE;
background-color: rgb(230, 235, 235);
padding: 1em;
border-radius: 1.5em;
}
}
.rich_button {
text-decoration: none;
display: inline-block;
background-color: rgb(230, 235, 235);
color: #000;
text-align: center;
border-radius: 1em;
line-height: 2em;
overflow: hidden;
}
.rich_button span {
display: inline-block;
height: 2em;
width: 2em;
font-weight: bold;
background-color: #008080;
color: #fff;
border-radius: 1em;
margin-left: 0.2em;
box-shadow: 0 0 0.2em rgba(0, 0, 0, 0.3);
}
.rich_button:hover {
background: rgb(133, 136, 136);
color: #fff;
}
.rich_button:hover span {
background-color: rgb(1, 140, 140);
}
#add_content_header, #edit_content_header {
font-size: 120%;
position: fixed;
top: 4em;
padding-left: 0.8em;
right: 2em;
}
#edit_content_header {
top: 1.5em;
}

View File

@ -1,4 +1,4 @@
{% extends "agenda_culturel/page_events.html" %}
{% extends "agenda_culturel/page-events.html" %}
{% block title %}{{ object.title }}{% endblock %}

View File

@ -1,14 +1,38 @@
{% extends "agenda_culturel/page.html" %}
{% block title %}Accueil{% endblock %}
{% block title %}Tous les événements{% endblock %}
{% block content %}
<h1>Événements</h1>
<ul>
{% for event in object_list %}
<li><a href="{{ BASE_URL }}{{ event.get_absolute_url }}">{{ event.start_day|date }} : {{ event.title }}</a></li>
{% empty %}
<li>Il n'y a pas d'événement.</li>
<h1>Derniers événements soumis</h1>
<section>
<form method="get" class="form django-form">
{% csrf_token %}<br />
{{ filter.form }}<br />
<button type="submit">Filtrer</button><br />
</form>
</section>
{% for obj in paginator_filter %}
{{ obj.title }} <br />
{% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
{% if paginator_filter.has_previous %}
<a href="?page=1">&laquo; premier</a>
<a href="?page={{ paginator_filter.previous_page_number }}">précédent</a>
{% endif %}
<span class="current">
Page {{ paginator_filter.number }} sur {{ paginator_filter.paginator.num_pages }}
</span>
{% if paginator_filter.has_next %}
<a href="?page={{ paginator_filter.next_page_number }}">suivant</a>
<a href="?page={{ paginator_filter.paginator.num_pages }}">dernier &raquo;</a>
{% endif %}
</span>
</div>
{% endblock %}

View File

@ -19,9 +19,9 @@
<span class="mode selected">{{ mode }}</span>
{% else %}
{% if category %}
<a href="{% url 'view_mode_cat' mode.name category.pk %}" class="mode">{{ mode }}</a>
<a href="{% url 'view_mode_cat' mode.name category.pk %}" class="mode button">{{ mode }}</a>
{% else %}
<a href="{% url 'view_mode' mode.name %}" class="mode">{{ mode }}</a>
<a href="{% url 'view_mode' mode.name %}" class="mode button">{{ mode }}</a>
{% endif %}
{% endif %}
{% endfor %}
@ -29,9 +29,9 @@
<div id="categories" class="nav-buttons">
{% for cat in categories %}
{% if category == cat %}
<span class="cat {{ cat.css_class }} selected">{{ cat }} <a href="{% url 'view_mode' selected_mode.name %}" class="close"></a></span>
<span class="cat {{ cat.css_class }} selected button">{{ cat }} <a href="{% url 'view_mode' selected_mode.name %}" class="close"></a></span>
{% else %}
<a href="{% url 'view_mode_cat' selected_mode.name cat.pk %}" class="cat {{ cat.css_class }} {% if category == None %}selected{% endif %}">{{ cat }}</a>
<a href="{% url 'view_mode_cat' selected_mode.name cat.pk %}" class="cat {{ cat.css_class }} {% if category == None %}selected{% endif %} button">{{ cat }}</a>
{% endif %}
{% endfor %}
</div>
@ -48,9 +48,9 @@
{% if events %}
{% for date in dates %}
<h3>{{ date |date:"DATE_FORMAT" }}</h3>
{% with events_date=events|in_date:date %}
{% if events_date %}
<h3>{{ date |date:"l j F"| capfirst }}</h3>
<lu>
{% for event in events_date %}
<li>{% if category %}
@ -58,12 +58,10 @@
{% else %}
{% url 'view_mode_cat' selected_mode.name event.category.pk as url_cat %}
{{ event.category | small_cat:url_cat }}
{% endif %} {{ event.title }}
{% endif %} <a href="{{ event.get_absolute_url }}">{{ event.title }}</a>
</li>
{% endfor %}
</lu>
{% else %}
<p class="warning-simple">Aucun événement ce jour-là.</p>
{% endif %}
{% endwith %}
{% endfor %}

View File

@ -18,17 +18,35 @@
{% block entete_header %}
{% endblock %}
</head>
{% load event_extra %}
<body>
<div id="full_content" class="{% block main_class %}{% endblock %}">
<header>
<h1>Les nuits énigmagmatiques</h1>
<h1><a href="{% url 'home' %}">Les nuits énigmagmatiques</a></h1>
<div role="doc-subtitle">Agenda culturel de Clermont-Ferrand et des environs</div>
<div class="buttons">
{% if user.is_authenticated %}
<a href="{% url 'view_all_events' %}" id="edit_content_header" class="button rich_button">gérer les événements <span class="button">{% nb_draft_events %}</span></a>
{% endif %}
{% block add_content %}
<a href="{% url 'event_submission_form' %}" id="add_content_header" class="button rich_button">ajouter un événement <span class="button">+</span></a>
{% endblock %}
</div>
</header>
<section>
{% block content %}{% endblock %}
</section>
<footer>
<ul>
{% if user.is_authenticated %}
<li><a href="{% url 'admin:index' %}">administration</a></li>
<li><a href="{% url 'logout' %}?next={% url 'home' %}">déconnexion</a></li>
<li>vous êtes connecté(e) en tant que {{ user }}</li>
{% else %}
<li><a href="{% url 'login' %}?next={% url 'view_all_events' %}">connexion</a></li>
{% endif %}
</ul>
</footer>
</div>

View File

@ -0,0 +1,40 @@
{% extends "agenda_culturel/page.html" %}
{% block title %}Connexion{% endblock %}
{% block content %}
<h1>Connexion</h1>
{% if form.errors %}
<p>Vos identifiants sont incorrects. Veuillez réessayer.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Vous n'avez pas l'autorisation d'accéder à cette page.
Pour y accéder, veuillez vous connecter avec un compte autorisé.</p>
{% else %}
<p>Veuillez vous identifier pour consulter cette page.</p>
{% endif %}
{% else %}
<p>Veuillez vous identifier pour consulter cette page.</p>
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}<div style="clear: both"></div></td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td>
<td>{{ form.password }}<div style="clear: both"></div></td>
</tr>
</table>
<input type="submit" value="login" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
{% endblock %}

View File

@ -86,6 +86,6 @@ def css_categories():
@register.filter
def small_cat(category, url=None):
if url is None:
return mark_safe('<span class="small-cat selected ' + category.css_class() + '">' + category.name + "</span>")
return mark_safe('<span class="small-cat selected ' + category.css_class() + ' button">' + category.name + "</span>")
else:
return mark_safe('<a class="small-cat selected ' + category.css_class() + '" href="' + url + '">' + category.name + "</a>")
return mark_safe('<a class="small-cat selected ' + category.css_class() + ' button" href="' + url + '">' + category.name + "</a>")

View File

@ -9,3 +9,7 @@ register = template.Library()
@register.filter
def in_date(event, date):
return event.filter((Q(start_day__lte=date) & Q(end_day__gte=date)) | (Q(end_day=None) & Q(start_day=date)))
@register.simple_tag
def nb_draft_events():
return Event.objects.filter(status=Event.STATUS.DRAFT).count()

View File

@ -3,7 +3,7 @@ from django.conf.urls.static import static
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.urls import path, include, re_path
from django.contrib.auth import views as auth_views
from .views import *
@ -13,11 +13,13 @@ urlpatterns = [
path("", home, name="home"),
re_path(r'^(?P<mode>' + modes + ')/$', view_mode, name='view_mode'),
re_path(r'^(?P<mode>' + modes + ')/(?P<cat_id>\d+)/$', view_mode_cat, name='view_mode_cat'),
path("events/", event_list, name='view_all_events'),
path("event/<int:pk>-<extra>", EventDetailView.as_view(), name="view_event"),
path("proposer", EventSubmissionFormView.as_view(), name="event_submission_form"),
path("a-propos", , name="about"),
path("admin/", admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path("test_app/", include("test_app.urls")),
]
if settings.DEBUG:

View File

@ -12,6 +12,11 @@ from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from django.utils.translation import activate, get_language_info
import django_filters
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib.auth.decorators import login_required
class DisplayMode(StrEnum):
this_week = "this week"
@ -75,7 +80,6 @@ def view_mode_cat(request, mode, cat_id):
return render(request, 'agenda_culturel/page-events.html', context)
class EventDetailView(DetailView):
model = Event
template_name = "agenda_culturel/event.html"
@ -100,3 +104,40 @@ class EventSubmissionFormView(FormView):
def create_event(self, valid_data):
url = valid_data["url"]
create_event_from_submission.delay(url)
class EventFilter(django_filters.FilterSet):
tags = django_filters.CharFilter(lookup_expr='icontains')
o = django_filters.OrderingFilter(
# tuple-mapping retains order
fields=(
('created_date', 'created_date'),
('modified_date', 'modified_date'),
('status', 'status'),
('title', 'title'),
('start_day', 'start_day'),
),
)
class Meta:
model = Event
fields = ['title', 'status', 'category', 'tags']
@login_required(login_url="/accounts/login/")
def event_list(request):
filter = EventFilter(request.GET, queryset=Event.objects.all())
paginator = Paginator(filter.qs, 10)
page = request.GET.get('page')
try:
response = paginator.page(page)
except PageNotAnInteger:
response = paginator.page(1)
except EmptyPage:
response = paginator.page(paginator.num_pages)
return render(request, 'agenda_culturel/list.html', {'filter': filter, 'paginator_filter': response})

View File

@ -28,3 +28,4 @@ cffi==1.16.0
django-extensions==3.2.3
djipsum==1.1.5
django-better-admin-arrayfield==1.4.2
django-filter==23.3