Compare commits

...

55 commits

Author SHA1 Message Date
6c8ddb847b
fix: annuaire -> app 2024-10-21 19:54:27 +02:00
31ee1ba03e
feat: Add nix setup 2024-10-21 19:25:50 +02:00
4d76fa1d6a Delete .pre-commit-config.yaml 2024-10-16 15:49:34 +02:00
2a08c3d251 Move ldap config to secrets 2023-01-31 20:01:42 +01:00
6e893afd90 Update 2023-01-31 14:15:34 +01:00
aa94996155 poetry: Update les dépendances et export vers le format requirements.txt 2023-01-31 13:44:07 +01:00
4d52756763 annuaire/settings: Sépare les paramètres de prod et de développement 2023-01-31 13:43:05 +01:00
a3de7cfc1e Ajoute pre-commit 2023-01-31 13:42:12 +01:00
4606dbe9c2 annuaire/settings: Ajout de DEFAULT_AUTO_FIELD 2023-01-30 21:24:12 +01:00
b0226afa1e annuaire/urls: Ajout de djdt en mode debug 2023-01-30 21:23:52 +01:00
f6e2f8404d manage.py: Formatte avec black 2023-01-30 21:23:16 +01:00
e260671939 Passage à Poetry et ajout de shell.nix 2023-01-30 21:22:59 +01:00
Tom Hubrecht
213ec87059 Merge branch 'thubrecht/recherche' into 'master'
Fixe la recherche dans l'annuaire

See merge request klub-dev-ens/annuaire!27
2023-01-30 11:29:11 +01:00
Tom Hubrecht
be5b47e48d Merge branch 'thubrecht/transfert' into 'master'
Transfert de l'ancien annuaire

See merge request klub-dev-ens/annuaire!26
2023-01-30 11:28:26 +01:00
cacf66de3a Update CSS (Again) 2021-10-12 15:10:55 +02:00
2cc79d11da Update CSS 2021-10-12 11:29:01 +02:00
4e7fe564cf On ne filtre les départements que si on en donne 2021-10-12 11:18:54 +02:00
b3f7e944c3 On corrige la recherche pour filtrer sur les promotions et les départements 2021-10-09 11:52:20 +02:00
ebab4f5cb2 Màj du script de transfert, et correction de l'affichage de certaines infos 2021-10-08 17:58:41 +02:00
b1e591ce2c Update 2021-10-08 09:37:01 +02:00
54e6877998 Utilitaire pour transférer les anciennes fiches 2021-10-08 09:37:01 +02:00
500f7e6155 On rajoute les champs « études passées » et « expériences » 2021-10-08 09:36:59 +02:00
Martin Pepin
ac89359368 Merge branch 'thubrecht/raz' into 'master'
Thubrecht/raz

See merge request klub-dev-ens/annuaire!21
2021-02-23 23:27:29 +01:00
2b9b53bc19 Merge css 2021-02-23 23:20:31 +01:00
Martin Pepin
d21d5e9325 Merge branch 'thubrecht/mobile' into 'master'
Thubrecht/mobile

Closes #23

See merge request klub-dev-ens/annuaire!20
2021-02-23 23:11:25 +01:00
d1046d80d6 Pinaillage 2021-02-23 22:53:51 +01:00
1586b3e185 Entry -> Entrance 2021-02-23 22:39:31 +01:00
939c18f45f On utilise les fonctions déjà présentes 2021-02-23 22:32:52 +01:00
ef0d42a9c7 Update 2021-02-23 22:19:04 +01:00
ea556a1241 Fiche 2021-02-10 21:29:57 +01:00
9cdeca2f40 Pareil pour la page d'accueil encore 2021-02-10 21:22:27 +01:00
735e4609fb Pareil pour la page d'accueil 2021-02-10 21:17:33 +01:00
7d90974bfa Taille du formulaire 2021-02-10 21:14:32 +01:00
67671547bb Modif du css 2021-02-10 21:00:08 +01:00
a00dd80850 Traduction & small css change 2021-02-07 01:27:15 +01:00
30a6220c5e Si on ne peut pas contacter le LDAP on ne plante pas 2021-02-06 17:04:24 +01:00
e2d3fe5fbf Réinitialisation du profil 2021-02-06 12:40:05 +01:00
fcabe88016 On rajoute un menu déroulant 2021-02-06 12:38:20 +01:00
2078790076 Mobile friendly 2021-02-06 12:37:54 +01:00
07e2220b24 Add viewport 2021-02-06 01:39:30 +01:00
87f3515e3c On rajoute un menu déroulant 2021-02-06 01:37:31 +01:00
e0a5b616aa Mobile friendly 2021-02-06 01:36:53 +01:00
Martin Pepin
846a7548d1 Merge branch 'thubrecht/datepicker' into 'master'
Thubrecht/datepicker

Closes #22

See merge request klub-dev-ens/annuaire!18
2021-02-06 00:51:13 +01:00
cf7397476e On réduit la taille de la page de modifs 2021-02-06 00:32:47 +01:00
f5c2fed71f Par défault on a 20ans tout pile 2021-02-06 00:25:38 +01:00
981ace031e On enlève les % pour now 2021-02-06 00:17:23 +01:00
7f3dbd8ec8 JS pour le datepicker 2021-02-06 00:08:34 +01:00
c8f4686388 CSS pour le datepicker 2021-02-06 00:07:54 +01:00
7001751817 On déplace la date de naissance 2021-02-06 00:05:43 +01:00
be324dfcf6 On désactive la localisation qui casse tout 2021-02-06 00:05:43 +01:00
a1c7822a74 Rajoute un datepicker 2021-02-06 00:05:43 +01:00
Martin Pepin
3b5b670a0c Merge branch 'thubrecht/connexion' into 'master'
Thubrecht/connexion

See merge request klub-dev-ens/annuaire!17
2021-02-06 00:03:50 +01:00
05bced9a5b Supprime fichier en trop 2021-02-04 23:51:11 +01:00
c8a6f0eaeb On demande le login uniquement en POST, ce qui permet d'accéder à la page d'accueil sans être connecté 2021-02-04 23:50:07 +01:00
de57c09ed0 On rajoute les champs « études passées » et « expériences » 2021-02-04 23:50:03 +01:00
47 changed files with 3708 additions and 412 deletions

5
.credentials/ANNUAIRE Normal file
View file

@ -0,0 +1,5 @@
{
"PROTOCOL": "http",
"URL": "annuaire.example.com",
"PORT": 80
}

12
.credentials/LDAP Normal file
View file

@ -0,0 +1,12 @@
{
"SPI": {
"PROTOCOL": "ldaps",
"URL": "ldap.example.com",
"PORT": 636
},
"CRI": {
"PROTOCOL": "ldap",
"URL": "ldap.example.com",
"PORT": 636
}
}

1
.credentials/SECRET_KEY Normal file
View file

@ -0,0 +1 @@
insecure-key

1
.envrc Normal file
View file

@ -0,0 +1 @@
use nix

4
.gitignore vendored
View file

@ -9,10 +9,12 @@
/venv/
.vagrant/
static/
/static/
*.sqlite3
fiches/templates/fiches/base_old.html
fiches/static/fiches/css_old/
.vscode
.direnv
annuaire/settings/secret.py

View file

@ -1,165 +0,0 @@
"""
Django settings for annuaire project.
Generated by 'django-admin startproject' using Django 2.2b1.
For more information on this file, see
https://docs.djangoproject.com/en/dev/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/dev/ref/settings/
"""
import os
from django.urls import reverse_lazy
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "84=n(@@wl(04oc$(-+3surgrlf&uq3=m)=(hpg$immi1h69s)p"
# À bouger dans un ficher secret quand il sera créé ?
LDAP = {
"SPI": {
"PROTOCOL": "ldaps",
"URL": "ldap.spi.ens.fr",
"PORT": 636,
},
"CRI": {
"PROTOCOL": "ldap",
"URL": "annuaire.ens.fr",
"PORT": 389,
},
}
ANNUAIRE = {
"PROTOCOL": "http",
"URL": "annuaireweb.ens.fr",
"PORT": 80,
}
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"authens",
"fiches",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "annuaire.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"fiches.backends.BackendFiches",
)
WSGI_APPLICATION = "annuaire.wsgi.application"
# Database
# https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
}
# Password validation
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
# Internationalization
# https://docs.djangoproject.com/en/dev/topics/i18n/
LANGUAGE_CODE = "fr-fr"
LANGUAGES = [
("fr", "Français"),
("en", "English"),
]
LOCALE_PATHS = [os.path.join(BASE_DIR, "locale")]
TIME_ZONE = "UTC"
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/dev/howto/static-files/
STATIC_URL = "/static/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"
LOGIN_URL = reverse_lazy("authens:login")
LOGOUT_REDIRECT_URL = reverse_lazy("home")
AUTHENS_USE_OLDCAS = False
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"

183
app/settings.py Normal file
View file

@ -0,0 +1,183 @@
"""
Django settings for the annuaire project
"""
import os
from pathlib import Path
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _
from loadcredential import Credentials
credentials = Credentials(env_prefix="ANNUAIRE_")
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# WARNING: keep the secret key used in production secret!
SECRET_KEY = credentials["SECRET_KEY"]
# WARNING: don't run with debug turned on in production!
DEBUG = credentials.get_json("DEBUG", False)
ALLOWED_HOSTS = credentials.get_json("ALLOWED_HOSTS", [])
ADMINS = credentials.get_json("ADMINS", [])
###
# List the installed applications
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"authens",
"fiches",
]
###
# List the installed middlewares
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
###
# The main url configuration
ROOT_URLCONF = "app.urls"
###
# Template configuration:
# - Django Templating Language is used
# - Application directories can be used
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
###
# Database configuration
# -> https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
DATABASES = credentials.get_json(
"DATABASES",
{
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
},
)
CACHES = credentials.get_json(
"CACHES",
default={
"default": {
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
},
},
)
###
# WSGI application configuration
WSGI_APPLICATION = "app.wsgi.application"
###
# Staticfiles configuration
STATIC_ROOT = credentials["STATIC_ROOT"]
STATIC_URL = "/static/"
MEDIA_ROOT = credentials.get("MEDIA_ROOT", BASE_DIR / "media")
MEDIA_URL = "/media/"
###
# Internationalization configuration
# -> https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = "fr-fr"
TIME_ZONE = "Europe/Paris"
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = [
("fr", _("Français")),
("en", _("Anglais")),
]
LOCALE_PATHS = [BASE_DIR / "locale"]
###
# Authentication configuration
AUTHENS_USE_OLDCAS = False
AUTHENS_USE_PASSWORD = False
LOGIN_URL = reverse_lazy("authens:login")
LOGOUT_REDIRECT_URL = reverse_lazy("home")
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"fiches.backends.BackendFiches",
)
AUTH_PASSWORD_VALIDATORS = map(
lambda v: {"NAME": f"django.contrib.auth.password_validation.{v}"},
[
"UserAttributeSimilarityValidator",
"MinimumLengthValidator",
"CommonPasswordValidator",
"NumericPasswordValidator",
],
)
LDAP = credentials.get_json("LDAP")
ANNUAIRE = credentials.get_json("ANNUAIRE")
# FIXME: Add correct email settings
# Development settings
if DEBUG:
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
AUTH_PASSWORD_VALIDATORS = []
PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"]
LOGIN_URL = reverse_lazy("authens:login")
AUTHENS_USE_PASSWORD = True

View file

@ -14,10 +14,9 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.conf import settings
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from fiches.views import BirthdayView, HomeView
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("", include("fiches.urls")),
@ -26,5 +25,9 @@ urlpatterns = [
path("i18n/", include("django.conf.urls.i18n")),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
if settings.DEBUG and "debug_toolbar" in settings.INSTALLED_APPS:
from debug_toolbar import urls as debug_urls
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + [
path("__debug__/", include(debug_urls))
]

View file

@ -11,6 +11,6 @@ import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'annuaire.settings')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')
application = get_wsgi_application()

45
default.nix Normal file
View file

@ -0,0 +1,45 @@
{
sources ? import ./npins,
pkgs ? import sources.nixpkgs { },
}:
let
nix-pkgs = import sources.nix-pkgs { inherit pkgs; };
python3 = pkgs.python3.override {
packageOverrides = _: _: {
inherit (nix-pkgs) authens loadcredential;
};
};
in
{
devShell = pkgs.mkShell {
name = "annuaire.dev";
packages = [
(python3.withPackages (ps: [
ps.django
ps.pillow
ps.loadcredential
ps.authens
ps.python-dateutil
]))
];
env = {
DJANGO_SETTINGS_MODULE = "app.settings";
CREDENTIALS_DIRECTORY = builtins.toString ./.credentials;
ANNUAIRE_DEBUG = builtins.toJSON true;
ANNUAIRE_STATIC_ROOT = builtins.toString ./.static;
};
shellHook = ''
if [ ! -d .static ]; then
mkdir .static
fi
'';
};
}

View file

@ -6,6 +6,11 @@ from fiches.models import Address, Department, Mail, Phone, Profile, Social
class ProfileForm(forms.ModelForm):
birth_date = forms.DateField(
input_formats=["%Y-%m-%d"],
required=False,
)
class Meta:
model = Profile
exclude = ["user"]
@ -28,10 +33,10 @@ class SearchForm(forms.Form):
raise forms.ValidationError(_("Tous les champs sont vides"), code="invalid")
PhoneFormSet = inlineformset_factory(Profile, Phone, exclude=[])
PhoneFormSet = inlineformset_factory(Profile, Phone, exclude=[], extra=0)
SocialFormSet = inlineformset_factory(Profile, Social, exclude=[])
SocialFormSet = inlineformset_factory(Profile, Social, exclude=[], extra=0)
MailFormSet = inlineformset_factory(Profile, Mail, exclude=[])
MailFormSet = inlineformset_factory(Profile, Mail, exclude=[], extra=0)
AddressFormSet = inlineformset_factory(Profile, Address, exclude=[])
AddressFormSet = inlineformset_factory(Profile, Address, exclude=[], extra=0)

View file

@ -13,7 +13,7 @@ from ._ldap import AnnuaireLDAP
class Command(BaseCommand):
help = "Si possible, import les photos des conscrit·e·s dans l'annuaire."
help = "Si possible, importe les photos des conscrit·e·s dans l'annuaire."
def add_arguments(self, parser):
group = parser.add_mutually_exclusive_group()

View file

@ -1,3 +1,7 @@
from datetime import date
from typing import Optional
from dateutil.relativedelta import relativedelta
from django.contrib.auth.models import User
from django.core.validators import MinValueValidator
from django.db import models
@ -37,10 +41,18 @@ class Profile(models.Model):
default=False, verbose_name=_("conserver la fiche annuaire ?")
)
def __str__(self):
def __str__(self) -> str:
return self.full_name
def birthday(self):
@property
def age(self) -> Optional[int]:
if self.birth_date is not None:
return relativedelta(date.today(), self.birth_date).year
def birthday(self) -> str:
if self.birth_date is None:
return "Unknown"
return self.birth_date.strftime("%d%m")
@ -49,7 +61,7 @@ class Department(models.Model):
max_length=255, verbose_name=_("nom du département"), unique=True
)
def __str__(self):
def __str__(self) -> str:
return self.name
@ -60,7 +72,7 @@ class Phone(models.Model):
name = models.CharField(max_length=255, verbose_name=_("type"))
number = models.CharField(max_length=1023, verbose_name=_("numéro"))
def __str__(self):
def __str__(self) -> str:
return "{} : {}".format(self.name, self.number)
@ -82,7 +94,7 @@ class Mail(models.Model):
name = models.CharField(max_length=255, verbose_name=_("type"))
mail = models.CharField(max_length=1023, verbose_name=_("adresse mail"))
def __str__(self):
def __str__(self) -> str:
return "{} : {}".format(self.name, self.mail)
@ -93,5 +105,5 @@ class Address(models.Model):
name = models.CharField(max_length=255, verbose_name=_("type"))
content = models.TextField(verbose_name=_("adresse"))
def __str__(self):
def __str__(self) -> str:
return "{} : {}".format(self.name, self.content)

View file

@ -28,73 +28,38 @@
font-weight: 400;
src: local("Source Code Pro Regular"), local("SourceCodePro-Regular"), url("../fonts/source-code-pro/source-code-pro-v12-latin-regular.woff2") format("woff2"), url("../fonts/source-code-pro/source-code-pro-v12-latin-regular.woff") format("woff");
}
#main-menu a a, #account-area a, a {
a, #main-menu a a, #account-area a {
text-decoration: none;
color: #FFDC00;
}
#main-menu a a:hover, #account-area a:hover, a:hover,
a:hover, #main-menu a a:hover, #account-area a:hover,
a:active,
#main-menu a a:active,
#account-area a:active,
a:active,
a:focus,
#main-menu a a:focus,
#account-area a:focus,
a:focus {
#account-area a:focus {
color: #ffbb00;
}
* {
box-sizing: border-box;
}
body, html {
height: 100%;
}
body {
display: grid;
grid-template-columns: auto auto;
grid-template-areas: "aside main";
background-color: #301827;
color: #FFFFFF;
font-family: "Fira Sans", "Roboto", sans-serif;
}
#aside {
grid-area: aside;
padding: 0 0 0 10vw;
background-color: #1f0e19;
box-shadow: 4px 0 0 rgba(31, 14, 25, 0.3);
z-index: 1000;
}
#main {
grid-area: main;
padding: 0 10vw 0 0;
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: #301827;
z-index: 500;
}
@media only screen and (max-width: 1200px) {
#header {
margin: 0;
}
#main {
margin: 0;
}
}
#menu {
display: grid;
float: right;
width: 320px;
grid-template-columns: auto;
grid-template-rows: auto auto auto auto 120px;
grid-template-rows: auto auto auto auto auto 15px;
grid-template-areas: "title" "language" "search" "menu" "account";
}
#menu #hamburger {
display: none;
grid-area: hamburger;
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9TS1VaHOwg4pChOlkoKuKoVShChVIrtOpgcukXNGlIUlwcBdeCgx+LVQcXZ10dXAVB8APEzc1J0UVK/F9SaBHjwXE/3t173L0DhGaVqWZPHFA1y8gkE2IuvyoGXyEggD6EEZeYqc+l0yl4jq97+Ph6F+NZ3uf+HGGlYDLAJxLPMt2wiDeIpzctnfM+cYSVJYX4nHjcoAsSP3JddvmNc8lhgWdGjGxmnjhCLJa6WO5iVjZU4iniqKJqlC/kXFY4b3FWq3XWvid/YaigrSxzneYIkljEEtIQIaOOCqqwEKNVI8VEhvYTHv5hx58ml0yuChg5FlCDCsnxg//B727N4uSEmxRKAIEX2/4YBYK7QKth29/Htt06AfzPwJXW8deawMwn6Y2OFj0CBraBi+uOJu8BlzvA0JMuGZIj+WkKxSLwfkbflAcGb4H+Nbe39j5OH4AsdZW6AQ4OgbESZa97vLu3u7d/z7T7+wEsq3KLN3ZkxAAAAAlwSFlzAAAA7AAAAOwBeShxvQAAADNJREFUWMPt1EERAEAIA7Ee/h0hjpPBg0RBp49NrnvTmc0Btf2AARVAipVQikGKpdgArvsZZAhH7c55ywAAAABJRU5ErkJggg==");
height: 30px;
width: 30px;
float: right;
margin-top: 20px;
}
#title {
grid-area: title;
@ -136,6 +101,7 @@ body {
background-position: center;
border: none;
transition: 25ms ease-in-out;
cursor: pointer;
}
#search-area button:hover {
background-color: #FFDC00;
@ -205,7 +171,7 @@ body {
#account-area {
grid-area: account;
display: block;
padding: 20px;
padding-top: 20px;
text-align: center;
}
#account-area .clipper {
@ -222,6 +188,7 @@ body {
color: #FFFFFF;
box-shadow: 2px 2px 0 rgba(31, 14, 25, 0.3);
transition: 25ms ease-in-out;
cursor: pointer;
}
.content button:hover,
@ -262,7 +229,7 @@ body {
.content {
max-width: 780px;
width: 50vw;
width: 70vw;
margin: 20px;
}
.content h2 {
@ -279,10 +246,10 @@ body {
}
#content-home form {
display: grid;
width: 400px;
width: min(400px, 100%);
margin: 0 auto;
grid-template-columns: 150px 250px;
gap: 20px;
grid-template-columns: 30% 65%;
gap: 5%;
}
#content-home form label {
grid-column: 1;
@ -308,7 +275,7 @@ body {
#content-view-profile {
display: grid;
grid-template-rows: 150px auto auto;
grid-template-rows: min(150px, 45%) auto auto;
grid-template-columns: 3fr 1fr;
grid-template-areas: "header header" "infos infos" "free-text free-text";
gap: 20px;
@ -398,7 +365,7 @@ body {
}
#content-edit-profile form {
width: 400px;
width: max(600px, 80%);
margin: 0 auto;
}
#content-edit-profile form .form-entry {
@ -504,6 +471,7 @@ body {
}
#content-edit-profile #free-text-edit-form textarea {
width: 100%;
height: 100px;
padding: 5px;
resize: none;
}
@ -545,4 +513,102 @@ body {
text-align: center;
}
* {
box-sizing: border-box;
}
body, html {
height: 100%;
}
body {
display: grid;
grid-template-areas: "aside main";
background-color: #301827;
color: #FFFFFF;
font-family: "Fira Sans", "Roboto", sans-serif;
overflow-y: scroll;
border: none;
}
#aside {
grid-area: aside;
padding: 0 0 0 10vw;
background-color: #1f0e19;
box-shadow: 4px 0 0 rgba(31, 14, 25, 0.3);
z-index: 10;
}
#main {
grid-area: main;
padding: 0 10vw 0 0;
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: #301827;
z-index: 5;
}
@media screen and (max-width: 900px) {
body {
grid-template-rows: max-content auto;
grid-template-areas: "aside" "main";
}
h1 {
font-size: 1.5em;
}
#aside,
#main {
padding: 0;
box-shadow: unset;
width: 100vw;
}
#content-home,
#content-birthdays,
#content-view-profile,
#content-edit-profile {
width: auto;
}
#content-home form input[type=submit] {
grid-column: 1/3;
}
#title {
font-size: 1.75rem;
}
.content h2 {
font-size: 1.5rem;
}
#footer,
.content {
max-width: 100%;
}
#menu {
width: auto;
float: none;
grid-template-columns: auto 50px;
grid-template-areas: "title hamburger" "language language" "search search" "menu menu" "account account";
}
#menu #hamburger {
display: grid;
}
#menu #main-menu,
#menu #account-area {
display: none;
}
#search-area {
justify-content: center;
margin: auto;
width: 80%;
}
}
/*# sourceMappingURL=annuaire.css.map */

View file

@ -0,0 +1 @@
{"version":3,"sourceRoot":"","sources":["../scss/_fonts.scss","../scss/_links.scss","../scss/_colors.scss","../scss/_header.scss","../scss/_buttons.scss","../scss/_errors.scss","../scss/_content.scss","../scss/_footer.scss","../scss/_common.scss"],"names":[],"mappings":";AASA;AACA;EACI;EACA;EACA;EACA;;AAKJ;AACA;EACI;EACA;EACA;EACA;;AAKJ;AACA;EACI;EACA;EACA;EACA;;AAUJ;AAUA;AACA;EACI;EACA;EACA;EACA;;ACzDJ;EACI;EACA,OCOQ;;;ADJZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGI,OCEc;;;ACJlB;EACI;EACA;EACA;EAEA;EACA;EACA,qBACI;;AAMJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIN;EACI;EAGA;EACA;EACA;EACA;;AAIA;EACI;;;AAIR;EACI;EACA;EACA;EACA,QAhDgB;EAiDhB;EACA;;AAGA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI,kBDzEI;;;AC6EZ;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EAEA,OD5Fc;;AC+FlB;EACI,OD7FI;EC8FJ;;AAGJ;AAAA;EAEI;EACA;EACA;EACA,ODzGc;;AC4GlB;EACI;;AAGJ;EACI;;;AAKJ;EAEI;EACA;EACA;EACA;EAEA,OD1HI;EC2HJ;;AAGJ;EAEI,OD/HU;;;ACmIlB;EAEI;EAEA;EACA,ODjIa;ECkIb;;AAEA;EAEI;EACA;EACA;EACA;EAEA,ODnJI;ECoJJ;;AAGJ;EAEI,ODxJU;;;AC4JlB;EACI;EACA;EACA;EACA;;AAIA;EACI,aH7GU;;;AIlElB;AAAA;AAAA;EACI;EACA,kBFUqB;EETrB;EACA;EACA,OFSe;EERf;EACA;EACA;;;AAGJ;AAAA;AAAA;EACI,kBFC2B;;;AGf/B;EACI;EACA;;;AAGJ;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;;;ACrBR;EACI,OJqBW;;;AIlBf;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAWJ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAMJ;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAIA;EACI;;;AAYhB;EACI;EACA;EACA;EACA,qBACI;EAGJ;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;;AAEA;EACI;EACA,OJnGU;EIoGV;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA;;AAGJ;EACI;EAEA;EACA,OJpHS;EIqHT;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA,kBJtHe;EIuHf;;AAEA;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA,OJvJF;EIwJE;EACA;;AAGJ;EACI;EACA;EACA;;AAGJ;EACE;;AASlB;EACI;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;;;AAMR;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA,kBJpLe;EIqLf;;AAEA;EACI;;AAGJ;EACI;EACA,OJ7MC;EI8MD;EACA;EACA;;AAGJ;EACI;;AAGJ;EAGI;EACA;;AAIR;EACI;EACA;EACA;EACA,qBACI;EAEJ;EACA;EACA;;AAEA;EACI;;AAMJ;EACI;EACA;;AAEJ;EAAqB;;AACrB;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;AAAA;EAEI;;AAGJ;EACI;;AAUA;EAAqB;;AACrB;EAAqB;;AAGrB;AAAA;EAEI;;AAIR;EAEI;;AAIR;EACI;;AAGJ;EACI;;AAIA;EACI;EACA;;AAIR;EACI;EACA;;AAIA;EACI;;AAGJ;EACI;EACA;EACA;;AAMR;EACI;EACA;EACA;EACA;;AAKJ;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;;AAKJ;EACI;;AAGJ;EACI;;AAGJ;EACI;EACA,OJ3WC;EI4WD;;AASJ;EACI;;;AC7XhB;EACI;EACA;EACA,OLGkB;EKFlB;;AAEA;EACI;EACA;;;ACNR;EACI;;;AAMJ;EACI;;;AAGJ;EACI;EACA,qBACI;EAEJ,kBNnBc;EMoBd,ONdQ;EMeR,aR6CY;EQ5CZ;EACA;;;AAGJ;EACI;EACA;EACA,kBN5Be;EM6Bf;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA,kBNxCc;EMyCd;;;AAIJ;EACE;IACE;IACA,qBACI;;;EAIN;IACE;;;EAGF;AAAA;IAEE;IACA;IACA;;;EAGF;AAAA;AAAA;AAAA;IAIE;;;EAKE;IACE;;;EAKN;IACE;;;EAIA;IACE;;;EAIJ;AAAA;IAEE;;;EAGF;IACE;IACA;IACA;IACA,qBACE;;EAMF;IACE;;EAGF;AAAA;IAEE;;;EAIJ;IACE;IACA;IACA","file":"annuaire.css"}

View file

@ -0,0 +1,258 @@
/*
MIT License
Copyright (c) 2019 Hidenao Miyamoto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
.datepicker {
display: none;
}
.datepicker.active {
display: block;
}
.datepicker-dropdown {
position: absolute;
top: 0;
left: 0;
z-index: 20;
padding-top: 4px;
}
.datepicker-dropdown.datepicker-orient-top {
padding-top: 0;
padding-bottom: 4px;
}
.datepicker-picker {
display: inline-block;
border-radius: 0px;
background-color: #301827;
}
.datepicker-dropdown .datepicker-picker {
box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
}
.datepicker-picker span {
display: block;
flex: 1;
border: 0;
border-radius: 0px;
cursor: default;
text-align: center;
-webkit-touch-callout: none;
user-select: none;
}
.datepicker-main {
padding: 2px;
}
.datepicker-footer {
box-shadow: inset 0 1px 1px rgba(10, 10, 10, 0.1);
background-color: whitesmoke;
}
.datepicker-grid, .datepicker-view .days-of-week, .datepicker-view, .datepicker-controls {
display: flex;
}
.datepicker-grid {
flex-wrap: wrap;
}
.datepicker-view .days .datepicker-cell, .datepicker-view .dow {
flex-basis: 14.2857142857%;
}
.datepicker-view.datepicker-grid .datepicker-cell {
flex-basis: 25%;
}
.datepicker-cell, .datepicker-view .week {
height: 2.25rem;
line-height: 2.25rem;
}
.datepicker-title {
box-shadow: inset 0 -1px 1px rgba(10, 10, 10, 0.1);
background-color: #1f0e19;
padding: 0.375rem 0.75rem;
text-align: center;
font-weight: 700;
}
.datepicker-header .datepicker-controls {
padding: 2px 2px 0;
}
.datepicker-controls .button {
display: inline-flex;
position: relative;
align-items: center;
justify-content: center;
margin: 0;
border: 1px solid #dbdbdb;
border-radius: 0px;
box-shadow: none;
background-color: white;
cursor: pointer;
padding: calc(0.375em - 1px) 0.75em;
height: 2.25em;
vertical-align: top;
text-align: center;
line-height: 1.5;
white-space: nowrap;
color: #363636;
font-size: 1rem;
}
.datepicker-controls .button:focus, .datepicker-controls .button:active {
outline: none;
}
.datepicker-controls .button:hover {
border-color: #b5b5b5;
color: #363636;
}
.datepicker-controls .button:focus {
border-color: #3273dc;
color: #363636;
}
.datepicker-controls .button:focus:not(:active) {
box-shadow: 0 0 0 0.125em rgba(50, 115, 220, 0.25);
}
.datepicker-controls .button:active {
border-color: #4a4a4a;
color: #363636;
}
.datepicker-controls .button[disabled] {
cursor: not-allowed;
}
.datepicker-header .datepicker-controls .button {
border-color: transparent;
font-weight: bold;
}
.datepicker-header .datepicker-controls .button:hover {
background-color: #f9f9f9;
}
.datepicker-header .datepicker-controls .button:focus:not(:active) {
box-shadow: 0 0 0 0.125em rgba(255, 255, 255, 0.25);
}
.datepicker-header .datepicker-controls .button:active {
background-color: #f2f2f2;
}
.datepicker-header .datepicker-controls .button[disabled] {
box-shadow: none;
}
.datepicker-footer .datepicker-controls .button {
margin: calc(0.375rem - 1px) 0.375rem;
border-radius: 0px;
width: 100%;
font-size: 0.75rem;
}
.datepicker-controls .view-switch {
flex: auto;
}
.datepicker-controls .prev-btn,
.datepicker-controls .next-btn {
padding-right: 0.375rem;
padding-left: 0.375rem;
width: 2.25rem;
}
.datepicker-controls .prev-btn.disabled,
.datepicker-controls .next-btn.disabled {
visibility: hidden;
}
.datepicker-view .dow {
height: 1.5rem;
line-height: 1.5rem;
font-size: 0.875rem;
font-weight: 700;
}
.datepicker-view .week {
width: 2.25rem;
color: #b5b5b5;
font-size: 0.75rem;
}
@media (max-width: 22.5rem) {
.datepicker-view .week {
width: 1.96875rem;
}
}
.datepicker-grid {
width: 15.75rem;
}
@media (max-width: 22.5rem) {
.calendar-weeks + .days .datepicker-grid {
width: 13.78125rem;
}
}
.datepicker-cell:not(.disabled):hover {
background-color: #281420;
cursor: pointer;
}
.datepicker-cell.focused:not(.selected) {
background-color: #1f1019;
}
.datepicker-cell.selected, .datepicker-cell.selected:hover {
background-color: #3b1e31;
color: #ffdc00;
font-weight: 600;
}
.datepicker-cell.disabled {
color: #dbdbdb;
}
.datepicker-cell.prev:not(.disabled), .datepicker-cell.next:not(.disabled) {
color: #7a7a7a;
}
.datepicker-cell.prev.selected, .datepicker-cell.next.selected {
color: #ccb000;
}
.datepicker-cell.highlighted:not(.selected):not(.today) {
border-radius: 0;
background-color: #3b1e31;
}
.datepicker-cell.highlighted:not(.selected):not(.today):not(.disabled):hover {
background-color: #331a2a;
}
.datepicker-cell.highlighted:not(.selected):not(.today).focused {
background-color: #1f1019;
}
.datepicker-cell.today:not(.selected) {
background-color: #3b1e31;
}
.datepicker-cell.today:not(.selected):not(.disabled) {
color: #fff;
}
.datepicker-cell.today.focused:not(.selected) {
background-color: #331a2a;
}
.datepicker-view.datepicker-grid .datepicker-cell {
height: 4.5rem;
line-height: 4.5rem;
}
.datepicker-input.in-edit {
border-color: #2366d1;
}
.datepicker-input.in-edit:focus, .datepicker-input.in-edit:active {
box-shadow: 0 0 0.25em 0.25em rgba(35, 102, 209, 0.2);
}
/*# sourceMappingURL=datepicker.css.map */

View file

@ -0,0 +1 @@
{"version":3,"sourceRoot":"","sources":["../scss/datepicker.scss"],"names":[],"mappings":"AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0FA;EACE;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;EACA,SAvDc;EAwDd,aA1DmB;;AA4DnB;EACE;EACA,gBA9DiB;;;AAkErB;EACE;EACA,eA3EiB;EA4EjB,kBA9EoB;;AAgFpB;EACE,YAvEiB;;AA0EnB;EACE;EACA;EACA;EACA,eAtFe;EAuFf;EACA;EACA;EACA;;;AAIJ;EACE;;;AAGF;EACE;EACA,kBA/GM;;;AAkHR;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE,QA3GkB;EA4GlB,aA5GkB;;;AA+GpB;EACE;EACA,kBAnH0B;EAoH1B;EACA;EACA,aA3HoB;;;AAiIpB;EACE;;AAMA;EAqBE;EACA;EACA;EACA;EACA;EACA;EACA,eAzKa;EA0Kb;EACA,kBAvLE;EAwLF;EACA;EACA;EACA;EACA;EACA,aA/KgB;EAgLhB;EACA,OA7LC;EA8LD,WAjLgB;;AAmLhB;EAEE;;AAGF;EACE,cAlMK;EAmML,OAvMD;;AA0MD;EACE,cA1MD;EA2MC,OA5MD;;AA8MC;EACE;;AAIJ;EACE,cAjNI;EAkNJ,OArND;;AAwND;EACE;;AAGF;EA1KJ;EACA;;AA4KM;EACE;;AAIA;EACE;;AAIJ;EACE;;AAGF;EACE;;AAIJ;EA3LJ;EACA,eA7CuB;EA8CvB;EACA,WA5CmB;;AA0OnB;EACE;;AAGF;AAAA;EAEE;EACA;EACA,OAzOgB;;AA2OhB;AAAA;EACE;;;AAYJ;EAEE;EACA;EACA;EACA,aApQkB;;AAuQpB;EAEE,OAlQgB;EAmQhB,OAtRS;EAuRT,WA7QiB;;AA+QjB;EANF;IAOI,OAhPmB;;;;AAqPzB;EAIE;;AAEA;EACE;IACE;;;;AAQJ;EACE;EACA;;AAGF;EACE,kBAjS6B;;AAqS7B;EAEE,kBApS8B;EAqS9B,OApSmB;EAqSnB,aApSyB;;AAwS7B;EACE,OAjUW;;AAsUX;EACE,OAnTmB;;AAsTrB;EACE;;AAIJ;EACE;EACA,kBAtTmC;;AAwTnC;EACE;;AAGF;EACE,kBArU2B;;AA0U7B;EACE,kBArU2B;;AAuU3B;EACE,OAvUc;;AA2UlB;EACE;;AAQJ;EAEE;EACA;;;AAIJ;EACE,cAlV8B;;AAoV9B;EAEE","file":"datepicker.css"}

File diff suppressed because one or more lines are too long

View file

@ -8,6 +8,7 @@
color: colors.$page-button-text;
box-shadow: 2px 2px 0 colors.$shadow;
transition: 25ms ease-in-out;
cursor: pointer;
}
%button:hover {

View file

@ -15,13 +15,14 @@ body, html {
body {
display: grid;
grid-template-columns: auto auto;
grid-template-areas:
"aside main";
background-color: colors.$page-background;
color: colors.$page-text;
font-family: fonts.$regular-fonts;
overflow-y: scroll;
border:none;
}
#aside {
@ -29,7 +30,7 @@ body {
padding: 0 0 0 10vw;
background-color: colors.$aside-background;
box-shadow: 4px 0 0 colors.$shadow;
z-index: 1000;
z-index: 10;
}
#main {
@ -39,16 +40,84 @@ body {
flex-direction: column;
justify-content: space-between;
background-color: colors.$main-background;
z-index: 500;
z-index: 5;
}
@media only screen and (max-width: 1200px) {
#header {
margin: 0;
// Pour les vues mobile
@media screen and (max-width: 900px) {
body {
grid-template-rows: max-content auto;
grid-template-areas:
"aside"
"main";
}
h1 {
font-size: 1.5em;
}
#aside,
#main {
margin: 0;
padding: 0;
box-shadow: unset;
width: 100vw;
}
}
#content-home,
#content-birthdays,
#content-view-profile,
#content-edit-profile {
width: auto;
}
#content-home {
form {
input[type="submit"] {
grid-column: 1/3;
}
}
}
#title {
font-size: 1.75rem;
}
.content {
h2 {
font-size: 1.5rem;
}
}
#footer,
.content {
max-width: 100%;
}
#menu {
width: auto;
float: none;
grid-template-columns: auto 50px;
grid-template-areas:
"title hamburger"
"language language"
"search search"
"menu menu"
"account account";
#hamburger {
display: grid;
}
#main-menu,
#account-area {
display: none;
}
}
#search-area {
justify-content: center;
margin: auto;
width: 80%;
}
}

View file

@ -8,7 +8,7 @@
.content {
max-width: 780px;
width: 50vw;
width: 70vw;
margin: 20px;
h2 {
@ -35,10 +35,10 @@
#content-home {
form {
display: grid;
width: 400px;
width: min(400px, 100%);
margin: 0 auto;
grid-template-columns: 150px 250px;
gap: 20px;
grid-template-columns: 30% 65%;
gap: 5%;
label {
grid-column: 1;
@ -82,7 +82,7 @@
#content-view-profile {
display: grid;
grid-template-rows: 150px auto auto;
grid-template-rows: min(150px, 45%) auto auto;
grid-template-columns: 3fr 1fr;
grid-template-areas:
"header header"
@ -195,7 +195,7 @@
#content-edit-profile {
form {
width: 400px;
width: max(600px, 80%);
margin: 0 auto;
.form-entry {
@ -338,6 +338,7 @@
#free-text-edit-form {
textarea {
width: 100%;
height: 100px;
padding: 5px;
resize: none;
}

View file

@ -12,13 +12,23 @@ $account-area-height: 120px;
width: 320px;
// height: 100%;
grid-template-columns: auto;
grid-template-rows: auto auto auto auto $account-area-height;
grid-template-rows: auto auto auto auto auto 15px;
grid-template-areas:
"title"
"language"
"search"
"menu"
"account";
#hamburger {
display: none;
grid-area: hamburger;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kT1Iw0AcxV9TS1VaHOwg4pChOlkoKuKoVShChVIrtOpgcukXNGlIUlwcBdeCgx+LVQcXZ10dXAVB8APEzc1J0UVK/F9SaBHjwXE/3t173L0DhGaVqWZPHFA1y8gkE2IuvyoGXyEggD6EEZeYqc+l0yl4jq97+Ph6F+NZ3uf+HGGlYDLAJxLPMt2wiDeIpzctnfM+cYSVJYX4nHjcoAsSP3JddvmNc8lhgWdGjGxmnjhCLJa6WO5iVjZU4iniqKJqlC/kXFY4b3FWq3XWvid/YaigrSxzneYIkljEEtIQIaOOCqqwEKNVI8VEhvYTHv5hx58ml0yuChg5FlCDCsnxg//B727N4uSEmxRKAIEX2/4YBYK7QKth29/Htt06AfzPwJXW8deawMwn6Y2OFj0CBraBi+uOJu8BlzvA0JMuGZIj+WkKxSLwfkbflAcGb4H+Nbe39j5OH4AsdZW6AQ4OgbESZa97vLu3u7d/z7T7+wEsq3KLN3ZkxAAAAAlwSFlzAAAA7AAAAOwBeShxvQAAADNJREFUWMPt1EERAEAIA7Ee/h0hjpPBg0RBp49NrnvTmc0Btf2AARVAipVQikGKpdgArvsZZAhH7c55ywAAAABJRU5ErkJggg==');
height: 30px;
width: 30px;
float: right;
margin-top: 20px;
}
}
#title {
@ -68,6 +78,7 @@ $account-area-height: 120px;
background-position: center;
border: none;
transition: 25ms ease-in-out;
cursor: pointer;
}
button:hover {
@ -158,7 +169,7 @@ $account-area-height: 120px;
#account-area {
grid-area: account;
display: block;
padding: 20px;
padding-top: 20px;
text-align: center;
@extend %menu-link;

View file

@ -1,4 +1,4 @@
@use "common";
@use "header";
@use "content";
@use "footer";
@use "common";

View file

@ -0,0 +1,414 @@
/*
MIT License
Copyright (c) 2019 Hidenao Miyamoto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
//== foundational variables ==//
$black: hsl(0, 0%, 4%) !default;
$white: hsl(0, 0%, 100%) !default;
$light: hsl(0, 0%, 96%) !default; // white-ter
$dark: hsl(0, 0%, 21%) !default; // grey-darker
$link: hsl(217, 71%, 53%) !default; // blue
$grey-dark: lighten($black, 25%) !default;
$grey-light: darken($light, 25%) !default;
$grey-lighter: darken($light, 10%) !default;
//== datepicker variables ==//
$dp-background-color: #301827 !default;
$dp-border-color: #1f0e19 !default;
$dp-border-radius: 0px !default;
$dp-border-radius-small: 0px !default;
$dp-line-height-base: 1.5 !default;
$dp-font-size-normal: 1rem !default;
$dp-font-size-small: 0.75rem !default;
$dp-font-weight-semibold: 600 !default;
$dp-font-weight-bold: 700 !default;
$dp-dropdown-offset: 4px !default;
$dp-dropdown-shadow: 0 2px 3px rgba($black, 0.1), 0 0 0 1px rgba($black, 0.1) !default;
$dp-dropdown-z: 20 !default;
$dp-title-background-color: #1f0e19 !default;
$dp-cell-size-base: 2.25rem !default;
$dp-cell-focus-background-color: darken(#301827, 5%) !default;
$dp-cell-prevnext-color: hsl(0, 0%, 48%) !default; // grey
$dp-cell-disabled-color: $grey-lighter !default;
$dp-cell-selected-background-color: #3b1e31 !default;
$dp-cell-selected-color: #ffdc00 !default; // link(blue)-invert
$dp-cell-selected-font-weight: 600 !default;
$dp-cell-today-background-color: #3b1e31 !default; // turquoise (primary)
$dp-cell-today-color: #fff !default; // turquoise-invert
$dp-cell-highlighted-background-color: #3b1e31 !default;
$dp-range-start-end-background-color: $grey-light !default;
$dp-range-start-end-color: $dp-cell-selected-color !default;
$dp-range-background-color: $grey-lighter !default;
$dp-range-today-background-color: $dp-cell-today-background-color !default;
$dp-week-color: $grey-light !default;
$dp-footer-background-color: $light !default;
$dp-input-in-edit-border-color: darken($link, 5%) !default;
$dp-input-in-edit-focus-box-shadow-size: 0 0 0.25em 0.25em !default;
//== non-configurable variables ==//
$dp-cell-shrink-threshold: $dp-cell-size-base * 10; // = 8 * 1.25
$dp-cell-shrinked-width: $dp-cell-size-base * 7 / 8;
//== mixins ==//
@mixin dp-header-button-common {
border-color: transparent;
font-weight: bold;
}
@mixin dp-footer-button-common {
margin: calc(0.375rem - 1px) 0.375rem;
border-radius: $dp-border-radius-small;
width: 100%;
font-size: $dp-font-size-small;
}
//== styles ==//
.datepicker {
display: none;
&.active {
display: block;
}
}
.datepicker-dropdown {
position: absolute;
top: 0;
left: 0;
z-index: $dp-dropdown-z;
padding-top: $dp-dropdown-offset;
&.datepicker-orient-top {
padding-top: 0;
padding-bottom: $dp-dropdown-offset;
}
}
.datepicker-picker {
display: inline-block;
border-radius: $dp-border-radius;
background-color: $dp-background-color;
.datepicker-dropdown & {
box-shadow: $dp-dropdown-shadow;
}
span {
display: block;
flex: 1;
border: 0;
border-radius: $dp-border-radius;
cursor: default;
text-align: center;
-webkit-touch-callout: none;
user-select: none;
}
}
.datepicker-main {
padding: 2px;
}
.datepicker-footer {
box-shadow: inset 0 1px 1px rgba($black, 0.1);
background-color: $dp-footer-background-color;
}
%flex-container {
display: flex;
}
%flex-wrap {
flex-wrap: wrap;
}
%flex-basis-day {
flex-basis: percentage(1 / 7);
}
%flex-basis-month-year {
flex-basis: 25%;
}
%datepicker-cell-height {
height: $dp-cell-size-base;
line-height: $dp-cell-size-base;
}
.datepicker-title {
box-shadow: inset 0 -1px 1px rgba($black, 0.1);
background-color: $dp-title-background-color;
padding: 0.375rem 0.75rem;
text-align: center;
font-weight: $dp-font-weight-bold;
}
.datepicker-controls {
@extend %flex-container;
.datepicker-header & {
padding: 2px 2px 0;
}
@if mixin-exists(dp-button) {
@include dp-button;
} @else {
.button {
$button-color: $dark;
$button-background-color: $white;
$button-border-color: $grey-lighter;
$button-border-width: 1px;
$button-padding-vertical: calc(0.375em - #{$button-border-width});
$button-padding-horizontal: 0.75em;
$button-hover-color: $dark; // link-hover
$button-hover-border-color: $grey-light; // link-hover-border
$button-focus-color: $dark; // link-focus
$button-focus-border-color: $link; // link-focus-border
$button-focus-box-shadow-size: 0 0 0 0.125em;
$button-focus-box-shadow-color: rgba($link, 0.25);
$button-active-color: $dark; // link-active
$button-active-border-color: $grey-dark; // link-active-border
display: inline-flex;
position: relative;
align-items: center;
justify-content: center;
margin: 0;
border: $button-border-width solid $button-border-color;
border-radius: $dp-border-radius; // control-radius
box-shadow: none;
background-color: $button-background-color;
cursor: pointer;
padding: $button-padding-vertical $button-padding-horizontal;
height: 2.25em; // control-height
vertical-align: top;
text-align: center;
line-height: $dp-line-height-base; // control-line-height
white-space: nowrap;
color: $button-color;
font-size: $dp-font-size-normal; // size-normal
&:focus,
&:active {
outline: none;
}
&:hover {
border-color: $button-hover-border-color;
color: $button-hover-color;
}
&:focus {
border-color: $button-focus-border-color;
color: $button-focus-color;
&:not(:active) {
box-shadow: $button-focus-box-shadow-size $button-focus-box-shadow-color;
}
}
&:active {
border-color: $button-active-border-color;
color: $button-active-color;
}
&[disabled] {
cursor: not-allowed;
}
.datepicker-header & {
@include dp-header-button-common;
&:hover {
background-color: darken($white, 2.5%);
}
&:focus {
&:not(:active) {
box-shadow: 0 0 0 0.125em rgba($white, 0.25);
}
}
&:active {
background-color: darken($white, 5%);
}
&[disabled] {
box-shadow: none;
}
}
.datepicker-footer & {
@include dp-footer-button-common;
}
}
}
.view-switch {
flex: auto;
}
.prev-btn,
.next-btn {
padding-right: 0.375rem;
padding-left: 0.375rem;
width: $dp-cell-size-base;
&.disabled {
visibility: hidden;
}
}
}
.datepicker-view {
@extend %flex-container;
.days-of-week {
@extend %flex-container;
}
.dow {
@extend %flex-basis-day;
height: $dp-font-size-normal * $dp-line-height-base;
line-height: $dp-font-size-normal * $dp-line-height-base;
font-size: ($dp-font-size-small + $dp-font-size-normal) / 2;
font-weight: $dp-font-weight-bold;
}
.week {
@extend %datepicker-cell-height;
width: $dp-cell-size-base;
color: $dp-week-color;
font-size: $dp-font-size-small;
@media (max-width: $dp-cell-shrink-threshold) {
width: $dp-cell-shrinked-width;
}
}
}
.datepicker-grid {
@extend %flex-container;
@extend %flex-wrap;
width: $dp-cell-size-base * 7;
@media (max-width: $dp-cell-shrink-threshold) {
.calendar-weeks + .days & {
width: $dp-cell-shrinked-width * 7;
}
}
}
.datepicker-cell {
@extend %datepicker-cell-height;
&:not(.disabled):hover {
background-color: darken($dp-background-color, 2.5%);
cursor: pointer;
}
&.focused:not(.selected) {
background-color: $dp-cell-focus-background-color;
}
&.selected {
&,
&:hover {
background-color: $dp-cell-selected-background-color;
color: $dp-cell-selected-color;
font-weight: $dp-cell-selected-font-weight;
}
}
&.disabled {
color: $dp-cell-disabled-color;
}
&.prev,
&.next {
&:not(.disabled) {
color: $dp-cell-prevnext-color;
}
&.selected {
color: darken($dp-cell-selected-color, 10%);
}
}
&.highlighted:not(.selected):not(.today) {
border-radius: 0;
background-color: $dp-cell-highlighted-background-color;
&:not(.disabled):hover {
background-color: darken($dp-cell-highlighted-background-color, 2.5%);
}
&.focused {
background-color: $dp-cell-focus-background-color;
}
}
&.today {
&:not(.selected) {
background-color: $dp-cell-today-background-color;
&:not(.disabled) {
color: $dp-cell-today-color;
}
}
&.focused:not(.selected) {
background-color: darken($dp-cell-today-background-color, 2.5%);
}
}
.datepicker-view .days & {
@extend %flex-basis-day;
}
.datepicker-view.datepicker-grid & {
@extend %flex-basis-month-year;
height: $dp-cell-size-base * 2;
line-height: $dp-cell-size-base * 2;
}
}
.datepicker-input.in-edit {
border-color: $dp-input-in-edit-border-color;
&:focus,
&:active {
box-shadow: $dp-input-in-edit-focus-box-shadow-size rgba($dp-input-in-edit-border-color, 0.2);
}
}

View file

@ -1,21 +1,27 @@
{% load i18n %}
{% load staticfiles %}
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<meta content="width=device-width, initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0;" name="viewport">
<title>
{% block title_onglet %}{% trans "Annuaire des élèves de l'ENS" %}{% endblock %}
</title>
<link rel="stylesheet" type="text/css" href="{% static "fiches/css/normalize.css" %}" />
<link rel="stylesheet" type="text/css" href="{% static "fiches/css/annuaire.css" %}" />
<link rel="stylesheet" type="text/css" href="{% static "fiches/css/datepicker.css" %}" />
</head>
<body>
<div id="aside">
<div id="menu">
<h1 id="title">
{% block title %} <a href='{% url "home" %}'>{% trans "Annuaire des élèves de l'ENS" %}</a>{% endblock %}
</h1>
<a id="hamburger" href="javascript:void(0);" onclick="toggleMenu()"></a>
<div id="language_switch">
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
@ -31,17 +37,13 @@
<button type="submit">{% trans "Rechercher" %}</button>
</form>
<h1 id="title">
{% block title %} <a href='{% url "home" %}'>{% trans "Annuaire des élèves de l'ENS" %}</a>{% endblock %}
</h1>
<div id="main-menu">
<nav>
<a href='{% url "home" %}'>{% trans "Accueil" %}</a>
<a href='{% url "fiche_modif" %}'>{% trans "Modifier sa fiche d'annuaire" %}</a>
{% if user.is_authenticated %}
<a href='{% url "fiche" request.user.profile.user %}'>{% trans "Consulter sa fiche d'annuaire" %}</a>
<a href='{% url "fiche_modif" %}'>{% trans "Modifier sa fiche d'annuaire" %}</a>
<a href='{% url "fiche_reset" %}'>{% trans "Réinitialiser sa fiche d'annuaire" %}</a>
{% endif %}
<a href='{% url "birthday" %}'>{% trans "Anniversaires à venir" %}</a>
</nav>
@ -77,7 +79,21 @@
{% endblock %}
</div>
</div>
<script>
function toggleMenu() {
var menu = document.getElementById("main-menu");
var account = document.getElementById("account-area");
if (menu.style.display === "none") {
menu.style.display = "grid"
account.style.display = "grid"
} else {
menu.style.display = "none"
account.style.display = "none"
}
}
</script>
{% block extra_js %}{% endblock %}
</body>
{% block extra_js %}{% endblock %}
</html>

View file

@ -1,5 +1,5 @@
{% extends "fiches/base.html" %}
{% load i18n %}
{% load i18n l10n %}
{% block content %}
@ -40,7 +40,9 @@
<div class="birthdate">
<span class="label">{% trans "Date de naissance" %}</span>
<span class="separator"></span>
{% localize on %}
<span class="value">{{ profile.birth_date }}</span>
{% endlocalize %}
</div>
{% endif %}
@ -104,7 +106,7 @@
<div class="studies">
<span class="label">{% trans "Études passées" %}</span>
<span class="separator"></span>
<span class="value">{{ profile.past_studies }}</span>
<span class="value">{{ profile.past_studies|linebreaksbr }}</span>
</div>
{% endif %}
@ -112,7 +114,7 @@
<div class="studies">
<span class="label">{% trans "Expériences passées" %}</span>
<span class="separator"></span>
<span class="value">{{ profile.experiences }}</span>
<span class="value">{{ profile.experiences|linebreaksbr }}</span>
</div>
{% endif %}
</div>
@ -120,7 +122,7 @@
{% if profile.text_field %}
<div class="free-text">
<span class="label">{% trans "Champ libre" %}</span>
<p class="value">{{ profile.text_field }}</p>
<p class="value">{{ profile.text_field|linebreaksbr }}</p>
</div>
{% endif %}

View file

@ -1,6 +1,5 @@
{% extends "fiches/base.html" %}
{% load i18n %}
{% load staticfiles %}
{% load i18n static %}
{% block content %}
@ -21,6 +20,10 @@
<label for="id_pronoun">{% trans "Pronom(s) utilisé(s) :" %}</label>
{{ form.pronoun }}
</div>
<div class="form-entry">
<label for="id_birth_date">{% trans "Date de naissance :" %}</label>
{{ form.birth_date }}
</div>
<div class="form-entry">
<label for="id_picture">{% trans "Photo :" %}</label>
<div id="photo-edit-form" class="wide-form-entry">
@ -29,8 +32,6 @@
<a href="{{ form.instance.picture.url }}">
<img src="{{ form.instance.picture.url }}">
</a>
{% else %}
<img>
{% endif %}
</div>
<div class="photo-edit-controls">
@ -67,10 +68,6 @@
{{ form.experiences }}
</div>
</div>
<div class="form-entry">
<label for="id_birth_date">{% trans "Date de naissance :" %}</label>
{{ form.birth_date }}
</div>
<div class="form-entry">
<label for="id_thurne">{% trans "Thurne :" %}</label>
{{ form.thurne }}
@ -116,5 +113,14 @@
{% endblock %}
{% block extra_js %}
<script type="text/javascript" src="{% static "fiches/js/forms.js" %}"></script>
<script src="{% static "fiches/js/forms.js" %}"></script>
<script src="{% static "fiches/js/datepicker.min.js" %}"></script>
<script>
const elem = document.querySelector('input[name="birth_date"]');
const datepicker = new Datepicker(elem, {
format: "yyyy-mm-dd",
defaultViewDate: "{{ default_birth_date }}",
});
</script>
{% endblock %}

View file

@ -0,0 +1,19 @@
{% extends "fiches/base.html" %}
{% load i18n %}
{% block content %}
<div class="content" id="content-reset">
<h2>{% trans "Réinitialiser ma fiche annuaire" %}</h2>
<p id="warning">{% trans "Votre fiche annuaire sera réinitialisée. Votre nom, département et promotion seront récupérés de l'annuaire de l'administration." %}</p>
<form method="post" action="">
{% csrf_token %}
<input type="submit" name="reset" id="reset" value="{% trans "Réinitialiser" %}">
<input type="submit" name="abort" id="abort" value="{% trans "Annuler" %}">
</form>
</div>
{% endblock %}

View file

@ -1,9 +1,11 @@
from django.urls import path
from . import views
urlpatterns = [
path("", views.HomeView.as_view(), name="home"),
path("fiche/edit", views.EditView.as_view(), name="fiche_modif"),
path("fiche/<user>", views.FicheView.as_view(), name="fiche"),
path("fiche/_edit", views.EditView.as_view(), name="fiche_modif"),
path("fiche/_reset", views.ResetView.as_view(), name="fiche_reset"),
path("fiche/<slug:slug>", views.FicheView.as_view(), name="fiche"),
path("birthday", views.BirthdayView.as_view(), name="birthday"),
]

23
fiches/utils.py Normal file
View file

@ -0,0 +1,23 @@
from .management.commands._ldap import ClipperLDAP
def get_ldap_infos(clipper_login):
ldap = ClipperLDAP()
try:
res = ldap.search("(uid={})".format(clipper_login))
except Exception:
return None
if not res:
return None
if len(res) != 1:
raise RuntimeError("LDAP returned too many results: {}".format(res))
(res,) = res
promo, dept = ldap.parse_dept(ldap.extract_ldap_info(res, "homeDirectory"))
return {
"name": ldap.extract_ldap_info(res, "cn"),
"promo": promo,
"dept": dept,
}

View file

@ -1,37 +1,34 @@
from django.shortcuts import render
from django.shortcuts import get_object_or_404, redirect
from datetime import date, timedelta
from django.contrib.auth.decorators import login_required
from fiches.models import Profile, Phone, Social, Mail, Address
from fiches.forms import (
ProfileForm,
SearchForm,
PhoneFormSet,
SocialFormSet,
MailFormSet,
AddressFormSet,
)
from django.forms import formset_factory
from django.forms.models import model_to_dict
from django.urls import reverse
from django.db.models import Q
from django.core.mail import send_mail
from django.db.models import DateTimeField, Q, Value
from django.http import HttpResponseRedirect
from django.template.loader import render_to_string
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.utils.decorators import method_decorator
from datetime import timedelta
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from django.views.generic.edit import FormView, UpdateView
from django.http import HttpResponseRedirect
from django.views.generic.list import ListView
from fiches.forms import (
AddressFormSet,
MailFormSet,
PhoneFormSet,
ProfileForm,
SearchForm,
SocialFormSet,
)
from fiches.models import Department, Profile
from fiches.utils import get_ldap_infos
@method_decorator(login_required, name="dispatch")
class FicheView(DetailView):
model = Profile
template_name = "fiches/fiche.html"
def get_object(self):
return get_object_or_404(Profile, user__username=self.kwargs.get("user"))
slug_field = "user__username"
@method_decorator(login_required, name="dispatch")
@ -109,6 +106,14 @@ class EditView(UpdateView):
)
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
today = date.today()
context["default_birth_date"] = today.replace(
year=(today.year - 20)
).isoformat()
return context
def get_object(self):
return self.request.user.profile
@ -123,10 +128,21 @@ class HomeView(FormView):
form_class = SearchForm
def form_valid(self, form):
name = form.cleaned_data["name"]
promotion = form.cleaned_data["year"]
depts = form.cleaned_data["department"]
result = Profile.objects.filter(
Q(full_name__icontains=form.cleaned_data["name"])
| Q(nickname__icontains=form.cleaned_data["name"])
Q(full_name__icontains=name)
| Q(nickname__icontains=name)
| Q(user__username__icontains=name)
)
if depts:
result = result.filter(department__in=depts)
if promotion:
result = result.filter(promotion=promotion)
return self.render_to_response(self.get_context_data(result=result))
@ -141,13 +157,54 @@ class BirthdayView(ListView):
context["result"] = list(
Profile.objects.filter(
birth_date__day=today.day, birth_date__month=today.month
).annotate(day=Value(today, output_field=DateTimeField()))
)
)
for i in range(1, 7):
for _ in range(1, 7):
today = today + timedelta(days=1)
context["result"] += list(
Profile.objects.filter(
birth_date__day=today.day, birth_date__month=today.month
)
).annotate(day=Value(today, output_field=DateTimeField()))
)
return context
@method_decorator(login_required, name="dispatch")
class ResetView(UpdateView):
model = Profile
template_name = "fiches/reset.html"
fields = []
success_url = reverse_lazy("fiche_modif")
def get_object(self):
return self.request.user.profile
def post(self, request, *args, **kwargs):
if "reset" in request.POST:
# On réinitialise le profil
profile = self.get_object()
base_infos = get_ldap_infos(profile.user.cas_account.cas_login)
# On supprime les trucs inutiles
profile.phone_set.all().delete()
profile.social_set.all().delete()
profile.mail_set.all().delete()
profile.address_set.all().delete()
profile.nickname = ""
profile.pronoun = ""
profile.birth_date = None
profile.past_studies = ""
profile.experiences = ""
profile.thurne = ""
profile.text_field = ""
profile.picture.delete()
# On réinitialise avec les infos du LDAP
if base_infos is not None:
profile.full_name = base_infos["name"]
profile.department.clear()
profile.department.add(Department.objects.get(name=base_infos["dept"]))
profile.promotion = base_infos["promo"]
profile.save()
return HttpResponseRedirect(self.success_url)

Binary file not shown.

View file

@ -7,26 +7,26 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-01-28 00:03+0000\n"
"PO-Revision-Date: 2021-02-04 21:28+0100\n"
"Last-Translator: Tom Hubrecht <tom.hubrecht@ens.fr>\n"
"POT-Creation-Date: 2021-02-06 12:02+0000\n"
"PO-Revision-Date: 2021-10-08 09:36+0200\n"
"Last-Translator: Test Translator <test@translator>\n"
"Language-Team: \n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.4.1\n"
"X-Generator: Poedit 3.0\n"
#: fiches/forms.py:15
#: fiches/forms.py:20
msgid "Nom/Surnom"
msgstr "Name/Nickname"
#: fiches/forms.py:16
#: fiches/forms.py:21
msgid "Promotion"
msgstr "Entry year"
msgstr "Entrance year"
#: fiches/forms.py:28
#: fiches/forms.py:33
msgid "Tous les champs sont vides"
msgstr "All fields are empty"
@ -56,7 +56,7 @@ msgstr "department"
#: fiches/models.py:24
msgid "promotion"
msgstr "entry year"
msgstr "entrance year"
#: fiches/models.py:27
msgid "date de naissance"
@ -116,56 +116,60 @@ msgstr "e-mail"
msgid "adresse"
msgstr "address"
#: fiches/templates/fiches/base.html:10 fiches/templates/fiches/base.html:35
#: fiches/templates/fiches/base.html:10 fiches/templates/fiches/base.html:21
msgid "Annuaire des élèves de l'ENS"
msgstr "ENS student directory"
#: fiches/templates/fiches/base.html:30
#: fiches/templates/fiches/base.html:36
msgid "Recherche Rapide"
msgstr "Quick Search"
#: fiches/templates/fiches/base.html:31
#: fiches/templates/fiches/base.html:37
msgid "Rechercher"
msgstr "Search"
#: fiches/templates/fiches/base.html:41
#: fiches/templates/fiches/base.html:42
msgid "Accueil"
msgstr "Home"
#: fiches/templates/fiches/base.html:42
msgid "Modifier sa fiche d'annuaire"
msgstr "Edit your directory record"
#: fiches/templates/fiches/base.html:44
msgid "Consulter sa fiche d'annuaire"
msgstr "View your directory record"
#: fiches/templates/fiches/base.html:45
msgid "Modifier sa fiche d'annuaire"
msgstr "Edit your directory record"
#: fiches/templates/fiches/base.html:46
msgid "Réinitialiser sa fiche d'annuaire"
msgstr "Reset your directory record"
#: fiches/templates/fiches/base.html:48
msgid "Anniversaires à venir"
msgstr "Upcoming birthdays"
#: fiches/templates/fiches/base.html:52
#: fiches/templates/fiches/base.html:54
#, python-format
msgid "Connecté en tant que <span class=\"clipper\">%(user)s</span>"
msgstr "Connected as <span class=\"clipper\">%(user)s</span>"
#: fiches/templates/fiches/base.html:53
#: fiches/templates/fiches/base.html:55
msgid "Se déconnecter"
msgstr "Log out"
#: fiches/templates/fiches/base.html:55
#: fiches/templates/fiches/base.html:57
msgid "Se connecter"
msgstr "Log in"
#: fiches/templates/fiches/base.html:71
#: fiches/templates/fiches/base.html:73
msgid "Crée par KDENS &middot; Propulsé par Django"
msgstr "Created by KDENS &middot; Powered by Django"
#: fiches/templates/fiches/base.html:75
#: fiches/templates/fiches/base.html:77
msgid "Page des élèves"
msgstr "Students' page"
#: fiches/templates/fiches/base.html:76
#: fiches/templates/fiches/base.html:78
msgid "Contacter l'équipe annuaire"
msgstr "Contact the directory team"
@ -189,168 +193,168 @@ msgstr "Department"
msgid "Date de naissance"
msgstr "Birth date"
#: fiches/templates/fiches/fiche.html:49
#: fiches/templates/fiches/fiche.html:51
msgid "Thurne"
msgstr "Room"
#: fiches/templates/fiches/fiche.html:57
#: fiches/templates/fiches/fiche.html:59
msgid "Téléphone"
msgstr "Phone number"
#: fiches/templates/fiches/fiche.html:69
#: fiches/templates/fiches/fiche.html:71
msgid "Réseau social,Réseaux sociaux"
msgstr "Social network,Social networks"
#: fiches/templates/fiches/fiche.html:81
#: fiches/templates/fiches/fiche.html:83
msgid "Mail,Mails"
msgstr "E-mail,E-mails"
#: fiches/templates/fiches/fiche.html:93
#: fiches/templates/fiches/fiche.html:95
msgid "Adresse,Adresses"
msgstr "Address,Addresses"
#: fiches/templates/fiches/fiche.html:105
#: fiches/templates/fiches/fiche.html:107
msgid "Études passées"
msgstr "Past studies"
#: fiches/templates/fiches/fiche.html:113
#: fiches/templates/fiches/fiche.html:115
msgid "Expériences passées"
msgstr "Experiences"
#: fiches/templates/fiches/fiche.html:122
#: fiches/templates/fiches/fiche.html:124
msgid "Champ libre"
msgstr "Free space"
#: fiches/templates/fiches/fiches_modif.html:8
#: fiches/templates/fiches/fiches_modif.html:7
msgid "Modifier ma page d'annuaire"
msgstr "Edit my directory record"
#: fiches/templates/fiches/fiches_modif.html:13
#: fiches/templates/fiches/fiches_modif.html:12
msgid "Nom :"
msgstr "Name:"
#: fiches/templates/fiches/fiches_modif.html:17
#: fiches/templates/fiches/fiches_modif.html:16
msgid "Surnom :"
msgstr "Nickname:"
#: fiches/templates/fiches/fiches_modif.html:21
#: fiches/templates/fiches/fiches_modif.html:20
msgid "Pronom(s) utilisé(s) :"
msgstr "Pronoun(s):"
#: fiches/templates/fiches/fiches_modif.html:25
msgid "Photo :"
msgstr "Photo:"
#: fiches/templates/fiches/fiches_modif.html:39
msgid "Effacer (cochez la case) :"
msgstr "Delete (check the box):"
#: fiches/templates/fiches/fiches_modif.html:44
msgid "Nouvelle photo :"
msgstr "New photo:"
#: fiches/templates/fiches/fiches_modif.html:51
msgid "Département :"
msgstr "Department:"
#: fiches/templates/fiches/fiches_modif.html:55
#: fiches/templates/fiches/home.html:14
msgid "Promotion :"
msgstr "Entry year:"
#: fiches/templates/fiches/fiches_modif.html:59
msgid "Études passées :"
msgstr "Past studies:"
#: fiches/templates/fiches/fiches_modif.html:65
msgid "Expériences :"
msgstr "Experiences:"
#: fiches/templates/fiches/fiches_modif.html:71
#: fiches/templates/fiches/fiches_modif.html:24
msgid "Date de naissance :"
msgstr "Birth date:"
#: fiches/templates/fiches/fiches_modif.html:75
#: fiches/templates/fiches/fiches_modif.html:28
msgid "Photo :"
msgstr "Photo:"
#: fiches/templates/fiches/fiches_modif.html:40
msgid "Effacer (cochez la case) :"
msgstr "Delete (check the box):"
#: fiches/templates/fiches/fiches_modif.html:45
msgid "Nouvelle photo :"
msgstr "New photo:"
#: fiches/templates/fiches/fiches_modif.html:52
msgid "Département :"
msgstr "Department:"
#: fiches/templates/fiches/fiches_modif.html:56
#: fiches/templates/fiches/home.html:14
msgid "Promotion :"
msgstr "Entrance year:"
#: fiches/templates/fiches/fiches_modif.html:60
msgid "Études passées :"
msgstr "Past studies:"
#: fiches/templates/fiches/fiches_modif.html:66
msgid "Expériences :"
msgstr "Experiences:"
#: fiches/templates/fiches/fiches_modif.html:72
msgid "Thurne :"
msgstr "Room :"
#: fiches/templates/fiches/fiches_modif.html:78
#: fiches/templates/fiches/fiches_modif.html:75
msgid "Personnel"
msgstr "Private"
#: fiches/templates/fiches/fiches_modif.html:78
#: fiches/templates/fiches/fiches_modif.html:75
msgid "0612345678"
msgstr "0612345678"
#: fiches/templates/fiches/fiches_modif.html:79
#: fiches/templates/fiches/fiches_modif.html:76
msgid "Numéro(s) de téléphone :"
msgstr "Phone number(s):"
#: fiches/templates/fiches/fiches_modif.html:80
#: fiches/templates/fiches/fiches_modif.html:77
msgid "Ajouter un numéro"
msgstr "Add a phone number"
#: fiches/templates/fiches/fiches_modif.html:83
#: fiches/templates/fiches/fiches_modif.html:80
msgid "InstaTok"
msgstr "InstaTok"
#: fiches/templates/fiches/fiches_modif.html:83
#: fiches/templates/fiches/fiches_modif.html:80
msgid "mon_profil_instatok"
msgstr "my_instatok_profile"
#: fiches/templates/fiches/fiches_modif.html:84
#: fiches/templates/fiches/fiches_modif.html:81
msgid "Réseaux sociaux :"
msgstr "Social networks:"
#: fiches/templates/fiches/fiches_modif.html:85
#: fiches/templates/fiches/fiches_modif.html:82
msgid "Ajouter un réseau social"
msgstr "Add a social network"
#: fiches/templates/fiches/fiches_modif.html:88
#: fiches/templates/fiches/fiches_modif.html:85
msgid "Professionelle"
msgstr "Professional"
#: fiches/templates/fiches/fiches_modif.html:88
#: fiches/templates/fiches/fiches_modif.html:85
msgid "moi@ens.fr"
msgstr "me@ens.fr"
#: fiches/templates/fiches/fiches_modif.html:89
#: fiches/templates/fiches/fiches_modif.html:86
msgid "Mail(s) :"
msgstr "E-mail(s):"
#: fiches/templates/fiches/fiches_modif.html:90
#: fiches/templates/fiches/fiches_modif.html:87
msgid "Ajouter un email"
msgstr "Add an e-mail"
#: fiches/templates/fiches/fiches_modif.html:93
#: fiches/templates/fiches/fiches_modif.html:90
msgid "Bureau"
msgstr "Office"
#: fiches/templates/fiches/fiches_modif.html:93
#: fiches/templates/fiches/fiches_modif.html:90
msgid "45 rue d'Ulm"
msgstr "45 rue d'Ulm"
#: fiches/templates/fiches/fiches_modif.html:94
#: fiches/templates/fiches/fiches_modif.html:91
msgid "Adresse(s) :"
msgstr "Address(es):"
#: fiches/templates/fiches/fiches_modif.html:95
#: fiches/templates/fiches/fiches_modif.html:92
msgid "Ajouter une adresse"
msgstr "Add an address"
#: fiches/templates/fiches/fiches_modif.html:99
#: fiches/templates/fiches/fiches_modif.html:96
msgid "Champ libre :"
msgstr "Free space:"
#: fiches/templates/fiches/fiches_modif.html:105
#: fiches/templates/fiches/fiches_modif.html:102
msgid "Apparaître sur l'annuaire papier ?"
msgstr "Appear on the paper directory?"
#: fiches/templates/fiches/fiches_modif.html:109
#: fiches/templates/fiches/fiches_modif.html:106
msgid "Conserver la fiche annuaire ?"
msgstr "Keep the directory record?"
#: fiches/templates/fiches/fiches_modif.html:112
#: fiches/templates/fiches/fiches_modif.html:109
msgid "Enregistrer"
msgstr "Save"
@ -370,5 +374,25 @@ msgstr "Department:"
msgid "Recherche"
msgstr "Search"
#: fiches/templates/fiches/reset.html:8
msgid "Réinitialiser ma fiche annuaire"
msgstr "Reset your directory record"
#: fiches/templates/fiches/reset.html:9
msgid ""
"Votre fiche annuaire sera réinitialisée. Votre nom, département et promotion "
"seront récupérés de l'annuaire de l'administration."
msgstr ""
"Your directory record will be reset. Your name, department and promotion "
"will be copied from the administration directory."
#: fiches/templates/fiches/reset.html:13
msgid "Réinitialiser"
msgstr "Reset"
#: fiches/templates/fiches/reset.html:14
msgid "Annuler"
msgstr "Cancel"
#~ msgid "Department :"
#~ msgstr "Department:"

View file

@ -5,7 +5,7 @@ import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'annuaire.settings')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
@ -17,5 +17,5 @@ def main():
execute_from_command_line(sys.argv)
if __name__ == '__main__':
if __name__ == "__main__":
main()

80
npins/default.nix Normal file
View file

@ -0,0 +1,80 @@
# Generated by npins. Do not modify; will be overwritten regularly
let
data = builtins.fromJSON (builtins.readFile ./sources.json);
version = data.version;
mkSource =
spec:
assert spec ? type;
let
path =
if spec.type == "Git" then
mkGitSource spec
else if spec.type == "GitRelease" then
mkGitSource spec
else if spec.type == "PyPi" then
mkPyPiSource spec
else if spec.type == "Channel" then
mkChannelSource spec
else
builtins.throw "Unknown source type ${spec.type}";
in
spec // { outPath = path; };
mkGitSource =
{
repository,
revision,
url ? null,
hash,
branch ? null,
...
}:
assert repository ? type;
# At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository
# In the latter case, there we will always be an url to the tarball
if url != null then
(builtins.fetchTarball {
inherit url;
sha256 = hash; # FIXME: check nix version & use SRI hashes
})
else
assert repository.type == "Git";
let
urlToName =
url: rev:
let
matched = builtins.match "^.*/([^/]*)(\\.git)?$" repository.url;
short = builtins.substring 0 7 rev;
appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else "";
in
"${if matched == null then "source" else builtins.head matched}${appendShort}";
name = urlToName repository.url revision;
in
builtins.fetchGit {
url = repository.url;
rev = revision;
inherit name;
# hash = hash;
};
mkPyPiSource =
{ url, hash, ... }:
builtins.fetchurl {
inherit url;
sha256 = hash;
};
mkChannelSource =
{ url, hash, ... }:
builtins.fetchTarball {
inherit url;
sha256 = hash;
};
in
if version == 3 then
builtins.mapAttrs (_: mkSource) data.pins
else
throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`"

22
npins/sources.json Normal file
View file

@ -0,0 +1,22 @@
{
"pins": {
"nix-pkgs": {
"type": "Git",
"repository": {
"type": "Git",
"url": "https://git.hubrecht.ovh/hubrecht/nix-pkgs"
},
"branch": "main",
"revision": "3e731378f3984313ef902c5e5a49e002e6e2c27e",
"url": null,
"hash": "1vy2dj9fyy653w6idvi1r73s0nd2a332a1xkppddjip6rk0i030p"
},
"nixpkgs": {
"type": "Channel",
"name": "nixpkgs-unstable",
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-24.11pre691017.b69de56fac8c/nixexprs.tar.xz",
"hash": "0z32pj0lh5ng2a6cn0qfmka8cynnygckn5615mkaxq2aplkvgzx3"
}
},
"version": 3
}

1141
poetry.lock generated Normal file

File diff suppressed because it is too large Load diff

34
pyproject.toml Normal file
View file

@ -0,0 +1,34 @@
[tool.poetry]
name = "annuaire"
version = "0.1.0"
description = ""
authors = ["Klub-Dev ENS <klub-dev@ens.fr>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.9"
Django = "^3.2.0"
Pillow = "^9.4.0"
authens = "^0.1b4"
python-dateutil = "^2.8.2"
[tool.poetry.group.dev.dependencies]
ipython = "^8.9.0"
isort = "^5.12.0"
flake8 = "^6.0.0"
black = "^22.12.0"
django-types = "^0.16.0"
django-debug-toolbar = "^3.8.1"
[tool.poetry.group.prod.dependencies]
python-ldap = "^3.4.3"
psycopg2 = "^2.9.5"
gunicorn = "^20.1.0"
django-redis = "^5.2.0"
[tool.isort]
profile = "black"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

View file

@ -1,6 +1,394 @@
-r requirements.txt
django-debug-toolbar
ipython
black
flake8
isort
appnope==0.1.3 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "darwin" \
--hash=sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24 \
--hash=sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e
asgiref==3.6.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac \
--hash=sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506
asttokens==2.2.1 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3 \
--hash=sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c
authens==0.1b4 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:3430c85d0c11c7ca78cba484d5dfd18e9ba3370a0f2abbdd14aafb8feb8807a5
backcall==0.2.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e \
--hash=sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255
black==22.12.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320 \
--hash=sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351 \
--hash=sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350 \
--hash=sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f \
--hash=sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf \
--hash=sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148 \
--hash=sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4 \
--hash=sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d \
--hash=sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc \
--hash=sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d \
--hash=sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2 \
--hash=sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f
certifi==2022.12.7 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \
--hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18
charset-normalizer==3.0.1 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b \
--hash=sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42 \
--hash=sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d \
--hash=sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b \
--hash=sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a \
--hash=sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59 \
--hash=sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154 \
--hash=sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1 \
--hash=sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c \
--hash=sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a \
--hash=sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d \
--hash=sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6 \
--hash=sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b \
--hash=sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b \
--hash=sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783 \
--hash=sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5 \
--hash=sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918 \
--hash=sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555 \
--hash=sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639 \
--hash=sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786 \
--hash=sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e \
--hash=sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed \
--hash=sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820 \
--hash=sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8 \
--hash=sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3 \
--hash=sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541 \
--hash=sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14 \
--hash=sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be \
--hash=sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e \
--hash=sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76 \
--hash=sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b \
--hash=sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c \
--hash=sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b \
--hash=sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3 \
--hash=sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc \
--hash=sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6 \
--hash=sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59 \
--hash=sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4 \
--hash=sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d \
--hash=sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d \
--hash=sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3 \
--hash=sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a \
--hash=sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea \
--hash=sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6 \
--hash=sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e \
--hash=sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603 \
--hash=sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24 \
--hash=sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a \
--hash=sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58 \
--hash=sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678 \
--hash=sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a \
--hash=sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c \
--hash=sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6 \
--hash=sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18 \
--hash=sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174 \
--hash=sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317 \
--hash=sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f \
--hash=sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc \
--hash=sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837 \
--hash=sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41 \
--hash=sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c \
--hash=sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579 \
--hash=sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753 \
--hash=sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8 \
--hash=sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291 \
--hash=sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087 \
--hash=sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866 \
--hash=sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3 \
--hash=sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d \
--hash=sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1 \
--hash=sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca \
--hash=sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e \
--hash=sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db \
--hash=sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72 \
--hash=sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d \
--hash=sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc \
--hash=sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539 \
--hash=sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d \
--hash=sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af \
--hash=sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b \
--hash=sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602 \
--hash=sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f \
--hash=sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478 \
--hash=sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c \
--hash=sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e \
--hash=sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479 \
--hash=sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7 \
--hash=sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8
click==8.1.3 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \
--hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48
colorama==0.4.6 ; python_version >= "3.9" and python_version < "4.0" and sys_platform == "win32" or python_version >= "3.9" and python_version < "4.0" and platform_system == "Windows" \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
decorator==5.1.1 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330 \
--hash=sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186
django-debug-toolbar==3.8.1 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:24ef1a7d44d25e60d7951e378454c6509bf536dce7e7d9d36e7c387db499bc27 \
--hash=sha256:879f8a4672d41621c06a4d322dcffa630fc4df056cada6e417ed01db0e5e0478
django-types==0.16.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:29d23af8b88fa1579b47418e92ffc1d89bfbdf11eab64d2ae006fa09e54fed9a \
--hash=sha256:9df4e1936f304f309a59f4cee19a607e151282fc0d97238833a382fafc5052c8
django==3.2.16 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:18ba8efa36b69cfcd4b670d0fa187c6fe7506596f0ababe580e16909bcdec121 \
--hash=sha256:3adc285124244724a394fa9b9839cc8cd116faf7d159554c43ecdaa8cdf0b94d
executing==1.2.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc \
--hash=sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107
flake8==6.0.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7 \
--hash=sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181
idna==3.4 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
ipython==8.9.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:71618e82e6d59487bea059626e7c79fb4a5b760d1510d02fab1160db6fdfa1f7 \
--hash=sha256:9c207b0ef2d276d1bfcfeb9a62804336abbe4b170574ea061500952319b1d78c
isort==5.12.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504 \
--hash=sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6
jedi==0.18.2 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e \
--hash=sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612
lxml==4.9.2 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:01d36c05f4afb8f7c20fd9ed5badca32a2029b93b1750f571ccc0b142531caf7 \
--hash=sha256:04876580c050a8c5341d706dd464ff04fd597095cc8c023252566a8826505726 \
--hash=sha256:05ca3f6abf5cf78fe053da9b1166e062ade3fa5d4f92b4ed688127ea7d7b1d03 \
--hash=sha256:090c6543d3696cbe15b4ac6e175e576bcc3f1ccfbba970061b7300b0c15a2140 \
--hash=sha256:0dc313ef231edf866912e9d8f5a042ddab56c752619e92dfd3a2c277e6a7299a \
--hash=sha256:0f2b1e0d79180f344ff9f321327b005ca043a50ece8713de61d1cb383fb8ac05 \
--hash=sha256:13598ecfbd2e86ea7ae45ec28a2a54fb87ee9b9fdb0f6d343297d8e548392c03 \
--hash=sha256:16efd54337136e8cd72fb9485c368d91d77a47ee2d42b057564aae201257d419 \
--hash=sha256:1ab8f1f932e8f82355e75dda5413a57612c6ea448069d4fb2e217e9a4bed13d4 \
--hash=sha256:223f4232855ade399bd409331e6ca70fb5578efef22cf4069a6090acc0f53c0e \
--hash=sha256:2455cfaeb7ac70338b3257f41e21f0724f4b5b0c0e7702da67ee6c3640835b67 \
--hash=sha256:2899456259589aa38bfb018c364d6ae7b53c5c22d8e27d0ec7609c2a1ff78b50 \
--hash=sha256:2a29ba94d065945944016b6b74e538bdb1751a1db6ffb80c9d3c2e40d6fa9894 \
--hash=sha256:2a87fa548561d2f4643c99cd13131acb607ddabb70682dcf1dff5f71f781a4bf \
--hash=sha256:2e430cd2824f05f2d4f687701144556646bae8f249fd60aa1e4c768ba7018947 \
--hash=sha256:36c3c175d34652a35475a73762b545f4527aec044910a651d2bf50de9c3352b1 \
--hash=sha256:3818b8e2c4b5148567e1b09ce739006acfaa44ce3156f8cbbc11062994b8e8dd \
--hash=sha256:3ab9fa9d6dc2a7f29d7affdf3edebf6ece6fb28a6d80b14c3b2fb9d39b9322c3 \
--hash=sha256:3efea981d956a6f7173b4659849f55081867cf897e719f57383698af6f618a92 \
--hash=sha256:4c8f293f14abc8fd3e8e01c5bd86e6ed0b6ef71936ded5bf10fe7a5efefbaca3 \
--hash=sha256:5344a43228767f53a9df6e5b253f8cdca7dfc7b7aeae52551958192f56d98457 \
--hash=sha256:58bfa3aa19ca4c0f28c5dde0ff56c520fbac6f0daf4fac66ed4c8d2fb7f22e74 \
--hash=sha256:5b4545b8a40478183ac06c073e81a5ce4cf01bf1734962577cf2bb569a5b3bbf \
--hash=sha256:5f50a1c177e2fa3ee0667a5ab79fdc6b23086bc8b589d90b93b4bd17eb0e64d1 \
--hash=sha256:63da2ccc0857c311d764e7d3d90f429c252e83b52d1f8f1d1fe55be26827d1f4 \
--hash=sha256:6749649eecd6a9871cae297bffa4ee76f90b4504a2a2ab528d9ebe912b101975 \
--hash=sha256:6804daeb7ef69e7b36f76caddb85cccd63d0c56dedb47555d2fc969e2af6a1a5 \
--hash=sha256:689bb688a1db722485e4610a503e3e9210dcc20c520b45ac8f7533c837be76fe \
--hash=sha256:699a9af7dffaf67deeae27b2112aa06b41c370d5e7633e0ee0aea2e0b6c211f7 \
--hash=sha256:6b418afe5df18233fc6b6093deb82a32895b6bb0b1155c2cdb05203f583053f1 \
--hash=sha256:76cf573e5a365e790396a5cc2b909812633409306c6531a6877c59061e42c4f2 \
--hash=sha256:7b515674acfdcadb0eb5d00d8a709868173acece5cb0be3dd165950cbfdf5409 \
--hash=sha256:7b770ed79542ed52c519119473898198761d78beb24b107acf3ad65deae61f1f \
--hash=sha256:7d2278d59425777cfcb19735018d897ca8303abe67cc735f9f97177ceff8027f \
--hash=sha256:7e91ee82f4199af8c43d8158024cbdff3d931df350252288f0d4ce656df7f3b5 \
--hash=sha256:821b7f59b99551c69c85a6039c65b75f5683bdc63270fec660f75da67469ca24 \
--hash=sha256:822068f85e12a6e292803e112ab876bc03ed1f03dddb80154c395f891ca6b31e \
--hash=sha256:8340225bd5e7a701c0fa98284c849c9b9fc9238abf53a0ebd90900f25d39a4e4 \
--hash=sha256:85cabf64adec449132e55616e7ca3e1000ab449d1d0f9d7f83146ed5bdcb6d8a \
--hash=sha256:880bbbcbe2fca64e2f4d8e04db47bcdf504936fa2b33933efd945e1b429bea8c \
--hash=sha256:8d0b4612b66ff5d62d03bcaa043bb018f74dfea51184e53f067e6fdcba4bd8de \
--hash=sha256:8e20cb5a47247e383cf4ff523205060991021233ebd6f924bca927fcf25cf86f \
--hash=sha256:925073b2fe14ab9b87e73f9a5fde6ce6392da430f3004d8b72cc86f746f5163b \
--hash=sha256:998c7c41910666d2976928c38ea96a70d1aa43be6fe502f21a651e17483a43c5 \
--hash=sha256:9b22c5c66f67ae00c0199f6055705bc3eb3fcb08d03d2ec4059a2b1b25ed48d7 \
--hash=sha256:9f102706d0ca011de571de32c3247c6476b55bb6bc65a20f682f000b07a4852a \
--hash=sha256:a08cff61517ee26cb56f1e949cca38caabe9ea9fbb4b1e10a805dc39844b7d5c \
--hash=sha256:a0a336d6d3e8b234a3aae3c674873d8f0e720b76bc1d9416866c41cd9500ffb9 \
--hash=sha256:a35f8b7fa99f90dd2f5dc5a9fa12332642f087a7641289ca6c40d6e1a2637d8e \
--hash=sha256:a38486985ca49cfa574a507e7a2215c0c780fd1778bb6290c21193b7211702ab \
--hash=sha256:a5da296eb617d18e497bcf0a5c528f5d3b18dadb3619fbdadf4ed2356ef8d941 \
--hash=sha256:a6e441a86553c310258aca15d1c05903aaf4965b23f3bc2d55f200804e005ee5 \
--hash=sha256:a82d05da00a58b8e4c0008edbc8a4b6ec5a4bc1e2ee0fb6ed157cf634ed7fa45 \
--hash=sha256:ab323679b8b3030000f2be63e22cdeea5b47ee0abd2d6a1dc0c8103ddaa56cd7 \
--hash=sha256:b1f42b6921d0e81b1bcb5e395bc091a70f41c4d4e55ba99c6da2b31626c44892 \
--hash=sha256:b23e19989c355ca854276178a0463951a653309fb8e57ce674497f2d9f208746 \
--hash=sha256:b264171e3143d842ded311b7dccd46ff9ef34247129ff5bf5066123c55c2431c \
--hash=sha256:b26a29f0b7fc6f0897f043ca366142d2b609dc60756ee6e4e90b5f762c6adc53 \
--hash=sha256:b64d891da92e232c36976c80ed7ebb383e3f148489796d8d31a5b6a677825efe \
--hash=sha256:b9cc34af337a97d470040f99ba4282f6e6bac88407d021688a5d585e44a23184 \
--hash=sha256:bc718cd47b765e790eecb74d044cc8d37d58562f6c314ee9484df26276d36a38 \
--hash=sha256:be7292c55101e22f2a3d4d8913944cbea71eea90792bf914add27454a13905df \
--hash=sha256:c83203addf554215463b59f6399835201999b5e48019dc17f182ed5ad87205c9 \
--hash=sha256:c9ec3eaf616d67db0764b3bb983962b4f385a1f08304fd30c7283954e6a7869b \
--hash=sha256:ca34efc80a29351897e18888c71c6aca4a359247c87e0b1c7ada14f0ab0c0fb2 \
--hash=sha256:ca989b91cf3a3ba28930a9fc1e9aeafc2a395448641df1f387a2d394638943b0 \
--hash=sha256:d02a5399126a53492415d4906ab0ad0375a5456cc05c3fc0fc4ca11771745cda \
--hash=sha256:d17bc7c2ccf49c478c5bdd447594e82692c74222698cfc9b5daae7ae7e90743b \
--hash=sha256:d5bf6545cd27aaa8a13033ce56354ed9e25ab0e4ac3b5392b763d8d04b08e0c5 \
--hash=sha256:d6b430a9938a5a5d85fc107d852262ddcd48602c120e3dbb02137c83d212b380 \
--hash=sha256:da248f93f0418a9e9d94b0080d7ebc407a9a5e6d0b57bb30db9b5cc28de1ad33 \
--hash=sha256:da4dd7c9c50c059aba52b3524f84d7de956f7fef88f0bafcf4ad7dde94a064e8 \
--hash=sha256:df0623dcf9668ad0445e0558a21211d4e9a149ea8f5666917c8eeec515f0a6d1 \
--hash=sha256:e5168986b90a8d1f2f9dc1b841467c74221bd752537b99761a93d2d981e04889 \
--hash=sha256:efa29c2fe6b4fdd32e8ef81c1528506895eca86e1d8c4657fda04c9b3786ddf9 \
--hash=sha256:f1496ea22ca2c830cbcbd473de8f114a320da308438ae65abad6bab7867fe38f \
--hash=sha256:f49e52d174375a7def9915c9f06ec4e569d235ad428f70751765f48d5926678c
matplotlib-inline==0.1.6 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311 \
--hash=sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304
mccabe==0.7.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \
--hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e
mypy-extensions==0.4.3 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \
--hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8
parso==0.8.3 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0 \
--hash=sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75
pathspec==0.11.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229 \
--hash=sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc
pexpect==4.8.0 ; python_version >= "3.9" and python_version < "4.0" and sys_platform != "win32" \
--hash=sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937 \
--hash=sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c
pickleshare==0.7.5 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca \
--hash=sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56
pillow==9.4.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:013016af6b3a12a2f40b704677f8b51f72cb007dac785a9933d5c86a72a7fe33 \
--hash=sha256:0845adc64fe9886db00f5ab68c4a8cd933ab749a87747555cec1c95acea64b0b \
--hash=sha256:0884ba7b515163a1a05440a138adeb722b8a6ae2c2b33aea93ea3118dd3a899e \
--hash=sha256:09b89ddc95c248ee788328528e6a2996e09eaccddeeb82a5356e92645733be35 \
--hash=sha256:0dd4c681b82214b36273c18ca7ee87065a50e013112eea7d78c7a1b89a739153 \
--hash=sha256:0e51f608da093e5d9038c592b5b575cadc12fd748af1479b5e858045fff955a9 \
--hash=sha256:0f3269304c1a7ce82f1759c12ce731ef9b6e95b6df829dccd9fe42912cc48569 \
--hash=sha256:16a8df99701f9095bea8a6c4b3197da105df6f74e6176c5b410bc2df2fd29a57 \
--hash=sha256:19005a8e58b7c1796bc0167862b1f54a64d3b44ee5d48152b06bb861458bc0f8 \
--hash=sha256:1b4b4e9dda4f4e4c4e6896f93e84a8f0bcca3b059de9ddf67dac3c334b1195e1 \
--hash=sha256:28676836c7796805914b76b1837a40f76827ee0d5398f72f7dcc634bae7c6264 \
--hash=sha256:2968c58feca624bb6c8502f9564dd187d0e1389964898f5e9e1fbc8533169157 \
--hash=sha256:3f4cc516e0b264c8d4ccd6b6cbc69a07c6d582d8337df79be1e15a5056b258c9 \
--hash=sha256:3fa1284762aacca6dc97474ee9c16f83990b8eeb6697f2ba17140d54b453e133 \
--hash=sha256:43521ce2c4b865d385e78579a082b6ad1166ebed2b1a2293c3be1d68dd7ca3b9 \
--hash=sha256:451f10ef963918e65b8869e17d67db5e2f4ab40e716ee6ce7129b0cde2876eab \
--hash=sha256:46c259e87199041583658457372a183636ae8cd56dbf3f0755e0f376a7f9d0e6 \
--hash=sha256:46f39cab8bbf4a384ba7cb0bc8bae7b7062b6a11cfac1ca4bc144dea90d4a9f5 \
--hash=sha256:519e14e2c49fcf7616d6d2cfc5c70adae95682ae20f0395e9280db85e8d6c4df \
--hash=sha256:53dcb50fbdc3fb2c55431a9b30caeb2f7027fcd2aeb501459464f0214200a503 \
--hash=sha256:54614444887e0d3043557d9dbc697dbb16cfb5a35d672b7a0fcc1ed0cf1c600b \
--hash=sha256:575d8912dca808edd9acd6f7795199332696d3469665ef26163cd090fa1f8bfa \
--hash=sha256:5dd5a9c3091a0f414a963d427f920368e2b6a4c2f7527fdd82cde8ef0bc7a327 \
--hash=sha256:5f532a2ad4d174eb73494e7397988e22bf427f91acc8e6ebf5bb10597b49c493 \
--hash=sha256:60e7da3a3ad1812c128750fc1bc14a7ceeb8d29f77e0a2356a8fb2aa8925287d \
--hash=sha256:653d7fb2df65efefbcbf81ef5fe5e5be931f1ee4332c2893ca638c9b11a409c4 \
--hash=sha256:6663977496d616b618b6cfa43ec86e479ee62b942e1da76a2c3daa1c75933ef4 \
--hash=sha256:6abfb51a82e919e3933eb137e17c4ae9c0475a25508ea88993bb59faf82f3b35 \
--hash=sha256:6c6b1389ed66cdd174d040105123a5a1bc91d0aa7059c7261d20e583b6d8cbd2 \
--hash=sha256:6d9dfb9959a3b0039ee06c1a1a90dc23bac3b430842dcb97908ddde05870601c \
--hash=sha256:765cb54c0b8724a7c12c55146ae4647e0274a839fb6de7bcba841e04298e1011 \
--hash=sha256:7a21222644ab69ddd9967cfe6f2bb420b460dae4289c9d40ff9a4896e7c35c9a \
--hash=sha256:7ac7594397698f77bce84382929747130765f66406dc2cd8b4ab4da68ade4c6e \
--hash=sha256:7cfc287da09f9d2a7ec146ee4d72d6ea1342e770d975e49a8621bf54eaa8f30f \
--hash=sha256:83125753a60cfc8c412de5896d10a0a405e0bd88d0470ad82e0869ddf0cb3848 \
--hash=sha256:847b114580c5cc9ebaf216dd8c8dbc6b00a3b7ab0131e173d7120e6deade1f57 \
--hash=sha256:87708d78a14d56a990fbf4f9cb350b7d89ee8988705e58e39bdf4d82c149210f \
--hash=sha256:8a2b5874d17e72dfb80d917213abd55d7e1ed2479f38f001f264f7ce7bae757c \
--hash=sha256:8f127e7b028900421cad64f51f75c051b628db17fb00e099eb148761eed598c9 \
--hash=sha256:94cdff45173b1919350601f82d61365e792895e3c3a3443cf99819e6fbf717a5 \
--hash=sha256:99d92d148dd03fd19d16175b6d355cc1b01faf80dae93c6c3eb4163709edc0a9 \
--hash=sha256:9a3049a10261d7f2b6514d35bbb7a4dfc3ece4c4de14ef5876c4b7a23a0e566d \
--hash=sha256:9d9a62576b68cd90f7075876f4e8444487db5eeea0e4df3ba298ee38a8d067b0 \
--hash=sha256:9e5f94742033898bfe84c93c831a6f552bb629448d4072dd312306bab3bd96f1 \
--hash=sha256:a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e \
--hash=sha256:a2e0f87144fcbbe54297cae708c5e7f9da21a4646523456b00cc956bd4c65815 \
--hash=sha256:a4dfdae195335abb4e89cc9762b2edc524f3c6e80d647a9a81bf81e17e3fb6f0 \
--hash=sha256:a96e6e23f2b79433390273eaf8cc94fec9c6370842e577ab10dabdcc7ea0a66b \
--hash=sha256:aabdab8ec1e7ca7f1434d042bf8b1e92056245fb179790dc97ed040361f16bfd \
--hash=sha256:b222090c455d6d1a64e6b7bb5f4035c4dff479e22455c9eaa1bdd4c75b52c80c \
--hash=sha256:b52ff4f4e002f828ea6483faf4c4e8deea8d743cf801b74910243c58acc6eda3 \
--hash=sha256:b70756ec9417c34e097f987b4d8c510975216ad26ba6e57ccb53bc758f490dab \
--hash=sha256:b8c2f6eb0df979ee99433d8b3f6d193d9590f735cf12274c108bd954e30ca858 \
--hash=sha256:b9b752ab91e78234941e44abdecc07f1f0d8f51fb62941d32995b8161f68cfe5 \
--hash=sha256:ba6612b6548220ff5e9df85261bddc811a057b0b465a1226b39bfb8550616aee \
--hash=sha256:bd752c5ff1b4a870b7661234694f24b1d2b9076b8bf337321a814c612665f343 \
--hash=sha256:c3c4ed2ff6760e98d262e0cc9c9a7f7b8a9f61aa4d47c58835cdaf7b0b8811bb \
--hash=sha256:c5c1362c14aee73f50143d74389b2c158707b4abce2cb055b7ad37ce60738d47 \
--hash=sha256:cb362e3b0976dc994857391b776ddaa8c13c28a16f80ac6522c23d5257156bed \
--hash=sha256:d197df5489004db87d90b918033edbeee0bd6df3848a204bca3ff0a903bef837 \
--hash=sha256:d3b56206244dc8711f7e8b7d6cad4663917cd5b2d950799425076681e8766286 \
--hash=sha256:d5b2f8a31bd43e0f18172d8ac82347c8f37ef3e0b414431157718aa234991b28 \
--hash=sha256:d7081c084ceb58278dd3cf81f836bc818978c0ccc770cbbb202125ddabec6628 \
--hash=sha256:db74f5562c09953b2c5f8ec4b7dfd3f5421f31811e97d1dbc0a7c93d6e3a24df \
--hash=sha256:df41112ccce5d47770a0c13651479fbcd8793f34232a2dd9faeccb75eb5d0d0d \
--hash=sha256:e1339790c083c5a4de48f688b4841f18df839eb3c9584a770cbd818b33e26d5d \
--hash=sha256:e621b0246192d3b9cb1dc62c78cfa4c6f6d2ddc0ec207d43c0dedecb914f152a \
--hash=sha256:e8c5cf126889a4de385c02a2c3d3aba4b00f70234bfddae82a5eaa3ee6d5e3e6 \
--hash=sha256:e9d7747847c53a16a729b6ee5e737cf170f7a16611c143d95aa60a109a59c336 \
--hash=sha256:eaef5d2de3c7e9b21f1e762f289d17b726c2239a42b11e25446abf82b26ac132 \
--hash=sha256:ed3e4b4e1e6de75fdc16d3259098de7c6571b1a6cc863b1a49e7d3d53e036070 \
--hash=sha256:ef21af928e807f10bf4141cad4746eee692a0dd3ff56cfb25fce076ec3cc8abe \
--hash=sha256:f09598b416ba39a8f489c124447b007fe865f786a89dbfa48bb5cf395693132a \
--hash=sha256:f0caf4a5dcf610d96c3bd32932bfac8aee61c96e60481c2a0ea58da435e25acd \
--hash=sha256:f6e78171be3fb7941f9910ea15b4b14ec27725865a73c15277bc39f5ca4f8391 \
--hash=sha256:f715c32e774a60a337b2bb8ad9839b4abf75b267a0f18806f6f4f5f1688c4b5a \
--hash=sha256:fb5c1ad6bad98c57482236a21bf985ab0ef42bd51f7ad4e4538e89a997624e12
platformdirs==2.6.2 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490 \
--hash=sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2
prompt-toolkit==3.0.36 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63 \
--hash=sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305
ptyprocess==0.7.0 ; python_version >= "3.9" and python_version < "4.0" and sys_platform != "win32" \
--hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \
--hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220
pure-eval==0.2.2 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350 \
--hash=sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3
pyasn1-modules==0.2.8 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \
--hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74
pyasn1==0.4.8 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \
--hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba
pycodestyle==2.10.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053 \
--hash=sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610
pyflakes==3.0.1 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf \
--hash=sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd
pygments==2.14.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297 \
--hash=sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717
python-cas==1.6.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:2abc0dae93c3b14097999fb7062f23cd09bc9f4e33d93f03c0cc040bd71ed50e \
--hash=sha256:b8f1dcb1b6c56b3ff4f86bbef47bcdfcf932061ccd4812ae35e3f63954dfdb28
python-ldap==3.4.3 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:ab26c519a0ef2a443a2a10391fa3c5cb52d7871323399db949ebfaa9f25ee2a0
pytz==2022.7.1 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0 \
--hash=sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a
requests==2.28.2 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa \
--hash=sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf
six==1.16.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
sqlparse==0.4.3 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34 \
--hash=sha256:69ca804846bb114d2ec380e4360a8a340db83f0ccf3afceeb1404df028f57268
stack-data==0.6.2 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815 \
--hash=sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8
tomli==2.0.1 ; python_version >= "3.9" and python_full_version < "3.11.0a7" \
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
traitlets==5.9.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8 \
--hash=sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9
typing-extensions==4.4.0 ; python_version >= "3.9" and python_version < "3.10" \
--hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \
--hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e
urllib3==1.26.14 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72 \
--hash=sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1
wcwidth==0.2.6 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e \
--hash=sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0

314
requirements-prod.txt Normal file
View file

@ -0,0 +1,314 @@
asgiref==3.6.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac \
--hash=sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506
async-timeout==4.0.2 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15 \
--hash=sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c
authens==0.1b4 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:3430c85d0c11c7ca78cba484d5dfd18e9ba3370a0f2abbdd14aafb8feb8807a5
certifi==2022.12.7 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \
--hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18
charset-normalizer==3.0.1 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b \
--hash=sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42 \
--hash=sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d \
--hash=sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b \
--hash=sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a \
--hash=sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59 \
--hash=sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154 \
--hash=sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1 \
--hash=sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c \
--hash=sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a \
--hash=sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d \
--hash=sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6 \
--hash=sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b \
--hash=sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b \
--hash=sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783 \
--hash=sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5 \
--hash=sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918 \
--hash=sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555 \
--hash=sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639 \
--hash=sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786 \
--hash=sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e \
--hash=sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed \
--hash=sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820 \
--hash=sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8 \
--hash=sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3 \
--hash=sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541 \
--hash=sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14 \
--hash=sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be \
--hash=sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e \
--hash=sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76 \
--hash=sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b \
--hash=sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c \
--hash=sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b \
--hash=sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3 \
--hash=sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc \
--hash=sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6 \
--hash=sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59 \
--hash=sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4 \
--hash=sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d \
--hash=sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d \
--hash=sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3 \
--hash=sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a \
--hash=sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea \
--hash=sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6 \
--hash=sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e \
--hash=sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603 \
--hash=sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24 \
--hash=sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a \
--hash=sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58 \
--hash=sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678 \
--hash=sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a \
--hash=sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c \
--hash=sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6 \
--hash=sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18 \
--hash=sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174 \
--hash=sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317 \
--hash=sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f \
--hash=sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc \
--hash=sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837 \
--hash=sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41 \
--hash=sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c \
--hash=sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579 \
--hash=sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753 \
--hash=sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8 \
--hash=sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291 \
--hash=sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087 \
--hash=sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866 \
--hash=sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3 \
--hash=sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d \
--hash=sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1 \
--hash=sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca \
--hash=sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e \
--hash=sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db \
--hash=sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72 \
--hash=sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d \
--hash=sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc \
--hash=sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539 \
--hash=sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d \
--hash=sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af \
--hash=sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b \
--hash=sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602 \
--hash=sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f \
--hash=sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478 \
--hash=sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c \
--hash=sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e \
--hash=sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479 \
--hash=sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7 \
--hash=sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8
django-redis==5.2.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:1d037dc02b11ad7aa11f655d26dac3fb1af32630f61ef4428860a2e29ff92026 \
--hash=sha256:8a99e5582c79f894168f5865c52bd921213253b7fd64d16733ae4591564465de
django==3.2.16 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:18ba8efa36b69cfcd4b670d0fa187c6fe7506596f0ababe580e16909bcdec121 \
--hash=sha256:3adc285124244724a394fa9b9839cc8cd116faf7d159554c43ecdaa8cdf0b94d
gunicorn==20.1.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e \
--hash=sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8
idna==3.4 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
lxml==4.9.2 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:01d36c05f4afb8f7c20fd9ed5badca32a2029b93b1750f571ccc0b142531caf7 \
--hash=sha256:04876580c050a8c5341d706dd464ff04fd597095cc8c023252566a8826505726 \
--hash=sha256:05ca3f6abf5cf78fe053da9b1166e062ade3fa5d4f92b4ed688127ea7d7b1d03 \
--hash=sha256:090c6543d3696cbe15b4ac6e175e576bcc3f1ccfbba970061b7300b0c15a2140 \
--hash=sha256:0dc313ef231edf866912e9d8f5a042ddab56c752619e92dfd3a2c277e6a7299a \
--hash=sha256:0f2b1e0d79180f344ff9f321327b005ca043a50ece8713de61d1cb383fb8ac05 \
--hash=sha256:13598ecfbd2e86ea7ae45ec28a2a54fb87ee9b9fdb0f6d343297d8e548392c03 \
--hash=sha256:16efd54337136e8cd72fb9485c368d91d77a47ee2d42b057564aae201257d419 \
--hash=sha256:1ab8f1f932e8f82355e75dda5413a57612c6ea448069d4fb2e217e9a4bed13d4 \
--hash=sha256:223f4232855ade399bd409331e6ca70fb5578efef22cf4069a6090acc0f53c0e \
--hash=sha256:2455cfaeb7ac70338b3257f41e21f0724f4b5b0c0e7702da67ee6c3640835b67 \
--hash=sha256:2899456259589aa38bfb018c364d6ae7b53c5c22d8e27d0ec7609c2a1ff78b50 \
--hash=sha256:2a29ba94d065945944016b6b74e538bdb1751a1db6ffb80c9d3c2e40d6fa9894 \
--hash=sha256:2a87fa548561d2f4643c99cd13131acb607ddabb70682dcf1dff5f71f781a4bf \
--hash=sha256:2e430cd2824f05f2d4f687701144556646bae8f249fd60aa1e4c768ba7018947 \
--hash=sha256:36c3c175d34652a35475a73762b545f4527aec044910a651d2bf50de9c3352b1 \
--hash=sha256:3818b8e2c4b5148567e1b09ce739006acfaa44ce3156f8cbbc11062994b8e8dd \
--hash=sha256:3ab9fa9d6dc2a7f29d7affdf3edebf6ece6fb28a6d80b14c3b2fb9d39b9322c3 \
--hash=sha256:3efea981d956a6f7173b4659849f55081867cf897e719f57383698af6f618a92 \
--hash=sha256:4c8f293f14abc8fd3e8e01c5bd86e6ed0b6ef71936ded5bf10fe7a5efefbaca3 \
--hash=sha256:5344a43228767f53a9df6e5b253f8cdca7dfc7b7aeae52551958192f56d98457 \
--hash=sha256:58bfa3aa19ca4c0f28c5dde0ff56c520fbac6f0daf4fac66ed4c8d2fb7f22e74 \
--hash=sha256:5b4545b8a40478183ac06c073e81a5ce4cf01bf1734962577cf2bb569a5b3bbf \
--hash=sha256:5f50a1c177e2fa3ee0667a5ab79fdc6b23086bc8b589d90b93b4bd17eb0e64d1 \
--hash=sha256:63da2ccc0857c311d764e7d3d90f429c252e83b52d1f8f1d1fe55be26827d1f4 \
--hash=sha256:6749649eecd6a9871cae297bffa4ee76f90b4504a2a2ab528d9ebe912b101975 \
--hash=sha256:6804daeb7ef69e7b36f76caddb85cccd63d0c56dedb47555d2fc969e2af6a1a5 \
--hash=sha256:689bb688a1db722485e4610a503e3e9210dcc20c520b45ac8f7533c837be76fe \
--hash=sha256:699a9af7dffaf67deeae27b2112aa06b41c370d5e7633e0ee0aea2e0b6c211f7 \
--hash=sha256:6b418afe5df18233fc6b6093deb82a32895b6bb0b1155c2cdb05203f583053f1 \
--hash=sha256:76cf573e5a365e790396a5cc2b909812633409306c6531a6877c59061e42c4f2 \
--hash=sha256:7b515674acfdcadb0eb5d00d8a709868173acece5cb0be3dd165950cbfdf5409 \
--hash=sha256:7b770ed79542ed52c519119473898198761d78beb24b107acf3ad65deae61f1f \
--hash=sha256:7d2278d59425777cfcb19735018d897ca8303abe67cc735f9f97177ceff8027f \
--hash=sha256:7e91ee82f4199af8c43d8158024cbdff3d931df350252288f0d4ce656df7f3b5 \
--hash=sha256:821b7f59b99551c69c85a6039c65b75f5683bdc63270fec660f75da67469ca24 \
--hash=sha256:822068f85e12a6e292803e112ab876bc03ed1f03dddb80154c395f891ca6b31e \
--hash=sha256:8340225bd5e7a701c0fa98284c849c9b9fc9238abf53a0ebd90900f25d39a4e4 \
--hash=sha256:85cabf64adec449132e55616e7ca3e1000ab449d1d0f9d7f83146ed5bdcb6d8a \
--hash=sha256:880bbbcbe2fca64e2f4d8e04db47bcdf504936fa2b33933efd945e1b429bea8c \
--hash=sha256:8d0b4612b66ff5d62d03bcaa043bb018f74dfea51184e53f067e6fdcba4bd8de \
--hash=sha256:8e20cb5a47247e383cf4ff523205060991021233ebd6f924bca927fcf25cf86f \
--hash=sha256:925073b2fe14ab9b87e73f9a5fde6ce6392da430f3004d8b72cc86f746f5163b \
--hash=sha256:998c7c41910666d2976928c38ea96a70d1aa43be6fe502f21a651e17483a43c5 \
--hash=sha256:9b22c5c66f67ae00c0199f6055705bc3eb3fcb08d03d2ec4059a2b1b25ed48d7 \
--hash=sha256:9f102706d0ca011de571de32c3247c6476b55bb6bc65a20f682f000b07a4852a \
--hash=sha256:a08cff61517ee26cb56f1e949cca38caabe9ea9fbb4b1e10a805dc39844b7d5c \
--hash=sha256:a0a336d6d3e8b234a3aae3c674873d8f0e720b76bc1d9416866c41cd9500ffb9 \
--hash=sha256:a35f8b7fa99f90dd2f5dc5a9fa12332642f087a7641289ca6c40d6e1a2637d8e \
--hash=sha256:a38486985ca49cfa574a507e7a2215c0c780fd1778bb6290c21193b7211702ab \
--hash=sha256:a5da296eb617d18e497bcf0a5c528f5d3b18dadb3619fbdadf4ed2356ef8d941 \
--hash=sha256:a6e441a86553c310258aca15d1c05903aaf4965b23f3bc2d55f200804e005ee5 \
--hash=sha256:a82d05da00a58b8e4c0008edbc8a4b6ec5a4bc1e2ee0fb6ed157cf634ed7fa45 \
--hash=sha256:ab323679b8b3030000f2be63e22cdeea5b47ee0abd2d6a1dc0c8103ddaa56cd7 \
--hash=sha256:b1f42b6921d0e81b1bcb5e395bc091a70f41c4d4e55ba99c6da2b31626c44892 \
--hash=sha256:b23e19989c355ca854276178a0463951a653309fb8e57ce674497f2d9f208746 \
--hash=sha256:b264171e3143d842ded311b7dccd46ff9ef34247129ff5bf5066123c55c2431c \
--hash=sha256:b26a29f0b7fc6f0897f043ca366142d2b609dc60756ee6e4e90b5f762c6adc53 \
--hash=sha256:b64d891da92e232c36976c80ed7ebb383e3f148489796d8d31a5b6a677825efe \
--hash=sha256:b9cc34af337a97d470040f99ba4282f6e6bac88407d021688a5d585e44a23184 \
--hash=sha256:bc718cd47b765e790eecb74d044cc8d37d58562f6c314ee9484df26276d36a38 \
--hash=sha256:be7292c55101e22f2a3d4d8913944cbea71eea90792bf914add27454a13905df \
--hash=sha256:c83203addf554215463b59f6399835201999b5e48019dc17f182ed5ad87205c9 \
--hash=sha256:c9ec3eaf616d67db0764b3bb983962b4f385a1f08304fd30c7283954e6a7869b \
--hash=sha256:ca34efc80a29351897e18888c71c6aca4a359247c87e0b1c7ada14f0ab0c0fb2 \
--hash=sha256:ca989b91cf3a3ba28930a9fc1e9aeafc2a395448641df1f387a2d394638943b0 \
--hash=sha256:d02a5399126a53492415d4906ab0ad0375a5456cc05c3fc0fc4ca11771745cda \
--hash=sha256:d17bc7c2ccf49c478c5bdd447594e82692c74222698cfc9b5daae7ae7e90743b \
--hash=sha256:d5bf6545cd27aaa8a13033ce56354ed9e25ab0e4ac3b5392b763d8d04b08e0c5 \
--hash=sha256:d6b430a9938a5a5d85fc107d852262ddcd48602c120e3dbb02137c83d212b380 \
--hash=sha256:da248f93f0418a9e9d94b0080d7ebc407a9a5e6d0b57bb30db9b5cc28de1ad33 \
--hash=sha256:da4dd7c9c50c059aba52b3524f84d7de956f7fef88f0bafcf4ad7dde94a064e8 \
--hash=sha256:df0623dcf9668ad0445e0558a21211d4e9a149ea8f5666917c8eeec515f0a6d1 \
--hash=sha256:e5168986b90a8d1f2f9dc1b841467c74221bd752537b99761a93d2d981e04889 \
--hash=sha256:efa29c2fe6b4fdd32e8ef81c1528506895eca86e1d8c4657fda04c9b3786ddf9 \
--hash=sha256:f1496ea22ca2c830cbcbd473de8f114a320da308438ae65abad6bab7867fe38f \
--hash=sha256:f49e52d174375a7def9915c9f06ec4e569d235ad428f70751765f48d5926678c
pillow==9.4.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:013016af6b3a12a2f40b704677f8b51f72cb007dac785a9933d5c86a72a7fe33 \
--hash=sha256:0845adc64fe9886db00f5ab68c4a8cd933ab749a87747555cec1c95acea64b0b \
--hash=sha256:0884ba7b515163a1a05440a138adeb722b8a6ae2c2b33aea93ea3118dd3a899e \
--hash=sha256:09b89ddc95c248ee788328528e6a2996e09eaccddeeb82a5356e92645733be35 \
--hash=sha256:0dd4c681b82214b36273c18ca7ee87065a50e013112eea7d78c7a1b89a739153 \
--hash=sha256:0e51f608da093e5d9038c592b5b575cadc12fd748af1479b5e858045fff955a9 \
--hash=sha256:0f3269304c1a7ce82f1759c12ce731ef9b6e95b6df829dccd9fe42912cc48569 \
--hash=sha256:16a8df99701f9095bea8a6c4b3197da105df6f74e6176c5b410bc2df2fd29a57 \
--hash=sha256:19005a8e58b7c1796bc0167862b1f54a64d3b44ee5d48152b06bb861458bc0f8 \
--hash=sha256:1b4b4e9dda4f4e4c4e6896f93e84a8f0bcca3b059de9ddf67dac3c334b1195e1 \
--hash=sha256:28676836c7796805914b76b1837a40f76827ee0d5398f72f7dcc634bae7c6264 \
--hash=sha256:2968c58feca624bb6c8502f9564dd187d0e1389964898f5e9e1fbc8533169157 \
--hash=sha256:3f4cc516e0b264c8d4ccd6b6cbc69a07c6d582d8337df79be1e15a5056b258c9 \
--hash=sha256:3fa1284762aacca6dc97474ee9c16f83990b8eeb6697f2ba17140d54b453e133 \
--hash=sha256:43521ce2c4b865d385e78579a082b6ad1166ebed2b1a2293c3be1d68dd7ca3b9 \
--hash=sha256:451f10ef963918e65b8869e17d67db5e2f4ab40e716ee6ce7129b0cde2876eab \
--hash=sha256:46c259e87199041583658457372a183636ae8cd56dbf3f0755e0f376a7f9d0e6 \
--hash=sha256:46f39cab8bbf4a384ba7cb0bc8bae7b7062b6a11cfac1ca4bc144dea90d4a9f5 \
--hash=sha256:519e14e2c49fcf7616d6d2cfc5c70adae95682ae20f0395e9280db85e8d6c4df \
--hash=sha256:53dcb50fbdc3fb2c55431a9b30caeb2f7027fcd2aeb501459464f0214200a503 \
--hash=sha256:54614444887e0d3043557d9dbc697dbb16cfb5a35d672b7a0fcc1ed0cf1c600b \
--hash=sha256:575d8912dca808edd9acd6f7795199332696d3469665ef26163cd090fa1f8bfa \
--hash=sha256:5dd5a9c3091a0f414a963d427f920368e2b6a4c2f7527fdd82cde8ef0bc7a327 \
--hash=sha256:5f532a2ad4d174eb73494e7397988e22bf427f91acc8e6ebf5bb10597b49c493 \
--hash=sha256:60e7da3a3ad1812c128750fc1bc14a7ceeb8d29f77e0a2356a8fb2aa8925287d \
--hash=sha256:653d7fb2df65efefbcbf81ef5fe5e5be931f1ee4332c2893ca638c9b11a409c4 \
--hash=sha256:6663977496d616b618b6cfa43ec86e479ee62b942e1da76a2c3daa1c75933ef4 \
--hash=sha256:6abfb51a82e919e3933eb137e17c4ae9c0475a25508ea88993bb59faf82f3b35 \
--hash=sha256:6c6b1389ed66cdd174d040105123a5a1bc91d0aa7059c7261d20e583b6d8cbd2 \
--hash=sha256:6d9dfb9959a3b0039ee06c1a1a90dc23bac3b430842dcb97908ddde05870601c \
--hash=sha256:765cb54c0b8724a7c12c55146ae4647e0274a839fb6de7bcba841e04298e1011 \
--hash=sha256:7a21222644ab69ddd9967cfe6f2bb420b460dae4289c9d40ff9a4896e7c35c9a \
--hash=sha256:7ac7594397698f77bce84382929747130765f66406dc2cd8b4ab4da68ade4c6e \
--hash=sha256:7cfc287da09f9d2a7ec146ee4d72d6ea1342e770d975e49a8621bf54eaa8f30f \
--hash=sha256:83125753a60cfc8c412de5896d10a0a405e0bd88d0470ad82e0869ddf0cb3848 \
--hash=sha256:847b114580c5cc9ebaf216dd8c8dbc6b00a3b7ab0131e173d7120e6deade1f57 \
--hash=sha256:87708d78a14d56a990fbf4f9cb350b7d89ee8988705e58e39bdf4d82c149210f \
--hash=sha256:8a2b5874d17e72dfb80d917213abd55d7e1ed2479f38f001f264f7ce7bae757c \
--hash=sha256:8f127e7b028900421cad64f51f75c051b628db17fb00e099eb148761eed598c9 \
--hash=sha256:94cdff45173b1919350601f82d61365e792895e3c3a3443cf99819e6fbf717a5 \
--hash=sha256:99d92d148dd03fd19d16175b6d355cc1b01faf80dae93c6c3eb4163709edc0a9 \
--hash=sha256:9a3049a10261d7f2b6514d35bbb7a4dfc3ece4c4de14ef5876c4b7a23a0e566d \
--hash=sha256:9d9a62576b68cd90f7075876f4e8444487db5eeea0e4df3ba298ee38a8d067b0 \
--hash=sha256:9e5f94742033898bfe84c93c831a6f552bb629448d4072dd312306bab3bd96f1 \
--hash=sha256:a1c2d7780448eb93fbcc3789bf3916aa5720d942e37945f4056680317f1cd23e \
--hash=sha256:a2e0f87144fcbbe54297cae708c5e7f9da21a4646523456b00cc956bd4c65815 \
--hash=sha256:a4dfdae195335abb4e89cc9762b2edc524f3c6e80d647a9a81bf81e17e3fb6f0 \
--hash=sha256:a96e6e23f2b79433390273eaf8cc94fec9c6370842e577ab10dabdcc7ea0a66b \
--hash=sha256:aabdab8ec1e7ca7f1434d042bf8b1e92056245fb179790dc97ed040361f16bfd \
--hash=sha256:b222090c455d6d1a64e6b7bb5f4035c4dff479e22455c9eaa1bdd4c75b52c80c \
--hash=sha256:b52ff4f4e002f828ea6483faf4c4e8deea8d743cf801b74910243c58acc6eda3 \
--hash=sha256:b70756ec9417c34e097f987b4d8c510975216ad26ba6e57ccb53bc758f490dab \
--hash=sha256:b8c2f6eb0df979ee99433d8b3f6d193d9590f735cf12274c108bd954e30ca858 \
--hash=sha256:b9b752ab91e78234941e44abdecc07f1f0d8f51fb62941d32995b8161f68cfe5 \
--hash=sha256:ba6612b6548220ff5e9df85261bddc811a057b0b465a1226b39bfb8550616aee \
--hash=sha256:bd752c5ff1b4a870b7661234694f24b1d2b9076b8bf337321a814c612665f343 \
--hash=sha256:c3c4ed2ff6760e98d262e0cc9c9a7f7b8a9f61aa4d47c58835cdaf7b0b8811bb \
--hash=sha256:c5c1362c14aee73f50143d74389b2c158707b4abce2cb055b7ad37ce60738d47 \
--hash=sha256:cb362e3b0976dc994857391b776ddaa8c13c28a16f80ac6522c23d5257156bed \
--hash=sha256:d197df5489004db87d90b918033edbeee0bd6df3848a204bca3ff0a903bef837 \
--hash=sha256:d3b56206244dc8711f7e8b7d6cad4663917cd5b2d950799425076681e8766286 \
--hash=sha256:d5b2f8a31bd43e0f18172d8ac82347c8f37ef3e0b414431157718aa234991b28 \
--hash=sha256:d7081c084ceb58278dd3cf81f836bc818978c0ccc770cbbb202125ddabec6628 \
--hash=sha256:db74f5562c09953b2c5f8ec4b7dfd3f5421f31811e97d1dbc0a7c93d6e3a24df \
--hash=sha256:df41112ccce5d47770a0c13651479fbcd8793f34232a2dd9faeccb75eb5d0d0d \
--hash=sha256:e1339790c083c5a4de48f688b4841f18df839eb3c9584a770cbd818b33e26d5d \
--hash=sha256:e621b0246192d3b9cb1dc62c78cfa4c6f6d2ddc0ec207d43c0dedecb914f152a \
--hash=sha256:e8c5cf126889a4de385c02a2c3d3aba4b00f70234bfddae82a5eaa3ee6d5e3e6 \
--hash=sha256:e9d7747847c53a16a729b6ee5e737cf170f7a16611c143d95aa60a109a59c336 \
--hash=sha256:eaef5d2de3c7e9b21f1e762f289d17b726c2239a42b11e25446abf82b26ac132 \
--hash=sha256:ed3e4b4e1e6de75fdc16d3259098de7c6571b1a6cc863b1a49e7d3d53e036070 \
--hash=sha256:ef21af928e807f10bf4141cad4746eee692a0dd3ff56cfb25fce076ec3cc8abe \
--hash=sha256:f09598b416ba39a8f489c124447b007fe865f786a89dbfa48bb5cf395693132a \
--hash=sha256:f0caf4a5dcf610d96c3bd32932bfac8aee61c96e60481c2a0ea58da435e25acd \
--hash=sha256:f6e78171be3fb7941f9910ea15b4b14ec27725865a73c15277bc39f5ca4f8391 \
--hash=sha256:f715c32e774a60a337b2bb8ad9839b4abf75b267a0f18806f6f4f5f1688c4b5a \
--hash=sha256:fb5c1ad6bad98c57482236a21bf985ab0ef42bd51f7ad4e4538e89a997624e12
psycopg2==2.9.5 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:093e3894d2d3c592ab0945d9eba9d139c139664dcf83a1c440b8a7aa9bb21955 \
--hash=sha256:190d51e8c1b25a47484e52a79638a8182451d6f6dff99f26ad9bd81e5359a0fa \
--hash=sha256:1a5c7d7d577e0eabfcf15eb87d1e19314c8c4f0e722a301f98e0e3a65e238b4e \
--hash=sha256:1e5a38aa85bd660c53947bd28aeaafb6a97d70423606f1ccb044a03a1203fe4a \
--hash=sha256:322fd5fca0b1113677089d4ebd5222c964b1760e361f151cbb2706c4912112c5 \
--hash=sha256:4cb9936316d88bfab614666eb9e32995e794ed0f8f6b3b718666c22819c1d7ee \
--hash=sha256:920bf418000dd17669d2904472efeab2b20546efd0548139618f8fa305d1d7ad \
--hash=sha256:922cc5f0b98a5f2b1ff481f5551b95cd04580fd6f0c72d9b22e6c0145a4840e0 \
--hash=sha256:a5246d2e683a972e2187a8714b5c2cf8156c064629f9a9b1a873c1730d9e245a \
--hash=sha256:b9ac1b0d8ecc49e05e4e182694f418d27f3aedcfca854ebd6c05bb1cffa10d6d \
--hash=sha256:d3ef67e630b0de0779c42912fe2cbae3805ebaba30cda27fea2a3de650a9414f \
--hash=sha256:f5b6320dbc3cf6cfb9f25308286f9f7ab464e65cfb105b64cc9c52831748ced2 \
--hash=sha256:fc04dd5189b90d825509caa510f20d1d504761e78b8dfb95a0ede180f71d50e5
pyasn1-modules==0.2.8 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \
--hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74
pyasn1==0.4.8 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \
--hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba
python-cas==1.6.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:2abc0dae93c3b14097999fb7062f23cd09bc9f4e33d93f03c0cc040bd71ed50e \
--hash=sha256:b8f1dcb1b6c56b3ff4f86bbef47bcdfcf932061ccd4812ae35e3f63954dfdb28
python-ldap==3.4.3 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:ab26c519a0ef2a443a2a10391fa3c5cb52d7871323399db949ebfaa9f25ee2a0
pytz==2022.7.1 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0 \
--hash=sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a
redis==4.4.2 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:a010f6cb7378065040a02839c3f75c7e0fb37a87116fb4a95be82a95552776c7 \
--hash=sha256:e6206448e2f8a432871d07d432c13ed6c2abcf6b74edb436c99752b1371be387
requests==2.28.2 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa \
--hash=sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf
setuptools==67.0.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:883131c5b6efa70b9101c7ef30b2b7b780a4283d5fc1616383cdf22c83cbefe6 \
--hash=sha256:9d790961ba6219e9ff7d9557622d2fe136816a264dd01d5997cfc057d804853d
six==1.16.0 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
sqlparse==0.4.3 ; python_version >= "3.9" and python_version < "4.0" \
--hash=sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34 \
--hash=sha256:69ca804846bb114d2ec380e4360a8a340db83f0ccf3afceeb1404df028f57268
urllib3==1.26.14 ; python_version >= "3.9" and python_version < "4" \
--hash=sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72 \
--hash=sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1

View file

@ -1,5 +0,0 @@
django==2.2.*
Pillow
django_cas_ng
python-ldap
authens

2
setup.cfg Normal file
View file

@ -0,0 +1,2 @@
[flake8]
max-line-length = 99

2
shell.nix Normal file
View file

@ -0,0 +1,2 @@
(import ./. { }).devShell

242
transfert.py Normal file
View file

@ -0,0 +1,242 @@
import json
import os
import sys
from datetime import datetime
import django
from django.contrib.auth import get_user_model
print("\nTransfert des fiches annuaires :")
# Configuration
print("Paramétrage de Django...", end=" ")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "annuaire.settings.prod")
django.setup()
User = get_user_model()
from authens.models import CASAccount # noqa
from fiches.management.commands._ldap import ClipperLDAP # noqa
from fiches.models import Address, Department, Mail, Phone, Profile # noqa
print("[ok]")
# Utilitaires
def parse_date(s):
try:
return datetime.strptime(s, "%Y-%m-%d").date()
except (ValueError, TypeError):
return None
def get_text_field(data):
text = ""
if data["interests"]:
text += "Mes intérêts :\n" + data["interests"] + "\n\n"
if data["websites"]:
text += "Mes pages web :\n\n" + data["websites"] + "\n\n"
if data["comments"]:
text += data["comments"] + "\n\n"
return text
def get_address(data):
content = data["lines"] + "\n"
if data["zip"] and data["city"]:
content += data["zip"] + ", " + data["city"]
elif data["zip"] or data["city"]:
content += data["zip"] + data["city"]
if data["country"]:
content += ", " + data["country"]
return content
def parse_list(s):
s = s or ""
return [p for p in s.replace(",", ";").replace("\n", ";").split(";") if p]
def create_phones(s, profile, numeros, name="Téléphone"):
for p in parse_list(s):
numeros.append(Phone(profile=profile, name=name, number=p))
def create_mails(s, profile, mails, name="E-mail"):
for m in parse_list(s):
mails.append(Mail(profile=profile, name=name, mail=m))
print("Récupération des comptes clipper...", end=" ")
ldap = ClipperLDAP()
clippers = {c.uid: c for c in ldap.get_clipper_list(stdout=sys.stdout)}
print("[ok]")
depts = {
dept: Department.objects.get_or_create(name=dept)[0].id
for dept in ldap.verbose_depts.values()
}
users_to_create = []
users = {}
profiles_to_create = []
dept_m2m_to_create = []
print("Création des comptes...", end=" ")
for clipper in clippers.values():
user = User(username=clipper.uid, email=clipper.email)
users_to_create.append(user)
User.objects.bulk_create(users_to_create)
users = {u.username: (u, clippers[u.username]) for u in User.objects.all()}
print("[ok]")
print("Création des comptes Authens...", end=" ")
cas_accounts = []
for (u, c) in users.values():
cas_accounts.append(CASAccount(user=u, cas_login=c.uid, entrance_year=c.year))
CASAccount.objects.bulk_create(cas_accounts)
print("[ok]")
fiches = {}
references = {}
adresses = []
devises = {}
numeros = []
mails = []
fiches_pk = {}
print("Récupération des anciennes fiches :")
# On recrée les profils
with open("old_fiches.json") as json_file:
data = json.load(json_file)
for obj in data:
if obj["model"] == "annuaire.fiches2021":
obj_data = obj["fields"]
try:
user, clipper = users[obj_data["login"]]
fiches_pk[obj["pk"]] = user.username
fiches[obj_data["login"]] = Profile(
user=user,
full_name=" ".join((obj_data["firstname"], obj_data["lastname"])),
promotion=clipper.year,
birth_date=parse_date((obj_data["birthdate"] or "")),
past_studies=(
(obj_data["past_studies"] or "")
+ "\n"
+ (obj_data["studies"] or "")
).strip(),
experiences=(obj_data["experiences"] or ""),
thurne=(obj_data["room"] or ""),
text_field=get_text_field(obj_data),
)
create_phones(obj_data["phones"], fiches[obj_data["login"]], numeros)
create_phones(
obj_data["mobiles"],
fiches[obj_data["login"]],
numeros,
name="Portable",
)
create_mails(obj_data["emails"], fiches[obj_data["login"]], mails)
dept_m2m_to_create.append(
Profile.department.through(
profile=fiches[obj_data["login"]],
department_id=depts[clipper.dept],
)
)
except KeyError:
print(f"\tLogin inconnu : {obj_data['login']}")
elif obj["model"] == "annuaire.lesreferences2021":
try:
username = fiches_pk[obj["pk"]]
surnom = obj["fields"]["nickname"]
if surnom:
fiche = fiches[username]
if fiche.nickname:
fiche.nickname += ", "
fiche.nickname += surnom
except KeyError:
pass
elif obj["model"] == "annuaire.adresses2021":
try:
username = fiches_pk[obj["pk"]]
obj_data = obj["fields"]
fiche = fiches[username]
a = get_address(obj_data).strip()
if a:
adresses.append(Address(profile=fiche, name="Adresse", content=a))
except KeyError:
pass
elif obj["model"] == "annuaire.devises2021":
try:
username = fiches_pk[obj["pk"]]
obj_data = obj["fields"]
fiche = fiches[username]
if obj_data["quote"]:
fiche.text_field += f"\n{obj_data['quote']}"
if obj_data["source"]:
fiche.text_field += f" ({obj_data['source']})"
if obj_data["author"]:
fiche.text_field += f", ({obj_data['author']})"
except KeyError:
pass
print("Création des nouvelles fiches fiches...", end=" ")
Profile.objects.bulk_create(fiches.values())
profils = {p.user.username: p for p in Profile.objects.select_related("user")}
print("[ok]")
print("Rattachement des départements...", end=" ")
for dept_m2m in dept_m2m_to_create:
dept_m2m.profile = profils[dept_m2m.profile.user.username]
Profile.department.through.objects.bulk_create(dept_m2m_to_create)
print("[ok]")
print("Création des numéros de téléphone...", end=" ")
for p in numeros:
p.profile = profils[p.profile.user.username]
Phone.objects.bulk_create(numeros)
print("[ok]")
print("Création des adresses mail...", end=" ")
for m in mails:
m.profile = profils[m.profile.user.username]
Mail.objects.bulk_create(mails)
print("[ok]")
print("Création des adresses...", end=" ")
for a in adresses:
a.profile = profils[a.profile.user.username]
Address.objects.bulk_create(adresses)
print("[ok]")